Advertisement
LuigiBlood

dd_controller.c MESS 64DD (2)

Apr 25th, 2015
400
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 20.41 KB | None | 0 0
  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 <= (int)(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.   if (reg == DD_ASIC_CMD_STATUS)
  339.   {
  340.     int Cur_Sector = dd->regs[DD_ASIC_CUR_SECTOR] >> 16;
  341.     if (Cur_Sector >= 0x5A)
  342.         Cur_Sector -= 0x5A;
  343.  
  344.     if ((dd->regs[DD_ASIC_CMD_STATUS] & DD_STATUS_BM_INT) && (SECTORS_PER_BLOCK < Cur_Sector))
  345.     {
  346.         dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_BM_INT;
  347.         clear_dd_interrupt(dd->bus->vr4300);
  348.         printf("DD_UPDATE_BM DD REG READ -");
  349.         dd_update_bm(opaque);
  350.     }
  351.   }
  352.  
  353.   *word = dd->regs[reg];
  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 -");
  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.   memcpy(word, dd->c2s_buffer + offset, sizeof(*word));
  570.   *word = byteswap_32(*word);
  571.  
  572.   if (offset == 0)
  573.   {
  574.     dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_BM_INT | DD_STATUS_BM_ERR | DD_STATUS_DATA_RQ | DD_STATUS_C2_XFER);
  575.     clear_dd_interrupt(dd->bus->vr4300);
  576.   }
  577.  
  578.   if (offset == (((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1) * 4) - 4)
  579.   {
  580.     printf("DD_UPDATE_BM C2S BUFFER -");
  581.     dd_update_bm(opaque);
  582.   }
  583.  
  584.   if (offset == ((((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1) * 0))
  585.    || offset == ((((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1) * 1))
  586.    || offset == ((((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1) * 2))
  587.    || offset == ((((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1) * 3)))
  588.     debug_mmio_read(dd, "DD_C2S_BUFFER", *word);
  589.   return 0;
  590. }
  591.  
  592. // Writes a word to the DD C2S BUFFER.
  593. int write_dd_c2s_buffer(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  594.   struct dd_controller *dd = (struct dd_controller *) opaque;
  595.   unsigned offset = address - DD_C2S_BUFFER_ADDRESS;
  596.  
  597.   dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_C2_XFER;
  598.   dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_BM_INT;
  599.   clear_dd_interrupt(dd->bus->vr4300);
  600.  
  601.   debug_mmio_write(dd, "DD_C2S_BUFFER", word, dqm);
  602.   return 0;
  603. }
  604.  
  605. // Reads a word from the DD DS buffer.
  606. int read_dd_ds_buffer(void *opaque, uint32_t address, uint32_t *word) {
  607.   struct dd_controller *dd = (struct dd_controller *) opaque;
  608.   unsigned offset = address - DD_DS_BUFFER_ADDRESS;
  609.  
  610.   memcpy(word, dd->ds_buffer + (address & 0xFC), sizeof(*word));
  611.   *word = byteswap_32(*word);
  612.  
  613.   //(SECTORS_PER_BLOCK >= (dd->regs[DD_ASIC_CUR_SECTOR] >> 16))
  614.  
  615.   if (offset == 0)
  616.   {
  617.     dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_BM_INT | DD_STATUS_BM_ERR | DD_STATUS_DATA_RQ | DD_STATUS_C2_XFER);
  618.     clear_dd_interrupt(dd->bus->vr4300);
  619.   }
  620.  
  621.   if (offset == ((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) - 3))
  622.   {
  623.     printf("DD_UPDATE_BM DS BUFFER -");
  624.     dd_update_bm(opaque);
  625.   }
  626.  
  627.   //debug_mmio_read(dd, "DD_DS_BUFFER", *word);
  628.   return 0;
  629. }
  630.  
  631. // Writes a word to the DD DS BUFFER.
  632. int write_dd_ds_buffer(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  633.   struct dd_controller *dd = (struct dd_controller *) opaque;
  634.   unsigned offset = address - DD_DS_BUFFER_ADDRESS;
  635.  
  636.   dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_DATA_RQ;
  637.   dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_BM_INT;
  638.   clear_dd_interrupt(dd->bus->vr4300);
  639.  
  640.   for (int i = 0; i < 4; i++)
  641.     dd->ds_buffer[offset + i] = (uint8_t)((word >> (8 * i)) & 0xFF);
  642.  
  643.   debug_mmio_write(dd, "DD_DS_BUFFER", word, dqm);
  644.   return 0;
  645. }
  646.  
  647. // Reads a word from the DD MS RAM.
  648. int read_dd_ms_ram(void *opaque, uint32_t address, uint32_t *word) {
  649.   struct dd_controller *dd = (struct dd_controller *) opaque;
  650.   unsigned offset = address - DD_MS_RAM_ADDRESS;
  651.  
  652.   memcpy(word, dd->ms_ram + offset, sizeof(*word));
  653.   *word = byteswap_32(*word);
  654.  
  655.   debug_mmio_read(dd, "DD_MS_RAM", *word);
  656.   return 0;
  657. }
  658.  
  659. // Writes a word to the DD MS RAM.
  660. int write_dd_ms_ram(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  661.   struct dd_controller *dd = (struct dd_controller *) opaque;
  662.   unsigned offset = address - DD_MS_RAM_ADDRESS;
  663.  
  664.   for (int i = 0; i < 4; i++)
  665.     dd->ms_ram[offset + i] = (uint8_t)((word >> (8 * i)) & 0xFF);
  666.  
  667.   //debug_mmio_write(dd, "DD_MS_RAM", word, dqm);
  668.   return 0;
  669. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement