From: vincent guffens <v.guffens@imperial.ac.uk>
To: grub-devel@gnu.org
Subject: [patch 1/3] PCI support (abstract interface)
Date: Tue, 16 May 2006 22:38:12 +0100 [thread overview]
Message-ID: <446A4644.80807@imperial.ac.uk> (raw)
Hello,
Here is a patch to add pci support to grub2.
2006-05-16 Vincent Guffens <vinsz@fsfe.org>
* 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 <vinsz@fsfe.org>
+
+ * 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 <okuji@enbug.org>
* 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");
+}
reply other threads:[~2006-05-16 21:38 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=446A4644.80807@imperial.ac.uk \
--to=v.guffens@imperial.ac.uk \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.