[1796] 2008-08-08 Marco Gerards <[email protected]>

Marco Gerards <[email protected]>
Newsgroups gmane.comp.boot-loaders.grub.cvs
Message-ID <[email protected]>
Revision: 1796
          http://svn.sv.gnu.org/viewvc/?view=rev&root=grub&revision=1796
Author:   marco_g
Date:     2008-08-07 23:37:33 +0000 (Thu, 07 Aug 2008)

Log Message:
-----------
2008-08-08  Marco Gerards  <[email protected]>

	* disk/ata.c (grub_ata_regget): Change return type to
	`grub_uint8_t'.
	(grub_ata_regget2): Likewise.
	(grub_ata_wait_status): New function.
	(grub_ata_wait_busy): Removed function, updated all users to use
	`grub_ata_wait_status'.
	(grub_ata_wait_drq): Likewise.
	(grub_ata_cmd): New function.
	(grub_ata_pio_read): Change return type to `grub_uint8_t'.  Add
	error handling.
	(grub_ata_pio_write): Add error handling.
	(grub_atapi_identify): Likewise.
	(grub_atapi_packet): Use `grub_ata_cmd' and improve error
	handling.
	(grub_ata_identify): Use `grub_ata_cmd' and improve error
	handling.  Actually use the detected registers.  Reorder the
	detection logic such that it is easier to read.
	(grub_ata_pciinit): Do not assign the same ID to each controller.
	(grub_ata_setaddress): Use `grub_ata_cmd' and improve error
	handling.
	(grub_atapi_readsector): Check the result of `grub_ata_pio_read'.

	* include/grub/err.h (grub_err_t): Add `GRUB_ERR_TIMEOUT'.

Modified Paths:
--------------
    trunk/grub2/ChangeLog
    trunk/grub2/disk/ata.c
    trunk/grub2/include/grub/err.h

Modified: trunk/grub2/ChangeLog
===================================================================
--- trunk/grub2/ChangeLog	2008-08-07 22:55:50 UTC (rev 1795)
+++ trunk/grub2/ChangeLog	2008-08-07 23:37:33 UTC (rev 1796)
@@ -1,5 +1,31 @@
 2008-08-08  Marco Gerards  <[email protected]>
 
+	* disk/ata.c (grub_ata_regget): Change return type to
+	`grub_uint8_t'.
+	(grub_ata_regget2): Likewise.
+	(grub_ata_wait_status): New function.
+	(grub_ata_wait_busy): Removed function, updated all users to use
+	`grub_ata_wait_status'.
+	(grub_ata_wait_drq): Likewise.
+	(grub_ata_cmd): New function.
+	(grub_ata_pio_read): Change return type to `grub_uint8_t'.  Add
+	error handling.
+	(grub_ata_pio_write): Add error handling.
+	(grub_atapi_identify): Likewise.
+	(grub_atapi_packet): Use `grub_ata_cmd' and improve error
+	handling.
+	(grub_ata_identify): Use `grub_ata_cmd' and improve error
+	handling.  Actually use the detected registers.  Reorder the
+	detection logic such that it is easier to read.
+	(grub_ata_pciinit): Do not assign the same ID to each controller.
+	(grub_ata_setaddress): Use `grub_ata_cmd' and improve error
+	handling.
+	(grub_atapi_readsector): Check the result of `grub_ata_pio_read'.
+
+	* include/grub/err.h (grub_err_t): Add `GRUB_ERR_TIMEOUT'.
+
+2008-08-08  Marco Gerards  <[email protected]>
+
 	* NEWS: Update.
 
 2008-08-07  Bean  <[email protected]>

Modified: trunk/grub2/disk/ata.c
===================================================================
--- trunk/grub2/disk/ata.c	2008-08-07 22:55:50 UTC (rev 1795)
+++ trunk/grub2/disk/ata.c	2008-08-07 23:37:33 UTC (rev 1796)
@@ -118,7 +118,7 @@
   grub_outb (val, dev->ioaddress + reg);
 }
 
-static inline int
+static inline grub_uint8_t
 grub_ata_regget (struct grub_ata_device *dev, int reg)
 {
   return grub_inb (dev->ioaddress + reg);
@@ -130,23 +130,30 @@
   grub_outb (val, dev->ioaddress2 + reg);
 }
 
-static inline int
+static inline grub_uint8_t
 grub_ata_regget2 (struct grub_ata_device *dev, int reg)
 {
   return grub_inb (dev->ioaddress2 + reg);
 }
 
-/* Wait until the device DEV has the status set to ready.  */
-static inline void
-grub_ata_wait_busy (struct grub_ata_device *dev)
+static inline grub_err_t
+grub_ata_wait_status (struct grub_ata_device *dev,
+		      grub_uint8_t maskset, grub_uint8_t maskclear)
 {
-  while ((grub_ata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_BUSY));
-}
+  int i;
 
-static inline void
-grub_ata_wait_drq (struct grub_ata_device *dev)
-{
-  while (! (grub_ata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_DRQ));
+  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");
 }
 
 static inline void
