Index: disk/scsi.c =================================================================== --- disk/scsi.c (revision 1830) +++ disk/scsi.c (working copy) @@ -111,6 +111,8 @@ scsi = disk->data; + grub_dprintf ("scsi", "READ10: sector=%lld, size=%d\n", sector, size); + rd.opcode = grub_scsi_cmd_read10; rd.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT; rd.lba = grub_cpu_to_be32 (sector); @@ -133,6 +135,8 @@ scsi = disk->data; + grub_dprintf ("scsi", "READ12: sector=%lld, size=%d\n", sector, size); + rd.opcode = grub_scsi_cmd_read12; rd.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT; rd.lba = grub_cpu_to_be32 (sector); @@ -143,7 +147,6 @@ return scsi->dev->read (scsi, sizeof (rd), (char *) &rd, size * 512, buf); } -#if 0 /* Send a SCSI request for DISK: write the data stored in BUF to SIZE sectors starting with SECTOR. */ static grub_err_t @@ -186,7 +189,6 @@ return scsi->dev->write (scsi, sizeof (wr), (char *) &wr, size * 512, buf); } -#endif static int @@ -194,8 +196,6 @@ { 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]; @@ -249,6 +249,7 @@ if (! p->open (name, scsi)) { disk->id = (unsigned long) "scsi"; /* XXX */ + disk->has_partitions = 1; disk->data = scsi; scsi->dev = p; scsi->lun = lun; @@ -274,19 +275,13 @@ /* Try to be conservative about the device types supported. */ - if (scsi->devtype != grub_scsi_devtype_direct - && scsi->devtype != grub_scsi_devtype_cdrom) + if (scsi->devtype != 0x00 && scsi->devtype != 0x05) { p->close (scsi); return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown SCSI device"); } - if (scsi->devtype == grub_scsi_devtype_cdrom) - disk->has_partitions = 0; - else - disk->has_partitions = 1; - err = grub_scsi_read_capacity (scsi); if (err) { @@ -297,11 +292,12 @@ /* 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); +/* disk->total_sectors = ((scsi->size) */ +/* << GRUB_DISK_SECTOR_BITS); */ + disk->total_sectors = scsi->size; grub_dprintf ("scsi", "capacity=%d, blksize=%d\n", - (int) disk->total_sectors, scsi->blocksize); + scsi->size, scsi->blocksize); return GRUB_ERR_NONE; } @@ -327,18 +323,15 @@ 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: + case 0: return grub_scsi_read10 (disk, sector, size, buf); - case grub_scsi_devtype_cdrom: + case 0x05: return grub_scsi_read12 (disk, sector, size, buf); } @@ -347,15 +340,14 @@ } static grub_err_t -grub_scsi_write (grub_disk_t disk __attribute((unused)), - grub_disk_addr_t sector __attribute((unused)), - grub_size_t size __attribute((unused)), - const char *buf __attribute((unused))) +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? */ + /* XXX: What is the sector size != 512? */ return grub_scsi_write10 (disk, sector, size, buf); #endif return GRUB_ERR_NOT_IMPLEMENTED_YET; Index: disk/ata.c =================================================================== --- disk/ata.c (revision 1830) +++ disk/ata.c (working copy) @@ -119,7 +119,7 @@ grub_outb (val, dev->ioaddress + reg); } -static inline grub_uint8_t +static inline int grub_ata_regget (struct grub_ata_device *dev, int reg) { return grub_inb (dev->ioaddress + reg); @@ -131,51 +131,29 @@ grub_outb (val, dev->ioaddress2 + reg); } -static inline grub_uint8_t +static inline int grub_ata_regget2 (struct grub_ata_device *dev, int reg) { return grub_inb (dev->ioaddress2 + reg); } -static inline grub_err_t -grub_ata_wait_status (struct grub_ata_device *dev, - grub_uint8_t maskset, grub_uint8_t maskclear) +/* Wait until the device DEV has the status set to ready. */ +static inline void +grub_ata_wait_busy (struct grub_ata_device *dev) { - int i; - - for (i = 0; i < 1000; i++) - { - grub_uint8_t reg; - - reg = grub_ata_regget (dev, GRUB_ATA_REG_STATUS); - if ((reg & maskset) == maskset && (reg & maskclear) == 0) - return GRUB_ERR_NONE; - - grub_millisleep (1); - } - - return grub_error (GRUB_ERR_TIMEOUT, "ata timeout"); + while ((grub_ata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_BUSY)); } static inline void -grub_ata_wait (void) +grub_ata_wait_drq (struct grub_ata_device *dev) { - grub_millisleep (50); + while (! (grub_ata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_DRQ)); } -static grub_err_t -grub_ata_cmd (struct grub_ata_device *dev, int cmd) +static inline void +grub_ata_wait (void) { - grub_err_t err; - - err = grub_ata_wait_status (dev, 0, - GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_BUSY); - if (err) - return err; - - grub_ata_regset (dev, GRUB_ATA_REG_CMD, cmd); - - return GRUB_ERR_NONE; + grub_millisleep (1); } /* Byteorder has to be changed before strings can be read. */ @@ -191,7 +169,7 @@ dst[len] = '\0'; } -static grub_err_t +static int grub_ata_pio_read (struct grub_ata_device *dev, char *buf, grub_size_t size) { @@ -202,17 +180,16 @@ return grub_ata_regget (dev, GRUB_ATA_REG_ERROR); /* Wait until the data is available. */ - if (grub_ata_wait_status (dev, GRUB_ATA_STATUS_DRQ, 0)) - return grub_errno;; + grub_ata_wait_drq (dev); /* Read in the data, word by word. */ for (i = 0; i < size / 2; i++) buf16[i] = grub_le_to_cpu16 (grub_inw(dev->ioaddress + GRUB_ATA_REG_DATA)); if (grub_ata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_ERR) - return grub_error (GRUB_ERR_READ_ERROR, "ATA read error"); + return grub_ata_regget (dev, GRUB_ATA_REG_ERROR); - return GRUB_ERR_NONE; + return 0; } static grub_err_t @@ -225,18 +202,17 @@ if (grub_ata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_ERR) return grub_ata_regget (dev, GRUB_ATA_REG_ERROR); - /* Wait until the data is available. */ - if (grub_ata_wait_status (dev, GRUB_ATA_STATUS_DRQ, 0)) - return 0; + /* Wait until the device is ready to write. */ + grub_ata_wait_drq (dev); /* Write the data, word by word. */ for (i = 0; i < size / 2; i++) grub_outw(grub_cpu_to_le16 (buf16[i]), dev->ioaddress + GRUB_ATA_REG_DATA); if (grub_ata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_ERR) - return grub_error (GRUB_ERR_WRITE_ERROR, "ATA write error"); + return grub_ata_regget (dev, GRUB_ATA_REG_ERROR); - return GRUB_ERR_NONE; + return 0; } static void @@ -268,33 +244,22 @@ if (! info) return grub_errno; - if (grub_ata_wait_status (dev, 0, GRUB_ATA_STATUS_BUSY)) - { - grub_free (info); - return grub_errno; - } + grub_ata_wait_busy (dev); grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4); + grub_ata_regset (dev, GRUB_ATA_REG_CMD, + GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE); + grub_ata_wait (); - if (grub_ata_cmd (dev, GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE)) - { - grub_free (info); - return grub_errno; - } + grub_ata_pio_read (dev, info, 256); - if (grub_ata_pio_read (dev, info, 256)) - { - grub_free (info); - return grub_errno; - } - dev->atapi = 1; grub_ata_dumpinfo (dev, info); grub_free (info); - return GRUB_ERR_NONE; + return 0; } static grub_err_t @@ -321,7 +286,7 @@ { char *info; grub_uint16_t *info16; - int ataerr = 0; + int ataerr; info = grub_malloc (GRUB_DISK_SECTOR_SIZE); if (! info) @@ -329,22 +294,13 @@ info16 = (grub_uint16_t *) info; - if (grub_ata_wait_status (dev, 0, GRUB_ATA_STATUS_BUSY)) - { - grub_free (info); - return grub_errno; - } + grub_ata_wait_busy (dev); grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4); - if (grub_ata_cmd (dev, GRUB_ATA_CMD_IDENTIFY_DEVICE)) - { - grub_free (info); - return grub_errno; - } + grub_ata_regset (dev, GRUB_ATA_REG_CMD, GRUB_ATA_CMD_IDENTIFY_DEVICE); grub_ata_wait (); - if (grub_ata_pio_read (dev, info, GRUB_DISK_SECTOR_SIZE)) - ataerr = grub_ata_regget (dev, GRUB_ATA_REG_ERROR); + ataerr = grub_ata_pio_read (dev, info, GRUB_DISK_SECTOR_SIZE); if (ataerr & 4) { /* ATAPI device detected. */ @@ -409,8 +365,8 @@ /* Setup the device information. */ dev->port = port; dev->device = device; - dev->ioaddress = addr; - dev->ioaddress2 = addr2; + dev->ioaddress = grub_ata_ioaddress[dev->port]; + dev->ioaddress2 = grub_ata_ioaddress2[dev->port]; dev->next = NULL; /* Try to detect if the port is in use by writing to it, @@ -429,11 +385,8 @@ /* Detect if the device is present by issuing a EXECUTE DEVICE DIAGNOSTICS command. */ grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4); - if (grub_ata_cmd (dev, GRUB_ATA_CMD_EXEC_DEV_DIAGNOSTICS)) - { - grub_free (dev); - return grub_errno; - } + grub_ata_regset (dev, GRUB_ATA_REG_CMD, + GRUB_ATA_CMD_EXEC_DEV_DIAGNOSTICS); grub_ata_wait (); grub_dprintf ("ata", "Registers: %x %x %x %x\n", @@ -450,19 +403,19 @@ { grub_dprintf ("ata", "ATAPI signature detected\n"); } - else if (grub_ata_regget (dev, GRUB_ATA_REG_SECTORS) == 0x01 - && grub_ata_regget (dev, GRUB_ATA_REG_LBALOW) == 0x01 - && grub_ata_regget (dev, GRUB_ATA_REG_LBAMID) == 0x00 - && grub_ata_regget (dev, GRUB_ATA_REG_LBAHIGH) == 0x00) + else if (! (grub_ata_regget (dev, GRUB_ATA_REG_SECTORS) == 0x01 + && grub_ata_regget (dev, GRUB_ATA_REG_LBALOW) == 0x01 + && grub_ata_regget (dev, GRUB_ATA_REG_LBAMID) == 0x00 + && grub_ata_regget (dev, GRUB_ATA_REG_LBAHIGH) == 0x00)) { - grub_dprintf ("ata", "ATA detected\n"); - } - else - { grub_dprintf ("ata", "incorrect signature\n"); grub_free (dev); return 0; } + else + { + grub_dprintf ("ata", "ATA detected\n"); + } /* Use the IDENTIFY DEVICE command to query the device. */ @@ -480,8 +433,7 @@ } static int -grub_ata_pciinit (int bus, int device, int func, - grub_pci_id_t pciid __attribute__((unused))) +grub_ata_pciinit (int bus, int device, int func, grub_pci_id_t pciid) { static int compat_use[2] = { 0 }; grub_pci_address_t addr; @@ -491,7 +443,6 @@ int rega; int regb; int i; - static int controller = 0; /* Read class. */ addr = grub_pci_make_address (bus, device, func, 2); @@ -540,13 +491,11 @@ if (rega && regb) { - grub_ata_device_initialize (controller * 2 + i, 0, rega, regb); - grub_ata_device_initialize (controller * 2 + i, 1, rega, regb); + grub_ata_device_initialize (i, 0, rega, regb); + grub_ata_device_initialize (i, 1, rega, regb); } } - controller++; - return 0; } @@ -574,8 +523,7 @@ grub_disk_addr_t sector, grub_size_t size) { - if (grub_ata_wait_status (dev, 0, GRUB_ATA_STATUS_BUSY)) - return grub_errno; + grub_ata_wait_busy (dev); switch (addressing) { @@ -671,31 +619,21 @@ if (rw == 0) { /* Read 256/65536 sectors. */ - if (grub_ata_cmd (dev, cmd)) - return grub_errno; - - /* Wait for the command to complete. */ - if (grub_ata_wait_status (dev, 0, GRUB_ATA_STATUS_BUSY)) - return grub_errno; - + grub_ata_regset (dev, GRUB_ATA_REG_CMD, cmd); + grub_ata_wait (); for (sect = 0; sect < batch; sect++) { if (grub_ata_pio_read (dev, buf, GRUB_DISK_SECTOR_SIZE)) - return grub_errno; + return grub_error (GRUB_ERR_READ_ERROR, "ATA read error"); buf += GRUB_DISK_SECTOR_SIZE; } } else { /* Write 256/65536 sectors. */ - if (grub_ata_cmd (dev, cmd)) - return grub_errno; - - /* Wait for the command to complete. */ - if (grub_ata_wait_status (dev, 0, GRUB_ATA_STATUS_BUSY)) - return grub_errno; - + grub_ata_regset (dev, GRUB_ATA_REG_CMD, cmd_write); + grub_ata_wait (); for (sect = 0; sect < batch; sect++) { if (grub_ata_pio_write (dev, buf, @@ -714,28 +652,18 @@ if (rw == 0) { /* Read sectors. */ - if (grub_ata_cmd (dev, cmd)) - return grub_errno; - - /* Wait for the command to complete. */ - if (grub_ata_wait_status (dev, 0, GRUB_ATA_STATUS_BUSY)) - return grub_errno; - + grub_ata_regset (dev, GRUB_ATA_REG_CMD, cmd); + grub_ata_wait (); for (sect = 0; sect < (size % batch); sect++) { if (grub_ata_pio_read (dev, buf, GRUB_DISK_SECTOR_SIZE)) - return grub_errno; + return grub_error (GRUB_ERR_READ_ERROR, "ATA read error"); buf += GRUB_DISK_SECTOR_SIZE; } } else { /* Write sectors. */ - if (grub_ata_cmd (dev, cmd)) - return grub_errno; - - /* Wait for the command to complete. */ - if (grub_ata_wait_status (dev, 0, GRUB_ATA_STATUS_BUSY)) - return grub_errno; - + grub_ata_regset (dev, GRUB_ATA_REG_CMD, cmd_write); + grub_ata_wait (); for (sect = 0; sect < (size % batch); sect++) { if (grub_ata_pio_write (dev, buf, GRUB_DISK_SECTOR_SIZE)) @@ -762,6 +690,9 @@ if (dev->atapi) continue; + if (dev->atapi) + continue; + if (hook (devname)) return 1; } @@ -933,8 +864,105 @@ .write = grub_atapi_write }; + +/* 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[5]; + 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[5]; + grub_sprintf (devname, "ata%d", dev->port * 2 + dev->device); + + if (!grub_strcmp (devname, name)) + { + devfnd = dev; + break; + } + } + + 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) { (void) mod; /* To stop warning. */