From 3affd0ece8f6af300e6b33eb796da59bd46037a2 Mon Sep 17 00:00:00 2001 From: phcoder Date: Wed, 14 Oct 2009 10:11:59 +0200 Subject: [PATCH] libpci initial stuff --- Makefile.in | 2 ++ bus/pci.c | 23 ++++++++--------- bus/usb/ohci.c | 6 ++--- bus/usb/uhci.c | 6 ++--- commands/lspci.c | 11 +++++--- conf/i386-pc.rmk | 7 ++++- configure.ac | 11 +++++++- disk/ata.c | 11 ++++---- include/grub/i386/pci.h | 5 ++++ include/grub/pci.h | 45 ++++++++++++++++++++++++++------ util/pci.c | 57 +++++++++++++++++++++++++++++++++++++++++ 11 files changed, 147 insertions(+), 37 deletions(-) create mode 100644 util/pci.c diff --git a/Makefile.in b/Makefile.in index e0edbdb04..4e45dc569 100644 --- a/Makefile.in +++ b/Makefile.in @@ -100,12 +100,14 @@ endif AWK = @AWK@ LIBCURSES = @LIBCURSES@ LIBUSB = @LIBUSB@ +LIBPCI = @LIBPCI@ YACC = @YACC@ UNIFONT_BDF = @UNIFONT_BDF@ # Options. enable_grub_emu = @enable_grub_emu@ enable_grub_emu_usb = @enable_grub_emu_usb@ +enable_grub_emu_pci = @enable_grub_emu_pci@ enable_grub_fstest = @enable_grub_fstest@ enable_grub_pe2elf = @enable_grub_pe2elf@ enable_grub_mkfont = @enable_grub_mkfont@ diff --git a/bus/pci.c b/bus/pci.c index 2c29c03ab..fe4cad181 100644 --- a/bus/pci.c +++ b/bus/pci.c @@ -21,41 +21,40 @@ #include grub_pci_address_t -grub_pci_make_address (int bus, int device, int function, int reg) +grub_pci_make_address (grub_pci_device_t dev, int reg) { - return (1 << 31) | (bus << 16) | (device << 11) | (function << 8) | (reg << 2); + return (1 << 31) | (dev.bus << 16) | (dev.device << 11) + | (dev.function << 8) | (reg << 2); } void grub_pci_iterate (grub_pci_iteratefunc_t hook) { - int bus; - int dev; - int func; + grub_pci_device_t dev; grub_pci_address_t addr; grub_pci_id_t id; grub_uint32_t hdr; - for (bus = 0; bus < 256; bus++) + for (dev.bus = 0; dev.bus < 256; dev.bus++) { - for (dev = 0; dev < 32; dev++) + for (dev.device = 0; dev.device < 32; dev.device++) { - for (func = 0; func < 8; func++) + for (dev.function = 0; dev.function < 8; dev.function++) { - addr = grub_pci_make_address (bus, dev, func, 0); + addr = grub_pci_make_address (dev, 0); id = grub_pci_read (addr); /* Check if there is a device present. */ if (id >> 16 == 0xFFFF) continue; - if (hook (bus, dev, func, id)) + if (hook (dev, id)) return; /* Probe only func = 0 if the device if not multifunction */ - if (func == 0) + if (dev.function == 0) { - addr = grub_pci_make_address (bus, dev, func, 3); + addr = grub_pci_make_address (dev, 3); hdr = grub_pci_read (addr); if (!(hdr & 0x800000)) break; diff --git a/bus/usb/ohci.c b/bus/usb/ohci.c index 32fb7cf91..5fe9c9507 100644 --- a/bus/usb/ohci.c +++ b/bus/usb/ohci.c @@ -113,7 +113,7 @@ grub_ohci_writereg32 (struct grub_ohci *o, /* Iterate over all PCI devices. Determine if a device is an OHCI controller. If this is the case, initialize it. */ static int NESTED_FUNC_ATTR -grub_ohci_pci_iter (int bus, int device, int func, +grub_ohci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__((unused))) { grub_uint32_t class_code; @@ -126,7 +126,7 @@ grub_ohci_pci_iter (int bus, int device, int func, grub_uint32_t revision; grub_uint32_t frame_interval; - addr = grub_pci_make_address (bus, device, func, 2); + addr = grub_pci_make_address (dev, 2); class_code = grub_pci_read (addr) >> 8; interf = class_code & 0xFF; @@ -138,7 +138,7 @@ grub_ohci_pci_iter (int bus, int device, int func, return 0; /* Determine IO base address. */ - addr = grub_pci_make_address (bus, device, func, 4); + addr = grub_pci_make_address (dev, 4); base = grub_pci_read (addr); #if 0 diff --git a/bus/usb/uhci.c b/bus/usb/uhci.c index 88ff5b3d8..0d3daa5f1 100644 --- a/bus/usb/uhci.c +++ b/bus/usb/uhci.c @@ -138,7 +138,7 @@ grub_uhci_portstatus (grub_usb_controller_t dev, /* Iterate over all PCI devices. Determine if a device is an UHCI controller. If this is the case, initialize it. */ static int NESTED_FUNC_ATTR -grub_uhci_pci_iter (int bus, int device, int func, +grub_uhci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__((unused))) { grub_uint32_t class_code; @@ -151,7 +151,7 @@ grub_uhci_pci_iter (int bus, int device, int func, struct grub_uhci *u; int i; - addr = grub_pci_make_address (bus, device, func, 2); + addr = grub_pci_make_address (dev, 2); class_code = grub_pci_read (addr) >> 8; interf = class_code & 0xFF; @@ -163,7 +163,7 @@ grub_uhci_pci_iter (int bus, int device, int func, return 0; /* Determine IO base address. */ - addr = grub_pci_make_address (bus, device, func, 8); + addr = grub_pci_make_address (dev, 8); base = grub_pci_read (addr); /* Stop if there is no IO space base address defined. */ if (! (base & 1)) diff --git a/commands/lspci.c b/commands/lspci.c index 5b3360a37..10618c7a9 100644 --- a/commands/lspci.c +++ b/commands/lspci.c @@ -115,15 +115,16 @@ grub_pci_get_class (int class, int subclass) } static int NESTED_FUNC_ATTR -grub_lspci_iter (int bus, int dev, int func, grub_pci_id_t pciid) +grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) { grub_uint32_t class; const char *sclass; grub_pci_address_t addr; - grub_printf ("%02x:%02x.%x %04x:%04x", bus, dev, func, pciid & 0xFFFF, - pciid >> 16); - addr = grub_pci_make_address (bus, dev, func, 2); + grub_printf ("%02x:%02x.%x %04x:%04x", grub_pci_get_bus (dev), + grub_pci_get_device (dev), grub_pci_get_function (dev), + pciid & 0xFFFF, pciid >> 16); + addr = grub_pci_make_address (dev, 2); class = grub_pci_read (addr); /* Lookup the class name, if there isn't a specific one, @@ -142,6 +143,8 @@ grub_lspci_iter (int bus, int dev, int func, grub_pci_id_t pciid) grub_printf ("\n"); + grub_pci_close (dev); + return 0; } diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index bf8fbfb9d..107ae7a22 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -165,7 +165,12 @@ grub_emu_LDFLAGS = $(LIBCURSES) ifeq ($(enable_grub_emu_usb), yes) grub_emu_SOURCES += disk/usbms.c util/usb.c bus/usb/usb.c \ commands/usbtest.c -grub_emu_LDFLAGS += $(LIBCURSES) $(LIBUSB) +grub_emu_LDFLAGS += $(LIBUSB) +endif + +ifeq ($(enable_grub_emu_pci), yes) +grub_emu_SOURCES += util/pci.c commands/lspci.c +grub_emu_LDFLAGS += $(LIBPCI) endif # Scripts. diff --git a/configure.ac b/configure.ac index 3e4da66c8..5a98e3433 100644 --- a/configure.ac +++ b/configure.ac @@ -499,6 +499,10 @@ AC_ARG_ENABLE([grub-emu], AC_ARG_ENABLE([grub-emu-usb], [AS_HELP_STRING([--enable-grub-emu-usb], [build and install the `grub-emu' debugging utility with USB support (default=guessed)])]) +AC_ARG_ENABLE([grub-emu-pci], + [AS_HELP_STRING([--enable-grub-emu-pci], + [build and install the `grub-emu' debugging utility with PCI support (potentially dangerous) (default=no)])]) + if test x"$enable_grub_emu" = xno ; then grub_emu_excuse="explicitly disabled" fi @@ -541,7 +545,7 @@ AC_CHECK_LIB([usb], [usb_claim_interface], [LIBUSB="-lusb"], AC_CHECK_HEADERS([usb.h], [], [grub_emu_usb_excuse=["need libusb headers"]]) [fi] -if test x"enable_grub_emu_usb" = xyes && test x"$grub_emu_usb_excuse" != x ; then +if test x"$enable_grub_emu_usb" = xyes && test x"$grub_emu_usb_excuse" != x ; then AC_MSG_ERROR([USB support for grub-emu was explicitly requested but can't be compiled]) fi if test x"$grub_emu_usb_excuse" = x ; then @@ -550,8 +554,13 @@ else enable_grub_emu_usb=no fi +if test x"$enable_grub_emu_pci" != xyes ; then + enable_grub_emu_pci = no +fi + AC_SUBST([enable_grub_emu]) AC_SUBST([enable_grub_emu_usb]) +AC_SUBST([enable_grub_emu_pci]) AC_ARG_ENABLE([grub-fstest], [AS_HELP_STRING([--enable-grub-fstest], diff --git a/disk/ata.c b/disk/ata.c index 78d396526..ef6b44184 100644 --- a/disk/ata.c +++ b/disk/ata.c @@ -388,7 +388,7 @@ grub_ata_device_initialize (int port, int device, int addr, int addr2) } static int NESTED_FUNC_ATTR -grub_ata_pciinit (int bus, int device, int func, +grub_ata_pciinit (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__((unused))) { static int compat_use[2] = { 0 }; @@ -402,7 +402,7 @@ grub_ata_pciinit (int bus, int device, int func, static int controller = 0; /* Read class. */ - addr = grub_pci_make_address (bus, device, func, 2); + addr = grub_pci_make_address (dev, 2); class = grub_pci_read (addr); /* Check if this class ID matches that of a PCI IDE Controller. */ @@ -429,9 +429,9 @@ grub_ata_pciinit (int bus, int device, int func, { /* 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); + addr = grub_pci_make_address (dev, 4 + 2 * i); bar1 = grub_pci_read (addr); - addr = grub_pci_make_address (bus, device, func, 5 + 2 * i); + addr = grub_pci_make_address (dev, 5 + 2 * i); bar2 = grub_pci_read (addr); /* Check if the BARs describe an IO region. */ @@ -444,7 +444,8 @@ grub_ata_pciinit (int bus, int device, int func, grub_dprintf ("ata", "PCI dev (%d,%d,%d) compat=%d rega=0x%x regb=0x%x\n", - bus, device, func, compat, rega, regb); + grub_pci_get_bus (dev), grub_pci_get_device (dev), + grub_pci_get_function (dev), compat, rega, regb); if (rega && regb) { diff --git a/include/grub/i386/pci.h b/include/grub/i386/pci.h index 996f64245..c8de9ff32 100644 --- a/include/grub/i386/pci.h +++ b/include/grub/i386/pci.h @@ -67,4 +67,9 @@ grub_pci_write_byte (grub_pci_address_t addr, grub_uint8_t data) grub_outb (data, GRUB_PCI_DATA_REG + (addr & 3)); } +static inline void +grub_pci_close (grub_pci_device_t dev __attribute__ ((unused))) +{ +} + #endif /* GRUB_CPU_PCI_H */ diff --git a/include/grub/pci.h b/include/grub/pci.h index 7c8b50528..2bea05410 100644 --- a/include/grub/pci.h +++ b/include/grub/pci.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2008 Free Software Foundation, Inc. + * Copyright (C) 2008,2009 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 @@ -36,15 +36,44 @@ #define GRUB_PCI_ADDR_IO_MASK ~0x03 typedef grub_uint32_t grub_pci_id_t; -typedef int NESTED_FUNC_ATTR (*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); +#ifdef GRUB_UTIL +#include +#else +typedef grub_uint32_t grub_pci_address_t; +struct grub_pci_device +{ + int bus; + int device; + int function; +}; +typedef struct grub_pci_device grub_pci_device_t; +static inline int +grub_pci_get_bus (grub_pci_device_t dev) +{ + return dev.bus; +} + +static inline int +grub_pci_get_device (grub_pci_device_t dev) +{ + return dev.device; +} + +static inline int +grub_pci_get_function (grub_pci_device_t dev) +{ + return dev.function; +} +#include +#endif + +typedef int NESTED_FUNC_ATTR (*grub_pci_iteratefunc_t) + (grub_pci_device_t dev, grub_pci_id_t pciid); + +grub_pci_address_t EXPORT_FUNC(grub_pci_make_address) (grub_pci_device_t dev, + int reg); void EXPORT_FUNC(grub_pci_iterate) (grub_pci_iteratefunc_t hook); -#include - #endif /* GRUB_PCI_H */ diff --git a/util/pci.c b/util/pci.c new file mode 100644 index 000000000..99962c31d --- /dev/null +++ b/util/pci.c @@ -0,0 +1,57 @@ +/* pci.c - Generic PCI interfaces. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2009 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 . + */ + +#include +#include + +struct pci_access *acc = 0; + +grub_pci_address_t +grub_pci_make_address (grub_pci_device_t dev, int reg) +{ + grub_pci_address_t ret; + ret.dev = dev; + ret.pos = reg << 2; + return ret; +} + +void +grub_pci_close (grub_pci_device_t dev) +{ + pci_free_dev (dev); +} + +void +grub_pci_iterate (grub_pci_iteratefunc_t hook) +{ + grub_pci_device_t cur; + for (cur = acc->devices; cur; cur = cur->next) + hook (cur, cur->vendor_id|(cur->device_id << 16)); +} + +GRUB_MOD_INIT (pci) +{ + acc = pci_alloc (); + pci_init (acc); +} + +GRUB_MOD_FINI (pci) +{ + pci_cleanup (acc); +}