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
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to