Advertisement
LuigiBlood

dd/controller.c (64DD 04/26)

Apr 26th, 2015
430
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 20.98 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. bool dd_sector55;
  110.  
  111. const unsigned int ddZoneSecSize[16] = {232,216,208,192,176,160,144,128,
  112.                                         216,208,192,176,160,144,128,112};
  113.  
  114. const unsigned int ddZoneTrackSize[16] = {158,158,149,149,149,149,149,114,
  115.                                           158,158,149,149,149,149,149,114};
  116.  
  117. const unsigned int ddStartOffset[16] =
  118.     {0x0,0x5F15E0,0xB79D00,0x10801A0,0x1523720,0x1963D80,0x1D414C0,0x20BBCE0,
  119.      0x23196E0,0x28A1E00,0x2DF5DC0,0x3299340,0x36D99A0,0x3AB70E0,0x3E31900,0x4149200};
  120.  
  121. //-------------------------------------
  122. void dd_clear_c2s(void *opaque)
  123. {
  124.   struct dd_controller *dd = (struct dd_controller *) opaque;
  125.  
  126.   dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_C2_XFER;
  127.   dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_BM_INT;
  128.   clear_dd_interrupt(dd->bus->vr4300);
  129. }
  130.  
  131. void dd_clear_ds(void *opaque)
  132. {
  133.   struct dd_controller *dd = (struct dd_controller *) opaque;
  134.  
  135.   dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_DATA_RQ;
  136.   dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_BM_INT;
  137.   clear_dd_interrupt(dd->bus->vr4300);
  138. }
  139.  
  140. void dd_write_sector(void *opaque)
  141. {
  142.     struct dd_controller *dd = (struct dd_controller *) opaque;
  143.  
  144.     //WRITE SECTOR
  145.     int Cur_Sector = dd->regs[DD_ASIC_CUR_SECTOR] >> 16;
  146.     if (Cur_Sector >= 0x5A)
  147.         Cur_Sector -= 0x5A;
  148.  
  149.     int offset = dd_track_offset;
  150.     offset += CUR_BLOCK * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone];
  151.     offset += (Cur_Sector - 1) * ddZoneSecSize[dd_zone];
  152.  
  153.     //for (int i = 0; i <= (int)(dd->regs[DD_ASIC_HOST_SECBYTE] >> 16); i++)
  154.         //dd->rom[offset + i] = dd->ds_buffer[i];
  155. }
  156.  
  157. void dd_read_sector(void *opaque)
  158. {
  159.     struct dd_controller *dd = (struct dd_controller *) opaque;
  160.  
  161.     //READ SECTOR
  162.     int Cur_Sector = dd->regs[DD_ASIC_CUR_SECTOR] >> 16;
  163.     if (Cur_Sector >= 0x5A)
  164.         Cur_Sector -= 0x5A;
  165.  
  166.     int offset = dd_track_offset;
  167.     offset += CUR_BLOCK * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone];
  168.     offset += Cur_Sector * ddZoneSecSize[dd_zone];
  169.  
  170.     for (int i = 0; i <= (int)(dd->regs[DD_ASIC_HOST_SECBYTE] >> 16); i++)
  171.         dd->ds_buffer[i] = dd->rom[offset + i];
  172. }
  173.  
  174. void dd_read_C2(void *opaque)
  175. {
  176.     struct dd_controller *dd = (struct dd_controller *) opaque;
  177.  
  178.     for (int i = 0; i < DD_C2S_BUFFER_LEN; i++)
  179.       dd->c2s_buffer[i] = 0;
  180. }
  181.  
  182. void dd_update_bm(void *opaque)
  183. {
  184.     struct dd_controller *dd = (struct dd_controller *) opaque;
  185.  
  186.   if (!(dd->regs[DD_ASIC_BM_STATUS_CTL] & DD_BM_STATUS_RUNNING))
  187.         return;
  188.     else
  189.     {
  190.         int Cur_Sector = dd->regs[DD_ASIC_CUR_SECTOR] >> 16;
  191.         if (Cur_Sector >= 0x5A)
  192.             Cur_Sector -= 0x5A;
  193.  
  194.     if (!dd_bm_mode_read)       //WRITE MODE
  195.         {
  196.             printf("--DD_UPDATE_BM WRITE Block %d Sector %X\n", ((dd->regs[DD_ASIC_CUR_TK] & 0x0FFF0000U) >> 15) + CUR_BLOCK, Cur_Sector);
  197.  
  198.             if (Cur_Sector == 0)
  199.             {
  200.                 Cur_Sector++;
  201.                 dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_DATA_RQ;
  202.             }
  203.             else if (Cur_Sector < SECTORS_PER_BLOCK)
  204.             {
  205.                 dd_write_sector(opaque);
  206.                 Cur_Sector++;
  207.                 dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_DATA_RQ;
  208.             }
  209.             else if (Cur_Sector < SECTORS_PER_BLOCK + 1)
  210.             {
  211.                 if (dd->regs[DD_ASIC_BM_STATUS_CTL] & DD_BM_STATUS_BLOCK)
  212.                 {
  213.                     dd_write_sector(opaque);
  214.                     //next block
  215.                     Cur_Sector = 1;
  216.                     CUR_BLOCK = 1 - CUR_BLOCK;
  217.                     dd->regs[DD_ASIC_BM_STATUS_CTL] &= ~DD_BM_STATUS_BLOCK;
  218.                     dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_DATA_RQ;
  219.                 }
  220.                 else
  221.                 {
  222.                     dd_write_sector(opaque);
  223.                     Cur_Sector++;
  224.                     dd->regs[DD_ASIC_BM_STATUS_CTL] &= ~DD_BM_STATUS_RUNNING;
  225.                 }
  226.             }
  227.         }
  228.         else                        //READ MODE
  229.         {
  230.             printf("--DD_UPDATE_BM READ Block %d Sector %X\n", ((dd->regs[DD_ASIC_CUR_TK] & 0x0FFF0000U) >> 15) + CUR_BLOCK, Cur_Sector);
  231.  
  232.             int Cur_Track = (dd->regs[DD_ASIC_CUR_TK] & 0x0FFF0000U) >> 16;
  233.  
  234.       dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_DATA_RQ | DD_STATUS_C2_XFER);
  235.  
  236.       if (!dd_sector55 && Cur_Sector == 0x59)
  237.       {
  238.         dd_sector55 = true;
  239.         Cur_Sector--;
  240.       }
  241.  
  242.             if (Cur_Track == 6 && CUR_BLOCK == 0 && dd->ipl_rom != NULL)
  243.             {
  244.                 dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_DATA_RQ;
  245.                 //dd->regs[DD_ASIC_BM_STATUS_CTL] |= DD_BM_STATUS_MICRO;
  246.             }
  247.             else if (Cur_Sector < SECTORS_PER_BLOCK)        //user sector
  248.             {
  249.                 dd_read_sector(opaque);
  250.                 Cur_Sector++;
  251.                 dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_DATA_RQ;
  252.             }
  253.             else if (Cur_Sector < SECTORS_PER_BLOCK + 4)    //C2
  254.             {
  255.                 Cur_Sector++;
  256.                 if (Cur_Sector == SECTORS_PER_BLOCK + 4)
  257.                 {
  258.                     dd_read_C2(opaque);
  259.                     dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_C2_XFER;
  260.                 }
  261.             }
  262.             else if (Cur_Sector == SECTORS_PER_BLOCK + 4)   //Gap
  263.             {
  264.         printf("SECTOR 0x59\n");
  265.                 if (dd->regs[DD_ASIC_BM_STATUS_CTL] & DD_BM_STATUS_BLOCK)
  266.                 {
  267.                     CUR_BLOCK = 1 - CUR_BLOCK;
  268.                     Cur_Sector = 0;
  269.                     dd->regs[DD_ASIC_BM_STATUS_CTL] &= ~DD_BM_STATUS_BLOCK;
  270.                 }
  271.                 else
  272.                     dd->regs[DD_ASIC_BM_STATUS_CTL] &= ~DD_BM_STATUS_RUNNING;
  273.             }
  274.         }
  275.  
  276.         dd->regs[DD_ASIC_CUR_SECTOR] = Cur_Sector << 16;
  277.         dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_BM_INT;
  278.     signal_dd_interrupt(dd->bus->vr4300);
  279.     }
  280. }
  281.  
  282. void dd_set_zone_and_track_offset(void *opaque)
  283. {
  284.     struct dd_controller *dd = (struct dd_controller *) opaque;
  285.  
  286.     int head = ((dd->regs[DD_ASIC_CUR_TK] & 0x10000000U) >> 25);    //Head * 8
  287.     int track = ((dd->regs[DD_ASIC_CUR_TK] & 0x0FFF0000U) >> 16);
  288.     int tr_off;
  289.  
  290.     if(track >= 0x425)
  291.     {
  292.         dd_zone = 7 + head;
  293.         tr_off = track - 0x425;
  294.     }
  295.     else if (track >= 0x390)
  296.     {
  297.         dd_zone = 6 + head;
  298.         tr_off = track - 0x390;
  299.     }
  300.     else if (track >= 0x2FB)
  301.     {
  302.         dd_zone = 5 + head;
  303.         tr_off = track - 0x2FB;
  304.     }
  305.     else if (track >= 0x266)
  306.     {
  307.         dd_zone = 4 + head;
  308.         tr_off = track - 0x266;
  309.     }
  310.     else if (track >= 0x1D1)
  311.     {
  312.         dd_zone = 3 + head;
  313.         tr_off = track - 0x1D1;
  314.     }
  315.     else if (track >= 0x13C)
  316.     {
  317.         dd_zone = 2 + head;
  318.         tr_off = track - 0x13C;
  319.     }
  320.     else if (track >= 0x9E)
  321.     {
  322.         dd_zone = 1 + head;
  323.         tr_off = track - 0x9E;
  324.     }
  325.     else
  326.     {
  327.         dd_zone = 0 + head;
  328.         tr_off = track;
  329.     }
  330.  
  331.     dd_track_offset = ddStartOffset[dd_zone] + tr_off*ddZoneSecSize[dd_zone]*SECTORS_PER_BLOCK*BLOCKS_PER_TRACK;
  332. }
  333. //------------------------------
  334.  
  335. // Initializes the DD.
  336. int dd_init(struct dd_controller *dd, struct bus_controller *bus,
  337.   const uint8_t *ddipl, const uint8_t *ddrom, size_t ddrom_size) {
  338.   dd->bus = bus;
  339.   dd->ipl_rom = ddipl;
  340.   dd->rom = ddrom;
  341.   dd->rom_size = ddrom_size;
  342.  
  343.   if (dd->ipl_rom != NULL)
  344.     dd->regs[DD_ASIC_ID_REG] = 0x00030000U;
  345.   else
  346.     dd->regs[DD_ASIC_ID_REG] = 0x00040000U;
  347.  
  348.   dd->regs[DD_ASIC_CMD_STATUS] = DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT;
  349.  
  350.   //if (dd->rom_size == 0x3DEC800) //original dumps
  351.   if (dd->rom_size > 0)
  352.     dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_DISK_PRES;
  353.  
  354.   dd_reset_hold = false;
  355.   dd_bm_mode_read = false;
  356.   dd_sector55 = false;
  357.  
  358.   return 0;
  359. }
  360.  
  361. // Reads a word from the DD MMIO register space.
  362. int read_dd_regs(void *opaque, uint32_t address, uint32_t *word) {
  363.   struct dd_controller *dd = (struct dd_controller *) opaque;
  364.   unsigned offset = address - DD_REGS_BASE_ADDRESS;
  365.   enum dd_register reg = (offset >> 2);
  366.  
  367.   *word = dd->regs[reg];
  368.   debug_mmio_read(dd, dd_register_mnemonics[reg], *word);
  369.  
  370.   if (reg == DD_ASIC_CMD_STATUS)
  371.   {
  372.     int Cur_Sector = dd->regs[DD_ASIC_CUR_SECTOR] >> 16;
  373.       if (Cur_Sector >= 0x5A)
  374.           Cur_Sector -= 0x5A;
  375.  
  376.     if ((dd->regs[DD_ASIC_CMD_STATUS] & DD_STATUS_BM_INT) && (SECTORS_PER_BLOCK < Cur_Sector))
  377.     {
  378.       dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_BM_INT;
  379.       clear_dd_interrupt(dd->bus->vr4300);
  380.       printf("DD_UPDATE_BM DD REG READ -");
  381.       dd_update_bm(opaque);
  382.     }
  383.   }
  384.  
  385.   //*word = dd->regs[reg];
  386.  
  387.   //if (reg != DD_ASIC_CMD_STATUS)
  388.     //debug_mmio_read(dd, dd_register_mnemonics[reg], *word);
  389.   return 0;
  390. }
  391.  
  392. // Writes a word to the DD MMIO register space.
  393. int write_dd_regs(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  394.   struct dd_controller *dd = (struct dd_controller *) opaque;
  395.   unsigned offset = address - DD_REGS_BASE_ADDRESS;
  396.   enum dd_register reg = (offset >> 2);
  397.  
  398.   debug_mmio_write(dd, dd_register_mnemonics[reg], word, dqm);
  399.  
  400.   //No matter what, the lower 16-bit is always ignored.
  401.   word &= 0xFFFF0000U;
  402.  
  403.   // Command register written: do something.
  404.   if (reg == DD_ASIC_CMD_STATUS) {
  405.  
  406.     time_t timer;
  407.     struct tm * timeinfo;
  408.     switch (word)
  409.     {
  410.         case DD_CMD_GET_MIN_SEC:        // Get time [minute/second]:
  411.             //Get Time
  412.             time(&timer);
  413.             timeinfo = localtime(&timer);
  414.  
  415.             //Put time in DATA as BCD
  416.             uint8_t min = (uint8_t)(((timeinfo->tm_min / 10) << 4) | (timeinfo->tm_min % 10));
  417.             uint8_t sec = (uint8_t)(((timeinfo->tm_sec / 10) << 4) | (timeinfo->tm_sec % 10));
  418.  
  419.             dd->regs[DD_ASIC_DATA] = (min << 24) | (sec << 16);
  420.             break;
  421.  
  422.         case DD_CMD_GET_DAY_HOUR:       // Get time [day/hour]:
  423.             //Get Time
  424.             time(&timer);
  425.             timeinfo = localtime(&timer);
  426.  
  427.             //Put time in DATA as BCD
  428.             uint8_t hour = (uint8_t)(((timeinfo->tm_hour / 10) << 4) | (timeinfo->tm_hour % 10));
  429.             uint8_t day = (uint8_t)(((timeinfo->tm_mday / 10) << 4) | (timeinfo->tm_mday % 10));
  430.  
  431.             dd->regs[DD_ASIC_DATA] = (day << 24) | (hour << 16);
  432.             break;
  433.  
  434.         case DD_CMD_GET_YEAR_MONTH:     // Get time [year/month]:
  435.             //Get Time
  436.             time(&timer);
  437.             timeinfo = localtime(&timer);
  438.  
  439.             //Put time in DATA as BCD
  440.             uint8_t year = (uint8_t)(((timeinfo->tm_year / 10) << 4) | (timeinfo->tm_year % 10));
  441.             uint8_t month = (uint8_t)((((timeinfo->tm_mon + 1) / 10) << 4) | ((timeinfo->tm_mon + 1) % 10));
  442.  
  443.             dd->regs[DD_ASIC_DATA] = (year << 24) | (month << 16);
  444.             break;
  445.  
  446.         case DD_CMD_CLR_DSK_CHNG:       //Clear Disk Change status bit
  447.             dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_DISK_CHNG;
  448.             break;
  449.  
  450.         case DD_CMD_CLR_RESET:          //Clear Reset status bit
  451.             dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_RST_STATE;
  452.             break;
  453.  
  454.         case DD_CMD_FEATURE_INQ:        //Feature Inquiry
  455.             dd->regs[DD_ASIC_DATA] = 0x00010000U;
  456.             break;
  457.  
  458.         case DD_CMD_SLEEP:              //Sleep
  459.             dd->regs[DD_ASIC_CMD_STATUS] |= (DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT);
  460.             break;
  461.  
  462.         case DD_CMD_STANDBY:            //Standby
  463.             dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_HEAD_RTRCT;
  464.             dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_MTR_N_SPIN;
  465.             break;
  466.  
  467.         case DD_CMD_START:              //Start
  468.             dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT);
  469.             break;
  470.  
  471.         case DD_CMD_SEEK_READ:          //SEEK READ
  472.             dd->regs[DD_ASIC_CUR_TK] = dd->regs[DD_ASIC_DATA] | 0x60000000U;
  473.             dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT);
  474.             dd_bm_mode_read = true;
  475.             dd_set_zone_and_track_offset(opaque);
  476.             printf("--READ\n");
  477.             break;
  478.  
  479.         case DD_CMD_SEEK_WRITE:         //SEEK WRITE
  480.             dd->regs[DD_ASIC_CUR_TK] = dd->regs[DD_ASIC_DATA] | 0x60000000U;
  481.             dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT);
  482.             dd_bm_mode_read = false;
  483.             dd_set_zone_and_track_offset(opaque);
  484.             printf("--WRITE\n");
  485.             break;
  486.  
  487.         case DD_CMD_RECALIBRATE:        //Recalibration
  488.             dd->regs[DD_ASIC_DATA] = 0;
  489.             break;
  490.  
  491.         case DD_CMD_IDX_LOCK_RETRY:     //Index Lock Retry
  492.             dd->regs[DD_ASIC_CUR_TK] |= 0x60000000U;
  493.             break;
  494.     }
  495.  
  496.     // Always signal an interrupt in response.
  497.     dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_MECHA_INT;
  498.     signal_dd_interrupt(dd->bus->vr4300);
  499.   }
  500.  
  501.   // Buffer manager control request: handle it.
  502.   else if (reg == DD_ASIC_BM_STATUS_CTL) {
  503.     if (word & DD_BM_CTL_RESET)
  504.       dd_reset_hold = true;
  505.  
  506.     if (!(word & DD_BM_CTL_RESET) && dd_reset_hold)
  507.     {
  508.       dd_reset_hold = false;
  509.       dd->regs[DD_ASIC_BM_STATUS_CTL] = 0;
  510.       dd->regs[DD_ASIC_CUR_SECTOR] = 0;
  511.       dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_BM_INT | DD_STATUS_BM_ERR | DD_STATUS_DATA_RQ | DD_STATUS_C2_XFER);
  512.       CUR_BLOCK = 0;
  513.     }
  514.  
  515.     if (word & DD_BM_CTL_MECHA_RST)
  516.       dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_MECHA_INT;
  517.  
  518.     if (word & DD_BM_CTL_BLK_TRANS)
  519.       dd->regs[DD_ASIC_BM_STATUS_CTL] |= DD_BM_STATUS_BLOCK;
  520.     else
  521.       dd->regs[DD_ASIC_BM_STATUS_CTL] &= ~DD_BM_STATUS_BLOCK;
  522.  
  523.     //SET SECTOR
  524.     dd->regs[DD_ASIC_CUR_SECTOR] = word & 0x00FF0000U;
  525.     if ((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) < 0x5A)
  526.         CUR_BLOCK = 0;
  527.     else
  528.         CUR_BLOCK = 1;
  529.  
  530.     if (!(dd->regs[DD_ASIC_CMD_STATUS] & DD_STATUS_BM_INT) && !(dd->regs[DD_ASIC_CMD_STATUS] & DD_STATUS_MECHA_INT))
  531.       clear_dd_interrupt(dd->bus->vr4300);
  532.    
  533.     //START BM -----------------------
  534.     if (word & DD_BM_CTL_START)
  535.     {
  536.       dd->regs[DD_ASIC_BM_STATUS_CTL] |= DD_BM_STATUS_RUNNING;
  537.       dd_sector55 = false;
  538.       printf("DD_UPDATE_BM START -");
  539.       dd_update_bm(opaque);
  540.     }
  541.   }
  542.  
  543.   // This is done by the IPL and a lot of games. The only word
  544.   // ever know to be written to this register is 0xAAAA0000.
  545.   else if (reg == DD_ASIC_HARD_RESET) {
  546.     assert(word == 0xAAAA0000 && "dd: Hard reset without magic word?");
  547.  
  548.     dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_RST_STATE;
  549.   }
  550.  
  551.   else if ((reg == DD_ASIC_CUR_TK) |
  552.     (reg == DD_ASIC_ERR_SECTOR) |
  553.     (reg == DD_ASIC_CUR_SECTOR) |
  554.     (reg == DD_ASIC_C1_S0) |
  555.     (reg == DD_ASIC_C1_S2) |
  556.     (reg == DD_ASIC_C1_S4) |
  557.     (reg == DD_ASIC_C1_S6) |
  558.     (reg == DD_ASIC_CUR_ADDR) |
  559.     (reg == DD_ASIC_ID_REG) |
  560.     (reg == DD_ASIC_TEST_REG))
  561.   {
  562.     // Do nothing. Not writable.
  563.   }
  564.  
  565.   else {
  566.     dd->regs[reg] &= ~dqm;
  567.     dd->regs[reg] |= word;
  568.   }
  569.  
  570.   return 0;
  571. }
  572.  
  573. // Reads a word from the DD IPL ROM.
  574. int read_dd_ipl_rom(void *opaque, uint32_t address, uint32_t *word) {
  575.   uint32_t offset = address - DD_IPL_ROM_ADDRESS;
  576.   struct dd_controller *dd = (struct dd_controller*) opaque;
  577.  
  578.   if (!dd->ipl_rom)
  579.     memset(word, 0, sizeof(*word));
  580.  
  581.   else {
  582.     memcpy(word, dd->ipl_rom + offset, sizeof(*word));
  583.     *word = byteswap_32(*word);
  584.   }
  585.  
  586.   //debug_mmio_read(dd, "DD_IPL_ROM", *word);
  587.   return 0;
  588. }
  589.  
  590. // Writes a word to the DD IPL ROM.
  591. int write_dd_ipl_rom(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  592.   assert(0 && "Attempt to write to DD IPL ROM.");
  593.   return 0;
  594. }
  595.  
  596. // Reads a word from the DD C2S buffer.
  597. int read_dd_c2s_buffer(void *opaque, uint32_t address, uint32_t *word) {
  598.   struct dd_controller *dd = (struct dd_controller *) opaque;
  599.   unsigned offset = address - DD_C2S_BUFFER_ADDRESS;
  600.  
  601.   memcpy(word, dd->c2s_buffer + offset, sizeof(*word));
  602.   *word = byteswap_32(*word);
  603. /*
  604.   if (offset == 0)
  605.   {
  606.     dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_BM_INT | DD_STATUS_BM_ERR | DD_STATUS_DATA_RQ | DD_STATUS_C2_XFER);
  607.     clear_dd_interrupt(dd->bus->vr4300);
  608.   }
  609.  
  610.   if (offset == (((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1) * 4) - 4)
  611.   {
  612.     printf("DD_UPDATE_BM C2S BUFFER -");
  613.       dd_update_bm(opaque);
  614.   }
  615. */
  616.   if (offset == ((((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1) * 0))
  617.    || offset == ((((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1) * 1))
  618.    || offset == ((((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1) * 2))
  619.    || offset == ((((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1) * 3)))
  620.     debug_mmio_read(dd, "DD_C2S_BUFFER", *word);
  621.   return 0;
  622. }
  623.  
  624. // Writes a word to the DD C2S BUFFER.
  625. int write_dd_c2s_buffer(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  626.   struct dd_controller *dd = (struct dd_controller *) opaque;
  627.   unsigned offset = address - DD_C2S_BUFFER_ADDRESS;
  628.  
  629.   debug_mmio_write(dd, "DD_C2S_BUFFER", word, dqm);
  630.   return 0;
  631. }
  632.  
  633. // Reads a word from the DD DS buffer.
  634. int read_dd_ds_buffer(void *opaque, uint32_t address, uint32_t *word) {
  635.   struct dd_controller *dd = (struct dd_controller *) opaque;
  636.   unsigned offset = address - DD_DS_BUFFER_ADDRESS;
  637.  
  638.   memcpy(word, dd->ds_buffer + (address & 0xFC), sizeof(*word));
  639.   *word = byteswap_32(*word);
  640.  
  641.   //(SECTORS_PER_BLOCK >= (dd->regs[DD_ASIC_CUR_SECTOR] >> 16))
  642. /*
  643.   if (offset == 0)
  644.   {
  645.     dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_BM_INT | DD_STATUS_BM_ERR | DD_STATUS_DATA_RQ | DD_STATUS_C2_XFER);
  646.     clear_dd_interrupt(dd->bus->vr4300);
  647.   }
  648.  
  649.   if (offset == ((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) - 3))
  650.   {
  651.     printf("DD_UPDATE_BM DS BUFFER -");
  652.       dd_update_bm(opaque);
  653.   }
  654. */
  655.   //debug_mmio_read(dd, "DD_DS_BUFFER", *word);
  656.   return 0;
  657. }
  658.  
  659. // Writes a word to the DD DS BUFFER.
  660. int write_dd_ds_buffer(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_DS_BUFFER_ADDRESS;
  663.  
  664.   for (int i = 0; i < 4; i++)
  665.     dd->ds_buffer[offset + i] = (uint8_t)((word >> (8 * i)) & 0xFF);
  666.  
  667.   debug_mmio_write(dd, "DD_DS_BUFFER", word, dqm);
  668.   return 0;
  669. }
  670.  
  671. // Reads a word from the DD MS RAM.
  672. int read_dd_ms_ram(void *opaque, uint32_t address, uint32_t *word) {
  673.   struct dd_controller *dd = (struct dd_controller *) opaque;
  674.   unsigned offset = address - DD_MS_RAM_ADDRESS;
  675.  
  676.   memcpy(word, dd->ms_ram + offset, sizeof(*word));
  677.   *word = byteswap_32(*word);
  678.  
  679.   debug_mmio_read(dd, "DD_MS_RAM", *word);
  680.   return 0;
  681. }
  682.  
  683. // Writes a word to the DD MS RAM.
  684. int write_dd_ms_ram(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  685.   struct dd_controller *dd = (struct dd_controller *) opaque;
  686.   unsigned offset = address - DD_MS_RAM_ADDRESS;
  687.  
  688.   for (int i = 0; i < 4; i++)
  689.     dd->ms_ram[offset + i] = (uint8_t)((word >> (8 * i)) & 0xFF);
  690.  
  691.   //debug_mmio_write(dd, "DD_MS_RAM", word, dqm);
  692.   return 0;
  693. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement