ata.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. /* ata.c - ATA disk access. */
  2. /*
  3. * GRUB -- GRand Unified Bootloader
  4. * Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
  5. *
  6. * GRUB is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * GRUB is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <grub/ata.h>
  20. #include <grub/dl.h>
  21. #include <grub/disk.h>
  22. #include <grub/mm.h>
  23. #include <grub/scsi.h>
  24. GRUB_MOD_LICENSE ("GPLv3+");
  25. static grub_ata_dev_t grub_ata_dev_list;
  26. /* Byteorder has to be changed before strings can be read. */
  27. static void
  28. grub_ata_strncpy (grub_uint16_t *dst16, grub_uint16_t *src16, grub_size_t len)
  29. {
  30. unsigned int i;
  31. for (i = 0; i < len / 2; i++)
  32. *(dst16++) = grub_swap_bytes16 (*(src16++));
  33. *dst16 = 0;
  34. }
  35. static void
  36. grub_ata_dumpinfo (struct grub_ata *dev, grub_uint16_t *info)
  37. {
  38. grub_uint16_t text[21];
  39. /* The device information was read, dump it for debugging. */
  40. grub_ata_strncpy (text, info + 10, 20);
  41. grub_dprintf ("ata", "Serial: %s\n", (char *) text);
  42. grub_ata_strncpy (text, info + 23, 8);
  43. grub_dprintf ("ata", "Firmware: %s\n", (char *) text);
  44. grub_ata_strncpy (text, info + 27, 40);
  45. grub_dprintf ("ata", "Model: %s\n", (char *) text);
  46. if (! dev->atapi)
  47. {
  48. grub_dprintf ("ata", "Addressing: %d\n", dev->addr);
  49. grub_dprintf ("ata", "Sectors: %lld\n", (unsigned long long) dev->size);
  50. grub_dprintf ("ata", "Sector size: %u\n", 1U << dev->log_sector_size);
  51. }
  52. }
  53. static grub_err_t
  54. grub_atapi_identify (struct grub_ata *dev)
  55. {
  56. struct grub_disk_ata_pass_through_parms parms;
  57. grub_uint16_t *info;
  58. grub_err_t err;
  59. info = grub_malloc (GRUB_DISK_SECTOR_SIZE);
  60. if (! info)
  61. return grub_errno;
  62. grub_memset (&parms, 0, sizeof (parms));
  63. parms.taskfile.disk = 0xE0;
  64. parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE;
  65. parms.size = GRUB_DISK_SECTOR_SIZE;
  66. parms.buffer = info;
  67. err = dev->dev->readwrite (dev, &parms, *dev->present);
  68. if (err)
  69. {
  70. *dev->present = 0;
  71. return err;
  72. }
  73. if (parms.size != GRUB_DISK_SECTOR_SIZE)
  74. {
  75. *dev->present = 0;
  76. return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
  77. "device cannot be identified");
  78. }
  79. dev->atapi = 1;
  80. grub_ata_dumpinfo (dev, info);
  81. grub_free (info);
  82. return GRUB_ERR_NONE;
  83. }
  84. static grub_err_t
  85. grub_ata_identify (struct grub_ata *dev)
  86. {
  87. struct grub_disk_ata_pass_through_parms parms;
  88. grub_uint64_t *info64;
  89. grub_uint32_t *info32;
  90. grub_uint16_t *info16;
  91. grub_err_t err;
  92. if (dev->atapi)
  93. return grub_atapi_identify (dev);
  94. info64 = grub_malloc (GRUB_DISK_SECTOR_SIZE);
  95. info32 = (grub_uint32_t *) info64;
  96. info16 = (grub_uint16_t *) info64;
  97. if (! info16)
  98. return grub_errno;
  99. grub_memset (&parms, 0, sizeof (parms));
  100. parms.buffer = info16;
  101. parms.size = GRUB_DISK_SECTOR_SIZE;
  102. parms.taskfile.disk = 0xE0;
  103. parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_DEVICE;
  104. err = dev->dev->readwrite (dev, &parms, *dev->present);
  105. if (err || parms.size != GRUB_DISK_SECTOR_SIZE)
  106. {
  107. grub_uint8_t sts = parms.taskfile.status;
  108. grub_free (info16);
  109. grub_errno = GRUB_ERR_NONE;
  110. if ((sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ
  111. | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_ERR
  112. && (parms.taskfile.error & 0x04 /* ABRT */))
  113. /* Device without ATA IDENTIFY, try ATAPI. */
  114. return grub_atapi_identify (dev);
  115. else if (sts == 0x00)
  116. {
  117. *dev->present = 0;
  118. /* No device, return error but don't print message. */
  119. return GRUB_ERR_UNKNOWN_DEVICE;
  120. }
  121. else
  122. {
  123. *dev->present = 0;
  124. /* Other Error. */
  125. return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
  126. "device cannot be identified");
  127. }
  128. }
  129. /* Now it is certain that this is not an ATAPI device. */
  130. dev->atapi = 0;
  131. /* CHS is always supported. */
  132. dev->addr = GRUB_ATA_CHS;
  133. /* Check if LBA is supported. */
  134. if (info16[49] & grub_cpu_to_le16_compile_time ((1 << 9)))
  135. {
  136. /* Check if LBA48 is supported. */
  137. if (info16[83] & grub_cpu_to_le16_compile_time ((1 << 10)))
  138. dev->addr = GRUB_ATA_LBA48;
  139. else
  140. dev->addr = GRUB_ATA_LBA;
  141. }
  142. /* Determine the amount of sectors. */
  143. if (dev->addr != GRUB_ATA_LBA48)
  144. dev->size = grub_le_to_cpu32 (info32[30]);
  145. else
  146. dev->size = grub_le_to_cpu64 (info64[25]);
  147. if (info16[106] & grub_cpu_to_le16_compile_time ((1 << 12)))
  148. {
  149. grub_uint32_t secsize;
  150. secsize = grub_le_to_cpu32 (grub_get_unaligned32 (&info16[117]));
  151. if (secsize & (secsize - 1) || !secsize
  152. || secsize > 1048576)
  153. secsize = 256;
  154. for (dev->log_sector_size = 0;
  155. (1U << dev->log_sector_size) < secsize;
  156. dev->log_sector_size++);
  157. dev->log_sector_size++;
  158. }
  159. else
  160. dev->log_sector_size = 9;
  161. /* Read CHS information. */
  162. dev->cylinders = grub_le_to_cpu16 (info16[1]);
  163. dev->heads = grub_le_to_cpu16 (info16[3]);
  164. dev->sectors_per_track = grub_le_to_cpu16 (info16[6]);
  165. grub_ata_dumpinfo (dev, info16);
  166. grub_free (info16);
  167. return 0;
  168. }
  169. static grub_err_t
  170. grub_ata_setaddress (struct grub_ata *dev,
  171. struct grub_disk_ata_pass_through_parms *parms,
  172. grub_disk_addr_t sector,
  173. grub_size_t size,
  174. grub_ata_addressing_t addressing)
  175. {
  176. switch (addressing)
  177. {
  178. case GRUB_ATA_CHS:
  179. {
  180. unsigned int cylinder;
  181. unsigned int head;
  182. unsigned int sect;
  183. if (dev->sectors_per_track == 0
  184. || dev->heads == 0)
  185. return grub_error (GRUB_ERR_OUT_OF_RANGE,
  186. "sector %d cannot be addressed "
  187. "using CHS addressing", sector);
  188. /* Calculate the sector, cylinder and head to use. */
  189. sect = ((grub_uint32_t) sector % dev->sectors_per_track) + 1;
  190. cylinder = (((grub_uint32_t) sector / dev->sectors_per_track)
  191. / dev->heads);
  192. head = ((grub_uint32_t) sector / dev->sectors_per_track) % dev->heads;
  193. if (sect > dev->sectors_per_track
  194. || cylinder > dev->cylinders
  195. || head > dev->heads)
  196. return grub_error (GRUB_ERR_OUT_OF_RANGE,
  197. "sector %d cannot be addressed "
  198. "using CHS addressing", sector);
  199. parms->taskfile.disk = 0xE0 | head;
  200. parms->taskfile.sectnum = sect;
  201. parms->taskfile.cyllsb = cylinder & 0xFF;
  202. parms->taskfile.cylmsb = cylinder >> 8;
  203. break;
  204. }
  205. case GRUB_ATA_LBA:
  206. if (size == 256)
  207. size = 0;
  208. parms->taskfile.disk = 0xE0 | ((sector >> 24) & 0x0F);
  209. parms->taskfile.sectors = size;
  210. parms->taskfile.lba_low = sector & 0xFF;
  211. parms->taskfile.lba_mid = (sector >> 8) & 0xFF;
  212. parms->taskfile.lba_high = (sector >> 16) & 0xFF;
  213. break;
  214. case GRUB_ATA_LBA48:
  215. if (size == 65536)
  216. size = 0;
  217. parms->taskfile.disk = 0xE0;
  218. /* Set "Previous". */
  219. parms->taskfile.sectors = size & 0xFF;
  220. parms->taskfile.lba_low = sector & 0xFF;
  221. parms->taskfile.lba_mid = (sector >> 8) & 0xFF;
  222. parms->taskfile.lba_high = (sector >> 16) & 0xFF;
  223. /* Set "Current". */
  224. parms->taskfile.sectors48 = (size >> 8) & 0xFF;
  225. parms->taskfile.lba48_low = (sector >> 24) & 0xFF;
  226. parms->taskfile.lba48_mid = (sector >> 32) & 0xFF;
  227. parms->taskfile.lba48_high = (sector >> 40) & 0xFF;
  228. break;
  229. }
  230. return GRUB_ERR_NONE;
  231. }
  232. static grub_err_t
  233. grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector,
  234. grub_size_t size, char *buf, int rw)
  235. {
  236. struct grub_ata *ata = disk->data;
  237. grub_ata_addressing_t addressing = ata->addr;
  238. grub_size_t batch;
  239. int cmd, cmd_write;
  240. grub_size_t nsectors = 0;
  241. grub_dprintf("ata", "grub_ata_readwrite (size=%llu, rw=%d)\n",
  242. (unsigned long long) size, rw);
  243. if (addressing == GRUB_ATA_LBA48 && ((sector + size) >> 28) != 0)
  244. {
  245. if (ata->dma)
  246. {
  247. cmd = GRUB_ATA_CMD_READ_SECTORS_DMA_EXT;
  248. cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_DMA_EXT;
  249. }
  250. else
  251. {
  252. cmd = GRUB_ATA_CMD_READ_SECTORS_EXT;
  253. cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_EXT;
  254. }
  255. }
  256. else
  257. {
  258. if (addressing == GRUB_ATA_LBA48)
  259. addressing = GRUB_ATA_LBA;
  260. if (ata->dma)
  261. {
  262. cmd = GRUB_ATA_CMD_READ_SECTORS_DMA;
  263. cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_DMA;
  264. }
  265. else
  266. {
  267. cmd = GRUB_ATA_CMD_READ_SECTORS;
  268. cmd_write = GRUB_ATA_CMD_WRITE_SECTORS;
  269. }
  270. }
  271. if (addressing != GRUB_ATA_CHS)
  272. batch = 256;
  273. else
  274. batch = 1;
  275. while (nsectors < size)
  276. {
  277. struct grub_disk_ata_pass_through_parms parms;
  278. grub_err_t err;
  279. if (size - nsectors < batch)
  280. batch = size - nsectors;
  281. grub_dprintf("ata", "rw=%d, sector=%llu, batch=%llu\n", rw, (unsigned long long) sector, (unsigned long long) batch);
  282. grub_memset (&parms, 0, sizeof (parms));
  283. grub_ata_setaddress (ata, &parms, sector, batch, addressing);
  284. parms.taskfile.cmd = (! rw ? cmd : cmd_write);
  285. parms.buffer = buf;
  286. parms.size = batch << ata->log_sector_size;
  287. parms.write = rw;
  288. if (ata->dma)
  289. parms.dma = 1;
  290. err = ata->dev->readwrite (ata, &parms, 0);
  291. if (err)
  292. return err;
  293. if (parms.size != batch << ata->log_sector_size)
  294. return grub_error (GRUB_ERR_READ_ERROR, "incomplete read");
  295. buf += batch << ata->log_sector_size;
  296. sector += batch;
  297. nsectors += batch;
  298. }
  299. return GRUB_ERR_NONE;
  300. }
  301. static inline void
  302. grub_ata_real_close (struct grub_ata *ata)
  303. {
  304. if (ata->dev->close)
  305. ata->dev->close (ata);
  306. }
  307. static struct grub_ata *
  308. grub_ata_real_open (int id, int bus)
  309. {
  310. struct grub_ata *ata;
  311. grub_ata_dev_t p;
  312. ata = grub_zalloc (sizeof (*ata));
  313. if (!ata)
  314. return NULL;
  315. for (p = grub_ata_dev_list; p; p = p->next)
  316. {
  317. grub_err_t err;
  318. if (p->open (id, bus, ata))
  319. {
  320. grub_errno = GRUB_ERR_NONE;
  321. continue;
  322. }
  323. ata->dev = p;
  324. /* Use the IDENTIFY DEVICE command to query the device. */
  325. err = grub_ata_identify (ata);
  326. if (err)
  327. {
  328. if (!grub_errno)
  329. grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATA device");
  330. grub_free (ata);
  331. return NULL;
  332. }
  333. return ata;
  334. }
  335. grub_free (ata);
  336. grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATA device");
  337. return NULL;
  338. }
  339. /* Context for grub_ata_iterate. */
  340. struct grub_ata_iterate_ctx
  341. {
  342. grub_disk_dev_iterate_hook_t hook;
  343. void *hook_data;
  344. };
  345. /* Helper for grub_ata_iterate. */
  346. static int
  347. grub_ata_iterate_iter (int id, int bus, void *data)
  348. {
  349. struct grub_ata_iterate_ctx *ctx = data;
  350. struct grub_ata *ata;
  351. int ret;
  352. char devname[40];
  353. ata = grub_ata_real_open (id, bus);
  354. if (!ata)
  355. {
  356. grub_errno = GRUB_ERR_NONE;
  357. return 0;
  358. }
  359. if (ata->atapi)
  360. {
  361. grub_ata_real_close (ata);
  362. return 0;
  363. }
  364. grub_snprintf (devname, sizeof (devname),
  365. "%s%d", grub_scsi_names[id], bus);
  366. ret = ctx->hook (devname, ctx->hook_data);
  367. grub_ata_real_close (ata);
  368. return ret;
  369. }
  370. static int
  371. grub_ata_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
  372. grub_disk_pull_t pull)
  373. {
  374. struct grub_ata_iterate_ctx ctx = { hook, hook_data };
  375. grub_ata_dev_t p;
  376. for (p = grub_ata_dev_list; p; p = p->next)
  377. if (p->iterate && p->iterate (grub_ata_iterate_iter, &ctx, pull))
  378. return 1;
  379. return 0;
  380. }
  381. static grub_err_t
  382. grub_ata_open (const char *name, grub_disk_t disk)
  383. {
  384. unsigned id, bus;
  385. struct grub_ata *ata;
  386. for (id = 0; id < GRUB_SCSI_NUM_SUBSYSTEMS; id++)
  387. if (grub_strncmp (grub_scsi_names[id], name,
  388. grub_strlen (grub_scsi_names[id])) == 0
  389. && grub_isdigit (name[grub_strlen (grub_scsi_names[id])]))
  390. break;
  391. if (id == GRUB_SCSI_NUM_SUBSYSTEMS)
  392. return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk");
  393. bus = grub_strtoul (name + grub_strlen (grub_scsi_names[id]), 0, 0);
  394. ata = grub_ata_real_open (id, bus);
  395. if (!ata)
  396. return grub_errno;
  397. if (ata->atapi)
  398. return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk");
  399. disk->total_sectors = ata->size;
  400. disk->max_agglomerate = (ata->maxbuffer >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS));
  401. if (disk->max_agglomerate > (256U >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS - ata->log_sector_size)))
  402. disk->max_agglomerate = (256U >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS - ata->log_sector_size));
  403. disk->log_sector_size = ata->log_sector_size;
  404. disk->id = grub_make_scsi_id (id, bus, 0);
  405. disk->data = ata;
  406. return 0;
  407. }
  408. static void
  409. grub_ata_close (grub_disk_t disk)
  410. {
  411. struct grub_ata *ata = disk->data;
  412. grub_ata_real_close (ata);
  413. }
  414. static grub_err_t
  415. grub_ata_read (grub_disk_t disk, grub_disk_addr_t sector,
  416. grub_size_t size, char *buf)
  417. {
  418. return grub_ata_readwrite (disk, sector, size, buf, 0);
  419. }
  420. static grub_err_t
  421. grub_ata_write (grub_disk_t disk,
  422. grub_disk_addr_t sector,
  423. grub_size_t size,
  424. const char *buf)
  425. {
  426. return grub_ata_readwrite (disk, sector, size, (char *) buf, 1);
  427. }
  428. static struct grub_disk_dev grub_atadisk_dev =
  429. {
  430. .name = "ATA",
  431. .id = GRUB_DISK_DEVICE_ATA_ID,
  432. .iterate = grub_ata_iterate,
  433. .open = grub_ata_open,
  434. .close = grub_ata_close,
  435. .read = grub_ata_read,
  436. .write = grub_ata_write,
  437. .next = 0
  438. };
  439. /* ATAPI code. */
  440. static grub_err_t
  441. grub_atapi_read (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
  442. grub_size_t size, char *buf)
  443. {
  444. struct grub_ata *dev = scsi->data;
  445. struct grub_disk_ata_pass_through_parms parms;
  446. grub_err_t err;
  447. grub_dprintf("ata", "grub_atapi_read (size=%llu)\n", (unsigned long long) size);
  448. grub_memset (&parms, 0, sizeof (parms));
  449. parms.taskfile.disk = 0;
  450. parms.taskfile.features = 0;
  451. parms.taskfile.atapi_ireason = 0;
  452. parms.taskfile.atapi_cnthigh = size >> 8;
  453. parms.taskfile.atapi_cntlow = size & 0xff;
  454. parms.taskfile.cmd = GRUB_ATA_CMD_PACKET;
  455. parms.cmd = cmd;
  456. parms.cmdsize = cmdsize;
  457. parms.size = size;
  458. parms.buffer = buf;
  459. err = dev->dev->readwrite (dev, &parms, 0);
  460. if (err)
  461. return err;
  462. if (parms.size != size)
  463. return grub_error (GRUB_ERR_READ_ERROR, "incomplete ATAPI read");
  464. return GRUB_ERR_NONE;
  465. }
  466. static grub_err_t
  467. grub_atapi_write (struct grub_scsi *scsi __attribute__((unused)),
  468. grub_size_t cmdsize __attribute__((unused)),
  469. char *cmd __attribute__((unused)),
  470. grub_size_t size __attribute__((unused)),
  471. const char *buf __attribute__((unused)))
  472. {
  473. // XXX: scsi.mod does not use write yet.
  474. return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "ATAPI write not implemented");
  475. }
  476. static grub_err_t
  477. grub_atapi_open (int id, int bus, struct grub_scsi *scsi)
  478. {
  479. struct grub_ata *ata;
  480. ata = grub_ata_real_open (id, bus);
  481. if (!ata)
  482. return grub_errno;
  483. if (! ata->atapi)
  484. return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATAPI device");
  485. scsi->data = ata;
  486. scsi->luns = 1;
  487. return GRUB_ERR_NONE;
  488. }
  489. /* Context for grub_atapi_iterate. */
  490. struct grub_atapi_iterate_ctx
  491. {
  492. grub_scsi_dev_iterate_hook_t hook;
  493. void *hook_data;
  494. };
  495. /* Helper for grub_atapi_iterate. */
  496. static int
  497. grub_atapi_iterate_iter (int id, int bus, void *data)
  498. {
  499. struct grub_atapi_iterate_ctx *ctx = data;
  500. struct grub_ata *ata;
  501. int ret;
  502. ata = grub_ata_real_open (id, bus);
  503. if (!ata)
  504. {
  505. grub_errno = GRUB_ERR_NONE;
  506. return 0;
  507. }
  508. if (!ata->atapi)
  509. {
  510. grub_ata_real_close (ata);
  511. return 0;
  512. }
  513. ret = ctx->hook (id, bus, 1, ctx->hook_data);
  514. grub_ata_real_close (ata);
  515. return ret;
  516. }
  517. static int
  518. grub_atapi_iterate (grub_scsi_dev_iterate_hook_t hook, void *hook_data,
  519. grub_disk_pull_t pull)
  520. {
  521. struct grub_atapi_iterate_ctx ctx = { hook, hook_data };
  522. grub_ata_dev_t p;
  523. for (p = grub_ata_dev_list; p; p = p->next)
  524. if (p->iterate && p->iterate (grub_atapi_iterate_iter, &ctx, pull))
  525. return 1;
  526. return 0;
  527. }
  528. static void
  529. grub_atapi_close (grub_scsi_t disk)
  530. {
  531. struct grub_ata *ata = disk->data;
  532. grub_ata_real_close (ata);
  533. }
  534. void
  535. grub_ata_dev_register (grub_ata_dev_t dev)
  536. {
  537. dev->next = grub_ata_dev_list;
  538. grub_ata_dev_list = dev;
  539. }
  540. void
  541. grub_ata_dev_unregister (grub_ata_dev_t dev)
  542. {
  543. grub_ata_dev_t *p, q;
  544. for (p = &grub_ata_dev_list, q = *p; q; p = &(q->next), q = q->next)
  545. if (q == dev)
  546. {
  547. *p = q->next;
  548. break;
  549. }
  550. }
  551. static struct grub_scsi_dev grub_atapi_dev =
  552. {
  553. .iterate = grub_atapi_iterate,
  554. .open = grub_atapi_open,
  555. .close = grub_atapi_close,
  556. .read = grub_atapi_read,
  557. .write = grub_atapi_write,
  558. .next = 0
  559. };
  560. GRUB_MOD_INIT(ata)
  561. {
  562. grub_disk_dev_register (&grub_atadisk_dev);
  563. /* ATAPI devices are handled by scsi.mod. */
  564. grub_scsi_dev_register (&grub_atapi_dev);
  565. }
  566. GRUB_MOD_FINI(ata)
  567. {
  568. grub_scsi_dev_unregister (&grub_atapi_dev);
  569. grub_disk_dev_unregister (&grub_atadisk_dev);
  570. }