grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

PCI support


From: Marco Gerards
Subject: PCI support
Date: Mon, 28 Jan 2008 15:03:33 +0100
User-agent: Gnus/5.110006 (No Gnus v0.6) Emacs/21.4 (gnu/linux)

Hi,

Here is a patch that allows you to iterate over PCI devices.  The file
pci.c adds a function to iterate over the devices and a function to
generate an address to query the PCI device.  Furthermore, there is a
function to actually access the hardware, which is machine specific.
I only implemented this for i386-pc.  I assume it can be shared with
linuxbios, i386-efi and i386-ieee1275.  When you want to use this,
just include <grub/pci.h>.

When you want to detect if your device is supported, just use
grub_pci_iterate.  It gives you every PCI device.  For example, the
class has to be read to determine if a device is an ATA device.  This
will be added to the ATA driver.

The lspci that is included shows the PCIID and the class of the
device.  It's not capable of reading pci.ids yet.  I have some code
for this, but it is just too damn slow...  But I am sure this will do
for now
:-)

I wanted to wait with this patch until the ATA driver is adapted.  But
I won't have time for that this week.  So I can better get this
committed and people working on this ;-).  There is some code for ATA,
but it was not tested yet.  The main problem here is qemu.

Does someone know if it is possible, at all, to have ATA devices
showing up as non-legacy PCI devices in Qemu?  IDE interfaces are
placed (and locked) in Legacy mode, meaning default IRQs and IO ports
are used.  This means just our old ISA code will be used.  To support
non-legacy modes, it would be nice if I could do some testing.  Does
someone have suggestions?

--
Marco



2009-01-28  Marco Gerards  <address@hidden>

        * bus/pci.c: New file.

        * include/grub/pci.h: Likewise.

        * include/grub/i386/pc/pci.h: Likewise.

        * commands/lspci.c: Likewise.

        * conf/i386-pc.rmk (pkglib_MODULES): Add `pci.mod' and
        `lspci.mod'.
        (pci_mod_SOURCES): New variable.
        (pci_mod_CFLAGS): Likewise.
        (pci_mod_LDFLAGS): Likewise.
        (lspci_mod_SOURCES): Likewise.
        (lspci_mod_CFLAGS): Likewise.
        (lspci_mod_LDFLAGS): Likewise.  


Index: bus/pci.c
===================================================================
RCS file: bus/pci.c
diff -N bus/pci.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ bus/pci.c   28 Jan 2008 13:47:00 -0000
@@ -0,0 +1,55 @@
+/* pci.c - Generic PCI interfaces.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/pci.h>
+
+grub_pci_address_t
+grub_pci_make_address (int bus, int device, int function, int reg)
+{
+  return (1 << 31) | (bus << 16) | (device << 11) | (function << 8) | (reg << 
2);
+}
+
+void
+grub_pci_iterate (grub_pci_iteratefunc_t hook)
+{
+  int bus;
+  int dev;
+  int func;
+  grub_pci_address_t addr;
+  grub_pci_id_t id;
+
+  for (bus = 0; bus < 256; bus++)
+    {
+      for (dev = 0; dev < 32; dev++)
+       {
+         for (func = 0; func < 3; func++)
+           {
+             addr = grub_pci_make_address (bus, dev, func, 0);
+             id = grub_pci_read (addr);
+
+             /* Check if there is a device present.  */
+             if (id >> 16 == 0xFFFF)
+               continue;
+
+             hook (bus, dev, func, id);
+           }
+       }
+    }
+}
Index: commands/lspci.c
===================================================================
RCS file: commands/lspci.c
diff -N commands/lspci.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ commands/lspci.c    28 Jan 2008 13:47:00 -0000
@@ -0,0 +1,163 @@
+/* lspci.c - List PCI devices.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2007  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/pci.h>
+#include <grub/dl.h>
+#include <grub/normal.h>
+#include <grub/misc.h>
+
+struct grub_pci_classname
+{
+  int class;
+  int subclass;
+  char *desc;
+};
+
+static const struct grub_pci_classname grub_pci_classes[] =
+  {
+    { 0, 0, "" },
+    { 1, 0, "SCSCI Controller" },
+    { 1, 1, "IDE Controller" },
+    { 1, 2, "Floppy Controller" },
+    { 1, 3, "IPI Controller" },
+    { 1, 4, "RAID Controller" },
+    { 1, 0x80, "Mass storage Controller" },
+    { 2, 0, "Ethernet Controller" },
+    { 2, 1, "Token Ring Controller" },
+    { 2, 2, "FDDI Controller" },
+    { 2, 3, "ATM Controller" },
+    { 2, 4, "ISDN Controller" },
+    { 2, 0x80, "Network controller" },
+    { 3, 0, "VGA Controller" },
+    { 3, 1, "XGA Controller" },
+    { 3, 2, "3D Controller" },
+    { 3, 0x80, "Display Controller" },
+    { 4, 0, "Multimedia Video Device" },
+    { 4, 1, "Multimedia Audio Device" },
+    { 4, 2, "Multimedia Telephony Device" },
+    { 4, 0x80, "Multimedia device" },
+    { 5, 0, "RAM Controller" },
+    { 5, 1, "Flash Memory Controller" },
+    { 5, 0x80, "Memory Controller" },
+    { 6, 0, "Host Bridge" },
+    { 6, 1, "ISA Bridge" },
+    { 6, 2, "EISA Bride" },
+    { 6, 3, "MCA Bridge" },
+    { 6, 4, "PCI-PCI Bridge" },
+    { 6, 5, "PCMCIA Bridge" },
+    { 6, 6, "NuBus Bridge" },
+    { 6, 7, "CardBus Bridge" },
+    { 6, 8, "Raceway Bridge" },
+    { 6, 0x80, "Unknown Bridge" },
+    { 7, 0x80, "Communication controller" },
+    { 8, 0x80, "System hardware" },
+    { 9, 0, "Keyboard Controller" },
+    { 9, 1, "Digitizer" },
+    { 9, 2, "Mouse Controller" },
+    { 9, 3, "Scanner Controller" },
+    { 9, 4, "Gameport Controller" },
+    { 9, 0x80, "Unknown Input Device" },
+    { 10, 0, "Generic Docking Station" },
+    { 10, 0x80, "Unkown Docking Station" },
+    { 11, 0, "80386 Processor" },
+    { 11, 1, "80486 Processor" },
+    { 11, 2, "Pentium Processor" },
+    { 11, 0x10, "Alpha Processor" },
+    { 11, 0x20, "PowerPC Processor" },
+    { 11, 0x30, "MIPS Processor" },
+    { 11, 0x40, "Co-Processor" },
+    { 11, 0x80, "Unkown Processor" },
+    { 12, 0x80, "Serial Bus Controller" },
+    { 13, 0x80, "Wireless Controller" },
+    { 14, 0, "I2O" },
+    { 15, 0, "iRDA Controller" },
+    { 15, 1, "Consumer IR" },
+    { 15, 0x10, "RF-Controller" },
+    { 15, 0x80, "Satellite Communication Controller" },
+    { 16, 0, "Network Decryption" },
+    { 16, 1, "Entertainment Decryption" },
+    { 16, 0x80, "Unkown Decryption Controller" },
+    { 17, 0, "Digital IO Module" },
+    { 17, 0x80, "Unkown Data Input System" },
+    { 0, 0, 0 },
+  };
+
+static const char *
+grub_pci_get_class (int class, int subclass)
+{
+  const struct grub_pci_classname *curr = grub_pci_classes;
+
+  while (curr->desc)
+    {
+      if (curr->class == class && curr->subclass == subclass)
+       return curr->desc;
+      curr++;
+    }
+
+  return 0;
+}
+
+static int
+grub_lspci_iter (int bus, int dev, int func, grub_pci_id_t pciid)
+{
+  grub_uint32_t class;
+  const char *sclass;
+  grub_pci_address_t addr;
+
+  grub_printf ("%02x:%02x.%x %04x:%04x.%d", 0, dev, func, pciid >> 16, pciid & 
0xFFFF, func);
+  addr = grub_pci_make_address (bus, dev, func, 2);
+  class = grub_pci_read (addr);
+         
+  /* Lookup the class name, if there isn't a specific one,
+     retry with 0x80 to get the generic class name.  */
+  sclass = grub_pci_get_class (class >> 24, (class >> 16) & 0xFF);
+  if (! sclass)
+    sclass = grub_pci_get_class (class >> 24, 0x80);
+  if (! sclass)
+    sclass = "";
+
+  grub_printf (" %s\n", sclass);
+
+  return 0;
+}
+
+static grub_err_t
+grub_cmd_lspci (struct grub_arg_list *state __attribute__ ((unused)),
+               int argc __attribute__ ((unused)),
+               char **args __attribute__ ((unused)))
+{
+  grub_pci_iterate (grub_lspci_iter);
+  return GRUB_ERR_NONE;
+}
+
+
+
+
+GRUB_MOD_INIT(pci)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("lspci", grub_cmd_lspci, GRUB_COMMAND_FLAG_BOTH,
+                        "lspci", "List PCI devices", 0);
+}
+
+
+GRUB_MOD_FINI(pci)
+{
+  grub_unregister_command ("lspci");
+}
Index: conf/i386-pc.rmk
===================================================================
RCS file: /sources/grub/grub2/conf/i386-pc.rmk,v
retrieving revision 1.100
diff -u -p -u -p -r1.100 i386-pc.rmk
--- conf/i386-pc.rmk    6 Jan 2008 15:34:11 -0000       1.100
+++ conf/i386-pc.rmk    28 Jan 2008 13:47:00 -0000
@@ -136,7 +136,7 @@ pkglib_MODULES = biosdisk.mod _chain.mod
        _multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod      \
        vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \
        videotest.mod play.mod bitmap.mod tga.mod cpuid.mod serial.mod  \
