1 /* ata.c - ATA disk access. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
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.
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.
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/>.
22 #include <grub/disk.h>
24 #include <grub/time.h>
26 #include <grub/scsi.h>
28 /* At the moment, only two IDE ports are supported. */
29 static const int grub_ata_ioaddress
[] = { 0x1f0, 0x170 };
30 static const int grub_ata_ioaddress2
[] = { 0x3f6, 0x376 };
32 static struct grub_ata_device
*grub_ata_devices
;
36 grub_ata_wait_not_busy (struct grub_ata_device
*dev
, int milliseconds
)
38 /* ATA requires 400ns (after a write to CMD register) or
39 1 PIO cycle (after a DRQ block transfer) before
40 first check of BSY. */
44 while (grub_ata_regget (dev
, GRUB_ATA_REG_STATUS
) & GRUB_ATA_STATUS_BUSY
)
46 if (i
>= milliseconds
)
48 grub_dprintf ("ata", "timeout: %dms\n", milliseconds
);
49 return grub_error (GRUB_ERR_TIMEOUT
, "ATA timeout");
65 /* Wait for !BSY, DRQ. */
67 grub_ata_wait_drq (struct grub_ata_device
*dev
, int rw
,
70 if (grub_ata_wait_not_busy (dev
, milliseconds
))
73 /* !DRQ implies error condition. */
74 grub_uint8_t sts
= grub_ata_regget (dev
, GRUB_ATA_REG_STATUS
);
75 if ((sts
& (GRUB_ATA_STATUS_DRQ
| GRUB_ATA_STATUS_ERR
))
76 != GRUB_ATA_STATUS_DRQ
)
78 grub_dprintf ("ata", "ata error: status=0x%x, error=0x%x\n",
79 sts
, grub_ata_regget (dev
, GRUB_ATA_REG_ERROR
));
81 return grub_error (GRUB_ERR_READ_ERROR
, "ATA read error");
83 return grub_error (GRUB_ERR_WRITE_ERROR
, "ATA write error");
89 /* Byteorder has to be changed before strings can be read. */
91 grub_ata_strncpy (char *dst
, char *src
, grub_size_t len
)
93 grub_uint16_t
*src16
= (grub_uint16_t
*) src
;
94 grub_uint16_t
*dst16
= (grub_uint16_t
*) dst
;
97 for (i
= 0; i
< len
/ 2; i
++)
98 *(dst16
++) = grub_be_to_cpu16 (*(src16
++));
103 grub_ata_pio_read (struct grub_ata_device
*dev
, char *buf
, grub_size_t size
)
105 grub_uint16_t
*buf16
= (grub_uint16_t
*) buf
;
108 /* Read in the data, word by word. */
109 for (i
= 0; i
< size
/ 2; i
++)
110 buf16
[i
] = grub_le_to_cpu16 (grub_inw(dev
->ioaddress
+ GRUB_ATA_REG_DATA
));
114 grub_ata_pio_write (struct grub_ata_device
*dev
, char *buf
, grub_size_t size
)
116 grub_uint16_t
*buf16
= (grub_uint16_t
*) buf
;
119 /* Write the data, word by word. */
120 for (i
= 0; i
< size
/ 2; i
++)
121 grub_outw(grub_cpu_to_le16 (buf16
[i
]), dev
->ioaddress
+ GRUB_ATA_REG_DATA
);
125 grub_ata_dumpinfo (struct grub_ata_device
*dev
, char *info
)
129 /* The device information was read, dump it for debugging. */
130 grub_ata_strncpy (text
, info
+ 20, 20);
131 grub_dprintf ("ata", "Serial: %s\n", text
);
132 grub_ata_strncpy (text
, info
+ 46, 8);
133 grub_dprintf ("ata", "Firmware: %s\n", text
);
134 grub_ata_strncpy (text
, info
+ 54, 40);
135 grub_dprintf ("ata", "Model: %s\n", text
);
139 grub_dprintf ("ata", "Addressing: %d\n", dev
->addr
);
140 grub_dprintf ("ata", "Sectors: %lld\n", dev
->size
);
145 grub_atapi_identify (struct grub_ata_device
*dev
)
149 info
= grub_malloc (GRUB_DISK_SECTOR_SIZE
);
153 grub_ata_regset (dev
, GRUB_ATA_REG_DISK
, 0xE0 | dev
->device
<< 4);
154 if (grub_ata_check_ready (dev
))
160 grub_ata_regset (dev
, GRUB_ATA_REG_CMD
, GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE
);
163 if (grub_ata_wait_drq (dev
, 0, GRUB_ATA_TOUT_STD
))
168 grub_ata_pio_read (dev
, info
, GRUB_DISK_SECTOR_SIZE
);
172 grub_ata_dumpinfo (dev
, info
);
176 return GRUB_ERR_NONE
;
180 grub_atapi_wait_drq (struct grub_ata_device
*dev
,
181 grub_uint8_t ireason
,
184 /* Wait for !BSY, DRQ, ireason */
185 if (grub_ata_wait_not_busy (dev
, milliseconds
))
188 grub_uint8_t sts
= grub_ata_regget (dev
, GRUB_ATA_REG_STATUS
);
189 grub_uint8_t irs
= grub_ata_regget (dev
, GRUB_ATAPI_REG_IREASON
);
191 /* OK if DRQ is asserted and interrupt reason is as expected. */
192 if ((sts
& GRUB_ATA_STATUS_DRQ
)
193 && (irs
& GRUB_ATAPI_IREASON_MASK
) == ireason
)
194 return GRUB_ERR_NONE
;
196 /* !DRQ implies error condition. */
197 grub_dprintf ("ata", "atapi error: status=0x%x, ireason=0x%x, error=0x%x\n",
198 sts
, irs
, grub_ata_regget (dev
, GRUB_ATA_REG_ERROR
));
200 if (! (sts
& GRUB_ATA_STATUS_DRQ
)
201 && (irs
& GRUB_ATAPI_IREASON_MASK
) == GRUB_ATAPI_IREASON_ERROR
)
203 if (ireason
== GRUB_ATAPI_IREASON_CMD_OUT
)
204 return grub_error (GRUB_ERR_READ_ERROR
, "ATA PACKET command error");
206 return grub_error (GRUB_ERR_READ_ERROR
, "ATAPI read error");
209 return grub_error (GRUB_ERR_READ_ERROR
, "ATAPI protocol error");
213 grub_atapi_packet (struct grub_ata_device
*dev
, char *packet
,
216 grub_ata_regset (dev
, GRUB_ATA_REG_DISK
, dev
->device
<< 4);
217 if (grub_ata_check_ready (dev
))
220 /* Send ATA PACKET command. */
221 grub_ata_regset (dev
, GRUB_ATA_REG_FEATURES
, 0);
222 grub_ata_regset (dev
, GRUB_ATAPI_REG_IREASON
, 0);
223 grub_ata_regset (dev
, GRUB_ATAPI_REG_CNTHIGH
, size
>> 8);
224 grub_ata_regset (dev
, GRUB_ATAPI_REG_CNTLOW
, size
& 0xFF);
226 grub_ata_regset (dev
, GRUB_ATA_REG_CMD
, GRUB_ATA_CMD_PACKET
);
228 /* Wait for !BSY, DRQ, !I/O, C/D. */
229 if (grub_atapi_wait_drq (dev
, GRUB_ATAPI_IREASON_CMD_OUT
, GRUB_ATA_TOUT_STD
))
232 /* Write the packet. */
233 grub_ata_pio_write (dev
, packet
, 12);
235 return GRUB_ERR_NONE
;
239 grub_ata_identify (struct grub_ata_device
*dev
)
242 grub_uint16_t
*info16
;
244 info
= grub_malloc (GRUB_DISK_SECTOR_SIZE
);
248 info16
= (grub_uint16_t
*) info
;
250 grub_ata_regset (dev
, GRUB_ATA_REG_DISK
, 0xE0 | dev
->device
<< 4);
251 if (grub_ata_check_ready (dev
))
257 grub_ata_regset (dev
, GRUB_ATA_REG_CMD
, GRUB_ATA_CMD_IDENTIFY_DEVICE
);
260 if (grub_ata_wait_drq (dev
, 0, GRUB_ATA_TOUT_STD
))
262 if (grub_ata_regget (dev
, GRUB_ATA_REG_ERROR
) & 0x04) /* ABRT */
264 /* Device without ATA IDENTIFY, try ATAPI. */
266 grub_errno
= GRUB_ERR_NONE
;
267 return grub_atapi_identify (dev
);
273 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
,
274 "device can not be identified");
278 grub_ata_pio_read (dev
, info
, GRUB_DISK_SECTOR_SIZE
);
280 /* Now it is certain that this is not an ATAPI device. */
283 /* CHS is always supported. */
284 dev
->addr
= GRUB_ATA_CHS
;
286 /* Check if LBA is supported. */
287 if (info16
[49] & (1 << 9))
289 /* Check if LBA48 is supported. */
290 if (info16
[83] & (1 << 10))
291 dev
->addr
= GRUB_ATA_LBA48
;
293 dev
->addr
= GRUB_ATA_LBA
;
296 /* Determine the amount of sectors. */
297 if (dev
->addr
!= GRUB_ATA_LBA48
)
298 dev
->size
= grub_le_to_cpu32(*((grub_uint32_t
*) &info16
[60]));
300 dev
->size
= grub_le_to_cpu64(*((grub_uint64_t
*) &info16
[100]));
302 /* Read CHS information. */
303 dev
->cylinders
= info16
[1];
304 dev
->heads
= info16
[3];
305 dev
->sectors_per_track
= info16
[6];
307 grub_ata_dumpinfo (dev
, info
);
315 grub_ata_device_initialize (int port
, int device
, int addr
, int addr2
)
317 struct grub_ata_device
*dev
;
318 struct grub_ata_device
**devp
;
320 grub_dprintf ("ata", "detecting device %d,%d (0x%x, 0x%x)\n",
321 port
, device
, addr
, addr2
);
323 dev
= grub_malloc (sizeof(*dev
));
327 /* Setup the device information. */
329 dev
->device
= device
;
330 dev
->ioaddress
= addr
;
331 dev
->ioaddress2
= addr2
;
334 grub_ata_regset (dev
, GRUB_ATA_REG_DISK
, dev
->device
<< 4);
337 /* If status is 0x00, it is safe to assume that there
338 is no device (or only a !READY) device connected. */
339 grub_int8_t sts
= grub_ata_regget (dev
, GRUB_ATA_REG_STATUS
);
340 grub_dprintf ("ata", "status=0x%x\n", sts
);
347 /* Try to detect if the port is in use by writing to it,
348 waiting for a while and reading it again. If the value
349 was preserved, there is a device connected.
350 But this tests often detects a second (slave) device
351 connected to a SATA controller which supports only one
352 (master) device. In this case, the status register
353 check above usually works. */
354 grub_ata_regset (dev
, GRUB_ATA_REG_SECTORS
, 0x5A);
356 grub_int8_t sec
= grub_ata_regget (dev
, GRUB_ATA_REG_SECTORS
);
357 grub_dprintf ("ata", "sectors=0x%x\n", sec
);
364 /* Use the IDENTIFY DEVICE command to query the device. */
365 if (grub_ata_identify (dev
))
371 /* Register the device. */
372 for (devp
= &grub_ata_devices
; *devp
; devp
= &(*devp
)->next
);
379 grub_ata_pciinit (int bus
, int device
, int func
,
380 grub_pci_id_t pciid
__attribute__((unused
)))
382 static int compat_use
[2] = { 0 };
383 grub_pci_address_t addr
;
390 static int controller
= 0;
393 addr
= grub_pci_make_address (bus
, device
, func
, 2);
394 class = grub_pci_read (addr
);
396 /* Check if this class ID matches that of a PCI IDE Controller. */
397 if (class >> 16 != 0x0101)
400 for (i
= 0; i
< 2; i
++)
402 /* Set to 0 when the channel operated in compatibility mode. */
403 int compat
= (class >> (8 + 2 * i
)) & 1;
408 /* If the channel is in compatibility mode, just assign the
409 default registers. */
410 if (compat
== 0 && !compat_use
[i
])
412 rega
= grub_ata_ioaddress
[i
];
413 regb
= grub_ata_ioaddress2
[i
];
418 /* Read the BARs, which either contain a mmapped IO address
419 or the IO port address. */
420 addr
= grub_pci_make_address (bus
, device
, func
, 4 + 2 * i
);
421 bar1
= grub_pci_read (addr
);
422 addr
= grub_pci_make_address (bus
, device
, func
, 5 + 2 * i
);
423 bar2
= grub_pci_read (addr
);
425 /* Check if the BARs describe an IO region. */
426 if ((bar1
& 1) && (bar2
& 1))
434 "PCI dev (%d,%d,%d) compat=%d rega=0x%x regb=0x%x\n",
435 bus
, device
, func
, compat
, rega
, regb
);
439 grub_errno
= GRUB_ERR_NONE
;
440 grub_ata_device_initialize (controller
* 2 + i
, 0, rega
, regb
);
442 /* Most errors rised by grub_ata_device_initialize() are harmless.
443 They just indicate this particular drive is not responding, most
444 likely because it doesn't exist. We might want to ignore specific
445 error types here, instead of printing them. */
449 grub_errno
= GRUB_ERR_NONE
;
452 grub_ata_device_initialize (controller
* 2 + i
, 1, rega
, regb
);
458 grub_errno
= GRUB_ERR_NONE
;
469 grub_ata_initialize (void)
471 grub_pci_iterate (grub_ata_pciinit
);
477 grub_ata_setlba (struct grub_ata_device
*dev
, grub_disk_addr_t sector
,
480 grub_ata_regset (dev
, GRUB_ATA_REG_SECTORS
, size
);
481 grub_ata_regset (dev
, GRUB_ATA_REG_LBALOW
, sector
& 0xFF);
482 grub_ata_regset (dev
, GRUB_ATA_REG_LBAMID
, (sector
>> 8) & 0xFF);
483 grub_ata_regset (dev
, GRUB_ATA_REG_LBAHIGH
, (sector
>> 16) & 0xFF);
487 grub_ata_setaddress (struct grub_ata_device
*dev
,
488 grub_ata_addressing_t addressing
,
489 grub_disk_addr_t sector
,
496 unsigned int cylinder
;
500 /* Calculate the sector, cylinder and head to use. */
501 sect
= ((grub_uint32_t
) sector
% dev
->sectors_per_track
) + 1;
502 cylinder
= (((grub_uint32_t
) sector
/ dev
->sectors_per_track
)
504 head
= ((grub_uint32_t
) sector
/ dev
->sectors_per_track
) % dev
->heads
;
506 if (sect
> dev
->sectors_per_track
507 || cylinder
> dev
->cylinders
508 || head
> dev
->heads
)
509 return grub_error (GRUB_ERR_OUT_OF_RANGE
,
510 "sector %d can not be addressed "
511 "using CHS addressing", sector
);
513 grub_ata_regset (dev
, GRUB_ATA_REG_DISK
, (dev
->device
<< 4) | head
);
514 if (grub_ata_check_ready (dev
))
517 grub_ata_regset (dev
, GRUB_ATA_REG_SECTNUM
, sect
);
518 grub_ata_regset (dev
, GRUB_ATA_REG_CYLLSB
, cylinder
& 0xFF);
519 grub_ata_regset (dev
, GRUB_ATA_REG_CYLMSB
, cylinder
>> 8);
527 grub_ata_regset (dev
, GRUB_ATA_REG_DISK
,
528 0xE0 | (dev
->device
<< 4) | ((sector
>> 24) & 0x0F));
529 if (grub_ata_check_ready (dev
))
532 grub_ata_setlba (dev
, sector
, size
);
539 grub_ata_regset (dev
, GRUB_ATA_REG_DISK
, 0xE0 | (dev
->device
<< 4));
540 if (grub_ata_check_ready (dev
))
543 /* Set "Previous". */
544 grub_ata_setlba (dev
, sector
>> 24, size
>> 8);
546 grub_ata_setlba (dev
, sector
, size
);
551 return GRUB_ERR_NONE
;
555 grub_ata_readwrite (grub_disk_t disk
, grub_disk_addr_t sector
,
556 grub_size_t size
, char *buf
, int rw
)
558 struct grub_ata_device
*dev
= (struct grub_ata_device
*) disk
->data
;
560 grub_dprintf("ata", "grub_ata_readwrite (size=%u, rw=%d)\n", size
, rw
);
562 grub_ata_addressing_t addressing
= dev
->addr
;
566 if (addressing
== GRUB_ATA_LBA48
&& ((sector
+ size
) >> 28) != 0)
569 cmd
= GRUB_ATA_CMD_READ_SECTORS_EXT
;
570 cmd_write
= GRUB_ATA_CMD_WRITE_SECTORS_EXT
;
574 if (addressing
== GRUB_ATA_LBA48
)
575 addressing
= GRUB_ATA_LBA
;
577 cmd
= GRUB_ATA_CMD_READ_SECTORS
;
578 cmd_write
= GRUB_ATA_CMD_WRITE_SECTORS
;
581 grub_size_t nsectors
= 0;
582 while (nsectors
< size
)
584 if (size
- nsectors
< batch
)
585 batch
= size
- nsectors
;
587 grub_dprintf("ata", "rw=%d, sector=%llu, batch=%u\n", rw
, sector
, batch
);
589 /* Send read/write commmand. */
590 if (grub_ata_setaddress (dev
, addressing
, sector
, batch
))
593 grub_ata_regset (dev
, GRUB_ATA_REG_CMD
, (! rw
? cmd
: cmd_write
));
596 for (sect
= 0; sect
< batch
; sect
++)
598 /* Wait for !BSY, DRQ. */
599 if (grub_ata_wait_drq (dev
, rw
, GRUB_ATA_TOUT_DATA
))
604 grub_ata_pio_read (dev
, buf
, GRUB_DISK_SECTOR_SIZE
);
606 grub_ata_pio_write (dev
, buf
, GRUB_DISK_SECTOR_SIZE
);
608 buf
+= GRUB_DISK_SECTOR_SIZE
;
613 /* Check for write error. */
614 if (grub_ata_wait_not_busy (dev
, GRUB_ATA_TOUT_DATA
))
617 if (grub_ata_regget (dev
, GRUB_ATA_REG_STATUS
)
618 & (GRUB_ATA_STATUS_DRQ
| GRUB_ATA_STATUS_ERR
))
619 return grub_error (GRUB_ERR_WRITE_ERROR
, "ATA write error");
626 return GRUB_ERR_NONE
;
632 grub_ata_iterate (int (*hook
) (const char *name
))
634 struct grub_ata_device
*dev
;
636 for (dev
= grub_ata_devices
; dev
; dev
= dev
->next
)
639 grub_sprintf (devname
, "ata%d", dev
->port
* 2 + dev
->device
);
652 grub_ata_open (const char *name
, grub_disk_t disk
)
654 struct grub_ata_device
*dev
;
656 for (dev
= grub_ata_devices
; dev
; dev
= dev
->next
)
659 grub_sprintf (devname
, "ata%d", dev
->port
* 2 + dev
->device
);
660 if (grub_strcmp (name
, devname
) == 0)
665 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "Can't open device");
668 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "not an ATA harddisk");
670 disk
->total_sectors
= dev
->size
;
672 disk
->id
= (unsigned long) dev
;
674 disk
->has_partitions
= 1;
681 grub_ata_close (grub_disk_t disk
__attribute__((unused
)))
687 grub_ata_read (grub_disk_t disk
, grub_disk_addr_t sector
,
688 grub_size_t size
, char *buf
)
690 return grub_ata_readwrite (disk
, sector
, size
, buf
, 0);
694 grub_ata_write (grub_disk_t disk
,
695 grub_disk_addr_t sector
,
699 return grub_ata_readwrite (disk
, sector
, size
, (char *) buf
, 1);
702 static struct grub_disk_dev grub_atadisk_dev
=
705 .id
= GRUB_DISK_DEVICE_ATA_ID
,
706 .iterate
= grub_ata_iterate
,
707 .open
= grub_ata_open
,
708 .close
= grub_ata_close
,
709 .read
= grub_ata_read
,
710 .write
= grub_ata_write
,
719 grub_atapi_iterate (int (*hook
) (const char *name
, int luns
))
721 struct grub_ata_device
*dev
;
723 for (dev
= grub_ata_devices
; dev
; dev
= dev
->next
)
726 grub_sprintf (devname
, "ata%d", dev
->port
* 2 + dev
->device
);
731 if (hook (devname
, 1))
740 grub_atapi_read (struct grub_scsi
*scsi
,
741 grub_size_t cmdsize
__attribute__((unused
)),
742 char *cmd
, grub_size_t size
, char *buf
)
744 struct grub_ata_device
*dev
= (struct grub_ata_device
*) scsi
->data
;
746 grub_dprintf("ata", "grub_atapi_read (size=%u)\n", size
);
748 if (grub_atapi_packet (dev
, cmd
, size
))
751 grub_size_t nread
= 0;
754 /* Wait for !BSY, DRQ, I/O, !C/D. */
755 if (grub_atapi_wait_drq (dev
, GRUB_ATAPI_IREASON_DATA_IN
, GRUB_ATA_TOUT_DATA
))
758 /* Get byte count for this DRQ assertion. */
759 unsigned cnt
= grub_ata_regget (dev
, GRUB_ATAPI_REG_CNTHIGH
) << 8
760 | grub_ata_regget (dev
, GRUB_ATAPI_REG_CNTLOW
);
761 grub_dprintf("ata", "DRQ count=%u\n", cnt
);
763 /* Count of last transfer may be uneven. */
764 if (! (0 < cnt
&& cnt
<= size
- nread
&& (! (cnt
& 1) || cnt
== size
- nread
)))
765 return grub_error (GRUB_ERR_READ_ERROR
, "Invalid ATAPI transfer count");
768 grub_ata_pio_read (dev
, buf
+ nread
, cnt
);
771 buf
[nread
+ cnt
- 1] = (char) grub_le_to_cpu16 (grub_inw (dev
->ioaddress
+ GRUB_ATA_REG_DATA
));
776 return GRUB_ERR_NONE
;
780 grub_atapi_write (struct grub_scsi
*scsi
__attribute__((unused
)),
781 grub_size_t cmdsize
__attribute__((unused
)),
782 char *cmd
__attribute__((unused
)),
783 grub_size_t size
__attribute__((unused
)),
784 char *buf
__attribute__((unused
)))
786 // XXX: scsi.mod does not use write yet.
787 return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET
, "ATAPI write not implemented");
791 grub_atapi_open (const char *name
, struct grub_scsi
*scsi
)
793 struct grub_ata_device
*dev
;
794 struct grub_ata_device
*devfnd
= 0;
796 for (dev
= grub_ata_devices
; dev
; dev
= dev
->next
)
799 grub_sprintf (devname
, "ata%d", dev
->port
* 2 + dev
->device
);
801 if (!grub_strcmp (devname
, name
))
808 grub_dprintf ("ata", "opening ATAPI dev `%s'\n", name
);
811 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "No such ATAPI device");
815 return GRUB_ERR_NONE
;
819 grub_atapi_close (struct grub_scsi
*scsi
)
821 grub_free (scsi
->name
);
824 static struct grub_scsi_dev grub_atapi_dev
=
827 .iterate
= grub_atapi_iterate
,
828 .open
= grub_atapi_open
,
829 .close
= grub_atapi_close
,
830 .read
= grub_atapi_read
,
831 .write
= grub_atapi_write
838 (void) mod
; /* To stop warning. */
840 /* To prevent two drivers operating on the same disks. */
841 grub_disk_firmware_is_tainted
= 1;
842 if (grub_disk_firmware_fini
)
844 grub_disk_firmware_fini ();
845 grub_disk_firmware_fini
= NULL
;
848 /* ATA initialization. */
849 grub_ata_initialize ();
851 grub_disk_dev_register (&grub_atadisk_dev
);
853 /* ATAPI devices are handled by scsi.mod. */
854 grub_scsi_dev_register (&grub_atapi_dev
);
859 grub_scsi_dev_unregister (&grub_atapi_dev
);
860 grub_disk_dev_unregister (&grub_atadisk_dev
);