Advertisement
LuigiBlood

dd_controller.c

Jan 8th, 2015
318
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 17.05 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. // TODO: Currently, the DD IPL spams the controller with DD_CMD_NOOP.
  19. // This is normal. Once you signify that a disk is present (using the
  20. // DD_STATUS_DISK_PRES), the DD IPL attempts to start performing seeks.
  21. //
  22.  
  23. #include "common.h"
  24. #include "bus/address.h"
  25. #include "bus/controller.h"
  26. #include "dd/controller.h"
  27. #include "vr4300/interface.h"
  28. #include <time.h>
  29.  
  30. #ifdef DEBUG_MMIO_REGISTER_ACCESS
  31. const char *dd_register_mnemonics[NUM_DD_REGISTERS] = {
  32. #define X(reg) #reg,
  33. #include "dd/registers.md"
  34. #undef X
  35. };
  36. #endif
  37.  
  38. // ASIC_CMD_STATUS flags.
  39. #define DD_CMD_NOOP           0x00000000U
  40. #define DD_CMD_SEEK_READ      0x00010000U //Disk needed
  41. #define DD_CMD_SEEK_WRITE     0x00020000U //Disk needed
  42. #define DD_CMD_RECALIBRATE    0x00030000U // ??? Disk needed
  43. #define DD_CMD_SLEEP          0x00040000U
  44. #define DD_CMD_START          0x00050000U //Disk needed
  45. #define DD_CMD_SET_STANDBY    0x00060000U
  46. #define DD_CMD_SET_SLEEP      0x00070000U
  47. #define DD_CMD_CLR_DSK_CHNG   0x00080000U
  48. #define DD_CMD_CLR_RESET      0x00090000U
  49. #define DD_CMD_READ_VERSION   0x000A0000U
  50. #define DD_CMD_SET_DISK_TYPE  0x000B0000U //Disk needed
  51. #define DD_CMD_REQUEST_STATUS 0x000C0000U
  52. #define DD_CMD_STANDBY        0x000D0000U
  53. #define DD_CMD_IDX_LOCK_RETRY 0x000E0000U // ???
  54. #define DD_CMD_SET_YEAR_MONTH 0x000F0000U
  55. #define DD_CMD_SET_DAY_HOUR   0x00100000U
  56. #define DD_CMD_SET_MIN_SEC    0x00110000U
  57. #define DD_CMD_GET_YEAR_MONTH 0x00120000U
  58. #define DD_CMD_GET_DAY_HOUR   0x00130000U
  59. #define DD_CMD_GET_MIN_SEC    0x00140000U
  60. #define DD_CMD_FEATURE_INQ    0x001B0000U
  61.  
  62. #define DD_STATUS_DATA_RQ     0x40000000U
  63. #define DD_STATUS_C2_XFER     0x10000000U
  64. #define DD_STATUS_BM_ERR      0x08000000U
  65. #define DD_STATUS_BM_INT      0x04000000U
  66. #define DD_STATUS_MECHA_INT   0x02000000U
  67. #define DD_STATUS_DISK_PRES   0x01000000U
  68. #define DD_STATUS_BUSY_STATE  0x00800000U
  69. #define DD_STATUS_RST_STATE   0x00400000U
  70. #define DD_STATUS_MTR_N_SPIN  0x00100000U
  71. #define DD_STATUS_HEAD_RTRCT  0x00080000U
  72. #define DD_STATUS_WR_PR_ERR   0x00040000U
  73. #define DD_STATUS_MECHA_ERR   0x00020000U
  74. #define DD_STATUS_DISK_CHNG   0x00010000U
  75.  
  76. // ASIC_BM_STATUS_CTL flags.
  77. #define DD_BM_STATUS_RUNNING  0x80000000U
  78. #define DD_BM_STATUS_ERROR    0x04000000U
  79. #define DD_BM_STATUS_MICRO    0x02000000U // ???
  80. #define DD_BM_STATUS_BLOCK    0x01000000U
  81. #define DD_BM_STATUS_C1CRR    0x00800000U
  82. #define DD_BM_STATUS_C1DBL    0x00400000U
  83. #define DD_BM_STATUS_C1SNG    0x00200000U
  84. #define DD_BM_STATUS_C1ERR    0x00010000U // Typo ???
  85.  
  86. #define DD_BM_CTL_START       0x80000000U
  87. #define DD_BM_CTL_MNGRMODE    0x40000000U
  88. #define DD_BM_CTL_INTMASK     0x20000000U
  89. #define DD_BM_CTL_RESET       0x10000000U
  90. #define DD_BM_CTL_DIS_OR_CHK  0x08000000U // ???
  91. #define DD_BM_CTL_DIS_C1_CRR  0x04000000U
  92. #define DD_BM_CTL_BLK_TRANS   0x02000000U
  93. #define DD_BM_CTL_MECHA_RST   0x01000000U
  94.  
  95. int   LBA;  //GET LBA
  96.  
  97. int BlockSizes[] = { 19720, 18360, 17680, 16320, 14960, 13600, 12240, 10880, 9520 };
  98.  
  99. int LBAs[] = {292, 292, 274, 274, 274, 274, 274, 204, 0,
  100.              0, 292, 292, 274, 274, 274, 274, 274, 204};
  101.  
  102. int Zones[7][16] =      //[Type][Zone]
  103.             {
  104.               {0, 1, 2, 2, 1,
  105.               3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3}, //Type 0
  106.  
  107.               {0, 1, 2, 3, 3, 2, 1,
  108.               4, 5, 6, 7, 8, 7, 6, 5, 4},   //Type 1
  109.  
  110.               {0, 1, 2, 3, 4, 4, 3, 2, 1,
  111.               5, 6, 7, 8, 7, 6, 5},     //Type 2
  112.  
  113.               {0, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1,
  114.               6, 7, 8, 7, 6},       //Type 3
  115.  
  116.               {0, 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1,
  117.               7, 8, 7},       //Type 4
  118.  
  119.               {0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1,
  120.               8},         //Type 5
  121.  
  122.               {0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1}      //Type 6 (ROM only)
  123.             };
  124.  
  125. static int getROMLBAoffset(int LBAoffset, int type)
  126.         {
  127.             int offset = 0;
  128.             int offset2 = 0;
  129.             int offset3 = 0;
  130.  
  131.             for (int LBA = 0; LBA < LBAoffset; LBA++)
  132.             {
  133.                 offset2 = 0;
  134.                 for (int i = 0; i <= offset3; i++)
  135.                 {
  136.                     if (i <= (type + 2))
  137.                         offset2 += LBAs[Zones[type][i]];
  138.                     else
  139.                         offset2 += LBAs[Zones[type][i] + 9];
  140.                 }
  141.  
  142.                 if ((LBA >= offset2) && (offset3 < 5 + (type * 2)))
  143.                     offset3++;
  144.  
  145.                 offset += BlockSizes[Zones[type][offset3]];
  146.             }
  147.             return offset;
  148.         }
  149.  
  150. // Initializes the DD.
  151. int dd_init(struct dd_controller *dd, struct bus_controller *bus,
  152.   const uint8_t *ddipl, const uint8_t *ddrom, size_t ddrom_size) {
  153.   dd->bus = bus;
  154.   dd->ipl_rom = ddipl;
  155.   dd->rom = ddrom;
  156.   dd->rom_size = ddrom_size;
  157.  
  158.   dd->regs[DD_ASIC_ID_REG] = 0x00030000U;
  159.   dd->regs[DD_ASIC_CMD_STATUS] = DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT;
  160.  
  161.   if (dd->rom_size == 0x3DEC800)
  162.     dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_DISK_PRES;
  163.  
  164.   return 0;
  165. }
  166.  
  167. // Reads a word from the DD MMIO register space.
  168. int read_dd_regs(void *opaque, uint32_t address, uint32_t *word) {
  169.   struct dd_controller *dd = (struct dd_controller *) opaque;
  170.   unsigned offset = address - DD_REGS_BASE_ADDRESS;
  171.   enum dd_register reg = (offset >> 2);
  172.  
  173.   //if (dd->rom_size == 0x3DEC800)
  174.     //dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_DISK_PRES;
  175.  
  176.   *word = dd->regs[reg];
  177.  
  178.   //if (reg != DD_ASIC_CMD_STATUS)
  179.     debug_mmio_read(dd, dd_register_mnemonics[reg], *word);
  180.   return 0;
  181. }
  182.  
  183. // Writes a word to the DD MMIO register space.
  184. int write_dd_regs(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  185.   struct dd_controller *dd = (struct dd_controller *) opaque;
  186.   unsigned offset = address - DD_REGS_BASE_ADDRESS;
  187.   enum dd_register reg = (offset >> 2);
  188.  
  189.   debug_mmio_write(dd, dd_register_mnemonics[reg], word, dqm);
  190.  
  191.   //No matter what, the lower 16-bit is always ignored.
  192.   word &= 0xFFFF0000U;
  193.  
  194.   // Command register written: do something.
  195.   if (reg == DD_ASIC_CMD_STATUS) {
  196.  
  197.     time_t timer;
  198.     struct tm * timeinfo;
  199.     // Get time [minute/second]:
  200.     if (word == DD_CMD_GET_MIN_SEC) {
  201.       //Get Time
  202.       time(&timer);
  203.       timeinfo = localtime(&timer);
  204.  
  205.       //Put time in DATA as BCD
  206.       uint8_t min = (uint8_t)(((timeinfo->tm_min / 10) << 4) | (timeinfo->tm_min % 10));
  207.       uint8_t sec = (uint8_t)(((timeinfo->tm_sec / 10) << 4) | (timeinfo->tm_sec % 10));
  208.  
  209.       dd->regs[DD_ASIC_DATA] = (min << 24) | (sec << 16);
  210.     }
  211.     // Get time [day/hour]:
  212.     else if (word == DD_CMD_GET_DAY_HOUR) {
  213.       //Get Time
  214.       time(&timer);
  215.       timeinfo = localtime(&timer);
  216.  
  217.       //Put time in DATA as BCD
  218.       uint8_t hour = (uint8_t)(((timeinfo->tm_hour / 10) << 4) | (timeinfo->tm_hour % 10));
  219.       uint8_t day = (uint8_t)(((timeinfo->tm_mday / 10) << 4) | (timeinfo->tm_mday % 10));
  220.  
  221.       dd->regs[DD_ASIC_DATA] = (day << 24) | (hour << 16);
  222.     }
  223.     // Get time [year/month]:
  224.     else if (word == DD_CMD_GET_YEAR_MONTH) {
  225.       //Get Time
  226.       time(&timer);
  227.       timeinfo = localtime(&timer);
  228.  
  229.       //Put time in DATA as BCD
  230.       uint8_t year = (uint8_t)(((timeinfo->tm_year / 10) << 4) | (timeinfo->tm_year % 10));
  231.       uint8_t month = (uint8_t)((((timeinfo->tm_mon + 1) / 10) << 4) | ((timeinfo->tm_mon + 1) % 10));
  232.  
  233.       dd->regs[DD_ASIC_DATA] = (year << 24) | (month << 16);
  234.     }
  235.  
  236.     //Clear Disk Change status bit
  237.     else if (word == DD_CMD_CLR_DSK_CHNG)
  238.       dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_DISK_CHNG;
  239.  
  240.     //Clear Reset status bit
  241.     else if (word == DD_CMD_CLR_RESET)
  242.       dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_RST_STATE;
  243.  
  244.     //Feature Inquiry
  245.     else if (word == DD_CMD_FEATURE_INQ)
  246.       dd->regs[DD_ASIC_DATA] = 0x00010000U;
  247.  
  248.     //Sleep
  249.     else if (word == DD_CMD_SLEEP)
  250.       dd->regs[DD_ASIC_CMD_STATUS] |= (DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT);
  251.  
  252.     //Standby
  253.     else if (word == DD_CMD_STANDBY)
  254.     {
  255.       dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_HEAD_RTRCT;
  256.       dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_MTR_N_SPIN;
  257.     }
  258.  
  259.     //Start
  260.     else if (word == DD_CMD_START)
  261.       dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT);
  262.  
  263.     //SEEK READ
  264.     else if (word == DD_CMD_SEEK_READ)
  265.     {
  266.       dd->regs[DD_ASIC_CUR_TK] = dd->regs[DD_ASIC_DATA] | 0x60000000U;
  267.       dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT);
  268.     }
  269.  
  270.     //SEEK WRITE
  271.     else if (word == DD_CMD_SEEK_WRITE)
  272.     {
  273.       dd->regs[DD_ASIC_CUR_TK] = dd->regs[DD_ASIC_DATA] | 0x60000000U;
  274.       dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT);
  275.     }
  276.  
  277.     //RECALIB
  278.     else if (word == DD_CMD_RECALIBRATE)
  279.       dd->regs[DD_ASIC_DATA] = 0;
  280.  
  281.     //Index Lock Retry
  282.     else if (word == DD_CMD_IDX_LOCK_RETRY)
  283.     {
  284.       //dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_C2_XFER;
  285.       dd->regs[DD_ASIC_CUR_TK] |= 0x60000000U;
  286.     }
  287.  
  288.     // Always signal an interrupt in response.
  289.     dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_MECHA_INT;
  290.     signal_dd_interrupt(dd->bus->vr4300);
  291.   }
  292.  
  293.   // Buffer manager control request: handle it.
  294.   else if (reg == DD_ASIC_BM_STATUS_CTL) {
  295.     if (word & DD_BM_CTL_RESET)
  296.     {
  297.       dd->regs[DD_ASIC_BM_STATUS_CTL] = 0;
  298.       dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_BM_INT | DD_STATUS_BM_ERR | DD_STATUS_DATA_RQ | DD_STATUS_C2_XFER);
  299.  
  300.       if (!(dd->regs[DD_ASIC_CMD_STATUS] & DD_STATUS_MECHA_INT))
  301.         clear_dd_interrupt(dd->bus->vr4300);
  302.     }
  303.  
  304.     if (word & DD_BM_CTL_MECHA_RST)
  305.     {
  306.       dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_MECHA_INT;
  307.       if (!(dd->regs[DD_ASIC_CMD_STATUS] & DD_STATUS_BM_INT))
  308.         clear_dd_interrupt(dd->bus->vr4300);
  309.     }
  310.  
  311.     if (word == 0)
  312.       dd->regs[DD_ASIC_BM_STATUS_CTL] = 0;
  313.  
  314.     if (word & DD_BM_CTL_BLK_TRANS)
  315.       dd->regs[DD_ASIC_BM_STATUS_CTL] |= DD_BM_STATUS_BLOCK;
  316.     else
  317.       dd->regs[DD_ASIC_BM_STATUS_CTL] &= ~DD_BM_STATUS_BLOCK;
  318.  
  319.     //SET SECTOR
  320.     if (word & DD_BM_CTL_MNGRMODE)
  321.       if (!(word & DD_BM_CTL_BLK_TRANS))
  322.         dd->regs[DD_ASIC_CUR_SECTOR] = word & 0x00FF0000U;
  323.  
  324.    
  325.     //START BM
  326.     if (word & DD_BM_CTL_START)
  327.     {
  328.       dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_BM_INT | DD_STATUS_DATA_RQ | DD_STATUS_C2_XFER | DD_STATUS_BM_ERR);
  329.  
  330.       LBA = ((dd->regs[DD_ASIC_CUR_TK] & ~0x6000FFFFU) >> 15);
  331.       if ((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) >= 0x5A)
  332.         LBA |= 1; //Block 1
  333.  
  334.       LBA ^= ((LBA & 2) >> 1);  //Calculate LBA proper
  335.  
  336.       //Put data
  337.       int offsetLBA = getROMLBAoffset(LBA, dd->rom[6] & 0x0F);
  338.  
  339.       if ((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) < 0x5A)
  340.         offsetLBA += (dd->regs[DD_ASIC_CUR_SECTOR] >> 16) * ((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1);
  341.       else
  342.         offsetLBA += ((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) - 5) * ((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1);
  343.  
  344.       for (int i = 0; i < DD_DS_BUFFER_LEN; i++)
  345.         dd->ds_buffer[i] = 0xFF;
  346.  
  347.       for (int i = 0; i < DD_C2S_BUFFER_LEN; i++)
  348.         dd->c2s_buffer[i] = 0x00;
  349.  
  350.       if (dd->rom_size == 0x3DEC800)
  351.         for (int i = 0; i <= (dd->regs[DD_ASIC_HOST_SECBYTE] >> 16); i++)
  352.           dd->ds_buffer[i] = dd->rom[offsetLBA + i];
  353.  
  354.       //if (dd->regs[DD_ASIC_BM_STATUS_CTL] & DD_BM_STATUS_BLOCK)
  355.         //dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_C2_XFER;
  356.  
  357.       dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_DATA_RQ; // | DD_STATUS_C2_XFER;
  358.       //dd->regs[DD_ASIC_BM_STATUS_CTL] |= DD_BM_STATUS_C1CRR;
  359.      
  360.       if (LBA == 12)
  361.       {
  362.         //for (int i = 0; i <= (dd->regs[DD_ASIC_HOST_SECBYTE] >> 16); i++)
  363.           //dd->ds_buffer[i] = 0xFF;
  364.         dd->regs[DD_ASIC_BM_STATUS_CTL] |= DD_BM_STATUS_MICRO;
  365.         dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_C2_XFER;
  366.       }
  367.  
  368.       //Interrupt!
  369.       dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_BM_INT;
  370.       signal_dd_interrupt(dd->bus->vr4300);
  371.     }
  372.   }
  373.  
  374.   // This is done by the IPL and a lot of games. The only word
  375.   // ever know to be written to this register is 0xAAAA0000.
  376.   else if (reg == DD_ASIC_HARD_RESET) {
  377.     assert(word == 0xAAAA0000 && "dd: Hard reset without magic word?");
  378.  
  379.     dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_RST_STATE;
  380.   }
  381.  
  382.   else if ((reg == DD_ASIC_CUR_TK) |
  383.     (reg == DD_ASIC_ERR_SECTOR) |
  384.     (reg == DD_ASIC_CUR_SECTOR) |
  385.     (reg == DD_ASIC_C1_S0) |
  386.     (reg == DD_ASIC_C1_S2) |
  387.     (reg == DD_ASIC_C1_S4) |
  388.     (reg == DD_ASIC_C1_S6) |
  389.     (reg == DD_ASIC_CUR_ADDR) |
  390.     (reg == DD_ASIC_ID_REG) |
  391.     (reg == DD_ASIC_TEST_REG))
  392.   {
  393.     // Do nothing. Not writable.
  394.   }
  395.  
  396.   else {
  397.     dd->regs[reg] &= ~dqm;
  398.     dd->regs[reg] |= word;
  399.   }
  400.  
  401.   return 0;
  402. }
  403.  
  404. // Reads a word from the DD IPL ROM.
  405. int read_dd_ipl_rom(void *opaque, uint32_t address, uint32_t *word) {
  406.   uint32_t offset = address - DD_IPL_ROM_ADDRESS;
  407.   struct dd_controller *dd = (struct dd_controller*) opaque;
  408.  
  409.   if (!dd->ipl_rom)
  410.     memset(word, 0, sizeof(*word));
  411.  
  412.   else {
  413.     memcpy(word, dd->ipl_rom + offset, sizeof(*word));
  414.     *word = byteswap_32(*word);
  415.   }
  416.  
  417.   //debug_mmio_read(dd, "DD_IPL_ROM", *word);
  418.   return 0;
  419. }
  420.  
  421. // Writes a word to the DD IPL ROM.
  422. int write_dd_ipl_rom(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  423.   assert(0 && "Attempt to write to DD IPL ROM.");
  424.   return 0;
  425. }
  426.  
  427. // Reads a word from the DD C2S buffer.
  428. int read_dd_c2s_buffer(void *opaque, uint32_t address, uint32_t *word) {
  429.   struct dd_controller *dd = (struct dd_controller *) opaque;
  430.   unsigned offset = address - DD_C2S_BUFFER_ADDRESS;
  431.  
  432.   if (offset == 0)
  433.     debug_mmio_read(dd, "DD_C2S_BUFFER", *word);
  434.   return 0;
  435. }
  436.  
  437. // Writes a word to the DD C2S BUFFER.
  438. int write_dd_c2s_buffer(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  439.   struct dd_controller *dd = (struct dd_controller *) opaque;
  440.   unsigned offset = address - DD_C2S_BUFFER_ADDRESS;
  441.  
  442.   debug_mmio_write(dd, "DD_C2S_BUFFER", word, dqm);
  443.   return 0;
  444. }
  445.  
  446. // Reads a word from the DD DS buffer.
  447. int read_dd_ds_buffer(void *opaque, uint32_t address, uint32_t *word) {
  448.   struct dd_controller *dd = (struct dd_controller *) opaque;
  449.   unsigned offset = address - DD_DS_BUFFER_ADDRESS;
  450.  
  451.   memcpy(word, dd->ds_buffer + (address & 0xFC), sizeof(*word));
  452.   *word = byteswap_32(*word);
  453.  
  454.   if ((offset == ((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) - 3)))
  455.   {
  456.     dd->regs[DD_ASIC_CUR_SECTOR] += 0x00010000U;
  457.  
  458.     LBA = ((dd->regs[DD_ASIC_CUR_TK] & ~0x6000FFFFU) >> 15);
  459.     if ((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) >= 0x5A)
  460.       LBA |= 1; //Block 1
  461.  
  462.     LBA ^= ((LBA & 2) >> 1);  //Calculate LBA proper
  463.  
  464.     int offsetLBA = getROMLBAoffset(LBA, dd->rom[6] & 0x0F);
  465.  
  466.     if ((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) < 0x5A)
  467.       offsetLBA += (dd->regs[DD_ASIC_CUR_SECTOR] >> 16) * ((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1);
  468.     else
  469.       offsetLBA += ((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) - 0x5A) * ((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1);
  470.  
  471.     printf("dd: DMA LBA %4d [0x%08X]: Sector %2X\n", LBA, offsetLBA, (dd->regs[DD_ASIC_CUR_SECTOR] >> 16));
  472.  
  473.     for (int i = 0; i < DD_DS_BUFFER_LEN; i++)
  474.       dd->ds_buffer[i] = 0xFF;
  475.  
  476.     if (dd->rom_size == 0x3DEC800)
  477.       for (int i = 0; i <= (dd->regs[DD_ASIC_HOST_SECBYTE] >> 16); i++)
  478.         dd->ds_buffer[i] = dd->rom[offsetLBA + i];
  479.  
  480.  
  481.     if (((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) >= (0x5A - 5)) && ((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) < 0x5A))
  482.     {
  483.       dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_C2_XFER;
  484.       dd->regs[DD_ASIC_CUR_SECTOR] = 0x005A0000U;
  485.     }
  486.     else if ((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) >= (0xB4 - 5))
  487.     {
  488.       dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_C2_XFER;
  489.       dd->regs[DD_ASIC_CUR_SECTOR] = 0x00000000U;
  490.     }
  491.   }
  492.  
  493.   //debug_mmio_read(dd, "DD_DS_BUFFER", *word);
  494.   return 0;
  495. }
  496.  
  497. // Writes a word to the DD DS BUFFER.
  498. int write_dd_ds_buffer(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  499.   struct dd_controller *dd = (struct dd_controller *) opaque;
  500.   unsigned offset = address - DD_DS_BUFFER_ADDRESS;
  501.  
  502.   debug_mmio_write(dd, "DD_DS_BUFFER", word, dqm);
  503.   return 0;
  504. }
  505.  
  506. // Reads a word from the DD MS RAM.
  507. int read_dd_ms_ram(void *opaque, uint32_t address, uint32_t *word) {
  508.   struct dd_controller *dd = (struct dd_controller *) opaque;
  509.   unsigned offset = address - DD_MS_RAM_ADDRESS;
  510.  
  511.   memcpy(word, dd->ms_ram + (address & 0x3C), sizeof(*word));
  512.  
  513.   debug_mmio_read(dd, "DD_MS_RAM", *word);
  514.   return 0;
  515. }
  516.  
  517. // Writes a word to the DD MS RAM.
  518. int write_dd_ms_ram(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  519.   struct dd_controller *dd = (struct dd_controller *) opaque;
  520.   unsigned offset = address - DD_MS_RAM_ADDRESS;
  521.  
  522.   //debug_mmio_write(dd, "DD_MS_RAM", word, dqm);
  523.   return 0;
  524. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement