Hello, Here is a patch to add pci support to grub2.
2006-05-16 Vincent Guffens <[EMAIL PROTECTED]> * drivers/: New directory * conf/i386-pc.rmk (pkgdata_MODULES): Added pci.mod to the list of modules. (DRIVERS_CFLAGS): Added. (pci_mod_SOURCES): Likewise. (pci_mod_CFLAGS): Likewise. (pci_mod_LDFLAGS): Likewise. * drivers/include/grub/pci.h: New file. * drivers/include/grub/list.h: Likewise. * drivers/pci/pci.c: Likewise. diff -rNu grub2/ChangeLog grub2-pci/ChangeLog --- grub2/ChangeLog 2006-05-14 22:16:16.000000000 +0100 +++ grub2-pci/ChangeLog 2006-05-16 21:51:22.000000000 +0100 @@ -1,3 +1,18 @@ +2006-05-16 Vincent Guffens <[EMAIL PROTECTED]> + + * drivers/: New directory. + + * conf/i386-pc.rmk (pkgdata_MODULES): Added pci.mod + to the list of modules. + (DRIVERS_CFLAGS): Added. + (pci_mod_SOURCES): Likewise. + (pci_mod_CFLAGS): Likewise. + (pci_mod_LDFLAGS): Likewise. + + * drivers/include/grub/pci.h: New file. + * drivers/include/grub/list.h: Likewise. + * drivers/pci/pci.c: Likewise. + 2006-05-14 Yoshinori K. Okuji <[EMAIL PROTECTED]> * kern/i386/pc/startup.S: Include grub/cpu/linux.h instead of diff -rNu grub2/conf/i386-pc.rmk grub2-pci/conf/i386-pc.rmk --- grub2/conf/i386-pc.rmk 2006-05-07 19:28:23.000000000 +0100 +++ grub2-pci/conf/i386-pc.rmk 2006-05-16 21:07:30.000000000 +0100 @@ -3,6 +3,7 @@ COMMON_ASFLAGS = -nostdinc -fno-builtin COMMON_CFLAGS = -fno-builtin -mrtd -mregparm=3 -m32 COMMON_LDFLAGS = -melf_i386 -nostdlib +DRIVERS_CFLAGS = -Idrivers/include -fno-strict-aliasing # Images. pkgdata_IMAGES = boot.img diskboot.img kernel.img pxeboot.img @@ -116,7 +117,7 @@ pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.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 + videotest.mod play.mod pci.mod # For _chain.mod. _chain_mod_SOURCES = loader/i386/pc/chainloader.c @@ -209,4 +210,9 @@ videotest_mod_CFLAGS = $(COMMON_CFLAGS) videotest_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For pci.mod +pci_mod_SOURCES = drivers/pci/pci.c +pci_mod_CFLAGS = $(COMMON_CFLAGS) $(DRIVERS_CFLAGS) +pci_mod_LDFLAGS = $(COMMON_LDFLAGS) + include $(srcdir)/conf/common.mk diff -rNu grub2/drivers/include/grub/list.h grub2-pci/drivers/include/grub/list.h --- grub2/drivers/include/grub/list.h 1970-01-01 01:00:00.000000000 +0100 +++ grub2-pci/drivers/include/grub/list.h 2006-05-16 21:10:58.000000000 +0100 @@ -0,0 +1,86 @@ +/* list.h - A very simple list. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006 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 2 of the License, or + * (at your option) any later version. + * + * This program 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +/* + If you want a list of struct myitem + you do + + struct myitem *item_list; + + where myitem MUST have its next pointer as the FIRST field + + and you can then add, delete the EL item, + grub_add_list (&item_list, el); + grub_del_list (&item_list, el); + + or call HOOK(item) for each element of the list + grub_iterate_list (item_list, hook); + + This brk version will point el to the list item for which + HOOK(EL) returns a non-null value + grub_iterate_list_brk (item_list, hook, el); + */ + +struct obj { + struct obj *next; /* MUST BE FIRST */ +}; + +#define grub_del_list(list, el) _grub_del_list((struct obj**) list, (struct obj*) el) +#define grub_add_list(list, el) _grub_add_list((struct obj**) list, (struct obj*) el) +#define grub_find_list(list, el) \ + (typeof(list)) _grub_find_list((struct obj*) list, (struct obj*) el) +#define grub_iterate_list(list, func) \ + {typeof(list) el = list; while (el) {func(el); el=el->next;}} +#define grub_iterate_list_brk(list, func, it) \ + {typeof(list) el = list; it = 0; \ + while (el) {if (func(el)) {it = el; break;} el=el->next; }} + +static inline struct obj* _grub_find_list (struct obj *list, struct obj *el) +{ + struct obj *it = list; + for (it = list; it; it=it->next) + { + if (it == el) return el; + } + return 0; +}; + +static inline void _grub_add_list (struct obj **list, struct obj *el) +{ + if ( (!el) || (_grub_find_list (*list, el)) ) + return; + + el->next = *list; + *list = el; +}; + +static inline void _grub_del_list (struct obj **list, struct obj *el) +{ + struct obj **p; + struct obj *q; + + for (p = list, q = *p; q; p = &(q->next), q = q->next) + if (q == el) + { + *p = q->next; + break; + } +}; diff -rNu grub2/drivers/include/grub/pci.h grub2-pci/drivers/include/grub/pci.h --- grub2/drivers/include/grub/pci.h 1970-01-01 01:00:00.000000000 +0100 +++ grub2-pci/drivers/include/grub/pci.h 2006-05-16 21:10:58.000000000 +0100 @@ -0,0 +1,119 @@ +/* pci.h Abstract interface for GRUB PCI support. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006 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 2 of the License, or + * (at your option) any later version. + * + * This program 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef GRUB_PCI_H_ +#define GRUB_PCI_H_ + +#include <grub/err.h> +#include <grub/types.h> +#include <grub/device.h> +#include <grub/net.h> + +/* Device type advertised by the driver */ +#define GRUB_NET_ETHERNET 0 + +#define GRUB_PCI_SLOT(devfn) ((devfn) >> 3) +#define GRUB_PCI_FUNC(devfn) ((devfn) & 0x07) + +struct grub_pci_ids +{ + grub_uint16_t vendor; + grub_uint16_t dev_id; + const char *name; +}; + +struct grub_pci_device; + +struct grub_pci_driver +{ + struct grub_pci_driver *next; + int type; + const char *name; + grub_err_t (*probe) (struct grub_pci_device *); + struct grub_pci_ids *ids; + int id_count; + grub_uint32_t class; +}; + +struct grub_pci_device +{ + struct grub_pci_device *next; + char *name; + grub_uint8_t bus; + grub_uint16_t vendor; + grub_uint16_t dev_id; + grub_uint8_t devfn; + grub_uint32_t class; + grub_addr_t ioaddr; + grub_addr_t membase; + grub_addr_t romaddr; + grub_uint8_t irq; + const struct grub_pci_driver *driver; +}; + +typedef struct grub_pci_device *grub_pci_device_t; + +struct grub_pci_io_support +{ + grub_err_t (*read_config_byte) (grub_pci_device_t, grub_addr_t, grub_uint8_t *value); + grub_err_t (*write_config_byte) (grub_pci_device_t, grub_addr_t, grub_uint8_t value); + grub_err_t (*read_config_word) (grub_pci_device_t, grub_addr_t, grub_uint16_t *value); + grub_err_t (*write_config_word) (grub_pci_device_t, grub_addr_t, grub_uint16_t value); + grub_err_t (*read_config_dword) (grub_pci_device_t, grub_addr_t, grub_uint32_t *value); + grub_err_t (*write_config_dword) (grub_pci_device_t, grub_addr_t, grub_uint32_t value); + grub_addr_t (*bus_base) (unsigned int bus); +}; + +struct grub_pci_support +{ + /* My name. */ + const char *name; + + void (*init)(void); + void (*fini)(void); + + void (*adjust) (grub_pci_device_t p); + + /* Base Address Register helper functions. There are up to 6 BARs + PCI_BASE_ADDRESS_{[0-5]} in the configuration space of each device */ + unsigned long (*bar_start) (grub_pci_device_t, unsigned int bar); + unsigned long (*bar_size) (grub_pci_device_t, unsigned int bar); + + int (*find_capability) (grub_pci_device_t, int cap); + + /* Call HOOK with each pci device. */ + grub_err_t (*iterate) (grub_err_t (*hook) (grub_pci_device_t)); + + /* Fill the pci device structure (romaddr, ioaddr, membase, irq) + given (bus, devfn, vendor, dev_id, class) */ + grub_err_t (*init_pdev) (grub_pci_device_t); + + /* Low level io functions. */ + struct grub_pci_io_support *io; +}; + +extern void grub_set_pci_support (struct grub_pci_support *); +extern void grub_unset_pci_support (struct grub_pci_support *); +extern void grub_register_pci_driver (struct grub_pci_driver *drv) ; +extern void grub_unregister_pci_driver (struct grub_pci_driver *drv); + +#endif + + diff -rNu grub2/drivers/pci/pci.c grub2-pci/drivers/pci/pci.c --- grub2/drivers/pci/pci.c 1970-01-01 01:00:00.000000000 +0100 +++ grub2-pci/drivers/pci/pci.c 2006-05-16 21:11:32.000000000 +0100 @@ -0,0 +1,284 @@ +/* pci.c - abstract PCI support for grub2. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006 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 2 of the License, or + * (at your option) any later version. + * + * This program 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <grub/pci.h> +#include <grub/dl.h> +#include <grub/misc.h> +#include <grub/normal.h> +#include <grub/mm.h> +#include <grub/net.h> +#include <grub/device.h> +#include <grub/list.h> + +/* This is not a list (there can be only one). */ +static struct grub_pci_support *grub_pci_support; +/* Lists of available drivers. */ +static struct grub_pci_driver *grub_pci_drivers; +/* Lists of PCI devices driven by GRUB. */ +static struct grub_pci_device *grub_pci_devices; + +/* Add DEV at the head of the PCI device list. */ +/* This function allocates the memory. */ +static void grub_register_pci_device (struct grub_pci_device *dev, + struct grub_pci_driver *drv) +{ + grub_pci_device_t ndev = (grub_pci_device_t) grub_malloc (sizeof(*ndev)); + + /* TODO: what about the name ? */ + + ndev->bus = dev->bus; + ndev->vendor = dev->vendor; + ndev->dev_id = dev->dev_id; + ndev->devfn = dev->devfn; + ndev->class = dev->class; + ndev->ioaddr = dev->ioaddr; + ndev->membase = dev->membase; + ndev->romaddr = dev->romaddr; + ndev->irq = dev->irq; + ndev->driver = drv; + + grub_add_list (&grub_pci_devices, ndev); +} + +/* Unlink DEV from the list of PCI devices. */ +/* This function frees the memory. */ +static void grub_unregister_pci_device (struct grub_pci_device *dev) +{ + grub_del_list (&grub_pci_devices, dev); + + /* TODO: Don't forget to free the name if used */ + + grub_free (dev); + +} + +void grub_set_pci_support (struct grub_pci_support *pci_s) +{ + if (grub_pci_support && grub_pci_support->fini) + grub_pci_support->fini (); + + grub_pci_support = pci_s; + + if (pci_s && pci_s->init) + pci_s->init (); +} + +void grub_unset_pci_support (struct grub_pci_support *pci_s) +{ + if (grub_pci_support == pci_s) + { + if (pci_s->fini) + pci_s->fini (); + grub_pci_support = 0; + } +} + +static int +is_alredy_driven (grub_pci_device_t pdev) +{ + grub_pci_device_t it; + auto int is_pdev_in_list (grub_pci_device_t); + + int is_pdev_in_list (grub_pci_device_t dev) + { + if ( (dev->bus == pdev->bus) && + (GRUB_PCI_SLOT(dev->devfn) == GRUB_PCI_SLOT(pdev->devfn)) && + (GRUB_PCI_FUNC(dev->dev_id) == GRUB_PCI_FUNC(pdev->dev_id)) ) + return 1; + else + return 0; + }; + grub_iterate_list_brk (grub_pci_devices, is_pdev_in_list, it); + + return (it != 0); + +} + +/* lspci functions. */ +static grub_err_t +print_pci_dev_n (grub_pci_device_t pdev) +{ + grub_printf ("%02x:%02x.%01x [%04x/%04x] class %04x\n",pdev->bus, + GRUB_PCI_SLOT(pdev->devfn), GRUB_PCI_FUNC(pdev->devfn), + pdev->vendor, pdev->dev_id, pdev->class >> 8); + + return 0; + +}; + +static grub_err_t +grub_cmd_lspci (struct grub_arg_list *state __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + + if (!grub_pci_support) + { + grub_printf ("No specific PCI support, try \"insmod pci_etherboot\"\n"); + return GRUB_ERR_TEST_FAILURE; + } + + grub_pci_support->iterate (print_pci_dev_n); + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_lspci_driver (struct grub_arg_list *state __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + struct grub_pci_driver *drv= grub_pci_drivers; + struct grub_pci_device *dev; + + + grub_printf ("Available PCI drivers:\n"); + while (drv) + { + dev = grub_pci_devices; + + grub_printf ("-> %s:",drv->name); + while (dev) + { + if (dev->driver == drv) + grub_printf ("(%02x:%02x.%01x) ",dev->bus, + GRUB_PCI_SLOT(dev->devfn), GRUB_PCI_FUNC(dev->devfn)); + dev=dev->next; + } + grub_printf ("\n"); + drv = drv->next; + } + + return GRUB_ERR_NONE; +} + +/* Scan driver functions. */ +static grub_err_t +scan_driver (grub_pci_device_t pdev) +{ + struct grub_pci_driver * drv = grub_pci_drivers; + grub_err_t er; + int i; + + /* If this device is already driven, do nothing */ + if (is_alredy_driven (pdev)) + return GRUB_ERR_TEST_FAILURE; + + while (drv) + { + for (i=0; i<drv->id_count; i++ ) + { + if ( ((pdev->vendor == drv->ids[i].vendor) && + (pdev->dev_id == drv->ids[i].dev_id)) || + ((pdev->class >> 8) == drv->class) ) + { + grub_pci_support->init_pdev (pdev); + + if ((pdev->class >> 8) != drv->class) + { + grub_dprintf ("pci","Probing for %s with driver %s\n", + drv->ids[i].name, drv->name); + } + else + { + grub_dprintf ("pci","Probing for class %04x with driver %s\n", + drv->class, drv->name); + } + + er = drv->probe (pdev); + + if (er == GRUB_ERR_NONE) { + grub_register_pci_device (pdev,drv); + return GRUB_ERR_NONE; + } + } + } + drv=drv->next; + } + + return GRUB_ERR_TEST_FAILURE; +} + + +/* Add DRV at the head of the driver list. */ +void grub_register_pci_driver (struct grub_pci_driver *drv) +{ + grub_add_list (&grub_pci_drivers, drv); + grub_pci_support->iterate (scan_driver); +} + +/* Unlink DRV from the driver list. */ +void grub_unregister_pci_driver (struct grub_pci_driver *drv) +{ + auto int find_used_driver (grub_pci_device_t); + grub_pci_device_t dev; + + int find_used_driver (grub_pci_device_t device) + { + if (device->driver == drv) + return 1; + else + return 0; + }; + + grub_iterate_list_brk (grub_pci_devices, find_used_driver, dev); + while ( dev ) + { + grub_unregister_pci_device (dev); + grub_iterate_list_brk (grub_pci_devices, find_used_driver, dev); + } + + grub_del_list (&grub_pci_drivers, drv); +} + + +static grub_err_t +grub_cmd_scan_pci_device (struct grub_arg_list *state __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + + if (!grub_pci_support) + { + grub_printf ("No specific PCI support, try \"insmod pci_etherboot\"\n"); + return GRUB_ERR_TEST_FAILURE; + } + + grub_pci_support->iterate (scan_driver); + return GRUB_ERR_NONE; +} + +/* GRUB module functions. */ +GRUB_MOD_INIT(pci) +{ + (void)mod; /* To stop warning. */ + grub_register_command ("lspci", grub_cmd_lspci, GRUB_COMMAND_FLAG_BOTH, + "lspci", "list the PCI devices", 0); + grub_register_command ("lspci_driver", grub_cmd_lspci_driver, GRUB_COMMAND_FLAG_BOTH, + "lspci_driver", "list available PCI drivers and the devices they drive", 0); + grub_register_command ("scan_pci_device", grub_cmd_scan_pci_device, GRUB_COMMAND_FLAG_BOTH, + "scan_pci_device", "Scan the PCI bus for devices for which we have a driver", 0); +} + +GRUB_MOD_FINI(pci) +{ + grub_unregister_command ("lspci"); + grub_unregister_command ("lspci_driver"); + grub_unregister_command ("scan_pci_device"); +} _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel