On Sun, Feb 08, 2009 at 07:09:53PM +0100, Robert Millan wrote:
> On Mon, Jan 19, 2009 at 11:15:41AM +0100, Marco Gerards wrote:
> > Perhaps my USB code might help in some occasions
> > for scsi.c, I am not completely sure if they are in sync. I sent in
> > the USB code earlier. This code can be committed, although endianess
> > is not handled correctly at all places.
Regarding scsi.c (and ata.c), there's more stuff in the other patch from Marco
at: http://mgerards.net/grub/grub_usb_2008-08-26.diff
It includes modifications that apply to revision 1830. I re-diffed them
against that version and am attaching them, just in case someone will find
them useful.
--
Robert Millan
The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
how) you may access your data; but nobody's threatening your freedom: we
still allow you to remove your data and not access it at all."
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. */
_______________________________________________
Grub-devel mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/grub-devel