@@ -155,6 +162,21 @@
   grub_millisleep (50);
 }
 
+static grub_err_t
+grub_ata_cmd (struct grub_ata_device *dev, int cmd)
+{
+  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;
+}
+
 /* Byteorder has to be changed before strings can be read.  */
 static inline void
 grub_ata_strncpy (char *dst, char *src, grub_size_t len)
@@ -164,11 +186,11 @@
   unsigned int i;
 
   for (i = 0; i < len / 2; i++)
-    *(dst16++) = grub_be_to_cpu16(*(src16++));
+    *(dst16++) = grub_be_to_cpu16 (*(src16++));
   dst[len] = '\0';
 }
 
-static int
+static grub_err_t
 grub_ata_pio_read (struct grub_ata_device *dev, char *buf,
 		   grub_size_t size)
 {
@@ -179,16 +201,17 @@
     return grub_ata_regget (dev, GRUB_ATA_REG_ERROR);
 
   /* Wait until the data is available.  */
-  grub_ata_wait_drq (dev);
+  if (grub_ata_wait_status (dev, GRUB_ATA_STATUS_DRQ, 0))
+    return grub_errno;;
 
   /* 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_ata_regget (dev, GRUB_ATA_REG_ERROR);
+    return grub_error (GRUB_ERR_READ_ERROR, "ATA read error");
 
-  return 0;
+  return GRUB_ERR_NONE;
 }
 
 static grub_err_t
@@ -201,17 +224,18 @@
   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 device is ready to write.  */
-  grub_ata_wait_drq (dev);
+  /* Wait until the data is available.  */
+  if (grub_ata_wait_status (dev, GRUB_ATA_STATUS_DRQ, 0))
+    return 0;
 
   /* 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_ata_regget (dev, GRUB_ATA_REG_ERROR);
+    return grub_error (GRUB_ERR_WRITE_ERROR, "ATA write error");
 
-  return 0;
+  return GRUB_ERR_NONE;
 }
 
 static void
@@ -243,22 +267,33 @@
   if (! info)
     return grub_errno;
 
-  grub_ata_wait_busy (dev);
+  if (grub_ata_wait_status (dev, 0, GRUB_ATA_STATUS_BUSY))
+    {
+      grub_free (info);
+      return grub_errno;
+    }
 
   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 ();
 
-  grub_ata_pio_read (dev, info, 256);
+  if (grub_ata_cmd (dev, GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE))
+    {
+      grub_free (info);
+      return grub_errno;
+    }
 
+  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 0;
+  return GRUB_ERR_NONE;
 }
 
 static grub_err_t
@@ -269,12 +304,14 @@
   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);
-  grub_ata_regset (dev, GRUB_ATA_REG_CMD, GRUB_ATA_CMD_PACKET);
-  grub_ata_wait ();
 
-  grub_ata_pio_write (dev, packet, 12);
+  if (grub_ata_cmd (dev, GRUB_ATA_CMD_PACKET))
+    return grub_errno;
 
-  return 0;
+  if (grub_ata_pio_write (dev, packet, 12))
+    return grub_errno;
+
+  return GRUB_ERR_NONE;
 }
 
 static grub_err_t
@@ -282,7 +319,7 @@
 {
   char *info;
   grub_uint16_t *info16;
-  int ataerr;
+  int ataerr = 0;
 
   info = grub_malloc (GRUB_DISK_SECTOR_SIZE);
   if (! info)
@@ -290,13 +327,22 @@
 
   info16 = (grub_uint16_t *) info;
 
-  grub_ata_wait_busy (dev);
+  if (grub_ata_wait_status (dev, 0, GRUB_ATA_STATUS_BUSY))
+    {
+      grub_free (info);
+      return grub_errno;
+    }
 
   grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4);
-  grub_ata_regset (dev, GRUB_ATA_REG_CMD, GRUB_ATA_CMD_IDENTIFY_DEVICE);
+  if (grub_ata_cmd (dev, GRUB_ATA_CMD_IDENTIFY_DEVICE))
+    {
+      grub_free (info);
+      return grub_errno;
+    }
   grub_ata_wait ();
 
-  ataerr = grub_ata_pio_read (dev, info, GRUB_DISK_SECTOR_SIZE);
+  if (grub_ata_pio_read (dev, info, GRUB_DISK_SECTOR_SIZE))
+    ataerr = grub_ata_regget (dev, GRUB_ATA_REG_ERROR);
   if (ataerr & 4)
     {
       /* ATAPI device detected.  */
@@ -361,8 +407,8 @@
   /* Setup the device information.  */
   dev->port = port;
   dev->device = device;
-  dev->ioaddress = grub_ata_ioaddress[dev->port];
-  dev->ioaddress2 = grub_ata_ioaddress2[dev->port];
+  dev->ioaddress = addr;
+  dev->ioaddress2 = addr2;
   dev->next = NULL;
 
   /* Try to detect if the port is in use by writing to it,
@@ -381,8 +427,11 @@
   /* Detect if the device is present by issuing a EXECUTE
      DEVICE DIAGNOSTICS command.  */
   grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4);
-  grub_ata_regset (dev, GRUB_ATA_REG_CMD,
-		   GRUB_ATA_CMD_EXEC_DEV_DIAGNOSTICS);
+  if (grub_ata_cmd (dev, GRUB_ATA_CMD_EXEC_DEV_DIAGNOSTICS))
+    {
+      grub_free (dev);
+      return grub_errno;
+    }
   grub_ata_wait ();
 
   grub_dprintf ("ata", "Registers: %x %x %x %x\n",
@@ -399,19 +448,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.  */
@@ -429,7 +478,8 @@
 }
 
 static int
-grub_ata_pciinit (int bus, int device, int func, grub_pci_id_t pciid)
+grub_ata_pciinit (int bus, int device, int func,
+		  grub_pci_id_t pciid __attribute__((unused)))
 {
   static int compat_use[2] = { 0 };
   grub_pci_address_t addr;
@@ -439,6 +489,7 @@
   int rega;
   int regb;
   int i;
+  static int controller = 0;
 
   /* Read class.  */
   addr = grub_pci_make_address (bus, device, func, 2);
@@ -487,11 +538,13 @@
 
       if (rega && regb)
 	{
-	  grub_ata_device_initialize (i, 0, rega, regb);
-	  grub_ata_device_initialize (i, 1, rega, regb);
+	  grub_ata_device_initialize (controller * 2 + i, 0, rega, regb);
+	  grub_ata_device_initialize (controller * 2 + i, 1, rega, regb);
 	}
     }
 
+  controller++;
+
   return 0;
 }
 
@@ -519,7 +572,8 @@
 		     grub_disk_addr_t sector,
 		     grub_size_t size)
 {
-  grub_ata_wait_busy (dev);
+  if (grub_ata_wait_status (dev, 0, GRUB_ATA_STATUS_BUSY))
+    return grub_errno;
 
   switch (addressing)
     {
@@ -615,21 +669,31 @@
       if (rw == 0)
 	{
 	  /* Read 256/65536 sectors.  */
-	  grub_ata_regset (dev, GRUB_ATA_REG_CMD, cmd);
-	  grub_ata_wait ();
+	  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;
+
 	  for (sect = 0; sect < batch; sect++)
 	    {
 	      if (grub_ata_pio_read (dev, buf,
 				     GRUB_DISK_SECTOR_SIZE))
-		return grub_error (GRUB_ERR_READ_ERROR, "ATA read error");
+		return grub_errno;
 	      buf += GRUB_DISK_SECTOR_SIZE;
 	    }
 	}
       else
 	{
 	  /* Write 256/65536 sectors.  */
-	  grub_ata_regset (dev, GRUB_ATA_REG_CMD, cmd_write);
-	  grub_ata_wait ();
+	  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;
+
 	  for (sect = 0; sect < batch; sect++)
 	    {
 	      if (grub_ata_pio_write (dev, buf,
@@ -648,18 +712,28 @@
   if (rw == 0)
     {
       /* Read sectors.  */
-      grub_ata_regset (dev, GRUB_ATA_REG_CMD, cmd);
-      grub_ata_wait ();
+      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;
+
       for (sect = 0; sect < (size % batch); sect++)
 	{
 	  if (grub_ata_pio_read (dev, buf, GRUB_DISK_SECTOR_SIZE))
-	    return grub_error (GRUB_ERR_READ_ERROR, "ATA read error");
+	    return grub_errno;
 	  buf += GRUB_DISK_SECTOR_SIZE;
 	}
     } else {
       /* Write sectors.  */
-      grub_ata_regset (dev, GRUB_ATA_REG_CMD, cmd_write);
-      grub_ata_wait ();
+      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;
+
       for (sect = 0; sect < (size % batch); sect++)
 	{
 	  if (grub_ata_pio_write (dev, buf, GRUB_DISK_SECTOR_SIZE))
@@ -746,7 +820,8 @@
 
   grub_atapi_packet (dev, (char *) &readcmd);
   grub_ata_wait ();
-  grub_ata_pio_read (dev, buf, GRUB_CDROM_SECTOR_SIZE);
+  if (grub_ata_pio_read (dev, buf, GRUB_CDROM_SECTOR_SIZE))
+    return grub_errno;
 
   return 0;
 }

Modified: trunk/grub2/include/grub/err.h
===================================================================
--- trunk/grub2/include/grub/err.h	2008-08-07 22:55:50 UTC (rev 1795)
+++ trunk/grub2/include/grub/err.h	2008-08-07 23:37:33 UTC (rev 1796)
@@ -51,7 +51,8 @@
     GRUB_ERR_NOT_IMPLEMENTED_YET,
     GRUB_ERR_SYMLINK_LOOP,
     GRUB_ERR_BAD_GZIP_DATA,
-    GRUB_ERR_MENU
+    GRUB_ERR_MENU,
+    GRUB_ERR_TIMEOUT
   }
 grub_err_t;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.