From owner-freebsd-hackers@FreeBSD.ORG Fri Jun 13 16:30:41 2003 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 7B40637B401 for ; Fri, 13 Jun 2003 16:30:41 -0700 (PDT) Received: from mail.gmx.net (pop.gmx.net [213.165.64.20]) by mx1.FreeBSD.org (Postfix) with SMTP id 4300743FB1 for ; Fri, 13 Jun 2003 16:30:40 -0700 (PDT) (envelope-from tmoestl@gmx.net) Received: (qmail 7326 invoked by uid 65534); 13 Jun 2003 23:30:39 -0000 Received: from p508E5CC8.dip.t-dialin.net (EHLO galatea.local) (80.142.92.200) by mail.gmx.net (mp009) with SMTP; 14 Jun 2003 01:30:39 +0200 Received: from tmm by galatea.local with local (Exim 4.20 #1) id 19Qy0e-0000Jj-VC for ; Sat, 14 Jun 2003 01:31:04 +0200 Date: Sat, 14 Jun 2003 01:31:04 +0200 From: Thomas Moestl To: freebsd-hackers@freebsd.org Message-ID: <20030613233104.GC670@crow.dom2ip.de> Mail-Followup-To: freebsd-hackers@freebsd.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="gKMricLos+KVdGMg" Content-Disposition: inline User-Agent: Mutt/1.4.1i Sender: Thomas Moestl Subject: PLEASE REVIEW: Adding a pci_if method to facilitate specialized PCI bus drivers X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 13 Jun 2003 23:30:41 -0000 --gKMricLos+KVdGMg Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi, I've attached a patch that adds a new pci_if method, assign_interrupt, and makes the PCI code implement and use it. This is private to the PCI bus and is only used internally (to find an interrupt of a child device); it is a method so that derived PCI bus drivers can override it. This is very useful for the sparc64 OFW PCI bus driver which I will commit soon, hopefully. On sparc64, there are some on-board devices which have special interrupt lines. To route their interrupts, we need not only know the device to route for, but also an interrupt index which is stored in the firmware for this device, and which is used to route on bridges instead of the intpin (in other cases, there's even the complete interrupt number stored there; for devices in PCI slots, we (usually) can use the intpin). This requires us to get this firmware property in the OFW PCI bus driver before routing the interrupt; that can't be done in the pcib route_interrupt method, since we don't know whether we are routing for another bridge (where we use whichever index we get passed) or for a child device (in which case we would need to look at the firmware property). Currently, the OFW PCI bus driver solves this by providing a stub version of the alloc_resource method, trapping the cases where rerouting is required and doing it before calling the generic PCI bus routine, but that leads to code duplication and is generally a bit ugly, as we are second-guessing where the PCI bus routines will want to route an interrupt. By moving the actual routing in a method which can be overridden, this can be solved cleanly, while not complicating the generic PCI bus code by much. If there are no objections, I would like to commit this soonish. Thoughts? Thanks, - Thomas -- Thomas Moestl http://www.tu-bs.de/~y0015675/ http://people.FreeBSD.org/~tmm/ PGP fingerprint: 1C97 A604 2BD0 E492 51D0 9C0F 1FE6 4F1D 419C 776C --gKMricLos+KVdGMg Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="pci-intr.diff" Index: dev/acpica/acpi_pci.c =================================================================== RCS file: /vol/ncvs/src/sys/dev/acpica/acpi_pci.c,v retrieving revision 1.3 diff -u -r1.3 acpi_pci.c --- dev/acpica/acpi_pci.c 17 Feb 2003 21:20:34 -0000 1.3 +++ dev/acpica/acpi_pci.c 13 Jun 2003 20:57:13 -0000 @@ -111,6 +111,7 @@ /* XXX: We should override these two. */ DEVMETHOD(pci_get_powerstate, pci_get_powerstate_method), DEVMETHOD(pci_set_powerstate, pci_set_powerstate_method), + DEVMETHOD(pci_assign_interrupt, pci_assign_interrupt_method), { 0, 0 } }; Index: dev/cardbus/cardbus.c =================================================================== RCS file: /vol/ncvs/src/sys/dev/cardbus/cardbus.c,v retrieving revision 1.38 diff -u -r1.38 cardbus.c --- dev/cardbus/cardbus.c 18 Feb 2003 21:24:00 -0000 1.38 +++ dev/cardbus/cardbus.c 13 Jun 2003 21:51:29 -0000 @@ -387,6 +387,7 @@ DEVMETHOD(pci_disable_io, pci_disable_io_method), DEVMETHOD(pci_get_powerstate, pci_get_powerstate_method), DEVMETHOD(pci_set_powerstate, pci_set_powerstate_method), + DEVMETHOD(pci_assign_interrupt, pci_assign_interrupt_method), {0,0} }; Index: dev/pci/pci.c =================================================================== RCS file: /vol/ncvs/src/sys/dev/pci/pci.c,v retrieving revision 1.219 diff -u -r1.219 pci.c --- dev/pci/pci.c 9 Jun 2003 18:08:46 -0000 1.219 +++ dev/pci/pci.c 13 Jun 2003 21:36:01 -0000 @@ -70,7 +70,8 @@ static int pci_memen(device_t pcib, int b, int s, int f); static int pci_add_map(device_t pcib, int b, int s, int f, int reg, struct resource_list *rl); -static void pci_add_resources(device_t pcib, device_t dev); +static void pci_add_resources(device_t pcib, device_t bus, + device_t dev); static int pci_probe(device_t dev); static int pci_attach(device_t dev); static void pci_load_vendor_data(void); @@ -119,6 +120,7 @@ DEVMETHOD(pci_disable_io, pci_disable_io_method), DEVMETHOD(pci_get_powerstate, pci_get_powerstate_method), DEVMETHOD(pci_set_powerstate, pci_set_powerstate_method), + DEVMETHOD(pci_assign_interrupt, pci_assign_interrupt_method), { 0, 0 } }; @@ -776,7 +778,7 @@ } static void -pci_add_resources(device_t pcib, device_t dev) +pci_add_resources(device_t pcib, device_t bus, device_t dev) { struct pci_devinfo *dinfo = device_get_ivars(dev); pcicfgregs *cfg = &dinfo->cfg; @@ -805,7 +807,7 @@ * If the re-route fails, then just stick with what we * have. */ - irq = PCIB_ROUTE_INTERRUPT(pcib, dev, cfg->intpin); + irq = PCI_ASSIGN_INTERRUPT(bus, dev); if (PCI_INTERRUPT_VALID(irq)) { pci_write_config(dev, PCIR_INTLINE, irq, 1); cfg->intline = irq; @@ -848,7 +850,7 @@ pcib = device_get_parent(bus); dinfo->cfg.dev = device_add_child(bus, NULL, -1); device_set_ivars(dinfo->cfg.dev, dinfo); - pci_add_resources(pcib, dinfo->cfg.dev); + pci_add_resources(pcib, bus, dinfo->cfg.dev); pci_print_verbose(dinfo); } @@ -1347,8 +1351,7 @@ */ if (!PCI_INTERRUPT_VALID(cfg->intline) && (cfg->intpin != 0)) { - cfg->intline = PCIB_ROUTE_INTERRUPT( - device_get_parent(dev), child, cfg->intpin); + cfg->intline = PCI_ASSIGN_INTERRUPT(dev, child); if (PCI_INTERRUPT_VALID(cfg->intline)) { pci_write_config(child, PCIR_INTLINE, cfg->intline, 1); @@ -1468,6 +1471,16 @@ cfg->subvendor, cfg->subdevice, cfg->baseclass, cfg->subclass, cfg->progif); return (0); +} + +int +pci_assign_interrupt_method(device_t dev, device_t child) +{ + struct pci_devinfo *dinfo = device_get_ivars(child); + pcicfgregs *cfg = &dinfo->cfg; + + return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, + cfg->intpin)); } static int Index: dev/pci/pci_if.m =================================================================== RCS file: /vol/ncvs/src/sys/dev/pci/pci_if.m,v retrieving revision 1.5 diff -u -r1.5 pci_if.m --- dev/pci/pci_if.m 16 Apr 2003 03:15:08 -0000 1.5 +++ dev/pci/pci_if.m 13 Jun 2003 21:06:02 -0000 @@ -77,3 +77,8 @@ device_t child; int space; }; + +METHOD int assign_interrupt { + device_t dev; + device_t child; +}; Index: dev/pci/pci_private.h =================================================================== RCS file: /vol/ncvs/src/sys/dev/pci/pci_private.h,v retrieving revision 1.8 diff -u -r1.8 pci_private.h --- dev/pci/pci_private.h 16 Apr 2003 03:15:08 -0000 1.8 +++ dev/pci/pci_private.h 13 Jun 2003 21:41:53 -0000 @@ -72,4 +72,5 @@ char *buf, size_t buflen); int pci_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf, size_t buflen); +int pci_assign_interrupt_method(device_t dev, device_t child); #endif /* _PCI_PRIVATE_H_ */ --gKMricLos+KVdGMg--