Advertisement
LuigiBlood

dd_controller.c 2

Jan 12th, 2015
300
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 17.24 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.   *word = dd->regs[reg];
  174.  
  175.   //if (reg != DD_ASIC_CMD_STATUS)
  176.     debug_mmio_read(dd, dd_register_mnemonics[reg], *word);
  177.   return 0;
  178. }
  179.  
  180. // Writes a word to the DD MMIO register space.
  181. int write_dd_regs(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  182.   struct dd_controller *dd = (struct dd_controller *) opaque;
  183.   unsigned offset = address - DD_REGS_BASE_ADDRESS;
  184.   enum dd_register reg = (offset >> 2);
  185.  
  186.   debug_mmio_write(dd, dd_register_mnemonics[reg], word, dqm);
  187.  
  188.   //No matter what, the lower 16-bit is always ignored.
  189.   word &= 0xFFFF0000U;
  190.  
  191.   // Command register written: do something.
  192.   if (reg == DD_ASIC_CMD_STATUS) {
  193.  
  194.     time_t timer;
  195.     struct tm * timeinfo;
  196.     // Get time [minute/second]:
  197.     if (word == DD_CMD_GET_MIN_SEC) {
  198.       //Get Time
  199.       time(&timer);
  200.       timeinfo = localtime(&timer);
  201.  
  202.       //Put time in DATA as BCD
  203.       uint8_t min = (uint8_t)(((timeinfo->tm_min / 10) << 4) | (timeinfo->tm_min % 10));
  204.       uint8_t sec = (uint8_t)(((timeinfo->tm_sec / 10) << 4) | (timeinfo->tm_sec % 10));
  205.  
  206.       dd->regs[DD_ASIC_DATA] = (min << 24) | (sec << 16);
  207.     }
  208.     // Get time [day/hour]:
  209.     else if (word == DD_CMD_GET_DAY_HOUR) {
  210.       //Get Time
  211.       time(&timer);
  212.       timeinfo = localtime(&timer);
  213.  
  214.       //Put time in DATA as BCD
  215.       uint8_t hour = (uint8_t)(((timeinfo->tm_hour / 10) << 4) | (timeinfo->tm_hour % 10));
  216.       uint8_t day = (uint8_t)(((timeinfo->tm_mday / 10) << 4) | (timeinfo->tm_mday % 10));
  217.  
  218.       dd->regs[DD_ASIC_DATA] = (day << 24) | (hour << 16);
  219.     }
  220.     // Get time [year/month]:
  221.     else if (word == DD_CMD_GET_YEAR_MONTH) {
  222.       //Get Time
  223.       time(&timer);
  224.       timeinfo = localtime(&timer);
  225.  
  226.       //Put time in DATA as BCD
  227.       uint8_t year = (uint8_t)(((timeinfo->tm_year / 10) << 4) | (timeinfo->tm_year % 10));
  228.       uint8_t month = (uint8_t)((((timeinfo->tm_mon + 1) / 10) << 4) | ((timeinfo->tm_mon + 1) % 10));
  229.  
  230.       dd->regs[DD_ASIC_DATA] = (year << 24) | (month << 16);
  231.     }
  232.  
  233.     //Clear Disk Change status bit
  234.     else if (word == DD_CMD_CLR_DSK_CHNG)
  235.       dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_DISK_CHNG;
  236.  
  237.     //Clear Reset status bit
  238.     else if (word == DD_CMD_CLR_RESET)
  239.       dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_RST_STATE;
  240.  
  241.     //Feature Inquiry
  242.     else if (word == DD_CMD_FEATURE_INQ)
  243.       dd->regs[DD_ASIC_DATA] = 0x00010000U;
  244.  
  245.     //Sleep
  246.     else if (word == DD_CMD_SLEEP)
  247.       dd->regs[DD_ASIC_CMD_STATUS] |= (DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT);
  248.  
  249.     //Standby
  250.     else if (word == DD_CMD_STANDBY)
  251.     {
  252.       dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_HEAD_RTRCT;
  253.       dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_MTR_N_SPIN;
  254.     }
  255.  
  256.     //Start
  257.     else if (word == DD_CMD_START)
  258.       dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT);
  259.  
  260.     //SEEK READ
  261.     else if (word == DD_CMD_SEEK_READ)
  262.     {
  263.       dd->regs[DD_ASIC_CUR_TK] = dd->regs[DD_ASIC_DATA] | 0x60000000U;
  264.       dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT);
  265.     }
  266.  
  267.     //SEEK WRITE
  268.     else if (word == DD_CMD_SEEK_WRITE)
  269.     {
  270.       dd->regs[DD_ASIC_CUR_TK] = dd->regs[DD_ASIC_DATA] | 0x60000000U;
  271.       dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT);
  272.     }
  273.  
  274.     //RECALIB
  275.     else if (word == DD_CMD_RECALIBRATE)
  276.       dd->regs[DD_ASIC_DATA] = 0;
  277.  
  278.     //Index Lock Retry
  279.     else if (word == DD_CMD_IDX_LOCK_RETRY)
  280.     {
  281.       //dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_C2_XFER;
  282.       dd->regs[DD_ASIC_CUR_TK] |= 0x60000000U;
  283.     }
  284.  
  285.     // Always signal an interrupt in response.
  286.     dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_MECHA_INT;
  287.     signal_dd_interrupt(dd->bus->vr4300);
  288.   }
  289.  
  290.   // Buffer manager control request: handle it.
  291.   else if (reg == DD_ASIC_BM_STATUS_CTL) {
  292.     if (word & DD_BM_CTL_RESET)
  293.     {
  294.       dd->regs[DD_ASIC_BM_STATUS_CTL] = 0;
  295.       dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_BM_INT | DD_STATUS_BM_ERR | DD_STATUS_DATA_RQ | DD_STATUS_C2_XFER);
  296.  
  297.       if (!(dd->regs[DD_ASIC_CMD_STATUS] & DD_STATUS_MECHA_INT))
  298.         clear_dd_interrupt(dd->bus->vr4300);
  299.     }
  300.  
  301.     if (word & DD_BM_CTL_MECHA_RST)
  302.     {
  303.       dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_MECHA_INT;
  304.       if (!(dd->regs[DD_ASIC_CMD_STATUS] & DD_STATUS_BM_INT))
  305.         clear_dd_interrupt(dd->bus->vr4300);
  306.     }
  307.  
  308.     if (word == 0)
  309.       dd->regs[DD_ASIC_BM_STATUS_CTL] = 0;
  310.  
  311.     if (word & DD_BM_CTL_BLK_TRANS)
  312.       dd->regs[DD_ASIC_BM_STATUS_CTL] |= DD_BM_STATUS_BLOCK;
  313.     else
  314.       dd->regs[DD_ASIC_BM_STATUS_CTL] &= ~DD_BM_STATUS_BLOCK;
  315.  
  316.     //SET SECTOR
  317.     if (word & DD_BM_CTL_MNGRMODE)
  318.       dd->regs[DD_ASIC_CUR_SECTOR] = word & 0x00FF0000U;
  319.  
  320.    
  321.     //START BM
  322.     if (word & DD_BM_CTL_START)
  323.     {
  324.       dd->regs[DD_ASIC_CMD_STATUS] &= ~(DD_STATUS_BM_INT | DD_STATUS_DATA_RQ | DD_STATUS_C2_XFER | DD_STATUS_BM_ERR);
  325.  
  326.       LBA = ((dd->regs[DD_ASIC_CUR_TK] & ~0xE000FFFFU) >> 15);
  327.       if ((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) >= 0x5A)
  328.         LBA |= 1; //Block 1
  329.  
  330.       LBA ^= ((LBA & 2) >> 1);  //Calculate LBA proper
  331.  
  332.       //Put data
  333.       int offsetLBA = getROMLBAoffset(LBA, dd->rom[6] & 0x0F);
  334.  
  335.       if ((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) < 0x5A)
  336.         offsetLBA += (dd->regs[DD_ASIC_CUR_SECTOR] >> 16) * ((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1);
  337.       else
  338.         offsetLBA += ((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) - 5) * ((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1);
  339.  
  340.       for (int i = 0; i < DD_DS_BUFFER_LEN; i++)
  341.         dd->ds_buffer[i] = 0xFF;
  342.  
  343.       for (int i = 0; i < DD_C2S_BUFFER_LEN; i++)
  344.         dd->c2s_buffer[i] = 0x00;
  345.  
  346.       if (dd->rom_size == 0x3DEC800)
  347.         for (int i = 0; i <= (dd->regs[DD_ASIC_HOST_SECBYTE] >> 16); i++)
  348.           dd->ds_buffer[i] = dd->rom[offsetLBA + i];
  349.  
  350.       //if (dd->regs[DD_ASIC_BM_STATUS_CTL] & DD_BM_STATUS_BLOCK)
  351.         //dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_C2_XFER;
  352.  
  353.       dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_DATA_RQ; // | DD_STATUS_C2_XFER;
  354.       //dd->regs[DD_ASIC_BM_STATUS_CTL] |= DD_BM_STATUS_C1CRR;
  355.      
  356.       if (LBA == 12)
  357.       {
  358.         //for (int i = 0; i <= (dd->regs[DD_ASIC_HOST_SECBYTE] >> 16); i++)
  359.           //dd->ds_buffer[i] = 0xFF;
  360.         dd->regs[DD_ASIC_BM_STATUS_CTL] |= DD_BM_STATUS_MICRO;
  361.         dd->regs[DD_ASIC_CMD_STATUS] &= ~DD_STATUS_C2_XFER;
  362.       }
  363.  
  364.       //Interrupt!
  365.       dd->regs[DD_ASIC_BM_STATUS_CTL] |= DD_BM_STATUS_RUNNING;
  366.       dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_BM_INT;
  367.       signal_dd_interrupt(dd->bus->vr4300);
  368.     }
  369.   }
  370.  
  371.   // This is done by the IPL and a lot of games. The only word
  372.   // ever know to be written to this register is 0xAAAA0000.
  373.   else if (reg == DD_ASIC_HARD_RESET) {
  374.     assert(word == 0xAAAA0000 && "dd: Hard reset without magic word?");
  375.  
  376.     dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_RST_STATE;
  377.   }
  378.  
  379.   else if ((reg == DD_ASIC_CUR_TK) |
  380.     (reg == DD_ASIC_ERR_SECTOR) |
  381.     (reg == DD_ASIC_CUR_SECTOR) |
  382.     (reg == DD_ASIC_C1_S0) |
  383.     (reg == DD_ASIC_C1_S2) |
  384.     (reg == DD_ASIC_C1_S4) |
  385.     (reg == DD_ASIC_C1_S6) |
  386.     (reg == DD_ASIC_CUR_ADDR) |
  387.     (reg == DD_ASIC_ID_REG) |
  388.     (reg == DD_ASIC_TEST_REG))
  389.   {
  390.     // Do nothing. Not writable.
  391.   }
  392.  
  393.   else {
  394.     dd->regs[reg] &= ~dqm;
  395.     dd->regs[reg] |= word;
  396.   }
  397.  
  398.   return 0;
  399. }
  400.  
  401. // Reads a word from the DD IPL ROM.
  402. int read_dd_ipl_rom(void *opaque, uint32_t address, uint32_t *word) {
  403.   uint32_t offset = address - DD_IPL_ROM_ADDRESS;
  404.   struct dd_controller *dd = (struct dd_controller*) opaque;
  405.  
  406.   if (!dd->ipl_rom)
  407.     memset(word, 0, sizeof(*word));
  408.  
  409.   else {
  410.     memcpy(word, dd->ipl_rom + offset, sizeof(*word));
  411.     *word = byteswap_32(*word);
  412.   }
  413.  
  414.   //debug_mmio_read(dd, "DD_IPL_ROM", *word);
  415.   return 0;
  416. }
  417.  
  418. // Writes a word to the DD IPL ROM.
  419. int write_dd_ipl_rom(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  420.   assert(0 && "Attempt to write to DD IPL ROM.");
  421.   return 0;
  422. }
  423.  
  424. // Reads a word from the DD C2S buffer.
  425. int read_dd_c2s_buffer(void *opaque, uint32_t address, uint32_t *word) {
  426.   struct dd_controller *dd = (struct dd_controller *) opaque;
  427.   unsigned offset = address - DD_C2S_BUFFER_ADDRESS;
  428.  
  429.   if (offset == 0)
  430.     debug_mmio_read(dd, "DD_C2S_BUFFER", *word);
  431.   return 0;
  432. }
  433.  
  434. // Writes a word to the DD C2S BUFFER.
  435. int write_dd_c2s_buffer(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  436.   struct dd_controller *dd = (struct dd_controller *) opaque;
  437.   unsigned offset = address - DD_C2S_BUFFER_ADDRESS;
  438.  
  439.   debug_mmio_write(dd, "DD_C2S_BUFFER", word, dqm);
  440.   return 0;
  441. }
  442.  
  443. // Reads a word from the DD DS buffer.
  444. int read_dd_ds_buffer(void *opaque, uint32_t address, uint32_t *word) {
  445.   struct dd_controller *dd = (struct dd_controller *) opaque;
  446.   unsigned offset = address - DD_DS_BUFFER_ADDRESS;
  447.  
  448.   memcpy(word, dd->ds_buffer + (address & 0xFC), sizeof(*word));
  449.   *word = byteswap_32(*word);
  450.  
  451.   if ((offset == ((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) - 3)))
  452.   {
  453.     dd->regs[DD_ASIC_CUR_SECTOR] += 0x00010000U;
  454.  
  455.     LBA = ((dd->regs[DD_ASIC_CUR_TK] & ~0xE000FFFFU) >> 15);
  456.     if ((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) >= 0x5A)
  457.       LBA |= 1; //Block 1
  458.  
  459.     LBA ^= ((LBA & 2) >> 1);  //Calculate LBA proper
  460.  
  461.     int offsetLBA = getROMLBAoffset(LBA, dd->rom[6] & 0x0F);
  462.  
  463.     if ((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) < 0x5A)
  464.       offsetLBA += (dd->regs[DD_ASIC_CUR_SECTOR] >> 16) * ((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1);
  465.     else
  466.       offsetLBA += ((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) - 0x5A) * ((dd->regs[DD_ASIC_HOST_SECBYTE] >> 16) + 1);
  467.  
  468.     printf("dd: DMA LBA %4d [0x%08X]: Sector %2X\n", LBA, offsetLBA, (dd->regs[DD_ASIC_CUR_SECTOR] >> 16));
  469.  
  470.     for (int i = 0; i < DD_DS_BUFFER_LEN; i++)
  471.       dd->ds_buffer[i] = 0xFF;
  472.  
  473.     if (dd->rom_size == 0x3DEC800)
  474.       for (int i = 0; i <= (dd->regs[DD_ASIC_HOST_SECBYTE] >> 16); i++)
  475.         dd->ds_buffer[i] = dd->rom[offsetLBA + i];
  476.  
  477.  
  478.     if (((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) >= (0x5A - 5)) && ((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) < 0x5A))
  479.     {
  480.       dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_C2_XFER;
  481.       //dd->regs[DD_ASIC_CUR_TK] &= 0x1FFF0000;
  482.       dd->regs[DD_ASIC_CUR_SECTOR] = 0x005A0000U;
  483.       //dd->regs[DD_ASIC_BM_STATUS_CTL] &= ~(DD_BM_STATUS_RUNNING | DD_BM_STATUS_BLOCK);
  484.     }
  485.     else if ((dd->regs[DD_ASIC_CUR_SECTOR] >> 16) >= (0xB4 - 5))
  486.     {
  487.       dd->regs[DD_ASIC_CMD_STATUS] |= DD_STATUS_C2_XFER;
  488.       //dd->regs[DD_ASIC_CUR_TK] &= 0x1FFF0000;
  489.       dd->regs[DD_ASIC_CUR_SECTOR] = 0x00000000U;
  490.       //dd->regs[DD_ASIC_BM_STATUS_CTL] &= ~(DD_BM_STATUS_RUNNING | DD_BM_STATUS_BLOCK);
  491.     }
  492.   }
  493.  
  494.   //debug_mmio_read(dd, "DD_DS_BUFFER", *word);
  495.   return 0;
  496. }
  497.  
  498. // Writes a word to the DD DS BUFFER.
  499. int write_dd_ds_buffer(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  500.   struct dd_controller *dd = (struct dd_controller *) opaque;
  501.   unsigned offset = address - DD_DS_BUFFER_ADDRESS;
  502.  
  503.   debug_mmio_write(dd, "DD_DS_BUFFER", word, dqm);
  504.   return 0;
  505. }
  506.  
  507. // Reads a word from the DD MS RAM.
  508. int read_dd_ms_ram(void *opaque, uint32_t address, uint32_t *word) {
  509.   struct dd_controller *dd = (struct dd_controller *) opaque;
  510.   unsigned offset = address - DD_MS_RAM_ADDRESS;
  511.  
  512.   memcpy(word, dd->ms_ram + (address & 0x3C), sizeof(*word));
  513.  
  514.   debug_mmio_read(dd, "DD_MS_RAM", *word);
  515.   return 0;
  516. }
  517.  
  518. // Writes a word to the DD MS RAM.
  519. int write_dd_ms_ram(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  520.   struct dd_controller *dd = (struct dd_controller *) opaque;
  521.   unsigned offset = address - DD_MS_RAM_ADDRESS;
  522.  
  523.   //debug_mmio_write(dd, "DD_MS_RAM", word, dqm);
  524.   return 0;
  525. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement