[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[1773] 2008-08-05 Marco Gerards <address@hidden>
From: |
Marco Gerards |
Subject: |
[1773] 2008-08-05 Marco Gerards <address@hidden> |
Date: |
Tue, 05 Aug 2008 09:41:11 +0000 |
Revision: 1773
http://svn.sv.gnu.org/viewvc/?view=rev&root=grub&revision=1773
Author: marco_g
Date: 2008-08-05 09:41:10 +0000 (Tue, 05 Aug 2008)
Log Message:
-----------
2008-08-05 Marco Gerards <address@hidden>
* disk/ata.c: Include <grub/pci.h>.
(enum grub_ata_commands): Add `GRUB_ATA_CMD_EXEC_DEV_DIAGNOSTICS'.
(grub_ata_initialize): Rewritten.
(grub_ata_device_initialize): New function.
Modified Paths:
--------------
trunk/grub2/ChangeLog
trunk/grub2/disk/ata.c
Modified: trunk/grub2/ChangeLog
===================================================================
--- trunk/grub2/ChangeLog 2008-08-04 22:54:06 UTC (rev 1772)
+++ trunk/grub2/ChangeLog 2008-08-05 09:41:10 UTC (rev 1773)
@@ -1,3 +1,10 @@
+2008-08-05 Marco Gerards <address@hidden>
+
+ * disk/ata.c: Include <grub/pci.h>.
+ (enum grub_ata_commands): Add `GRUB_ATA_CMD_EXEC_DEV_DIAGNOSTICS'.
+ (grub_ata_initialize): Rewritten.
+ (grub_ata_device_initialize): New function.
+
2008-08-04 Pavel Roskin <address@hidden>
* kern/main.c: Include grub/mm.h.
Modified: trunk/grub2/disk/ata.c
===================================================================
--- trunk/grub2/disk/ata.c 2008-08-04 22:54:06 UTC (rev 1772)
+++ trunk/grub2/disk/ata.c 2008-08-05 09:41:10 UTC (rev 1773)
@@ -22,6 +22,7 @@
#include <grub/disk.h>
#include <grub/mm.h>
#include <grub/time.h>
+#include <grub/pci.h>
/* XXX: For now this only works on i386. */
#include <grub/cpu/io.h>
@@ -71,7 +72,8 @@
GRUB_ATA_CMD_WRITE_SECTORS_EXT = 0x34,
GRUB_ATA_CMD_IDENTIFY_DEVICE = 0xEC,
GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE = 0xA1,
- GRUB_ATA_CMD_PACKET = 0xA0
+ GRUB_ATA_CMD_PACKET = 0xA0,
+ GRUB_ATA_CMD_EXEC_DEV_DIAGNOSTICS = 0x90
};
struct grub_ata_device
@@ -344,82 +346,163 @@
}
static grub_err_t
-grub_ata_initialize (void)
+grub_ata_device_initialize (int port, int device, int addr, int addr2)
{
struct grub_ata_device *dev;
struct grub_ata_device **devp;
- int port;
- int device;
- for (port = 0; port <= 1; port++)
+ grub_dprintf ("ata", "detecting device %d,%d (0x%x, 0x%x)\n",
+ port, device, addr, addr2);
+
+ dev = grub_malloc (sizeof(*dev));
+ if (! dev)
+ return grub_errno;
+
+ /* 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->next = NULL;
+
+ /* Try to detect if the port is in use by writing to it,
+ waiting for a while and reading it again. If the value
+ was preserved, there is a device connected. */
+ grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4);
+ grub_ata_wait ();
+ grub_ata_regset (dev, GRUB_ATA_REG_SECTORS, 0x5A);
+ grub_ata_wait ();
+ if (grub_ata_regget (dev, GRUB_ATA_REG_SECTORS) != 0x5A)
{
- for (device = 0; device <= 1; device++)
- {
- dev = grub_malloc (sizeof(*dev));
- if (! dev)
- return grub_errno;
+ grub_free(dev);
+ return 0;
+ }
- /* 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->next = NULL;
+ /* 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);
+ grub_ata_wait ();
- /* Try to detect if the port is in use by writing to it,
- waiting for a while and reading it again. If the value
- was preserved, there is a device connected. */
- grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4);
- grub_ata_wait ();
- grub_ata_regset (dev, GRUB_ATA_REG_SECTORS, 0x5A);
- grub_ata_wait ();
- if (grub_ata_regget (dev, GRUB_ATA_REG_SECTORS) != 0x5A)
- {
- grub_free(dev);
- continue;
- }
+ grub_dprintf ("ata", "Registers: %x %x %x %x\n",
+ grub_ata_regget (dev, GRUB_ATA_REG_SECTORS),
+ grub_ata_regget (dev, GRUB_ATA_REG_LBALOW),
+ grub_ata_regget (dev, GRUB_ATA_REG_LBAMID),
+ grub_ata_regget (dev, GRUB_ATA_REG_LBAHIGH));
- /* Detect if the device is present by issuing a reset. */
- grub_ata_regset2 (dev, GRUB_ATA_REG2_CONTROL, 6);
- grub_ata_wait ();
- grub_ata_regset2 (dev, GRUB_ATA_REG2_CONTROL, 2);
- grub_ata_wait ();
- grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4);
- grub_ata_wait ();
+ /* Check some registers to see if the channel is used. */
+ 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) == 0x14
+ && grub_ata_regget (dev, GRUB_ATA_REG_LBAHIGH) == 0xeb)
+ {
+ 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))
+ {
+ grub_dprintf ("ata", "incorrect signature\n");
+ grub_free (dev);
+ return 0;
+ }
+ else
+ {
+ grub_dprintf ("ata", "ATA detected\n");
+ }
- /* XXX: Check some registers to see if the reset worked as
- expected for this device. */
-#if 1
- /* Enable for ATAPI . */
- if (grub_ata_regget (dev, GRUB_ATA_REG_CYLLSB) != 0x14
- || grub_ata_regget (dev, GRUB_ATA_REG_CYLMSB) != 0xeb)
-#endif
- if (grub_ata_regget (dev, GRUB_ATA_REG_STATUS) == 0
- || (grub_ata_regget (dev, GRUB_ATA_REG_CYLLSB) != 0
- && grub_ata_regget (dev, GRUB_ATA_REG_CYLMSB) != 0
- && grub_ata_regget (dev, GRUB_ATA_REG_CYLLSB) != 0x3c
- && grub_ata_regget (dev, GRUB_ATA_REG_CYLLSB) != 0xc3))
- {
- grub_free (dev);
- continue;
- }
- /* Use the IDENTIFY DEVICE command to query the device. */
- if (grub_ata_identify (dev))
+ /* Use the IDENTIFY DEVICE command to query the device. */
+ if (grub_ata_identify (dev))
+ {
+ grub_free (dev);
+ return 0;
+ }
+
+ /* Register the device. */
+ for (devp = &grub_ata_devices; *devp; devp = &(*devp)->next);
+ *devp = dev;
+
+ return 0;
+}
+
+static int
+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;
+ grub_uint32_t class;
+ grub_uint32_t bar1;
+ grub_uint32_t bar2;
+ int rega;
+ int regb;
+ int i;
+
+ /* Read class. */
+ addr = grub_pci_make_address (bus, device, func, 2);
+ class = grub_pci_read (addr);
+
+ /* Check if this class ID matches that of a PCI IDE Controller. */
+ if (class >> 16 != 0x0101)
+ return 0;
+
+ for (i = 0; i < 2; i++)
+ {
+ /* Set to 0 when the channel operated in compatibility mode. */
+ int compat = (class >> (2 * i)) & 1;
+
+ rega = 0;
+ regb = 0;
+
+ /* If the channel is in compatibility mode, just assign the
+ default registers. */
+ if (compat == 0 && !compat_use[i])
+ {
+ rega = grub_ata_ioaddress[i];
+ regb = grub_ata_ioaddress2[i];
+ compat_use[i] = 0;
+ }
+ else if (compat)
+ {
+ /* Read the BARs, which either contain a mmapped IO address
+ or the IO port address. */
+ addr = grub_pci_make_address (bus, device, func, 4 + 2 * i);
+ bar1 = grub_pci_read (addr);
+ addr = grub_pci_make_address (bus, device, func, 5 + 2 * i);
+ bar2 = grub_pci_read (addr);
+
+ /* Check if the BARs describe an IO region. */
+ if ((bar1 & 1) && (bar2 & 1))
{
- grub_free (dev);
- continue;
+ rega = bar1 & ~3;
+ regb = bar2 & ~3;
}
+ }
- /* Register the device. */
- for (devp = &grub_ata_devices; *devp; devp = &(*devp)->next);
- *devp = dev;
+ grub_dprintf ("ata",
+ "PCI dev (%d,%d,%d) compat=%d rega=0x%x regb=0x%x\n",
+ bus, device, func, compat, rega, regb);
+
+ if (rega && regb)
+ {
+ grub_ata_device_initialize (i, 0, rega, regb);
+ grub_ata_device_initialize (i, 1, rega, regb);
}
}
return 0;
}
+static grub_err_t
+grub_ata_initialize (void)
+{
+ grub_pci_iterate (grub_ata_pciinit);
+ return 0;
+}
+
+
static void
grub_ata_setlba (struct grub_ata_device *dev, grub_disk_addr_t sector,
grub_size_t size)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [1773] 2008-08-05 Marco Gerards <address@hidden>,
Marco Gerards <=