ata.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  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. dev->log_sector_size = grub_log2ull (secsize) + 1;
  155. }
  156. else
  157. dev->log_sector_size = 9;
  158. /* Read CHS information. */
  159. dev->cylinders = grub_le_to_cpu16 (info16[1]);
  160. dev->heads = grub_le_to_cpu16 (info16[3]);
  161. dev->sectors_per_track = grub_le_to_cpu16 (info16[6]);
  162. grub_ata_dumpinfo (dev, info16);
  163. grub_free (info16);
  164. return 0;
  165. }
  166. static grub_err_t
  167. grub_ata_setaddress (struct grub_ata *dev,
  168. struct grub_disk_ata_pass_through_parms *parms,
  169. grub_disk_addr_t sector,
  170. grub_size_t size,
  171. grub_ata_addressing_t addressing)
  172. {
  173. switch (addressing)
  174. {
  175. case GRUB_ATA_CHS:
  176. {
  177. unsigned int cylinder;
  178. unsigned int head;
  179. unsigned int sect;
  180. if (dev->sectors_per_track == 0
  181. || dev->heads == 0)
  182. return grub_error (GRUB_ERR_OUT_OF_RANGE,
  183. "sector %" PRIxGRUB_UINT64_T " cannot be "
  184. "addressed using CHS addressing",
  185. sector);
  186. /* Calculate the sector, cylinder and head to use. */
  187. sect = ((grub_uint32_t) sector % dev->sectors_per_track) + 1;
  188. cylinder = (((grub_uint32_t) sector / dev->sectors_per_track)
  189. / dev->heads);
  190. head = ((grub_uint32_t) sector / dev->sectors_per_track) % dev->heads;
  191. if (sect > dev->sectors_per_track
  192. || cylinder > dev->cylinders
  193. || head > dev->heads)
  194. return grub_error (GRUB_ERR_OUT_OF_RANGE,
  195. "sector %" PRIxGRUB_UINT64_T " cannot be "
  196. "addressed using CHS addressing",
  197. sector);
  198. parms->taskfile.disk = 0xE0 | head;
  199. parms->taskfile.sectnum = sect;
  200. parms->taskfile.cyllsb = cylinder & 0xFF;
  201. parms->taskfile.cylmsb = cylinder >> 8;
  202. break;
  203. }
  204. case GRUB_ATA_LBA:
  205. if (size == 256)
  206. size = 0;
  207. parms->taskfile.disk = 0xE0 | ((sector >> 24) & 0x0F);
  208. parms->taskfile.sectors = size;
  209. parms->taskfile.lba_low = sector & 0xFF;
  210. parms->taskfile.lba_mid = (sector >> 8) & 0xFF;
  211. parms->taskfile.lba_high = (sector >> 16) & 0xFF;
  212. break;
  213. case GRUB_ATA_LBA48:
  214. if (size == 65536)
  215. size = 0;
  216. parms->taskfile.disk = 0xE0;
  217. /* Set "Previous". */
  218. parms->taskfile.sectors = size & 0xFF;
  219. parms->taskfile.lba_low = sector & 0xFF;
  220. parms->taskfile.lba_mid = (sector >> 8) & 0xFF;
  221. parms->taskfile.lba_high = (sector >> 16) & 0xFF;
  222. /* Set "Current". */
  223. parms->taskfile.sectors48 = (size >> 8) & 0xFF;
  224. parms->taskfile.lba48_low = (sector >> 24) & 0xFF;
  225. parms->taskfile.lba48_mid = (sector >> 32) & 0xFF;
  226. parms->taskfile.lba48_high = (sector >> 40) & 0xFF;
  227. break;
  228. }
  229. return GRUB_ERR_NONE;
  230. }
  231. static grub_err_t
  232. grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector,
  233. grub_size_t size, char *buf, int rw)
  234. {
  235. struct grub_ata *ata = disk->data;
  236. grub_ata_addressing_t addressing = ata->addr;
  237. grub_size_t batch;
  238. int cmd, cmd_write;
  239. grub_size_t nsectors = 0;
  240. grub_dprintf("ata", "grub_ata_readwrite (size=%llu, rw=%d)\n",
  241. (unsigned long long) size, rw);
  242. if (addressing == GRUB_ATA_LBA48 && ((sector + size) >> 28) != 0)
  243. {
  244. if (ata->dma)
  245. {
  246. cmd = GRUB_ATA_CMD_READ_SECTORS_DMA_EXT;
  247. cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_DMA_EXT;
  248. }
  249. else
  250. {
  251. cmd = GRUB_ATA_CMD_READ_SECTORS_EXT;
  252. cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_EXT;
  253. }
  254. }
  255. else
  256. {
  257. if (addressing == GRUB_ATA_LBA48)
  258. addressing = GRUB_ATA_LBA;
  259. if (ata->dma)
  260. {
  261. cmd = GRUB_ATA_CMD_READ_SECTORS_DMA;
  262. cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_DMA;
  263. }
  264. else
  265. {
  266. cmd = GRUB_ATA_CMD_READ_SECTORS;
  267. cmd_write = GRUB_ATA_CMD_WRITE_SECTORS;
  268. }
  269. }
  270. if (addressing != GRUB_ATA_CHS)
  271. batch = 256;
  272. else
  273. batch = 1;
  274. while (nsectors < size)
  275. {
  276. struct grub_disk_ata_pass_through_parms parms;
  277. grub_err_t err;
  278. if (size - nsectors < batch)
  279. batch = size - nsectors;
  280. grub_dprintf("ata", "rw=%d, sector=%llu, batch=%llu\n", rw, (unsigned long long) sector, (unsigned long long) batch);
  281. grub_memset (&parms, 0, sizeof (parms));
  282. grub_ata_setaddress (ata, &parms, sector, batch, addressing);
  283. parms.taskfile.cmd = (! rw ? cmd : cmd_write);
  284. parms.buffer = buf;
  285. parms.size = batch << ata->log_sector_size;
  286. parms.write = rw;
  287. if (ata->dma)
  288. parms.dma = 1;
  289. err = ata->dev->readwrite (ata, &parms, 0);
  290. if (err)
  291. return err;
  292. if (parms.size != batch << ata->log_sector_size)
  293. return grub_error (GRUB_ERR_READ_ERROR, "incomplete read");
  294. buf += batch << ata->log_sector_size;
  295. sector += batch;
  296. nsectors += batch;
  297. }
  298. return GRUB_ERR_NONE;
  299. }
  300. static inline void
  301. grub_ata_real_close (struct grub_ata *ata)
  302. {
  303. if (ata->dev->close)
  304. ata->dev->close (ata);
  305. }
  306. static struct grub_ata *
  307. grub_ata_real_open (int id, int bus)
  308. {
  309. struct grub_ata *ata;
  310. grub_ata_dev_t p;
  311. ata = grub_zalloc (sizeof (*ata));
  312. if (!ata)
  313. return NULL;
  314. for (p = grub_ata_dev_list; p; p = p->next)
  315. {
  316. grub_err_t err;
  317. if (p->open (id, bus, ata))
  318. {
  319. grub_errno = GRUB_ERR_NONE;
  320. continue;
  321. }
  322. ata->dev = p;
  323. /* Use the IDENTIFY DEVICE command to query the device. */
  324. err = grub_ata_identify (ata);
  325. if (err)
  326. {
  327. if (!grub_errno)
  328. grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATA device");
  329. grub_free (ata);
  330. return NULL;
  331. }
  332. return ata;
  333. }
  334. grub_free (ata);
  335. grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATA device");
  336. return NULL;
  337. }
  338. /* Context for grub_ata_iterate. */
  339. struct grub_ata_iterate_ctx
  340. {
  341. grub_disk_dev_iterate_hook_t hook;
  342. void *hook_data;
  343. };
  344. /* Helper for grub_ata_iterate. */
  345. static int
  346. grub_ata_iterate_iter (int id, int bus, void *data)
  347. {
  348. struct grub_ata_iterate_ctx *ctx = data;
  349. struct grub_ata *ata;
  350. int ret;
  351. char devname[40];
  352. ata = grub_ata_real_open (id, bus);
  353. if (!ata)
  354. {
  355. grub_errno = GRUB_ERR_NONE;
  356. return 0;
  357. }
  358. if (ata->atapi)
  359. {
  360. grub_ata_real_close (ata);
  361. return 0;
  362. }
  363. grub_snprintf (devname, sizeof (devname),
  364. "%s%d", grub_scsi_names[id], bus);
  365. ret = ctx->hook (devname, ctx->hook_data);
  366. grub_ata_real_close (ata);
  367. return ret;
  368. }
  369. static int
  370. grub_ata_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
  371. grub_disk_pull_t pull)
  372. {
  373. struct grub_ata_iterate_ctx ctx = { hook, hook_data };
  374. grub_ata_dev_t p;
  375. for (p = grub_ata_dev_list; p; p = p->next)
  376. if (p->iterate && p->iterate (grub_ata_iterate_iter, &ctx, pull))
  377. return 1;
  378. return 0;
  379. }
  380. static grub_err_t
  381. grub_ata_open (const char *name, grub_disk_t disk)
  382. {
  383. unsigned id, bus;
  384. struct grub_ata *ata;
  385. for (id = 0; id < GRUB_SCSI_NUM_SUBSYSTEMS; id++)
  386. if (grub_strncmp (grub_scsi_names[id], name,
  387. grub_strlen (grub_scsi_names[id])) == 0
  388. && grub_isdigit (name[grub_strlen (grub_scsi_names[id])]))
  389. break;
  390. if (id == GRUB_SCSI_NUM_SUBSYSTEMS)
  391. return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk");
  392. bus = grub_strtoul (name + grub_strlen (grub_scsi_names[id]), 0, 0);
  393. ata = grub_ata_real_open (id, bus);
  394. if (!ata)
  395. return grub_errno;
  396. if (ata->atapi)
  397. return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk");
  398. disk->total_sectors = ata->size;
  399. disk->max_agglomerate = (ata->maxbuffer >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS));
  400. if (disk->max_agglomerate > (256U >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS - ata->log_sector_size)))
  401. disk->max_agglomerate = (256U >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS - ata->log_sector_size));
  402. disk->log_sector_size = ata->log_sector_size;
  403. disk->id = grub_make_scsi_id (id, bus, 0);
  404. disk->data = ata;
  405. return 0;
  406. }
  407. static void
  408. grub_ata_close (grub_disk_t disk)
  409. {
  410. struct grub_ata *ata = disk->data;
  411. grub_ata_real_close (ata);
  412. }
  413. static grub_err_t
  414. grub_ata_read (grub_disk_t disk, grub_disk_addr_t sector,
  415. grub_size_t size, char *buf)
  416. {
  417. return grub_ata_readwrite (disk, sector, size, buf, 0);
  418. }
  419. static grub_err_t
  420. grub_ata_write (grub_disk_t disk,
  421. grub_disk_addr_t sector,
  422. grub_size_t size,
  423. const char *buf)
  424. {
  425. return grub_ata_readwrite (disk, sector, size, (char *) buf, 1);
  426. }
  427. static struct grub_disk_dev grub_atadisk_dev =
  428. {
  429. .name = "ATA",
  430. .id = GRUB_DISK_DEVICE_ATA_ID,
  431. .disk_iterate = grub_ata_iterate,
  432. .disk_open = grub_ata_open,
  433. .disk_close = grub_ata_close,
  434. .disk_read = grub_ata_read,
  435. .disk_write = grub_ata_write,
  436. .next = 0
  437. };
  438. /* ATAPI code. */
  439. static grub_err_t
  440. grub_atapi_read (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
  441. grub_size_t size, char *buf)
  442. {
  443. struct grub_ata *dev = scsi->data;
  444. struct grub_disk_ata_pass_through_parms parms;
  445. grub_err_t err;
  446. grub_dprintf("ata", "grub_atapi_read (size=%llu)\n", (unsigned long long) size);
  447. grub_memset (&parms, 0, sizeof (parms));
  448. parms.taskfile.disk = 0;
  449. parms.taskfile.features = 0;
  450. parms.taskfile.atapi_ireason = 0;
  451. parms.taskfile.atapi_cnthigh = size >> 8;
  452. parms.taskfile.atapi_cntlow = size & 0xff;
  453. parms.taskfile.cmd = GRUB_ATA_CMD_PACKET;
  454. parms.cmd = cmd;
  455. parms.cmdsize = cmdsize;
  456. parms.size = size;
  457. parms.buffer = buf;
  458. err = dev->dev->readwrite (dev, &parms, 0);
  459. if (err)
  460. return err;
  461. if (parms.size != size)
  462. return grub_error (GRUB_ERR_READ_ERROR, "incomplete ATAPI read");
  463. return GRUB_ERR_NONE;
  464. }
  465. static grub_err_t
  466. grub_atapi_write (struct grub_scsi *scsi __attribute__((unused)),
  467. grub_size_t cmdsize __attribute__((unused)),
  468. char *cmd __attribute__((unused)),
  469. grub_size_t size __attribute__((unused)),
  470. const char *buf __attribute__((unused)))
  471. {
  472. // XXX: scsi.mod does not use write yet.
  473. return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "ATAPI write not implemented");
  474. }
  475. static grub_err_t
  476. grub_atapi_open (int id, int bus, struct grub_scsi *scsi)
  477. {
  478. struct grub_ata *ata;
  479. ata = grub_ata_real_open (id, bus);
  480. if (!ata)
  481. return grub_errno;
  482. if (! ata->atapi)
  483. return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATAPI device");
  484. scsi->data = ata;
  485. scsi->luns = 1;
  486. return GRUB_ERR_NONE;
  487. }
  488. /* Context for grub_atapi_iterate. */
  489. struct grub_atapi_iterate_ctx
  490. {
  491. grub_scsi_dev_iterate_hook_t hook;
  492. void *hook_data;
  493. };
  494. /* Helper for grub_atapi_iterate. */
  495. static int
  496. grub_atapi_iterate_iter (int id, int bus, void *data)
  497. {
  498. struct grub_atapi_iterate_ctx *ctx = data;
  499. struct grub_ata *ata;
  500. int ret;
  501. ata = grub_ata_real_open (id, bus);
  502. if (!ata)
  503. {
  504. grub_errno = GRUB_ERR_NONE;
  505. return 0;
  506. }
  507. if (!ata->atapi)
  508. {
  509. grub_ata_real_close (ata);
  510. return 0;
  511. }
  512. ret = ctx->hook (id, bus, 1, ctx->hook_data);
  513. grub_ata_real_close (ata);
  514. return ret;
  515. }
  516. static int
  517. grub_atapi_iterate (grub_scsi_dev_iterate_hook_t hook, void *hook_data,
  518. grub_disk_pull_t pull)
  519. {
  520. struct grub_atapi_iterate_ctx ctx = { hook, hook_data };
  521. grub_ata_dev_t p;
  522. for (p = grub_ata_dev_list; p; p = p->next)
  523. if (p->iterate && p->iterate (grub_atapi_iterate_iter, &ctx, pull))
  524. return 1;
  525. return 0;
  526. }
  527. static void
  528. grub_atapi_close (grub_scsi_t disk)
  529. {
  530. struct grub_ata *ata = disk->data;
  531. grub_ata_real_close (ata);
  532. }
  533. void
  534. grub_ata_dev_register (grub_ata_dev_t dev)
  535. {
  536. dev->next = grub_ata_dev_list;
  537. grub_ata_dev_list = dev;
  538. }
  539. void
  540. grub_ata_dev_unregister (grub_ata_dev_t dev)
  541. {
  542. grub_ata_dev_t *p, q;
  543. for (p = &grub_ata_dev_list, q = *p; q; p = &(q->next), q = q->next)
  544. if (q == dev)
  545. {
  546. *p = q->next;
  547. break;
  548. }
  549. }
  550. static struct grub_scsi_dev grub_atapi_dev =
  551. {
  552. .iterate = grub_atapi_iterate,
  553. .open = grub_atapi_open,
  554. .close = grub_atapi_close,
  555. .read = grub_atapi_read,
  556. .write = grub_atapi_write,
  557. .next = 0
  558. };
  559. GRUB_MOD_INIT(ata)
  560. {
  561. grub_disk_dev_register (&grub_atadisk_dev);
  562. /* ATAPI devices are handled by scsi.mod. */
  563. grub_scsi_dev_register (&grub_atapi_dev);
  564. }
  565. GRUB_MOD_FINI(ata)
  566. {
  567. grub_scsi_dev_unregister (&grub_atapi_dev);
  568. grub_disk_dev_unregister (&grub_atadisk_dev);
  569. }