[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[patch 1/3] PCI support (abstract interface)
From: |
vincent guffens |
Subject: |
[patch 1/3] PCI support (abstract interface) |
Date: |
Tue, 16 May 2006 22:38:12 +0100 |
User-agent: |
Mozilla Thunderbird 1.0.8 (X11/20060502) |
Hello,
Here is a patch to add pci support to grub2.
2006-05-16 Vincent Guffens <address@hidden>
* 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 <address@hidden>
+
+ * 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 <address@hidden>
* 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");
+}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [patch 1/3] PCI support (abstract interface),
vincent guffens <=