-       ata.mod vga.mod
+       ata.mod vga.mod pci.mod lspci.mod
 
 # For biosdisk.mod.
 biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -264,4 +264,14 @@ vga_mod_SOURCES = term/i386/pc/vga.c
 vga_mod_CFLAGS = $(COMMON_CFLAGS)
 vga_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For pci.mod
+pci_mod_SOURCES = bus/pci.c
+pci_mod_CFLAGS = $(COMMON_CFLAGS)
+pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lspci.mod
+lspci_mod_SOURCES = commands/lspci.c
+lspci_mod_CFLAGS = $(COMMON_CFLAGS)
+lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
Index: include/grub/pci.h
===================================================================
RCS file: include/grub/pci.h
diff -N include/grub/pci.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ include/grub/pci.h  28 Jan 2008 13:47:00 -0000
@@ -0,0 +1,37 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef        GRUB_PCI_H
+#define        GRUB_PCI_H      1
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+
+typedef grub_uint32_t grub_pci_id_t;
+typedef int (*grub_pci_iteratefunc_t) (int bus, int device, int func,
+                                      grub_pci_id_t pciid);
+typedef grub_uint32_t grub_pci_address_t;
+
+grub_pci_address_t EXPORT_FUNC(grub_pci_make_address) (int bus, int device,
+                                                      int function, int reg);
+
+void EXPORT_FUNC(grub_pci_iterate) (grub_pci_iteratefunc_t hook);
+
+#include <grub/machine/pci.h>
+
+#endif /* GRUB_PCI_H */
Index: include/grub/i386/pc/pci.h
===================================================================
RCS file: include/grub/i386/pc/pci.h
diff -N include/grub/i386/pc/pci.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ include/grub/i386/pc/pci.h  28 Jan 2008 13:47:01 -0000
@@ -0,0 +1,35 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef        GRUB_CPU_PCI_H
+#define        GRUB_CPU_PCI_H  1
+
+#include <grub/types.h>
+#include <grub/i386/io.h>
+
+#define GRUB_PCI_ADDR_REG      0xcf8
+#define GRUB_PCI_DATA_REG      0xcfc
+
+static inline grub_uint32_t
+grub_pci_read (grub_pci_address_t addr)
+{
+  grub_outl (addr, GRUB_PCI_ADDR_REG);
+  return grub_inl (GRUB_PCI_DATA_REG);
+}
+
+#endif /* GRUB_CPU_PCI_H */





reply via email to

[Prev in Thread] Current Thread [Next in Thread]