Index: conf/i386-pc.rmk =================================================================== --- conf/i386-pc.rmk (revision 1802) +++ conf/i386-pc.rmk (working copy) @@ -163,7 +163,7 @@ pkglib_MODULES = biosdisk.mod _chain.mod vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \ videotest.mod play.mod bitmap.mod tga.mod cpuid.mod serial.mod \ ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod \ - aout.mod _bsd.mod bsd.mod pxe.mod pxecmd.mod + aout.mod _bsd.mod bsd.mod pxe.mod pxecmd.mod scsi.mod # For biosdisk.mod. biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c @@ -340,4 +340,9 @@ pxecmd_mod_SOURCES = commands/i386/pc/px pxecmd_mod_CFLAGS = $(COMMON_CFLAGS) pxecmd_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For scsi.mod +scsi_mod_SOURCES = disk/scsi.c +scsi_mod_CFLAGS = $(COMMON_CFLAGS) +scsi_mod_LDFLAGS = $(COMMON_LDFLAGS) + include $(srcdir)/conf/common.mk Index: disk/scsi.c =================================================================== --- disk/scsi.c (revision 0) +++ disk/scsi.c (revision 0) @@ -0,0 +1,377 @@ +/* scsi.c - scsi support. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static grub_scsi_dev_t grub_scsi_dev_list; + +void +grub_scsi_dev_register (grub_scsi_dev_t dev) +{ + dev->next = grub_scsi_dev_list; + grub_scsi_dev_list = dev; +} + +void +grub_scsi_dev_unregister (grub_scsi_dev_t dev) +{ + grub_scsi_dev_t *p, q; + + for (p = &grub_scsi_dev_list, q = *p; q; p = &(q->next), q = q->next) + if (q == dev) + { + *p = q->next; + break; + } +} + + +/* Determine the the device is removable and the type of the device + SCSI. */ +static grub_err_t +grub_scsi_inquiry (grub_scsi_t scsi) +{ + struct grub_scsi_inquiry iq; + struct grub_scsi_inquiry_data iqd; + grub_err_t err; + + iq.opcode = grub_scsi_cmd_inquiry; + iq.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT; + iq.reserved = 0; + iq.alloc_length = 0x24; /* XXX: Hardcoded for now */ + iq.reserved2 = 0; + + err = scsi->dev->read (scsi, sizeof (iq), (char *) &iq, + sizeof (iqd), (char *) &iqd); + if (err) + return err; + + scsi->devtype = iqd.devtype & GRUB_SCSI_DEVTYPE_MASK; + scsi->removable = iqd.rmb >> GRUB_SCSI_REMOVABLE_BIT; + + return GRUB_ERR_NONE; +} + +/* Read the capacity and block size of SCSI. */ +static grub_err_t +grub_scsi_read_capacity (grub_scsi_t scsi) +{ + struct grub_scsi_read_capacity rc; + struct grub_scsi_read_capacity_data rcd; + grub_err_t err; + + rc.opcode = grub_scsi_cmd_read_capacity; + rc.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT; + grub_memset (rc.reserved, 0, sizeof (rc.reserved)); + + err = scsi->dev->read (scsi, sizeof (rc), (char *) &rc, + sizeof (rcd), (char *) &rcd); + if (err) + return err; + + scsi->size = grub_be_to_cpu32 (rcd.size); + scsi->blocksize = grub_be_to_cpu32 (rcd.blocksize); + + return GRUB_ERR_NONE; +} + +/* Send a SCSI request for DISK: read SIZE sectors starting with + sector SECTOR to BUF. */ +static grub_err_t +grub_scsi_read10 (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + grub_scsi_t scsi; + struct grub_scsi_read10 rd; + + scsi = disk->data; + + rd.opcode = grub_scsi_cmd_read10; + rd.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT; + rd.lba = grub_cpu_to_be32 (sector); + rd.reserved = 0; + rd.size = grub_cpu_to_be16 (size); + rd.reserved2 = 0; + rd.pad = 0; + + return scsi->dev->read (scsi, sizeof (rd), (char *) &rd, size * 512, buf); +} + +/* Send a SCSI request for DISK: read SIZE sectors starting with + sector SECTOR to BUF. */ +static grub_err_t +grub_scsi_read12 (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + grub_scsi_t scsi; + struct grub_scsi_read12 rd; + + scsi = disk->data; + + rd.opcode = grub_scsi_cmd_read12; + rd.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT; + rd.lba = grub_cpu_to_be32 (sector); + rd.size = grub_cpu_to_be32 (size); + rd.reserved = 0; + rd.control = 0; + + return scsi->dev->read (scsi, sizeof (rd), (char *) &rd, size * 512, buf); +} + +/* Send a SCSI request for DISK: write the data stored in BUF to SIZE + sectors starting with SECTOR. */ +static grub_err_t +grub_scsi_write10 (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + grub_scsi_t scsi; + struct grub_scsi_write10 wr; + + scsi = disk->data; + + wr.opcode = grub_scsi_cmd_write10; + wr.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT; + wr.lba = grub_cpu_to_be32 (sector); + wr.reserved = 0; + wr.size = grub_cpu_to_be16 (size); + wr.reserved2 = 0; + wr.pad = 0; + + return scsi->dev->write (scsi, sizeof (wr), (char *) &wr, size * 512, buf); +} + +/* Send a SCSI request for DISK: write the data stored in BUF to SIZE + sectors starting with SECTOR. */ +static grub_err_t +grub_scsi_write12 (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + grub_scsi_t scsi; + struct grub_scsi_write10 wr; + + scsi = disk->data; + + wr.opcode = grub_scsi_cmd_write12; + wr.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT; + wr.lba = grub_cpu_to_be32 (sector); + wr.size = grub_cpu_to_be32 (size); + wr.reserved = 0; + wr.pad = 0; + + return scsi->dev->write (scsi, sizeof (wr), (char *) &wr, size * 512, buf); +} + + +static int +grub_scsi_iterate (int (*hook) (const char *name)) +{ + grub_scsi_dev_t p; + + auto int scsi_iterate (const char *name, int luns); + + int scsi_iterate (const char *name, int luns) + { + char sname[40]; + int i; + + /* In case of a single LUN, just return `usbX'. */ + if (luns == 1) + return hook (name); + + /* In case of multiple LUNs, every LUN will get a prefix to + distinguish it. */ + for (i = 0; i < luns; i++) + { + grub_sprintf (sname, "%s%c", name, 'a' + i); + if (hook (sname)) + return 1; + } + return 0; + } + + for (p = grub_scsi_dev_list; p; p = p->next) + if (p->iterate && (p->iterate) (scsi_iterate)) + return 1; + + return 0; +} + +static grub_err_t +grub_scsi_open (const char *name, grub_disk_t disk) +{ + grub_scsi_dev_t p; + grub_scsi_t scsi; + grub_err_t err; + int len; + int lun; + + scsi = grub_malloc (sizeof (*scsi)); + if (! scsi) + return grub_errno; + + len = grub_strlen (name); + lun = name[len - 1] - 'a'; + + /* Try to detect a LUN ('a'-'z'), otherwise just use the first + LUN. */ + if (lun < 0 || lun > 26) + lun = 0; + + for (p = grub_scsi_dev_list; p; p = p->next) + { + if (! p->open (name, scsi)) + { + disk->id = (unsigned long) "scsi"; /* XXX */ + disk->has_partitions = 0; + disk->data = scsi; + scsi->dev = p; + scsi->lun = lun; + scsi->name = grub_strdup (name); + if (! scsi->name) + { + p->close (scsi); + return grub_errno; + } + + grub_dprintf ("scsi", "dev opened\n"); + + err = grub_scsi_inquiry (scsi); + if (err) + { + grub_dprintf ("scsi", "inquiry failed\n"); + p->close (scsi); + return grub_errno; + } + + grub_dprintf ("scsi", "inquiry: devtype=0x%02x removable=%d\n", + scsi->devtype, scsi->removable); + + /* Try to be conservative about the device types + supported. */ + if (scsi->devtype != grub_scsi_devtype_direct + && scsi->devtype != grub_scsi_devtype_cdrom) + { + p->close (scsi); + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, + "unknown SCSI device"); + } + + err = grub_scsi_read_capacity (scsi); + if (err) + { + grub_dprintf ("scsi", "READ CAPACITY failed\n"); + p->close (scsi); + return grub_errno; + } + + /* SCSI blocks can be something else than 512, although GRUB + wants 512 byte blocks. */ + disk->total_sectors = ((scsi->size * scsi->blocksize) + << GRUB_DISK_SECTOR_BITS); + + grub_dprintf ("scsi", "capacity=%d, blksize=%d\n", + (int) disk->total_sectors, scsi->blocksize); + + return GRUB_ERR_NONE; + } + } + + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a SCSI disk"); +} + +static void +grub_scsi_close (grub_disk_t disk) +{ + grub_scsi_t scsi; + + scsi = disk->data; + return scsi->dev->close (scsi); +} + +static grub_err_t +grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + grub_scsi_t scsi; + + scsi = disk->data; + + /* SCSI sectors are variable in size. GRUB uses 512 byte + sectors. */ + sector = grub_divmod64 (sector, scsi->blocksize >> GRUB_DISK_SECTOR_BITS, + NULL); + + /* Depending on the type, select a read function. */ + switch (scsi->devtype) + { + case grub_scsi_devtype_direct: + return grub_scsi_read10 (disk, sector, size, buf); + + case grub_scsi_devtype_cdrom: + return grub_scsi_read12 (disk, sector, size, buf); + } + + /* XXX: Never reached. */ + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_scsi_write (grub_disk_t disk __attribute((unused)), grub_disk_addr_t sector, + grub_size_t size, const char *buf) +{ +#if 0 + /* XXX: Not tested yet! */ + + /* XXX: This should depend on the device type? */ + return grub_scsi_write10 (disk, sector, size, buf); +#endif + return GRUB_ERR_NOT_IMPLEMENTED_YET; +} + + +static struct grub_disk_dev grub_scsi_dev = + { + .name = "scsi", + .id = GRUB_DISK_DEVICE_SCSI_ID, + .iterate = grub_scsi_iterate, + .open = grub_scsi_open, + .close = grub_scsi_close, + .read = grub_scsi_read, + .write = grub_scsi_write, + .next = 0 + }; + +GRUB_MOD_INIT(scsi) +{ + grub_disk_dev_register (&grub_scsi_dev); +} + +GRUB_MOD_FINI(scsi) +{ + grub_disk_dev_unregister (&grub_scsi_dev); +} Index: disk/ata.c =================================================================== --- disk/ata.c (revision 1802) +++ disk/ata.c (working copy) @@ -23,6 +23,7 @@ #include #include #include +#include /* XXX: For now this only works on i386. */ #include @@ -299,14 +300,17 @@ grub_atapi_identify (struct grub_ata_dev static grub_err_t grub_atapi_packet (struct grub_ata_device *dev, char *packet) { + grub_err_t err; + grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4); grub_ata_regset (dev, GRUB_ATA_REG_FEATURES, 0); grub_ata_regset (dev, GRUB_ATA_REG_SECTORS, 0); grub_ata_regset (dev, GRUB_ATA_REG_LBAHIGH, 0xFF); grub_ata_regset (dev, GRUB_ATA_REG_LBAMID, 0xFF); - if (grub_ata_cmd (dev, GRUB_ATA_CMD_PACKET)) - return grub_errno; + grub_ata_regset (dev, GRUB_ATA_REG_CMD, GRUB_ATA_CMD_PACKET); + + grub_ata_wait (); if (grub_ata_pio_write (dev, packet, 12)) return grub_errno; @@ -757,6 +761,9 @@ grub_ata_iterate (int (*hook) (const cha char devname[5]; grub_sprintf (devname, "ata%d", dev->port * 2 + dev->device); + if (dev->atapi) + continue; + if (hook (devname)) return 1; } @@ -781,13 +788,13 @@ grub_ata_open (const char *name, grub_di return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't open device"); if (dev->atapi) - disk->total_sectors = 9000000; /* XXX */ - else - disk->total_sectors = dev->size; + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk"); + + disk->total_sectors = dev->size; disk->id = (unsigned long) dev; - disk->has_partitions = !dev->atapi; + disk->has_partitions = 1; disk->data = dev; return 0; @@ -799,33 +806,6 @@ grub_ata_close (grub_disk_t disk __attri } -struct grub_atapi_read -{ - grub_uint8_t code; - grub_uint8_t reserved1; - grub_uint32_t lba; - grub_uint32_t length; - grub_uint8_t reserved2[2]; -} __attribute__((packed)); - -static grub_err_t -grub_atapi_readsector (struct grub_ata_device *dev, - char *buf, grub_disk_addr_t sector) -{ - struct grub_atapi_read readcmd; - - readcmd.code = 0xA8; - readcmd.lba = grub_cpu_to_be32 (sector); - readcmd.length = grub_cpu_to_be32 (1); - - grub_atapi_packet (dev, (char *) &readcmd); - grub_ata_wait (); - if (grub_ata_pio_read (dev, buf, GRUB_CDROM_SECTOR_SIZE)) - return grub_errno; - - return 0; -} - static grub_err_t grub_ata_read (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t size, char *buf) @@ -834,41 +814,7 @@ grub_ata_read (grub_disk_t disk, grub_di int cdsector; char *sbuf; - if (! dev->atapi) - return grub_ata_readwrite (disk, sector, size, buf, 0); - - /* ATAPI is being used, so try to read from CDROM using ATAPI. */ - - sbuf = grub_malloc (GRUB_CDROM_SECTOR_SIZE); - if (! sbuf) - return grub_errno; - - /* CDROMs have sectors of 2048 bytes, so chop them into pieces of - 512 bytes. */ - while (size > 0) - { - int rsize; - int offset; - int max; - - cdsector = sector >> 2; - rsize = ((size * GRUB_DISK_SECTOR_SIZE > GRUB_CDROM_SECTOR_SIZE) - ? GRUB_CDROM_SECTOR_SIZE : size * GRUB_DISK_SECTOR_SIZE); - offset = (sector & 3) * GRUB_DISK_SECTOR_SIZE; - max = GRUB_CDROM_SECTOR_SIZE - offset; - rsize = (rsize > max) ? max : rsize; - - grub_atapi_readsector (dev, sbuf, cdsector); - grub_memcpy (buf + offset, sbuf, rsize); - - buf += rsize; - size -= rsize / GRUB_DISK_SECTOR_SIZE; - sector += rsize / GRUB_DISK_SECTOR_SIZE; - } - - grub_free (sbuf); - - return 0; + return grub_ata_readwrite (disk, sector, size, buf, 0); } static grub_err_t @@ -879,10 +825,7 @@ grub_ata_write (grub_disk_t disk, { struct grub_ata_device *dev = (struct grub_ata_device *) disk->data; - if (! dev->atapi) - return grub_ata_readwrite (disk, sector, size, (char *) buf, 1); - - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "ATAPI write not supported"); + return grub_ata_readwrite (disk, sector, size, (char *) buf, 1); } static struct grub_disk_dev grub_atadisk_dev = @@ -897,6 +840,105 @@ static struct grub_disk_dev grub_atadisk .next = 0 }; + + +/* ATAPI code. */ + +static int +grub_atapi_iterate (int (*hook) (const char *name, int luns)) +{ + struct grub_ata_device *dev; + + for (dev = grub_ata_devices; dev; dev = dev->next) + { + char devname[7]; + grub_sprintf (devname, "ata%d", dev->port * 2 + dev->device); + + if (! dev->atapi) + continue; + + if (hook (devname, 1)) + return 1; + } + + return 0; + +} + +static grub_err_t +grub_atapi_read (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, + grub_size_t size, char *buf) +{ + struct grub_ata_device *dev = (struct grub_ata_device *) scsi->data; + + if (grub_atapi_packet (dev, cmd)) + return grub_errno; + + grub_ata_wait (); /* XXX */ + + return grub_ata_pio_read (dev, buf, size); +} + +static grub_err_t +grub_atapi_write (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, + grub_size_t size, char *buf) +{ + struct grub_ata_device *dev = (struct grub_ata_device *) scsi->data; + + if (grub_atapi_packet (dev, cmd)) + return grub_errno; + + grub_ata_wait (); /* XXX */ + + return grub_ata_pio_write (dev, buf, size); +} + +static grub_err_t +grub_atapi_open (const char *name, struct grub_scsi *scsi) +{ + struct grub_ata_device *dev; + struct grub_ata_device *devfnd; + + for (dev = grub_ata_devices; dev; dev = dev->next) + { + char devname[7]; + grub_sprintf (devname, "ata%d", dev->port * 2 + dev->device); + + if (!grub_strcmp (devname, name)) + { + devfnd = dev; + break; + } + } + + grub_dprintf ("ata", "opening ATAPI dev `%s'\n", name); + + if (! devfnd) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such ATAPI device"); + + scsi->data = devfnd; + scsi->name = grub_strdup (name); + scsi->luns = 1; + + return GRUB_ERR_NONE; +} + +static void +grub_atapi_close (struct grub_scsi *scsi) +{ + grub_free (scsi->name); +} + +static struct grub_scsi_dev grub_atapi_dev = + { + .name = "ATAPI", + .iterate = grub_atapi_iterate, + .open = grub_atapi_open, + .close = grub_atapi_close, + .read = grub_atapi_read, + .write = grub_atapi_write + }; + GRUB_MOD_INIT(ata) @@ -915,9 +957,13 @@ GRUB_MOD_INIT(ata) grub_ata_initialize (); grub_disk_dev_register (&grub_atadisk_dev); + + /* ATAPI devices are handled by scsi.mod. */ + grub_scsi_dev_register (&grub_atapi_dev); } GRUB_MOD_FINI(ata) { + grub_scsi_dev_unregister (&grub_atapi_dev); grub_disk_dev_unregister (&grub_atadisk_dev); } Index: include/grub/scsi.h =================================================================== --- include/grub/scsi.h (revision 0) +++ include/grub/scsi.h (revision 0) @@ -0,0 +1,88 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_SCSI_H +#define GRUB_SCSI_H 1 + +typedef struct grub_scsi_dev *grub_scsi_dev_t; + +void grub_scsi_dev_register (grub_scsi_dev_t dev); +void grub_scsi_dev_unregister (grub_scsi_dev_t dev); + +struct grub_scsi; + +struct grub_scsi_dev +{ + /* The device name. */ + const char *name; + + /* Call HOOK with each device name, until HOOK returns non-zero. */ + int (*iterate) (int (*hook) (const char *name, int luns)); + + /* Open the device named NAME, and set up SCSI. */ + grub_err_t (*open) (const char *name, struct grub_scsi *scsi); + + /* Close the scsi device SCSI. */ + void (*close) (struct grub_scsi *scsi); + + /* Read SIZE bytes from the device SCSI into BUF after sending the + command CMD of size CMDSIZE. */ + grub_err_t (*read) (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, + grub_size_t size, char *buf); + + /* Write SIZE bytes from BUF to the device SCSI after sending the + command CMD of size CMDSIZE. */ + grub_err_t (*write) (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, + grub_size_t size, char *buf); + + /* The next scsi device. */ + struct grub_scsi_dev *next; +}; + +struct grub_scsi +{ + /* The scsi device name. */ + char *name; + + /* The underlying scsi device. */ + grub_scsi_dev_t dev; + + /* Type of SCSI device. XXX: Make enum. */ + grub_uint8_t devtype; + + /* Number of LUNs. */ + int luns; + + /* LUN for this `struct grub_scsi'. */ + int lun; + + /* Set to 0 when not removable, 1 when removable. */ + int removable; + + /* Size of the device in blocks. */ + int size; + + /* Size of one block. */ + int blocksize; + + /* Device-specific data. */ + void *data; +}; +typedef struct grub_scsi *grub_scsi_t; + +#endif /* GRUB_SCSI_H */ Index: include/grub/scsicmd.h =================================================================== --- include/grub/scsicmd.h (revision 0) +++ include/grub/scsicmd.h (revision 0) @@ -0,0 +1,122 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_SCSICMD_H +#define GRUB_SCSICMD_H 1 + +#include + +#define GRUB_SCSI_DEVTYPE_MASK 31 +#define GRUB_SCSI_REMOVABLE_BIT 7 +#define GRUB_SCSI_LUN_SHIFT 5 + +struct grub_scsi_inquiry +{ + grub_uint8_t opcode; + grub_uint8_t lun; + grub_uint16_t reserved; + grub_uint16_t alloc_length; + grub_uint8_t reserved2; + grub_uint8_t pad[5]; +} __attribute__((packed)); + +struct grub_scsi_inquiry_data +{ + grub_uint8_t devtype; + grub_uint8_t rmb; + grub_uint16_t reserved; + grub_uint8_t length; + grub_uint8_t reserved2[3]; + char vendor[8]; + char prodid[16]; + char prodrev[4]; +} __attribute__((packed)); + +struct grub_scsi_read_capacity +{ + grub_uint8_t opcode; + grub_uint8_t lun; + grub_uint8_t reserved[8]; + grub_uint8_t pad[2]; +} __attribute__((packed)); + +struct grub_scsi_read_capacity_data +{ + grub_uint32_t size; + grub_uint32_t blocksize; +} __attribute__((packed)); + +struct grub_scsi_read10 +{ + grub_uint8_t opcode; + grub_uint8_t lun; + grub_uint32_t lba; + grub_uint8_t reserved; + grub_uint16_t size; + grub_uint8_t reserved2; + grub_uint16_t pad; +} __attribute__((packed)); + +struct grub_scsi_read12 +{ + grub_uint8_t opcode; + grub_uint8_t lun; + grub_uint32_t lba; + grub_uint32_t size; + grub_uint8_t reserved; + grub_uint8_t control; +} __attribute__((packed)); + +struct grub_scsi_write10 +{ + grub_uint8_t opcode; + grub_uint8_t lun; + grub_uint32_t lba; + grub_uint8_t reserved; + grub_uint16_t size; + grub_uint8_t reserved2; + grub_uint16_t pad; +} __attribute__((packed)); + +struct grub_scsi_write12 +{ + grub_uint8_t opcode; + grub_uint8_t lun; + grub_uint32_t lba; + grub_uint32_t size; + grub_uint8_t reserved; + grub_uint8_t control; +} __attribute__((packed)); + +typedef enum + { + grub_scsi_cmd_inquiry = 0x12, + grub_scsi_cmd_read_capacity = 0x25, + grub_scsi_cmd_read10 = 0x28, + grub_scsi_cmd_write10 = 0x2a, + grub_scsi_cmd_read12 = 0xa8, + grub_scsi_cmd_write12 = 0xaa + } grub_scsi_cmd_t; + +typedef enum + { + grub_scsi_devtype_direct = 0x00, + grub_scsi_devtype_cdrom = 0x05 + } grub_scsi_devtype_t; + +#endif /* GRUB_SCSICMD_H */ Index: include/grub/disk.h =================================================================== --- include/grub/disk.h (revision 1802) +++ include/grub/disk.h (working copy) @@ -40,6 +40,7 @@ enum grub_disk_dev_id GRUB_DISK_DEVICE_NAND_ID, GRUB_DISK_DEVICE_UUID_ID, GRUB_DISK_DEVICE_PXE_ID, + GRUB_DISK_DEVICE_SCSI_ID, }; struct grub_disk;