SHARE
TWEET

dd_controller.c MESS 64DD

LuigiBlood Apr 25th, 2015 240 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //
  2. // dd/controller.c: DD controller.
  3. //
  4. // CEN64: Cycle-Accurate Nintendo 64 Simulator.
  5. // Copyright (C) 2014, Tyler J. Stachecki.
  6. //
  7. // This file is subject to the terms and conditions defined in
  8. // 'LICENSE', which is part of this source code package.
  9. //
  10.  
  11. //
  12. // Thanks go out to OzOnE and Luigiblood (Seru-kun) for reverse
  13. // engineering, documenting, and assisting with the reversal of
  14. // this device!
  15. //
  16.  
  17. //
  18. // LuigiBlood's notes:
  19. // Thanks to Happy_ for figuring out a lot of the 64DD stuff.
  20. //
  21.  
  22. //
  23. // TODO: Currently, the DD IPL spams the controller with DD_CMD_NOOP.
  24. // This is normal. Once you signify that a disk is present (using the
  25. // DD_STATUS_DISK_PRES), the DD IPL attempts to start performing seeks.
  26. //
  27.  
  28. #include "common.h"
  29. #include "bus/address.h"
  30. #include "bus/controller.h"
  31. #include "dd/controller.h"
  32. #include "vr4300/interface.h"
  33. #include <time.h>
  34.  
  35. #ifdef DEBUG_MMIO_REGISTER_ACCESS
  36. const char *dd_register_mnemonics[NUM_DD_REGISTERS] = {
  37. #define X(reg) #reg,
  38. #include "dd/registers.md"
  39. #undef X
  40. };
  41. #endif
  42.  
  43. // ASIC_CMD_STATUS flags.
  44. #define DD_CMD_NOOP           0x00000000U
  45. #define DD_CMD_SEEK_READ      0x00010000U //Disk needed
  46. #define DD_CMD_SEEK_WRITE     0x00020000U //Disk needed
  47. #define DD_CMD_RECALIBRATE    0x00030000U // ??? Disk needed
  48. #define DD_CMD_SLEEP          0x00040000U
  49. #define DD_CMD_START          0x00050000U //Disk needed
  50. #define DD_CMD_SET_STANDBY    0x00060000U
  51. #define DD_CMD_SET_SLEEP      0x00070000U
  52. #define DD_CMD_CLR_DSK_CHNG   0x00080000U
  53. #define DD_CMD_CLR_RESET      0x00090000U
  54. #define DD_CMD_READ_VERSION   0x000A0000U
  55. #define DD_CMD_SET_DISK_TYPE  0x000B0000U //Disk needed
  56. #define DD_CMD_REQUEST_STATUS 0x000C0000U
  57. #define DD_CMD_STANDBY        0x000D0000U
  58. #define DD_CMD_IDX_LOCK_RETRY 0x000E0000U // ???
  59. #define DD_CMD_SET_YEAR_MONTH 0x000F0000U
  60. #define DD_CMD_SET_DAY_HOUR   0x00100000U
  61. #define DD_CMD_SET_MIN_SEC    0x00110000U
  62. #define DD_CMD_GET_YEAR_MONTH 0x00120000U
  63. #define DD_CMD_GET_DAY_HOUR   0x00130000U
  64. #define DD_CMD_GET_MIN_SEC    0x00140000U
  65. #define DD_CMD_FEATURE_INQ    0x001B0000U
  66.  
  67. #define DD_STATUS_DATA_RQ     0x40000000U
  68. #define DD_STATUS_C2_XFER     0x10000000U
  69. #define DD_STATUS_BM_ERR      0x08000000U
  70. #define DD_STATUS_BM_INT      0x04000000U
  71. #define DD_STATUS_MECHA_INT   0x02000000U
  72. #define DD_STATUS_DISK_PRES   0x01000000U
  73. #define DD_STATUS_BUSY_STATE  0x00800000U
  74. #define DD_STATUS_RST_STATE   0x00400000U
  75. #define DD_STATUS_MTR_N_SPIN  0x00100000U
  76. #define DD_STATUS_HEAD_RTRCT  0x00080000U
  77. #define DD_STATUS_WR_PR_ERR   0x00040000U
  78. #define DD_STATUS_MECHA_ERR   0x00020000U
  79. #define DD_STATUS_DISK_CHNG   0x00010000U
  80.  
  81. // ASIC_BM_STATUS_CTL flags.
  82. #define DD_BM_STATUS_RUNNING  0x80000000U
  83. #define DD_BM_STATUS_ERROR    0x04000000U
  84. #define DD_BM_STATUS_MICRO    0x02000000U // ???
  85. #define DD_BM_STATUS_BLOCK    0x01000000U
  86. #define DD_BM_STATUS_C1CRR    0x00800000U
  87. #define DD_BM_STATUS_C1DBL    0x00400000U
  88. #define DD_BM_STATUS_C1SNG    0x00200000U
  89. #define DD_BM_STATUS_C1ERR    0x00010000U // Typo ???
  90.  
  91. #define DD_BM_CTL_START       0x80000000U
  92. #define DD_BM_CTL_MNGRMODE    0x40000000U
  93. #define DD_BM_CTL_INTMASK     0x20000000U
  94. #define DD_BM_CTL_RESET       0x10000000U
  95. #define DD_BM_CTL_DIS_OR_CHK  0x08000000U // ???
  96. #define DD_BM_CTL_DIS_C1_CRR  0x04000000U
  97. #define DD_BM_CTL_BLK_TRANS   0x02000000U
  98. #define DD_BM_CTL_MECHA_RST   0x01000000U
  99.  
  100. #define SECTORS_PER_BLOCK     85
  101. #define BLOCKS_PER_TRACK      2
  102.  
  103. bool dd_reset_hold;             //RESET HOLD
  104. bool dd_bm_mode_read;   //BM MODE 0 (false) = WRITE, MODE 1 (true) = READ
  105. int      LBA;                           //GET LBA
  106. int  CUR_BLOCK;                 //Current Block
  107. int  dd_zone;                   //Current Zone
  108. int  dd_track_offset;   //Offset to Track
  109.  
  110. const unsigned int ddZoneSecSize[16] = {232,216,208,192,176,160,144,128,
  111.                                         216,208,192,176,160,144,128,112};
  112.  
  113. const unsigned int ddZoneTrackSize[16] = {158,158,149,149,149,149,149,114,
  114.                                           158,158,149,149,149,149,149,114};
  115.  
  116. const unsigned int ddStartOffset[16] =
  117.         {0x0,0x5F15E0,0xB79D00,0x10801A0,0x1523720,0x1963D80,0x1D414C0,0x20BBCE0,
  118.          0x23196E0,0x28A1E00,0x2DF5DC0,0x3299340,0x36D99A0,0x3AB70E0,0x3E31900,0x4149200};
  119.  
  120. //-------------------------------------
  121. void dd_write_sector(void *opaque)
  122. {
  123.         struct dd_controller *dd = (struct dd_controller *) opaque;
  124.  
  125.         //WRITE SECTOR
  126.         int Cur_Sector = dd->regs[DD_ASIC_CUR_SECTOR] >> 16;
  127.         if (Cur_Sector >= 0x5A)
  128.                 Cur_Sector -= 0x5A;
  129.  
  130.         int offset = dd_track_offset;
  131.         offset += CUR_BLOCK * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone];
  132.         offset += (Cur_Sector - 1) * ddZoneSecSize[dd_zone];
  133.  
  134.         //for (int i = 0; i <= (dd->regs[DD_ASIC_HOST_SECBYTE] >> 16); i++)
  135.         //dd->rom[offset + i] = dd->ds_buffer[i];
  136. }
  137.  
  138. void dd_read_sector(void *opaque)
  139. {
  140.         struct dd_controller *dd = (struct dd_controller *) opaque;
  141.  
  142.         //READ SECTOR
  143.         int Cur_Sector = dd->regs[DD_ASIC_CUR_SECTOR] >> 16;
  144.         if (Cur_Sector >= 0x5A)
  145.                 Cur_Sector -= 0x5A;
  146.  
  147.         int offset = dd_track_offset;
  148.         offset += CUR_BLOCK * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone];
  149.         offset += Cur_Sector * ddZoneSecSize[dd_zone];
  150.  
  151.         for (int i = 0; i <= (int)(dd->regs[DD_ASIC_HOST_SECBYTE] >> 16); i++)
  152.         dd->ds_buffer[i] = dd->rom[offset + i];
  153. }
  154.  
  155. void dd_read_C2(void *opaque)
  156. {
  157.         struct dd_controller *dd = (struct dd_controller *) opaque;
  158.  
  159.         for (int i = 0; i < DD_C2S_BUFFER_LEN; i++)
  160.       dd->c2s_buffer[i] = 0;
  161. }
  162.  
  163. void dd_update_bm(void *opaque)
  164. {
  165.         struct dd_controller *dd = (struct dd_controller *) opaque;
  166.  
  167.         if (!(dd->regs[DD_ASIC_BM_STATUS_CTL] & DD_BM_STATUS_RUNNING))
  168.                 return;
  169.         else
  170.         {
  171.                 int Cur_Sector = dd->regs[DD_ASIC_CUR_SECTOR] >> 16;
  172.                 if (Cur_Sector >= 0x5A)
  173.                         Cur_Sector -= 0x5A;
  174.  
  175.                 if (!dd_bm_mode_read)           //WRITE MODE
  176.                 {
  177.                         printf("--DD_UPDATE_BM WRITE Block %d Sector %X\n", ((dd->regs[DD_ASIC_CUR_TK] & 0x0FFF0000U) >> 15) + CUR_BLOCK, Cur_Sector);
  178.  
  179.                         if (Cur_Sector == 0)
  180.                         {
  181.                                 Cur_Sector++;
  182.                                 dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_DATA_RQ;
  183.                         }
  184.                         else if (Cur_Sector < SECTORS_PER_BLOCK)
  185.                         {
  186.                                 dd_write_sector(opaque);
  187.                                 Cur_Sector++;
  188.                                 dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_DATA_RQ;
  189.                         }
  190.                         else if (Cur_Sector < SECTORS_PER_BLOCK + 1)
  191.                         {
  192.                                 if (dd->regs[DD_ASIC_BM_STATUS_CTL] & DD_BM_STATUS_BLOCK)
  193.                                 {
  194.                                         dd_write_sector(opaque);
  195.                                         //next block
  196.                                         Cur_Sector = 1;
  197.                                         CUR_BLOCK = 1 - CUR_BLOCK;
  198.                                         dd->regs[DD_ASIC_BM_STATUS_CTL] &= ~DD_BM_STATUS_BLOCK;
  199.                                         dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_DATA_RQ;
  200.                                 }
  201.                                 else
  202.                                 {
  203.                                         dd_write_sector(opaque);
  204.                                         Cur_Sector++;
  205.                                         dd->regs[DD_ASIC_BM_STATUS_CTL] &= ~DD_BM_STATUS_RUNNING;
  206.                                 }
  207.                         }
  208.                 }
  209.                 else                                            //READ MODE
  210.                 {
  211.                         printf("--DD_UPDATE_BM READ Block %d Sector %X\n", ((dd->regs[DD_ASIC_CUR_TK] & 0x0FFF0000U) >> 15) + CUR_BLOCK, Cur_Sector);
  212.  
  213.                         int Cur_Track = (dd->regs[DD_ASIC_CUR_TK] & 0x0FFF0000U) >> 16;
  214.  
  215.                         dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_DATA_RQ | DD_STATUS_C2_XFER);
  216.  
  217.                         if (Cur_Track == 6 && CUR_BLOCK == 0)
  218.                         {
  219.                                 dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_DATA_RQ;
  220.                                 //dd->regs[DD_ASIC_BM_STATUS_CTL] |= DD_BM_STATUS_MICRO;
  221.                         }
  222.                         else if (Cur_Sector < SECTORS_PER_BLOCK)                //user sector
  223.                         {
  224.                                 dd_read_sector(opaque);
  225.                                 Cur_Sector++;
  226.                                 dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_DATA_RQ;
  227.                         }
  228.                         else if (Cur_Sector < SECTORS_PER_BLOCK + 4)    //C2
  229.                         {
  230.                                 dd_read_C2(opaque);
  231.                                 Cur_Sector++;
  232.                                 if (Cur_Sector == SECTORS_PER_BLOCK + 4)
  233.                                         dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_C2_XFER;
  234.                         }
  235.                         else if (Cur_Sector == SECTORS_PER_BLOCK + 4)   //Gap
  236.                         {
  237.                                 if (dd->regs[DD_ASIC_BM_STATUS_CTL] & DD_BM_STATUS_BLOCK)
  238.                                 {
  239.                                         CUR_BLOCK = 1 - CUR_BLOCK;
  240.                                         Cur_Sector = 0;
  241.                                         dd->regs[DD_ASIC_BM_STATUS_CTL] &= ~DD_BM_STATUS_BLOCK;
  242.                                 }
  243.                                 else
  244.                                         dd->regs[DD_ASIC_BM_STATUS_CTL] &= ~DD_BM_STATUS_RUNNING;
  245.                         }
  246.                 }
  247.  
  248.                 dd->regs[DD_ASIC_CUR_SECTOR] = Cur_Sector << 16;
  249.                 dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_BM_INT;
  250.         signal_dd_interrupt(dd->bus->vr4300);
  251.         }
  252. }
  253.  
  254. void dd_set_zone_and_track_offset(void *opaque)
  255. {
  256.         struct dd_controller *dd = (struct dd_controller *) opaque;
  257.  
  258.         int head = ((dd->regs[DD_ASIC_CUR_TK] & 0x10000000U) >> 25);    //Head * 8
  259.         int track = ((dd->regs[DD_ASIC_CUR_TK] & 0x0FFF0000U) >> 16);
  260.         int tr_off;
  261.  
  262.         if(track >= 0x425)
  263.         {
  264.                 dd_zone = 7 + head;
  265.                 tr_off = track - 0x425;
  266.         }
  267.         else if (track >= 0x390)
  268.         {
  269.                 dd_zone = 6 + head;
  270.                 tr_off = track - 0x390;
  271.         }
  272.         else if (track >= 0x2FB)
  273.         {
  274.                 dd_zone = 5 + head;
  275.                 tr_off = track - 0x2FB;
  276.         }
  277.         else if (track >= 0x266)
  278.         {
  279.                 dd_zone = 4 + head;
  280.                 tr_off = track - 0x266;
  281.         }
  282.         else if (track >= 0x1D1)
  283.         {
  284.                 dd_zone = 3 + head;
  285.                 tr_off = track - 0x1D1;
  286.         }
  287.         else if (track >= 0x13C)
  288.         {
  289.                 dd_zone = 2 + head;
  290.                 tr_off = track - 0x13C;
  291.         }
  292.         else if (track >= 0x9E)
  293.         {
  294.                 dd_zone = 1 + head;
  295.                 tr_off = track - 0x9E;
  296.         }
  297.         else
  298.         {
  299.                 dd_zone = 0 + head;
  300.                 tr_off = track;
  301.         }
  302.  
  303.         dd_track_offset = ddStartOffset[dd_zone] + tr_off*ddZoneSecSize[dd_zone]*SECTORS_PER_BLOCK*BLOCKS_PER_TRACK;
  304. }
  305. //------------------------------
  306.  
  307. // Initializes the DD.
  308. int dd_init(struct dd_controller *dd, struct bus_controller *bus,
  309.   const uint8_t *ddipl, const uint8_t *ddrom, size_t ddrom_size) {
  310.   dd->bus = bus;
  311.   dd->ipl_rom = ddipl;
  312.   dd->rom = ddrom;
  313.   dd->rom_size = ddrom_size;
  314.  
  315.   if (dd->ipl_rom != NULL)
  316.     dd->regs[DD_ASIC_ID_REG] = 0x00030000U;
  317.   else
  318.     dd->regs[DD_ASIC_ID_REG] = 0x00040000U;
  319.  
  320.   dd->regs[DD_ASIC_CMD_STATUS] = DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT;
  321.  
  322.   //if (dd->rom_size == 0x3DEC800) //original dumps
  323.   if (dd->rom_size > 0)
  324.     dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_DISK_PRES;
  325.  
  326.   dd_reset_hold = false;
  327.   dd_bm_mode_read = false;
  328.  
  329.   return 0;
  330. }
  331.  
  332. // Reads a word from the DD MMIO register space.
  333. int read_dd_regs(void *opaque, uint32_t address, uint32_t *word) {
  334.   struct dd_controller *dd = (struct dd_controller *) opaque;
  335.   unsigned offset = address - DD_REGS_BASE_ADDRESS;
  336.   enum dd_register reg = (offset >> 2);
  337.  
  338.   *word = dd->regs[reg];
  339.  
  340.   if (reg == DD_ASIC_CMD_STATUS)
  341.   {
  342.         int Cur_Sector = dd->regs[DD_ASIC_CUR_SECTOR] >> 16;
  343.         if (Cur_Sector >= 0x5A)
  344.                 Cur_Sector -= 0x5A;
  345.  
  346.         if ((dd->regs[DD_ASIC_CMD_STATUS] & DD_STATUS_BM_INT) && (SECTORS_PER_BLOCK < Cur_Sector))
  347.         {
  348.                 dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_BM_INT;
  349.                 clear_dd_interrupt(dd->bus->vr4300);
  350.                 printf("DD_UPDATE_BM DD REG READ\n");
  351.                 dd_update_bm(opaque);
  352.         }
  353.   }
  354.  
  355.   //if (reg != DD_ASIC_CMD_STATUS)
  356.     debug_mmio_read(dd, dd_register_mnemonics[reg], *word);
  357.   return 0;
  358. }
  359.  
  360. // Writes a word to the DD MMIO register space.
  361. int write_dd_regs(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  362.   struct dd_controller *dd = (struct dd_controller *) opaque;
  363.   unsigned offset = address - DD_REGS_BASE_ADDRESS;
  364.   enum dd_register reg = (offset >> 2);
  365.  
  366.   debug_mmio_write(dd, dd_register_mnemonics[reg], word, dqm);
  367.  
  368.   //No matter what, the lower 16-bit is always ignored.
  369.   word &= 0xFFFF0000U;
  370.  
  371.   // Command register written: do something.
  372.   if (reg == DD_ASIC_CMD_STATUS) {
  373.  
  374.     time_t timer;
  375.     struct tm * timeinfo;
  376.     switch (word)
  377.     {
  378.         case DD_CMD_GET_MIN_SEC:                // Get time [minute/second]:
  379.                 //Get Time
  380.                 time(&timer);
  381.                 timeinfo = localtime(&timer);
  382.  
  383.                 //Put time in DATA as BCD
  384.                 uint8_t min = (uint8_t)(((timeinfo->tm_min / 10) << 4) | (timeinfo->tm_min % 10));
  385.                 uint8_t sec = (uint8_t)(((timeinfo->tm_sec / 10) << 4) | (timeinfo->tm_sec % 10));
  386.  
  387.                 dd->regs[DD_ASIC_DATA] = (min << 24) | (sec << 16);
  388.                 break;
  389.  
  390.         case DD_CMD_GET_DAY_HOUR:               // Get time [day/hour]:
  391.                         //Get Time
  392.                 time(&timer);
  393.                 timeinfo = localtime(&timer);
  394.  
  395.                     //Put time in DATA as BCD
  396.                 uint8_t hour = (uint8_t)(((timeinfo->tm_hour / 10) << 4) | (timeinfo->tm_hour % 10));
  397.                 uint8_t day = (uint8_t)(((timeinfo->tm_mday / 10) << 4) | (timeinfo->tm_mday % 10));
  398.  
  399.                 dd->regs[DD_ASIC_DATA] = (day << 24) | (hour << 16);
  400.                 break;
  401.  
  402.         case DD_CMD_GET_YEAR_MONTH:             // Get time [year/month]:
  403.                         //Get Time
  404.                 time(&timer);
  405.                 timeinfo = localtime(&timer);
  406.  
  407.                 //Put time in DATA as BCD
  408.                 uint8_t year = (uint8_t)(((timeinfo->tm_year / 10) << 4) | (timeinfo->tm_year % 10));
  409.                 uint8_t month = (uint8_t)((((timeinfo->tm_mon + 1) / 10) << 4) | ((timeinfo->tm_mon + 1) % 10));
  410.  
  411.                 dd->regs[DD_ASIC_DATA] = (year << 24) | (month << 16);
  412.                 break;
  413.  
  414.         case DD_CMD_CLR_DSK_CHNG:               //Clear Disk Change status bit
  415.                 dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_DISK_CHNG;
  416.                 break;
  417.  
  418.         case DD_CMD_CLR_RESET:                  //Clear Reset status bit
  419.                 dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_RST_STATE;
  420.                 break;
  421.  
  422.         case DD_CMD_FEATURE_INQ:                //Feature Inquiry
  423.                 dd->regs[DD_ASIC_DATA] = 0x00010000U;
  424.                 break;
  425.  
  426.         case DD_CMD_SLEEP:                              //Sleep
  427.                 dd->regs[DD_ASIC_CMD_STATUS] |= (DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT);
  428.                 break;
  429.  
  430.         case DD_CMD_STANDBY:                    //Standby
  431.                 dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_HEAD_RTRCT;
  432.                 dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_MTR_N_SPIN;
  433.                 break;
  434.  
  435.         case DD_CMD_START:                              //Start
  436.                 dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT);
  437.                 break;
  438.  
  439.         case DD_CMD_SEEK_READ:                  //SEEK READ
  440.                 dd->regs[DD_ASIC_CUR_TK] = dd->regs[DD_ASIC_DATA] | 0x60000000U;
  441.                 dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT);
  442.                 dd_bm_mode_read = true;
  443.                 dd_set_zone_and_track_offset(opaque);
  444.                 printf("--READ\n");
  445.                 break;
  446.  
  447.         case DD_CMD_SEEK_WRITE:                 //SEEK WRITE
  448.                 dd->regs[DD_ASIC_CUR_TK] = dd->regs[DD_ASIC_DATA] | 0x60000000U;
  449.                 dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT);
  450.                 dd_bm_mode_read = false;
  451.                 dd_set_zone_and_track_offset(opaque);
  452.                 printf("--WRITE\n");
  453.                 break;
  454.  
  455.         case DD_CMD_RECALIBRATE:                //Recalibration
  456.                 dd->regs[DD_ASIC_DATA] = 0;
  457.                 break;
  458.  
  459.         case DD_CMD_IDX_LOCK_RETRY:             //Index Lock Retry
  460.                 dd->regs[DD_ASIC_CUR_TK] |= 0x60000000U;
  461.                 break;
  462.     }
  463.  
  464.     // Always signal an interrupt in response.
  465.     dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_MECHA_INT;
  466.     signal_dd_interrupt(dd->bus->vr4300);
  467.   }
  468.  
  469.   // Buffer manager control request: handle it.
  470.   else if (reg == DD_ASIC_BM_STATUS_CTL) {
  471.     if (word & DD_BM_CTL_RESET)
  472.       dd_reset_hold = true;
  473.  
  474.     if (!(word & DD_BM_CTL_RESET) && dd_reset_hold)
  475.     {
  476.       dd_reset_hold = false;
  477.       dd->regs[DD_ASIC_BM_STATUS_CTL] = 0;
  478.       dd->regs[DD_ASIC_CUR_SECTOR] = 0;
  479.       dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_BM_INT | DD_STATUS_BM_ERR | DD_STATUS_DATA_RQ | DD_STATUS_C2_XFER);
  480.       CUR_BLOCK = 0;
  481.         }
  482.  
  483.     if (word & DD_BM_CTL_MECHA_RST)
  484.       dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_MECHA_INT;
  485.  
  486.     if (!(dd->regs[DD_ASIC_CMD_STATUS] & DD_STATUS_BM_INT) && !(dd->regs[DD_ASIC_CMD_STATUS] & DD_STATUS_MECHA_INT))
  487.         clear_dd_interrupt(dd->bus->vr4300);
  488.  
  489.     if (word & DD_BM_CTL_BLK_TRANS)
  490.       dd->regs[DD_ASIC_BM_STATUS_CTL] |= DD_BM_STATUS_BLOCK;
  491.     else
  492.       dd->regs[DD_ASIC_BM_STATUS_CTL] &= ~DD_BM_STATUS_BLOCK;
  493.  
  494.     //SET SECTOR
  495.     dd->regs[DD_ASIC_CUR_SECTOR] = word & 0x00FF0000U;
  496.     if ((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) < 0x5A)
  497.         CUR_BLOCK = 0;
  498.     else
  499.         CUR_BLOCK = 1;
  500.  
  501.    
  502.     //START BM -----------------------
  503.     if (word & DD_BM_CTL_START)
  504.     {
  505.       dd->regs[DD_ASIC_BM_STATUS_CTL] |= DD_BM_STATUS_RUNNING;
  506.       printf("DD_UPDATE_BM START\n");
  507.       dd_update_bm(opaque);
  508.         }
  509.   }
  510.  
  511.   // This is done by the IPL and a lot of games. The only word
  512.   // ever know to be written to this register is 0xAAAA0000.
  513.   else if (reg == DD_ASIC_HARD_RESET) {
  514.     assert(word == 0xAAAA0000 && "dd: Hard reset without magic word?");
  515.  
  516.     dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_RST_STATE;
  517.   }
  518.  
  519.   else if ((reg == DD_ASIC_CUR_TK) |
  520.     (reg == DD_ASIC_ERR_SECTOR) |
  521.     (reg == DD_ASIC_CUR_SECTOR) |
  522.     (reg == DD_ASIC_C1_S0) |
  523.     (reg == DD_ASIC_C1_S2) |
  524.     (reg == DD_ASIC_C1_S4) |
  525.     (reg == DD_ASIC_C1_S6) |
  526.     (reg == DD_ASIC_CUR_ADDR) |
  527.     (reg == DD_ASIC_ID_REG) |
  528.     (reg == DD_ASIC_TEST_REG))
  529.   {
  530.     // Do nothing. Not writable.
  531.   }
  532.  
  533.   else {
  534.     dd->regs[reg] &= ~dqm;
  535.     dd->regs[reg] |= word;
  536.   }
  537.  
  538.   return 0;
  539. }
  540.  
  541. // Reads a word from the DD IPL ROM.
  542. int read_dd_ipl_rom(void *opaque, uint32_t address, uint32_t *word) {
  543.   uint32_t offset = address - DD_IPL_ROM_ADDRESS;
  544.   struct dd_controller *dd = (struct dd_controller*) opaque;
  545.  
  546.   if (!dd->ipl_rom)
  547.     memset(word, 0, sizeof(*word));
  548.  
  549.   else {
  550.     memcpy(word, dd->ipl_rom + offset, sizeof(*word));
  551.     *word = byteswap_32(*word);
  552.   }
  553.  
  554.   //debug_mmio_read(dd, "DD_IPL_ROM", *word);
  555.   return 0;
  556. }
  557.  
  558. // Writes a word to the DD IPL ROM.
  559. int write_dd_ipl_rom(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  560.   assert(0 && "Attempt to write to DD IPL ROM.");
  561.   return 0;
  562. }
  563.  
  564. // Reads a word from the DD C2S buffer.
  565. int read_dd_c2s_buffer(void *opaque, uint32_t address, uint32_t *word) {
  566.   struct dd_controller *dd = (struct dd_controller *) opaque;
  567.   unsigned offset = address - DD_C2S_BUFFER_ADDRESS;
  568.  
  569.   if (offset == (((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1) * 4) - 4)
  570.   {
  571.         printf("DD_UPDATE_BM C2S BUFFER\n");
  572.         dd_update_bm(opaque);
  573.   }
  574.  
  575.   memcpy(word, dd->c2s_buffer + offset, sizeof(*word));
  576.   *word = byteswap_32(*word);
  577.  
  578.   if (offset == ((((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1) * 0))
  579.    || offset == ((((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1) * 1))
  580.    || offset == ((((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1) * 2))
  581.    || offset == ((((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1) * 3)))
  582.     debug_mmio_read(dd, "DD_C2S_BUFFER", *word);
  583.   return 0;
  584. }
  585.  
  586. // Writes a word to the DD C2S BUFFER.
  587. int write_dd_c2s_buffer(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  588.   struct dd_controller *dd = (struct dd_controller *) opaque;
  589.   unsigned offset = address - DD_C2S_BUFFER_ADDRESS;
  590.  
  591.   dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_C2_XFER;
  592.   dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_BM_INT;
  593.   clear_dd_interrupt(dd->bus->vr4300);
  594.  
  595.   debug_mmio_write(dd, "DD_C2S_BUFFER", word, dqm);
  596.   return 0;
  597. }
  598.  
  599. // Reads a word from the DD DS buffer.
  600. int read_dd_ds_buffer(void *opaque, uint32_t address, uint32_t *word) {
  601.   struct dd_controller *dd = (struct dd_controller *) opaque;
  602.   unsigned offset = address - DD_DS_BUFFER_ADDRESS;
  603.  
  604.   memcpy(word, dd->ds_buffer + (address & 0xFC), sizeof(*word));
  605.   *word = byteswap_32(*word);
  606.  
  607.   //(SECTORS_PER_BLOCK >= (dd->regs[DD_ASIC_CUR_SECTOR] >> 16))
  608.   if (offset == ((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) - 3))
  609.   {
  610.         printf("DD_UPDATE_BM DS BUFFER\n");
  611.         dd_update_bm(opaque);
  612.   }
  613.  
  614.   //debug_mmio_read(dd, "DD_DS_BUFFER", *word);
  615.   return 0;
  616. }
  617.  
  618. // Writes a word to the DD DS BUFFER.
  619. int write_dd_ds_buffer(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  620.   struct dd_controller *dd = (struct dd_controller *) opaque;
  621.   unsigned offset = address - DD_DS_BUFFER_ADDRESS;
  622.  
  623.   dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_DATA_RQ;
  624.   dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_BM_INT;
  625.   clear_dd_interrupt(dd->bus->vr4300);
  626.  
  627.   for (int i = 0; i < 4; i++)
  628.         dd->ds_buffer[offset + i] = (uint8_t)((word >> (8 * i)) & 0xFF);
  629.  
  630.   debug_mmio_write(dd, "DD_DS_BUFFER", word, dqm);
  631.   return 0;
  632. }
  633.  
  634. // Reads a word from the DD MS RAM.
  635. int read_dd_ms_ram(void *opaque, uint32_t address, uint32_t *word) {
  636.   struct dd_controller *dd = (struct dd_controller *) opaque;
  637.   unsigned offset = address - DD_MS_RAM_ADDRESS;
  638.  
  639.   memcpy(word, dd->ms_ram + offset, sizeof(*word));
  640.   *word = byteswap_32(*word);
  641.  
  642.   debug_mmio_read(dd, "DD_MS_RAM", *word);
  643.   return 0;
  644. }
  645.  
  646. // Writes a word to the DD MS RAM.
  647. int write_dd_ms_ram(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  648.   struct dd_controller *dd = (struct dd_controller *) opaque;
  649.   unsigned offset = address - DD_MS_RAM_ADDRESS;
  650.  
  651.   for (int i = 0; i < 4; i++)
  652.         dd->ms_ram[offset + i] = (uint8_t)((word >> (8 * i)) & 0xFF);
  653.  
  654.   //debug_mmio_write(dd, "DD_MS_RAM", word, dqm);
  655.   return 0;
  656. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top