atapi_imp.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #pragma once
  2. static struct ata_device ata_primary_master = {.io_base = 0x1F0, .control = 0x3F6, .slave = 0};
  3. static struct ata_device ata_primary_slave = {.io_base = 0x1F0, .control = 0x3F6, .slave = 1};
  4. static struct ata_device ata_secondary_master = {.io_base = 0x170, .control = 0x376, .slave = 0};
  5. static struct ata_device ata_secondary_slave = {.io_base = 0x170, .control = 0x376, .slave = 1};
  6. static void ata_io_wait(struct ata_device * dev) {
  7. inportb(dev->io_base + ATA_REG_ALTSTATUS);
  8. inportb(dev->io_base + ATA_REG_ALTSTATUS);
  9. inportb(dev->io_base + ATA_REG_ALTSTATUS);
  10. inportb(dev->io_base + ATA_REG_ALTSTATUS);
  11. }
  12. static int ata_status_wait(struct ata_device * dev, int timeout) {
  13. int status;
  14. if (timeout > 0) {
  15. int i = 0;
  16. while ((status = inportb(dev->io_base + ATA_REG_STATUS)) & ATA_SR_BSY && (i < timeout)) i++;
  17. } else {
  18. while ((status = inportb(dev->io_base + ATA_REG_STATUS)) & ATA_SR_BSY);
  19. }
  20. return status;
  21. }
  22. static void ata_soft_reset(struct ata_device * dev) {
  23. outportb(dev->control, 0x04);
  24. ata_io_wait(dev);
  25. outportb(dev->control, 0x00);
  26. }
  27. static int ata_wait(struct ata_device * dev, int advanced) {
  28. uint8_t status = 0;
  29. ata_io_wait(dev);
  30. status = ata_status_wait(dev, -1);
  31. if (advanced) {
  32. status = inportb(dev->io_base + ATA_REG_STATUS);
  33. if (status & ATA_SR_ERR) return 1;
  34. if (status & ATA_SR_DF) return 1;
  35. if (!(status & ATA_SR_DRQ)) return 1;
  36. }
  37. return 0;
  38. }
  39. static void atapi_device_init(struct ata_device * dev) {
  40. dev->is_atapi = 1;
  41. outportb(dev->io_base + 1, 1);
  42. outportb(dev->control, 0);
  43. outportb(dev->io_base + ATA_REG_HDDEVSEL, 0xA0 | dev->slave << 4);
  44. ata_io_wait(dev);
  45. outportb(dev->io_base + ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET);
  46. ata_io_wait(dev);
  47. ata_wait(dev, 0);
  48. uint16_t * buf = (uint16_t *)&dev->identity;
  49. for (int i = 0; i < 256; ++i) {
  50. buf[i] = inports(dev->io_base);
  51. }
  52. uint8_t * ptr = (uint8_t *)&dev->identity.model;
  53. for (int i = 0; i < 39; i+=2) {
  54. uint8_t tmp = ptr[i+1];
  55. ptr[i+1] = ptr[i];
  56. ptr[i] = tmp;
  57. }
  58. /* Detect medium */
  59. atapi_command_t command;
  60. memset(&command, 0, sizeof(command));
  61. command.command_bytes[0] = 0x25;
  62. uint16_t bus = dev->io_base;
  63. outportb(bus + ATA_REG_FEATURES, 0x00);
  64. outportb(bus + ATA_REG_LBA1, 0x08);
  65. outportb(bus + ATA_REG_LBA2, 0x08);
  66. outportb(bus + ATA_REG_COMMAND, ATA_CMD_PACKET);
  67. /* poll */
  68. while (1) {
  69. uint8_t status = inportb(dev->io_base + ATA_REG_STATUS);
  70. if ((status & ATA_SR_ERR)) goto atapi_error;
  71. if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRDY)) break;
  72. }
  73. for (int i = 0; i < 6; ++i) {
  74. outports(bus, command.command_words[i]);
  75. }
  76. /* poll */
  77. while (1) {
  78. uint8_t status = inportb(dev->io_base + ATA_REG_STATUS);
  79. if ((status & ATA_SR_ERR)) goto atapi_error_read;
  80. if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRDY)) break;
  81. if ((status & ATA_SR_DRQ)) break;
  82. }
  83. uint16_t data[4];
  84. for (int i = 0; i < 4; ++i) {
  85. data[i] = inports(bus);
  86. }
  87. #define htonl(l) ( (((l) & 0xFF) << 24) | (((l) & 0xFF00) << 8) | (((l) & 0xFF0000) >> 8) | (((l) & 0xFF000000) >> 24))
  88. uint32_t lba, blocks;;
  89. memcpy(&lba, &data[0], sizeof(uint32_t));
  90. lba = htonl(lba);
  91. memcpy(&blocks, &data[2], sizeof(uint32_t));
  92. blocks = htonl(blocks);
  93. dev->atapi_lba = lba;
  94. dev->atapi_sector_size = blocks;
  95. return;
  96. atapi_error_read:
  97. return;
  98. atapi_error:
  99. return;
  100. }
  101. static int ata_device_detect(struct ata_device * dev) {
  102. ata_soft_reset(dev);
  103. ata_io_wait(dev);
  104. outportb(dev->io_base + ATA_REG_HDDEVSEL, 0xA0 | dev->slave << 4);
  105. ata_io_wait(dev);
  106. ata_status_wait(dev, 10000);
  107. unsigned char cl = inportb(dev->io_base + ATA_REG_LBA1); /* CYL_LO */
  108. unsigned char ch = inportb(dev->io_base + ATA_REG_LBA2); /* CYL_HI */
  109. if (cl == 0xFF && ch == 0xFF) {
  110. /* Nothing here */
  111. return 0;
  112. }
  113. if ((cl == 0x00 && ch == 0x00) ||
  114. (cl == 0x3C && ch == 0xC3)) {
  115. return 1;
  116. } else if ((cl == 0x14 && ch == 0xEB) ||
  117. (cl == 0x69 && ch == 0x96)) {
  118. atapi_device_init(dev);
  119. return 2;
  120. }
  121. return 0;
  122. }
  123. static void ata_device_read_sectors_atapi(struct ata_device * dev, uint32_t lba, uint8_t * buf, int sectors) {
  124. if (!dev->is_atapi) return;
  125. uint16_t bus = dev->io_base;
  126. _try_again:
  127. outportb(dev->io_base + ATA_REG_HDDEVSEL, 0xA0 | dev->slave << 4);
  128. ata_io_wait(dev);
  129. outportb(bus + ATA_REG_FEATURES, 0x00);
  130. outportb(bus + ATA_REG_LBA1, dev->atapi_sector_size & 0xFF);
  131. outportb(bus + ATA_REG_LBA2, dev->atapi_sector_size >> 8);
  132. outportb(bus + ATA_REG_COMMAND, ATA_CMD_PACKET);
  133. /* poll */
  134. while (1) {
  135. uint8_t status = inportb(dev->io_base + ATA_REG_STATUS);
  136. if ((status & ATA_SR_ERR)) goto atapi_error_on_read_setup;
  137. if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ)) break;
  138. }
  139. atapi_command_t command;
  140. command.command_bytes[0] = 0x28;
  141. command.command_bytes[1] = 0;
  142. command.command_bytes[2] = (lba >> 0x18) & 0xFF;
  143. command.command_bytes[3] = (lba >> 0x10) & 0xFF;
  144. command.command_bytes[4] = (lba >> 0x08) & 0xFF;
  145. command.command_bytes[5] = (lba >> 0x00) & 0xFF;
  146. command.command_bytes[6] = sectors >> 16;
  147. command.command_bytes[7] = sectors >> 8;
  148. command.command_bytes[8] = sectors; /* bit 0 = PMI (0, last sector) */
  149. command.command_bytes[9] = 0; /* control */
  150. command.command_bytes[10] = 0;
  151. command.command_bytes[11] = 0;
  152. for (int i = 0; i < 6; ++i) {
  153. outports(bus, command.command_words[i]);
  154. }
  155. uint16_t size_to_read = dev->atapi_sector_size;
  156. for (int i = 0; i < sectors; ++i) {
  157. while (1) {
  158. uint8_t status = inportb(dev->io_base + ATA_REG_STATUS);
  159. if ((status & ATA_SR_ERR)) goto atapi_error_on_read_setup_cmd;
  160. if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ)) break;
  161. }
  162. inportsm(bus,buf,size_to_read/2);
  163. buf += size_to_read;
  164. while (1) {
  165. uint8_t status = inportb(dev->io_base + ATA_REG_STATUS);
  166. if ((status & ATA_SR_ERR)) goto atapi_error_on_read_setup;
  167. if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRDY)) break;
  168. }
  169. }
  170. return;
  171. atapi_error_on_read_setup:
  172. print("error on setup\n");
  173. return;
  174. atapi_error_on_read_setup_cmd:
  175. print("error on cmd\n");
  176. return;
  177. }
  178. #define ata_device_read_sector_atapi(a,b,c) ata_device_read_sectors_atapi(a,b,c,1)