summaryrefslogtreecommitdiff
path: root/sys/pci
diff options
context:
space:
mode:
Diffstat (limited to 'sys/pci')
-rw-r--r--sys/pci/ide_pci.c5
-rw-r--r--sys/pci/if_fxp.c186
-rw-r--r--sys/pci/if_fxpvar.h5
-rw-r--r--sys/pci/if_pn.c10
-rw-r--r--sys/pci/if_xl.c12
-rw-r--r--sys/pci/ohci_pci.c154
-rw-r--r--sys/pci/pci.c653
-rw-r--r--sys/pci/pci_compat.c192
-rw-r--r--sys/pci/pci_if.m44
-rw-r--r--sys/pci/pcireg.h4
-rw-r--r--sys/pci/pcisupport.c824
-rw-r--r--sys/pci/pcivar.h79
-rw-r--r--sys/pci/uhci_pci.c166
13 files changed, 1597 insertions, 737 deletions
diff --git a/sys/pci/ide_pci.c b/sys/pci/ide_pci.c
index 524b873417da7..6faef01500883 100644
--- a/sys/pci/ide_pci.c
+++ b/sys/pci/ide_pci.c
@@ -26,7 +26,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ide_pci.c,v 1.30 1999/04/13 19:38:12 peter Exp $
+ * $Id: ide_pci.c,v 1.31 1999/04/13 20:22:33 peter Exp $
*/
#include "pci.h"
@@ -1514,6 +1514,7 @@ ide_pci_attach(pcici_t tag, int unit)
wddma[unit].wdd_iobase = ide_pci_iobase;
wddma[unit].wdd_altiobase = ide_pci_altiobase;
+#if 0
/*
* This code below is mighty bogus. The config entries for the
* isa_devtab_bio are plugged in before the standard ISA bios scan.
@@ -1582,7 +1583,7 @@ ide_pci_attach(pcici_t tag, int unit)
}
}
}
-
+#endif
bmista_1 = inb(iobase_bm_1 + BMISTA_PORT);
bmista_2 = inb(iobase_bm_2 + BMISTA_PORT);
diff --git a/sys/pci/if_fxp.c b/sys/pci/if_fxp.c
index 77f0ade1d5af6..53b8d4db00c68 100644
--- a/sys/pci/if_fxp.c
+++ b/sys/pci/if_fxp.c
@@ -27,7 +27,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: if_fxp.c,v 1.65 1999/03/17 16:44:53 luigi Exp $
+ * $Id: if_fxp.c,v 1.66 1999/03/20 04:51:25 wes Exp $
*/
/*
@@ -89,6 +89,10 @@
#else /* __FreeBSD__ */
#include <sys/sockio.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
#include <net/ethernet.h>
#include <net/if_arp.h>
@@ -491,51 +495,31 @@ fxp_ether_ioctl(ifp, cmd, data)
#else /* __FreeBSD__ */
-static u_long fxp_count;
-static const char *fxp_probe __P((pcici_t, pcidi_t));
-static void fxp_attach __P((pcici_t, int));
-
-static void fxp_shutdown __P((int, void *));
-
-static struct pci_device fxp_device = {
- "fxp",
- fxp_probe,
- fxp_attach,
- &fxp_count,
- NULL
-};
-DATA_SET(pcidevice_set, fxp_device);
-
/*
* Return identification string if this is device is ours.
*/
-static const char *
-fxp_probe(config_id, device_id)
- pcici_t config_id;
- pcidi_t device_id;
+static int
+fxp_probe(device_t dev)
{
- if (((device_id & 0xffff) == FXP_VENDORID_INTEL) &&
- ((device_id >> 16) & 0xffff) == FXP_DEVICEID_i82557)
- return ("Intel EtherExpress Pro 10/100B Ethernet");
+ if ((pci_get_vendor(dev) == FXP_VENDORID_INTEL) &&
+ (pci_get_device(dev) == FXP_DEVICEID_i82557)) {
+ device_set_desc(dev, "Intel EtherExpress Pro 10/100B Ethernet");
+ return 0;
+ }
- return NULL;
+ return ENXIO;
}
-static void
-fxp_attach(config_id, unit)
- pcici_t config_id;
- int unit;
+static int
+fxp_attach(device_t dev)
{
- struct fxp_softc *sc;
- vm_offset_t pbase;
+ int error = 0;
+ struct fxp_softc *sc = device_get_softc(dev);
struct ifnet *ifp;
int s;
u_long val;
+ int rid;
- sc = malloc(sizeof(struct fxp_softc), M_DEVBUF, M_NOWAIT);
- if (sc == NULL)
- return;
- bzero(sc, sizeof(struct fxp_softc));
callout_handle_init(&sc->stat_ch);
s = splimp();
@@ -543,39 +527,56 @@ fxp_attach(config_id, unit)
/*
* Enable bus mastering.
*/
- val = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG);
+ val = pci_read_config(dev, PCIR_COMMAND, 2);
val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
- pci_conf_write(config_id, PCI_COMMAND_STATUS_REG, val);
+ pci_write_config(dev, PCIR_COMMAND, val, 2);
/*
* Map control/status registers.
*/
- if (!pci_map_mem(config_id, FXP_PCI_MMBA,
- (vm_offset_t *)&sc->csr, &pbase)) {
- printf("fxp%d: couldn't map memory\n", unit);
+ rid = FXP_PCI_MMBA;
+ sc->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
+ 0, ~0, 1, RF_ACTIVE);
+ if (!sc->mem) {
+ device_printf(dev, "could not map memory\n");
+ error = ENXIO;
goto fail;
- }
+ }
+ sc->csr = rman_get_virtual(sc->mem); /* XXX use bus_space */
/*
* Allocate our interrupt.
*/
- if (!pci_map_int(config_id, fxp_intr, sc, &net_imask)) {
- printf("fxp%d: couldn't map interrupt\n", unit);
+ rid = 0;
+ sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
+ RF_SHAREABLE | RF_ACTIVE);
+ if (sc->irq == NULL) {
+ device_printf(dev, "could not map interrupt\n");
+ error = ENXIO;
+ goto fail;
+ }
+
+ error = bus_setup_intr(dev, sc->irq, fxp_intr, sc, &sc->ih);
+ if (error) {
+ device_printf(dev, "could not setup irq\n");
goto fail;
}
/* Do generic parts of attach. */
if (fxp_attach_common(sc, sc->arpcom.ac_enaddr)) {
/* Failed! */
- (void) pci_unmap_int(config_id);
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
+ bus_release_resource(dev, SYS_RES_MEMORY, FXP_PCI_MMBA, sc->mem);
+ error = ENXIO;
goto fail;
}
- printf("fxp%d: Ethernet address %6D%s\n", unit,
+ device_printf(dev, "Ethernet address %6D%s\n",
sc->arpcom.ac_enaddr, ":", sc->phy_10Mbps_only ? ", 10Mbps" : "");
ifp = &sc->arpcom.ac_if;
- ifp->if_unit = unit;
+ ifp->if_unit = device_get_unit(dev);
ifp->if_name = "fxp";
ifp->if_output = ether_output;
ifp->if_baudrate = 100000000;
@@ -600,19 +601,63 @@ fxp_attach(config_id, unit)
bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
#endif
+ splx(s);
+ return 0;
+
+ fail:
+ splx(s);
+ return error;
+}
+
+/*
+ * Detach interface.
+ */
+static int
+fxp_detach(device_t dev)
+{
+ struct fxp_softc *sc = device_get_softc(dev);
+ int s;
+
+ s = splimp();
+
/*
- * Add shutdown hook so that DMA is disabled prior to reboot. Not
- * doing do could allow DMA to corrupt kernel memory during the
- * reboot before the driver initializes.
+ * Close down routes etc.
*/
- at_shutdown(fxp_shutdown, sc, SHUTDOWN_POST_SYNC);
+ if_detach(&sc->arpcom.ac_if);
- splx(s);
- return;
+ /*
+ * Stop DMA and drop transmit queue.
+ */
+ fxp_stop(sc);
+
+ /*
+ * Deallocate resources.
+ */
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
+ bus_release_resource(dev, SYS_RES_MEMORY, FXP_PCI_MMBA, sc->mem);
+
+ /*
+ * Free all the receive buffers.
+ */
+ if (sc->rfa_headm != NULL)
+ m_freem(sc->rfa_headm);
+
+ /*
+ * Free all media structures.
+ */
+ ifmedia_removeall(&sc->sc_media);
+
+ /*
+ * Free anciliary structures.
+ */
+ free(sc->cbl_base, M_DEVBUF);
+ free(sc->fxp_stats, M_DEVBUF);
+ free(sc->mcsp, M_DEVBUF);
- fail:
- free(sc, M_DEVBUF);
splx(s);
+
+ return 0;
}
/*
@@ -620,14 +665,39 @@ fxp_attach(config_id, unit)
* main purpose of this routine is to shut off receiver DMA so that
* kernel memory doesn't get clobbered during warmboot.
*/
-static void
-fxp_shutdown(howto, sc)
- int howto;
- void *sc;
+static int
+fxp_shutdown(device_t dev)
{
- fxp_stop((struct fxp_softc *) sc);
+ /*
+ * Make sure that DMA is disabled prior to reboot. Not doing
+ * do could allow DMA to corrupt kernel memory during the
+ * reboot before the driver initializes.
+ */
+ fxp_stop((struct fxp_softc *) device_get_softc(dev));
+ return 0;
}
+static device_method_t fxp_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, fxp_probe),
+ DEVMETHOD(device_attach, fxp_attach),
+ DEVMETHOD(device_detach, fxp_detach),
+ DEVMETHOD(device_shutdown, fxp_shutdown),
+
+ { 0, 0 }
+};
+
+static driver_t fxp_driver = {
+ "fxp",
+ fxp_methods,
+ DRIVER_TYPE_NET,
+ sizeof(struct fxp_softc),
+};
+
+static devclass_t fxp_devclass;
+
+DRIVER_MODULE(fxp, pci, fxp_driver, fxp_devclass, 0, 0);
+
#endif /* __NetBSD__ */
/*************************************************************
diff --git a/sys/pci/if_fxpvar.h b/sys/pci/if_fxpvar.h
index ce8d8fe9de6d7..042d2df962841 100644
--- a/sys/pci/if_fxpvar.h
+++ b/sys/pci/if_fxpvar.h
@@ -27,7 +27,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: if_fxpvar.h,v 1.5 1998/06/07 17:12:38 dfr Exp $
+ * $Id: if_fxpvar.h,v 1.6 1998/08/02 00:29:15 dg Exp $
*/
/*
@@ -48,6 +48,9 @@ struct fxp_softc {
#else
struct arpcom arpcom; /* per-interface network data */
caddr_t csr; /* control/status registers */
+ struct resource *mem; /* resource descriptor for registers */
+ struct resource *irq; /* resource descriptor for interrupt */
+ void *ih; /* interrupt handler cookie */
#endif /* __NetBSD__ */
struct mbuf *rfa_headm; /* first mbuf in receive frame area */
struct mbuf *rfa_tailm; /* last mbuf in receive frame area */
diff --git a/sys/pci/if_pn.c b/sys/pci/if_pn.c
index 425195e679ef1..3209051739d36 100644
--- a/sys/pci/if_pn.c
+++ b/sys/pci/if_pn.c
@@ -29,7 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: if_pn.c,v 1.50 1999/04/14 18:52:02 wpaul Exp $
+ * $Id: if_pn.c,v 1.16 1999/04/14 19:40:07 wpaul Exp $
*/
/*
@@ -97,7 +97,13 @@
#ifndef lint
static const char rcsid[] =
- "$Id: if_pn.c,v 1.50 1999/04/14 18:52:02 wpaul Exp $";
+ "$Id: if_pn.c,v 1.16 1999/04/14 19:40:07 wpaul Exp $";
+#endif
+
+#ifdef __alpha__
+#undef vtophys
+#define vtophys(va) (pmap_kextract(((vm_offset_t) (va))) \
+ + 1*1024*1024*1024)
#endif
/*
diff --git a/sys/pci/if_xl.c b/sys/pci/if_xl.c
index d9b9e61c43830..e848418da2ccc 100644
--- a/sys/pci/if_xl.c
+++ b/sys/pci/if_xl.c
@@ -29,7 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: if_xl.c,v 1.30 1999/04/15 03:18:33 wpaul Exp $
+ * $Id: if_xl.c,v 1.31 1999/04/16 01:56:06 ghelmer Exp $
*/
/*
@@ -122,6 +122,12 @@
#include <pci/pcireg.h>
#include <pci/pcivar.h>
+#ifdef __alpha__
+#undef vtophys
+#define vtophys(va) (pmap_kextract(((vm_offset_t) (va))) \
+ + 1*1024*1024*1024)
+#endif
+
/*
* The following #define causes the code to use PIO to access the
* chip's registers instead of memory mapped mode. The reason PIO mode
@@ -158,7 +164,7 @@
#if !defined(lint)
static const char rcsid[] =
- "$Id: if_xl.c,v 1.30 1999/04/15 03:18:33 wpaul Exp $";
+ "$Id: if_xl.c,v 1.31 1999/04/16 01:56:06 ghelmer Exp $";
#endif
/*
@@ -1513,7 +1519,7 @@ xl_attach(config_id, unit)
}
sc->xl_ldata = (struct xl_list_data *)sc->xl_ldata_ptr;
- round = (unsigned int)sc->xl_ldata_ptr & 0xF;
+ round = (uintptr_t)sc->xl_ldata_ptr & 0xF;
roundptr = sc->xl_ldata_ptr;
for (i = 0; i < 8; i++) {
if (round % 8) {
diff --git a/sys/pci/ohci_pci.c b/sys/pci/ohci_pci.c
index 3c20ff723e05d..1aea5f1db15db 100644
--- a/sys/pci/ohci_pci.c
+++ b/sys/pci/ohci_pci.c
@@ -44,6 +44,8 @@
* USB spec: http://www.teleport.com/cgi-bin/mailmerge.cgi/~usb/cgiform.tpl
*/
+#include "opt_bus.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -52,23 +54,13 @@
#include <sys/device.h>
#include <sys/proc.h>
#include <sys/queue.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
#include <pci/pcivar.h>
#include <pci/pcireg.h>
-#define PCI_CLASS_SERIALBUS 0x0c000000
-#define PCI_SUBCLASS_COMMUNICATIONS_SERIAL 0x00000000
-#define PCI_SUBCLASS_SERIALBUS_FIREWIRE 0x00000000
-#define PCI_SUBCLASS_SERIALBUS_ACCESS 0x00010000
-#define PCI_SUBCLASS_SERIALBUS_SSA 0x00020000
-#define PCI_SUBCLASS_SERIALBUS_USB 0x00030000
-#define PCI_SUBCLASS_SERIALBUS_FIBER 0x00040000
-
-#define PCI_INTERFACE(d) (((d) >> 8) & 0xff)
-#define PCI_SUBCLASS(d) ((d) & PCI_SUBCLASS_MASK)
-#define PCI_CLASS(d) ((d) & PCI_CLASS_MASK)
-
-
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdivar.h>
@@ -77,7 +69,6 @@
#include <dev/usb/ohcireg.h>
#include <dev/usb/ohcivar.h>
-
#define PCI_OHCI_VENDORID_ALI 0x10b9
#define PCI_OHCI_VENDORID_CMDTECH 0x1095
#define PCI_OHCI_VENDORID_COMPAQ 0x0e11
@@ -98,27 +89,12 @@ static const char *ohci_device_usb0673 = "CMD Tech 673 (USB0673) USB Host Contr
static const char *ohci_device_generic = "OHCI (generic) USB Host Controller";
-
-static const char *ohci_pci_probe __P((pcici_t, pcidi_t));
-static void ohci_pci_attach __P((pcici_t, int));
-
-static u_long ohci_count = 0;
-
-static struct pci_device ohci_pci_device = {
- "ohci",
- ohci_pci_probe,
- ohci_pci_attach,
- &ohci_count,
- NULL
-};
-
-DATA_SET(pcidevice_set, ohci_pci_device);
-
+#define PCI_OHCI_BASE_REG 0x10
static const char *
-ohci_pci_probe(pcici_t config_id, pcidi_t device_id)
+ohci_pci_match(device_t dev)
{
- u_int32_t class;
+ u_int32_t device_id = pci_get_devid(dev);
switch(device_id) {
case PCI_OHCI_DEVICEID_ALADDIN_V:
@@ -132,54 +108,72 @@ ohci_pci_probe(pcici_t config_id, pcidi_t device_id)
case PCI_OHCI_DEVICEID_NEC:
return (ohci_device_nec);
default:
- class = pci_conf_read(config_id, PCI_CLASS_REG);
- if ( (PCI_CLASS(class) == PCI_CLASS_SERIALBUS)
- && (PCI_SUBCLASS(class) == PCI_SUBCLASS_SERIALBUS_USB)
- && (PCI_INTERFACE(class) == PCI_INTERFACE_OHCI)) {
- return(ohci_device_generic);
+ if ( pci_get_class(dev) == PCIC_SERIALBUS
+ && pci_get_subclass(dev) == PCIS_SERIALBUS_USB
+ && pci_get_progif(dev) == PCI_INTERFACE_OHCI) {
+ return (ohci_device_generic);
}
}
return NULL; /* dunno */
}
-static void
-ohci_pci_attach(pcici_t config_id, int unit)
+static int
+ohci_pci_probe(device_t dev)
{
- vm_offset_t pbase;
+ const char *desc = ohci_pci_match(dev);
+ if (desc) {
+ device_set_desc(dev, desc);
+ return 0;
+ } else {
+ return ENXIO;
+ }
+}
+
+static int
+ohci_pci_attach(device_t dev)
+{
+ int unit = device_get_unit(dev);
+ ohci_softc_t *sc = device_get_softc(dev);
device_t usbus;
- ohci_softc_t *sc;
usbd_status err;
- int id;
+ int rid;
+ struct resource *res;
+ void *ih;
+ int error;
+
+ rid = PCI_CBMEM;
+ res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
+ 0, ~0, 1, RF_ACTIVE);
+ if (!res) {
+ device_printf(dev, "could not map memory\n");
+ return ENXIO;
+ }
- sc = malloc(sizeof(ohci_softc_t), M_DEVBUF, M_NOWAIT);
- /* Do not free it below, intr might use the sc */
- if ( sc == NULL ) {
- printf("ohci%d: could not allocate memory", unit);
- return;
- }
- memset(sc, 0, sizeof(ohci_softc_t));
+ sc->iot = rman_get_bustag(res);
+ sc->ioh = rman_get_bushandle(res);
- if(!pci_map_mem(config_id, PCI_CBMEM,
- (vm_offset_t *)&sc->sc_iobase, &pbase)) {
- printf("ohci%d: could not map memory\n", unit);
- return;
- }
+ rid = 0;
+ res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
+ RF_SHAREABLE | RF_ACTIVE);
+ if (res == NULL) {
+ device_printf(dev, "could not allocate irq\n");
+ return ENOMEM;
+ }
- if ( !pci_map_int(config_id, (pci_inthand_t *)ohci_intr,
- (void *) sc, &bio_imask)) {
- printf("ohci%d: could not map irq\n", unit);
- return;
+ error = bus_setup_intr(dev, res, (driver_intr_t *) ohci_intr, sc, &ih);
+ if (error) {
+ device_printf(dev, "could not setup irq\n");
+ return error;
}
- usbus = device_add_child(root_bus, "usb", -1, sc);
+ usbus = device_add_child(dev, "usb", -1, sc);
if (!usbus) {
- printf("ohci%d: could not add USB device to root bus\n", unit);
- return;
+ printf("ohci%d: could not add USB device\n", unit);
+ return ENOMEM;
}
- id = pci_conf_read(config_id, PCI_ID_REG);
- switch(id) {
+ switch (pci_get_devid(dev)) {
case PCI_OHCI_DEVICEID_ALADDIN_V:
device_set_desc(usbus, ohci_device_aladdin_v);
sprintf(sc->sc_vendor, "AcerLabs");
@@ -202,7 +196,7 @@ ohci_pci_attach(pcici_t config_id, int unit)
break;
default:
if (bootverbose)
- printf("(New OHCI DeviceId=0x%08x)\n", id);
+ printf("(New OHCI DeviceId=0x%08x)\n", pci_get_devid(dev));
device_set_desc(usbus, ohci_device_generic);
sprintf(sc->sc_vendor, "(unknown)");
}
@@ -211,8 +205,36 @@ ohci_pci_attach(pcici_t config_id, int unit)
err = ohci_init(sc);
if (err != USBD_NORMAL_COMPLETION) {
printf("ohci%d: init failed, error=%d\n", unit, err);
- device_delete_child(root_bus, usbus);
+ device_delete_child(dev, usbus);
}
- return;
+ return device_probe_and_attach(sc->sc_bus.bdev);
}
+
+static device_method_t ohci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ohci_pci_probe),
+ DEVMETHOD(device_attach, ohci_pci_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+
+ { 0, 0 }
+};
+
+static driver_t ohci_driver = {
+ "ohci",
+ ohci_methods,
+ DRIVER_TYPE_BIO,
+ sizeof(ohci_softc_t),
+};
+
+static devclass_t ohci_devclass;
+
+DRIVER_MODULE(ohci, pci, ohci_driver, ohci_devclass, 0, 0);
diff --git a/sys/pci/pci.c b/sys/pci/pci.c
index e449fc25e50fa..889550c9bc95a 100644
--- a/sys/pci/pci.c
+++ b/sys/pci/pci.c
@@ -23,10 +23,12 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: pci.c,v 1.93 1999/01/19 23:29:18 se Exp $
+ * $Id: pci.c,v 1.94 1999/04/11 02:47:31 eivind Exp $
*
*/
+#include "opt_bus.h"
+
#include "pci.h"
#if NPCI > 0
@@ -50,6 +52,11 @@
#include <vm/pmap.h>
#include <vm/vm_extern.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
#include <pci/pcireg.h>
#include <pci/pcivar.h>
#include <pci/pci_ioctl.h>
@@ -338,11 +345,10 @@ pci_readcfg(pcicfgregs *probe)
M_DEVBUF, M_WAITOK);
if (devlist_entry == NULL)
return (NULL);
+ bzero(devlist_entry, sizeof *devlist_entry);
cfg = &devlist_entry->cfg;
- bzero(cfg, sizeof *cfg);
-
cfg->bus = probe->bus;
cfg->slot = probe->slot;
cfg->func = probe->func;
@@ -450,113 +456,6 @@ pci_freecfg(struct pci_devinfo *dinfo)
}
#endif
-static void
-pci_addcfg(struct pci_devinfo *dinfo)
-{
- if (bootverbose) {
- int i;
- pcicfgregs *cfg = &dinfo->cfg;
-
- printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n",
- cfg->vendor, cfg->device, cfg->revid);
- printf("\tclass=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n",
- cfg->baseclass, cfg->subclass, cfg->progif,
- cfg->hdrtype, cfg->mfdev);
- printf("\tsubordinatebus=%x \tsecondarybus=%x\n",
- cfg->subordinatebus, cfg->secondarybus);
-#ifdef PCI_DEBUG
- printf("\tcmdreg=0x%04x, statreg=0x%04x, cachelnsz=%d (dwords)\n",
- cfg->cmdreg, cfg->statreg, cfg->cachelnsz);
- printf("\tlattimer=0x%02x (%d ns), mingnt=0x%02x (%d ns), maxlat=0x%02x (%d ns)\n",
- cfg->lattimer, cfg->lattimer * 30,
- cfg->mingnt, cfg->mingnt * 250, cfg->maxlat, cfg->maxlat * 250);
-#endif /* PCI_DEBUG */
- if (cfg->intpin > 0)
- printf("\tintpin=%c, irq=%d\n", cfg->intpin +'a' -1, cfg->intline);
-
- for (i = 0; i < cfg->nummaps; i++) {
- pcimap *m = &cfg->map[i];
- printf("\tmap[%d]: type %x, range %2d, base %08x, size %2d\n",
- i, m->type, m->ln2range, m->base, m->ln2size);
- }
- }
- pci_drvattach(dinfo); /* XXX currently defined in pci_compat.c */
-}
-
-/* scan one PCI bus for devices */
-
-static int
-pci_probebus(int bus)
-{
- pcicfgregs probe;
- int bushigh = bus;
-
-#ifdef SIMOS
-#undef PCI_SLOTMAX
-#define PCI_SLOTMAX 0
-#endif
-
- bzero(&probe, sizeof probe);
- /* XXX KDM */
- /* probe.parent = pci_bridgeto(bus); */
- probe.bus = bus;
- for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
- int pcifunchigh = 0;
- for (probe.func = 0; probe.func <= pcifunchigh; probe.func++) {
- struct pci_devinfo *dinfo = pci_readcfg(&probe);
- if (dinfo != NULL) {
- if (dinfo->cfg.mfdev)
- pcifunchigh = 7;
- /*
- * XXX: Temporarily move pci_addcfg() up before
- * the use of cfg->subordinatebus. This is
- * necessary, since pci_addcfg() calls the
- * device's probe(), which may read the bus#
- * from some device dependent register of
- * some host to PCI bridges. The probe will
- * eventually be moved to pci_readcfg(), and
- * pci_addcfg() will then be moved back down
- * below the conditional statement ...
- */
- pci_addcfg(dinfo);
-
- if (bushigh < dinfo->cfg.subordinatebus)
- bushigh = dinfo->cfg.subordinatebus;
- if (bushigh < dinfo->cfg.secondarybus)
- bushigh = dinfo->cfg.secondarybus;
-
- /* XXX KDM */
- /* cfg = NULL; we don't own this anymore ... */
- }
- }
- }
- return (bushigh);
-}
-
-/* scan a PCI bus tree reached through one PCI attachment point */
-
-int
-pci_probe(pciattach *parent)
-{
- int bushigh;
- int bus = 0;
-
- STAILQ_INIT(&pci_devq);
-
- bushigh = pci_bushigh();
- while (bus <= bushigh) {
- int newbushigh;
-
- printf("Probing for devices on PCI bus %d:\n", bus);
- newbushigh = pci_probebus(bus);
-
- if (bushigh < newbushigh)
- bushigh = newbushigh;
- bus++;
- }
- return (bushigh);
-}
-
/*
* This is the user interface to PCI configuration space.
*/
@@ -750,8 +649,8 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
"pci_match_conf) (%d)\npci_ioctl: "
"pat_buf_len should be = %d\n",
cio->pat_buf_len, cio->num_patterns,
- sizeof(struct pci_match_conf),
- sizeof(struct pci_match_conf) *
+ (int)sizeof(struct pci_match_conf),
+ (int)sizeof(struct pci_match_conf) *
cio->num_patterns);
printf("pci_ioctl: do your headers match your "
"kernel?\n");
@@ -945,4 +844,534 @@ pci_cdevinit(void *dummy)
SYSINIT(pcidev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+PCI_CDEV, pci_cdevinit, NULL);
+#include "pci_if.h"
+
+/*
+ * A simple driver to wrap the old pci driver mechanism for back-compat.
+ */
+
+static int
+pci_compat_probe(device_t dev)
+{
+ struct pci_device *dvp;
+ struct pci_devinfo *dinfo;
+ pcicfgregs *cfg;
+ const char *name;
+ int error;
+
+ dinfo = device_get_ivars(dev);
+ cfg = &dinfo->cfg;
+ dvp = device_get_driver(dev)->priv;
+
+ /*
+ * Do the wrapped probe.
+ */
+ error = ENXIO;
+ if (dvp && dvp->pd_probe) {
+ name = dvp->pd_probe(cfg, (cfg->device << 16) + cfg->vendor);
+ if (name) {
+ device_set_desc_copy(dev, name);
+ error = 0;
+ }
+ }
+
+ return error;
+}
+
+static int
+pci_compat_attach(device_t dev)
+{
+ struct pci_device *dvp;
+ struct pci_devinfo *dinfo;
+ pcicfgregs *cfg;
+ int unit;
+
+ dinfo = device_get_ivars(dev);
+ cfg = &dinfo->cfg;
+ dvp = device_get_driver(dev)->priv;
+
+ unit = device_get_unit(dev);
+ if (unit > *dvp->pd_count)
+ *dvp->pd_count = unit;
+ if (dvp->pd_attach)
+ dvp->pd_attach(cfg, unit);
+
+ /*
+ * XXX KDM for some devices, dvp->pd_name winds up NULL.
+ * I haven't investigated enough to figure out why this
+ * would happen.
+ */
+ if (dvp->pd_name != NULL)
+ strncpy(dinfo->conf.pd_name, dvp->pd_name,
+ sizeof(dinfo->conf.pd_name));
+ else
+ strncpy(dinfo->conf.pd_name, "????",
+ sizeof(dinfo->conf.pd_name));
+ dinfo->conf.pd_name[sizeof(dinfo->conf.pd_name) - 1] = 0;
+ dinfo->conf.pd_unit = unit;
+
+ return 0;
+}
+
+static device_method_t pci_compat_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, pci_compat_probe),
+ DEVMETHOD(device_attach, pci_compat_attach),
+
+ { 0, 0 }
+};
+
+static devclass_t pci_devclass;
+
+/*
+ * Create a new style driver around each old pci driver.
+ */
+static void
+pci_wrap_old_drivers(void)
+{
+ struct pci_device **dvpp, *dvp;
+
+ dvpp = (struct pci_device **)pcidevice_set.ls_items;
+ while ((dvp = *dvpp++) != NULL) {
+ driver_t *driver;
+ driver = malloc(sizeof(driver_t), M_DEVBUF, M_NOWAIT);
+ if (!driver)
+ continue;
+ bzero(driver, sizeof(driver_t));
+ driver->name = dvp->pd_name;
+ driver->methods = pci_compat_methods;
+ driver->type = 0; /* XXX fixup in pci_map_int() */
+ driver->softc = sizeof(struct pci_devinfo *);
+ driver->priv = dvp;
+ devclass_add_driver(pci_devclass, driver);
+ }
+}
+
+/*
+ * New style pci driver. Parent device is either a pci-host-bridge or a
+ * pci-pci-bridge. Both kinds are represented by instances of pcib.
+ */
+
+static void
+pci_print_verbose(struct pci_devinfo *dinfo)
+{
+ if (bootverbose) {
+ int i;
+ pcicfgregs *cfg = &dinfo->cfg;
+
+ printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n",
+ cfg->vendor, cfg->device, cfg->revid);
+ printf("\tclass=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n",
+ cfg->baseclass, cfg->subclass, cfg->progif,
+ cfg->hdrtype, cfg->mfdev);
+ printf("\tsubordinatebus=%x \tsecondarybus=%x\n",
+ cfg->subordinatebus, cfg->secondarybus);
+#ifdef PCI_DEBUG
+ printf("\tcmdreg=0x%04x, statreg=0x%04x, cachelnsz=%d (dwords)\n",
+ cfg->cmdreg, cfg->statreg, cfg->cachelnsz);
+ printf("\tlattimer=0x%02x (%d ns), mingnt=0x%02x (%d ns), maxlat=0x%02x (%d ns)\n",
+ cfg->lattimer, cfg->lattimer * 30,
+ cfg->mingnt, cfg->mingnt * 250, cfg->maxlat, cfg->maxlat * 250);
+#endif /* PCI_DEBUG */
+ if (cfg->intpin > 0)
+ printf("\tintpin=%c, irq=%d\n", cfg->intpin +'a' -1, cfg->intline);
+
+ for (i = 0; i < cfg->nummaps; i++) {
+ pcimap *m = &cfg->map[i];
+ printf("\tmap[%d]: type %x, range %2d, base %08x, size %2d\n",
+ i, m->type, m->ln2range, m->base, m->ln2size);
+ }
+ }
+}
+
+static int
+pci_add_children(device_t dev, int busno)
+{
+ pcicfgregs probe;
+ int bushigh = busno;
+
+#ifdef SIMOS
+#undef PCI_SLOTMAX
+#define PCI_SLOTMAX 0
+#endif
+
+ bzero(&probe, sizeof probe);
+ /* XXX KDM */
+ /* probe.parent = pci_bridgeto(bus); */
+ probe.bus = busno;
+ for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
+ int pcifunchigh = 0;
+ for (probe.func = 0; probe.func <= pcifunchigh; probe.func++) {
+ struct pci_devinfo *dinfo = pci_readcfg(&probe);
+ if (dinfo != NULL) {
+ if (dinfo->cfg.mfdev)
+ pcifunchigh = 7;
+
+ pci_print_verbose(dinfo);
+ dinfo->cfg.dev =
+ device_add_child(dev, NULL, -1, dinfo);
+
+ if (bushigh < dinfo->cfg.subordinatebus)
+ bushigh = dinfo->cfg.subordinatebus;
+ if (bushigh < dinfo->cfg.secondarybus)
+ bushigh = dinfo->cfg.secondarybus;
+ }
+ }
+ }
+
+ return bushigh;
+}
+
+static int
+pci_new_probe(device_t dev)
+{
+ STAILQ_INIT(&pci_devq);
+ device_set_desc(dev, "PCI bus");
+
+ pci_add_children(dev, device_get_unit(dev));
+
+ return 0;
+}
+
+static void
+pci_print_child(device_t dev, device_t child)
+{
+ printf(" at device %d.%d", pci_get_slot(child), pci_get_function(child));
+ printf(" on %s%d", device_get_name(dev), device_get_unit(dev));
+}
+
+static int
+pci_read_ivar(device_t dev, device_t child, int which, u_long *result)
+{
+ struct pci_devinfo *dinfo;
+ pcicfgregs *cfg;
+
+ dinfo = device_get_ivars(child);
+ cfg = &dinfo->cfg;
+
+ switch (which) {
+ case PCI_IVAR_SUBVENDOR:
+ *result = cfg->subvendor;
+ break;
+ case PCI_IVAR_SUBDEVICE:
+ *result = cfg->subdevice;
+ break;
+ case PCI_IVAR_VENDOR:
+ *result = cfg->vendor;
+ break;
+ case PCI_IVAR_DEVICE:
+ *result = cfg->device;
+ break;
+ case PCI_IVAR_DEVID:
+ *result = (cfg->device << 16) | cfg->vendor;
+ break;
+ case PCI_IVAR_CLASS:
+ *result = cfg->baseclass;
+ break;
+ case PCI_IVAR_SUBCLASS:
+ *result = cfg->subclass;
+ break;
+ case PCI_IVAR_PROGIF:
+ *result = cfg->progif;
+ break;
+ case PCI_IVAR_REVID:
+ *result = cfg->revid;
+ break;
+ case PCI_IVAR_INTPIN:
+ *result = cfg->intpin;
+ break;
+ case PCI_IVAR_IRQ:
+ *result = cfg->intline;
+ break;
+ case PCI_IVAR_BUS:
+ *result = cfg->bus;
+ break;
+ case PCI_IVAR_SLOT:
+ *result = cfg->slot;
+ break;
+ case PCI_IVAR_FUNCTION:
+ *result = cfg->func;
+ break;
+ case PCI_IVAR_SECONDARYBUS:
+ *result = cfg->secondarybus;
+ break;
+ case PCI_IVAR_SUBORDINATEBUS:
+ *result = cfg->subordinatebus;
+ break;
+ default:
+ return ENOENT;
+ }
+ return 0;
+}
+
+static int
+pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+ struct pci_devinfo *dinfo;
+ pcicfgregs *cfg;
+
+ dinfo = device_get_ivars(child);
+ cfg = &dinfo->cfg;
+
+ switch (which) {
+ case PCI_IVAR_SUBVENDOR:
+ case PCI_IVAR_SUBDEVICE:
+ case PCI_IVAR_VENDOR:
+ case PCI_IVAR_DEVICE:
+ case PCI_IVAR_DEVID:
+ case PCI_IVAR_CLASS:
+ case PCI_IVAR_SUBCLASS:
+ case PCI_IVAR_PROGIF:
+ case PCI_IVAR_REVID:
+ case PCI_IVAR_INTPIN:
+ case PCI_IVAR_IRQ:
+ case PCI_IVAR_BUS:
+ case PCI_IVAR_SLOT:
+ case PCI_IVAR_FUNCTION:
+ return EINVAL; /* disallow for now */
+
+ case PCI_IVAR_SECONDARYBUS:
+ cfg->secondarybus = value;
+ break;
+ case PCI_IVAR_SUBORDINATEBUS:
+ cfg->subordinatebus = value;
+ break;
+ default:
+ return ENOENT;
+ }
+ return 0;
+}
+
+static int
+pci_mapno(pcicfgregs *cfg, int reg)
+{
+ int i, nummaps;
+ pcimap *map;
+
+ nummaps = cfg->nummaps;
+ map = cfg->map;
+
+ for (i = 0; i < nummaps; i++)
+ if (map[i].reg == reg)
+ return (i);
+ return (-1);
+}
+
+static int
+pci_porten(pcicfgregs *cfg)
+{
+ return ((cfg->cmdreg & PCIM_CMD_PORTEN) != 0);
+}
+
+static int
+pci_isportmap(pcicfgregs *cfg, int map)
+
+{
+ return ((unsigned)map < cfg->nummaps
+ && (cfg->map[map].type & PCI_MAPPORT) != 0);
+}
+
+static int
+pci_memen(pcicfgregs *cfg)
+{
+ return ((cfg->cmdreg & PCIM_CMD_MEMEN) != 0);
+}
+
+static int
+pci_ismemmap(pcicfgregs *cfg, int map)
+{
+ return ((unsigned)map < cfg->nummaps
+ && (cfg->map[map].type & PCI_MAPMEM) != 0);
+}
+
+static struct resource *
+pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ int isdefault;
+ struct pci_devinfo *dinfo = device_get_ivars(child);
+ pcicfgregs *cfg = &dinfo->cfg;
+ struct resource *rv, **rvp = 0;
+ int map;
+
+ isdefault = (device_get_parent(child) == dev
+ && start == 0UL && end == ~0UL && count == 1);
+
+ switch (type) {
+ case SYS_RES_IRQ:
+ if (*rid != 0)
+ return 0;
+ if (isdefault && cfg->intline != 255) {
+ start = cfg->intline;
+ end = cfg->intline;
+ count = 1;
+ }
+ break;
+
+ case SYS_RES_DRQ: /* passthru for child isa */
+ break;
+
+ case SYS_RES_MEMORY:
+ if (isdefault) {
+ map = pci_mapno(cfg, *rid);
+ if (pci_memen(cfg) && pci_ismemmap(cfg, map)) {
+ start = cfg->map[map].base;
+ count = 1 << cfg->map[map].ln2size;
+ end = start + count;
+ rvp = &cfg->map[map].res;
+ } else
+ return 0;
+ }
+ break;
+
+ case SYS_RES_IOPORT:
+ if (isdefault) {
+ map = pci_mapno(cfg, *rid);
+ if (pci_porten(cfg) && pci_isportmap(cfg, map)) {
+ start = cfg->map[map].base;
+ count = 1 << cfg->map[map].ln2size;
+ end = start + count;
+ rvp = &cfg->map[map].res;
+ } else
+ return 0;
+ }
+ break;
+
+ default:
+ return 0;
+ }
+
+ rv = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
+ type, rid, start, end, count, flags);
+ if (rvp)
+ *rvp = rv;
+
+ return rv;
+}
+
+static int
+pci_release_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+ int rv;
+ struct pci_devinfo *dinfo = device_get_ivars(child);
+ pcicfgregs *cfg = &dinfo->cfg;
+ int map = 0;
+
+ switch (type) {
+ case SYS_RES_IRQ:
+ if (rid != 0)
+ return EINVAL;
+ break;
+
+ case SYS_RES_DRQ: /* passthru for child isa */
+ break;
+
+ case SYS_RES_MEMORY:
+ case SYS_RES_IOPORT:
+ /*
+ * Only check the map registers if this is a direct
+ * descendant.
+ */
+ if (device_get_parent(child) == dev)
+ map = pci_mapno(cfg, rid);
+ else
+ map = -1;
+ break;
+
+ default:
+ return (ENOENT);
+ }
+
+ rv = BUS_RELEASE_RESOURCE(device_get_parent(dev), child, type, rid, r);
+
+ if (rv == 0) {
+ switch (type) {
+ case SYS_RES_IRQ:
+ cfg->irqres = 0;
+ break;
+
+ case SYS_RES_DRQ: /* passthru for child isa */
+ break;
+
+ case SYS_RES_MEMORY:
+ case SYS_RES_IOPORT:
+ if (map != -1)
+ cfg->map[map].res = 0;
+ break;
+
+ default:
+ return ENOENT;
+ }
+ }
+
+ return rv;
+}
+
+static u_int32_t
+pci_read_config_method(device_t dev, device_t child, int reg, int width)
+{
+ struct pci_devinfo *dinfo = device_get_ivars(child);
+ pcicfgregs *cfg = &dinfo->cfg;
+ return pci_cfgread(cfg, reg, width);
+}
+
+static void
+pci_write_config_method(device_t dev, device_t child, int reg,
+ u_int32_t val, int width)
+{
+ struct pci_devinfo *dinfo = device_get_ivars(child);
+ pcicfgregs *cfg = &dinfo->cfg;
+ pci_cfgwrite(cfg, reg, val, width);
+}
+
+static int
+pci_modevent(module_t mod, int what, void *arg)
+{
+ switch (what) {
+ case MOD_LOAD:
+ pci_wrap_old_drivers();
+ break;
+
+ case MOD_UNLOAD:
+ break;
+ }
+
+ return 0;
+}
+
+static device_method_t pci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, pci_new_probe),
+ DEVMETHOD(device_attach, bus_generic_attach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, pci_print_child),
+ DEVMETHOD(bus_read_ivar, pci_read_ivar),
+ DEVMETHOD(bus_write_ivar, pci_write_ivar),
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+ DEVMETHOD(bus_alloc_resource, pci_alloc_resource),
+ DEVMETHOD(bus_release_resource, pci_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+
+ /* PCI interface */
+ DEVMETHOD(pci_read_config, pci_read_config_method),
+ DEVMETHOD(pci_write_config, pci_write_config_method),
+
+ { 0, 0 }
+};
+
+static driver_t pci_driver = {
+ "pci",
+ pci_methods,
+ DRIVER_TYPE_MISC,
+ 1, /* no softc */
+};
+
+DRIVER_MODULE(pci, pcib, pci_driver, pci_devclass, pci_modevent, 0);
+
#endif /* NPCI > 0 */
diff --git a/sys/pci/pci_compat.c b/sys/pci/pci_compat.c
index f107e54608f2f..bfa1d59a3cd46 100644
--- a/sys/pci/pci_compat.c
+++ b/sys/pci/pci_compat.c
@@ -23,10 +23,12 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: pci_compat.c,v 1.20 1999/01/19 23:29:19 se Exp $
+ * $Id: pci_compat.c,v 1.21 1999/04/11 02:46:20 eivind Exp $
*
*/
+#include "opt_bus.h"
+
#include "pci.h"
#if NPCI > 0
@@ -41,6 +43,11 @@
#include <vm/pmap.h>
#include <sys/interrupt.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
#include <pci/pcireg.h>
#include <pci/pcivar.h>
@@ -56,118 +63,45 @@
/* ------------------------------------------------------------------------- */
-static int
-pci_mapno(pcicfgregs *cfg, int reg)
-{
- int i, nummaps;
- pcimap *map;
-
- nummaps = cfg->nummaps;
- map = cfg->map;
-
- for (i = 0; i < nummaps; i++)
- if (map[i].reg == reg)
- return (i);
- return (-1);
-}
-
-static int
-pci_porten(pcicfgregs *cfg)
-{
- return ((cfg->cmdreg & PCIM_CMD_PORTEN) != 0);
-}
-
-static int
-pci_isportmap(pcicfgregs *cfg, int map)
-
-{
- return ((unsigned)map < cfg->nummaps
- && (cfg->map[map].type & PCI_MAPPORT) != 0);
-}
-
-static int
-pci_memen(pcicfgregs *cfg)
-{
- return ((cfg->cmdreg & PCIM_CMD_MEMEN) != 0);
-}
-
-static int
-pci_ismemmap(pcicfgregs *cfg, int map)
-{
- return ((unsigned)map < cfg->nummaps
- && (cfg->map[map].type & PCI_MAPMEM) != 0);
-}
-
-/* ------------------------------------------------------------------------- */
-
u_long
-pci_conf_read(pcici_t tag, u_long reg)
+pci_conf_read(pcici_t cfg, u_long reg)
{
- return (pci_cfgread(tag, reg, 4));
+ return (pci_read_config(cfg->dev, reg, 4));
}
void
-pci_conf_write(pcici_t tag, u_long reg, u_long data)
+pci_conf_write(pcici_t cfg, u_long reg, u_long data)
{
- pci_cfgwrite(tag, reg, data, 4);
+ pci_write_config(cfg->dev, reg, data, 4);
}
int pci_map_port(pcici_t cfg, u_long reg, pci_port_t* pa)
{
- int map;
-
- map = pci_mapno(cfg, reg);
- if (pci_porten(cfg) && pci_isportmap(cfg, map)) {
- u_int32_t iobase;
- u_int32_t iosize;
-
- iobase = cfg->map[map].base;
- iosize = 1 << cfg->map[map].ln2size;
-#ifdef RESOURCE_CHECK
- if (resource_claim(cfg, REST_PORT, RESF_NONE,
- iobase, iobase + iosize -1) == 0)
-#endif /* RESOURCE_CHECK */
- {
- *pa = iobase;
- return (1);
- }
+ int rid;
+ struct resource *res;
+
+ rid = reg;
+ res = bus_alloc_resource(cfg->dev, SYS_RES_IOPORT, &rid,
+ 0, ~0, 1, RF_ACTIVE);
+ if (res) {
+ *pa = rman_get_start(res);
+ return (1);
}
return (0);
}
int pci_map_mem(pcici_t cfg, u_long reg, vm_offset_t* va, vm_offset_t* pa)
{
- int map;
-
- map = pci_mapno(cfg, reg);
- if (pci_memen(cfg) && pci_ismemmap(cfg, map)) {
- u_int32_t paddr;
- u_int32_t psize;
-
- paddr = cfg->map[map].base;
- psize = 1 << cfg->map[map].ln2size;
-#ifdef RESOURCE_CHECK
- if (resource_claim(cfg, REST_MEM, RESF_NONE,
- paddr, paddr + psize -1) == 0)
-#endif /* RESOURCE_CHECK */
- {
- u_int32_t poffs;
- vm_offset_t vaddr;
-
- poffs = paddr - trunc_page(paddr);
-#ifdef __i386__
- vaddr = (vm_offset_t)pmap_mapdev(paddr-poffs, psize+poffs);
-#endif
-#ifdef __alpha__
- vaddr = paddr-poffs;
-#endif
- if (vaddr != NULL) {
- vaddr += poffs;
- *va = vaddr;
- *pa = paddr;
- return (1);
- }
- }
+ int rid;
+ struct resource *res;
+
+ rid = reg;
+ res = bus_alloc_resource(cfg->dev, SYS_RES_MEMORY, &rid,
+ 0, ~0, 1, RF_ACTIVE);
+ if (res) {
+ *pa = rman_get_start(res);
+ *va = (vm_offset_t) rman_get_virtual(res);
+ return (1);
}
return (0);
}
@@ -175,7 +109,7 @@ int pci_map_mem(pcici_t cfg, u_long reg, vm_offset_t* va, vm_offset_t* pa)
int
pci_map_dense(pcici_t cfg, u_long reg, vm_offset_t* va, vm_offset_t* pa)
{
- if(pci_map_mem(cfg, reg, va, pa)){
+ if (pci_map_mem(cfg, reg, va, pa)){
#ifdef __alpha__
vm_offset_t dense;
@@ -195,7 +129,7 @@ pci_map_dense(pcici_t cfg, u_long reg, vm_offset_t* va, vm_offset_t* pa)
int
pci_map_bwx(pcici_t cfg, u_long reg, vm_offset_t* va, vm_offset_t* pa)
{
- if(pci_map_mem(cfg, reg, va, pa)){
+ if (pci_map_mem(cfg, reg, va, pa)){
#ifdef __alpha__
vm_offset_t bwx;
@@ -228,14 +162,42 @@ pci_map_int_right(pcici_t cfg, pci_inthand_t *handler, void *arg,
#endif
if (cfg->intpin != 0) {
int irq = cfg->intline;
- void *dev_instance = (void *)-1; /* XXX use cfg->devdata */
- void *idesc;
+ driver_t *driver = device_get_driver(cfg->dev);
+ int rid = 0;
+ struct resource *res;
+ void *ih;
+ res = bus_alloc_resource(cfg->dev, SYS_RES_IRQ, &rid,
+ irq, irq, 1, RF_SHAREABLE|RF_ACTIVE);
+ if (!res) {
+ printf("pci_map_int: can't allocate interrupt\n");
+ return 0;
+ }
- idesc = intr_create(dev_instance, irq, handler, arg, maskptr,
- flags);
- error = intr_connect(idesc);
+ /*
+ * This is ugly. Translate the mask into a driver type.
+ */
+ if (maskptr == &tty_imask)
+ driver->type |= DRIVER_TYPE_TTY;
+ else if (maskptr == &bio_imask)
+ driver->type |= DRIVER_TYPE_BIO;
+ else if (maskptr == &net_imask)
+ driver->type |= DRIVER_TYPE_NET;
+ else if (maskptr == &cam_imask)
+ driver->type |= DRIVER_TYPE_CAM;
+
+ error = BUS_SETUP_INTR(device_get_parent(cfg->dev), cfg->dev,
+ res, handler, arg, &ih);
if (error != 0)
return 0;
+
+#ifdef NEW_BUS_PCI
+ /*
+ * XXX this apic stuff looks totally busted. It should
+ * move to the nexus code which actually registers the
+ * interrupt.
+ */
+#endif
+
#ifdef APIC_IO
nextpin = next_apic_irq(irq);
@@ -265,11 +227,21 @@ pci_map_int_right(pcici_t cfg, pci_inthand_t *handler, void *arg,
nextpin = next_apic_irq(irq);
while (nextpin >= 0) {
- idesc = intr_create(dev_instance, nextpin, handler,
- arg, maskptr, flags);
- error = intr_connect(idesc);
- if (error != 0)
+ rid = 0;
+ res = bus_alloc_resource(cfg->dev, SYS_RES_IRQ, &rid,
+ nextpin, nextpin, 1,
+ RF_SHAREABLE|RF_ACTIVE);
+ if (!res) {
+ printf("pci_map_int: can't allocate extra interrupt\n");
+ return 0;
+ }
+ error = BUS_SETUP_INTR(device_get_parent(cfg->dev),
+ cfg->dev, res, handler, arg,
+ &ih);
+ if (error != 0) {
+ printf("pci_map_int: BUS_SETUP_INTR failed\n");
return 0;
+ }
printf("Registered extra interrupt handler for int %d (in addition to int %d)\n", nextpin, irq);
nextpin = next_apic_irq(nextpin);
}
@@ -284,6 +256,7 @@ pci_unmap_int(pcici_t cfg)
return (0); /* not supported, yet, since cfg doesn't know about idesc */
}
+#if 0
/* ------------------------------------------------------------------------- */
/*
@@ -464,6 +437,7 @@ int pci_register_lkm (struct pci_device *dvp, int if_revision)
if (lkm == NULL) {
return (-1);
}
+ bzero(lkm, sizeof (*lkm));
lkm->dvp = dvp;
lkm->next = pci_lkm_head;
@@ -480,5 +454,7 @@ pci_configure(void)
/* ------------------------------------------------------------------------- */
+#endif
+
#endif /* PCI_COMPAT */
#endif /* NPCI > 0 */
diff --git a/sys/pci/pci_if.m b/sys/pci/pci_if.m
new file mode 100644
index 0000000000000..b2fa6758fef6a
--- /dev/null
+++ b/sys/pci/pci_if.m
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 1998 Doug Rabson
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $Id$
+#
+
+INTERFACE pci;
+
+METHOD u_int32_t read_config {
+ device_t dev;
+ device_t child;
+ int reg;
+ int width;
+};
+
+METHOD void write_config {
+ device_t dev;
+ device_t child;
+ int reg;
+ u_int32_t val;
+ int width;
+};
diff --git a/sys/pci/pcireg.h b/sys/pci/pcireg.h
index 0adb5404021e2..9c0dba09331d2 100644
--- a/sys/pci/pcireg.h
+++ b/sys/pci/pcireg.h
@@ -26,7 +26,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: pcireg.h,v 1.19 1997/09/20 07:41:58 dyson Exp $
+ * $Id: pcireg.h,v 1.20 1998/10/07 03:40:51 gibbs Exp $
*
*/
@@ -173,7 +173,7 @@
#define PCIS_MEMORY_OTHER 0x80
#define PCIC_BRIDGE 0x06
-#define PCIS_BRDIGE_HOST 0x00
+#define PCIS_BRIDGE_HOST 0x00
#define PCIS_BRIDGE_ISA 0x01
#define PCIS_BRIDGE_EISA 0x02
#define PCIS_BRIDGE_MCA 0x03
diff --git a/sys/pci/pcisupport.c b/sys/pci/pcisupport.c
index b292c92d8d1a3..1fe5f1e2ed31e 100644
--- a/sys/pci/pcisupport.c
+++ b/sys/pci/pcisupport.c
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** $Id: pcisupport.c,v 1.94 1999/02/21 11:39:37 dfr Exp $
+** $Id: pcisupport.c,v 1.95 1999/04/07 03:59:13 msmith Exp $
**
** Device driver for DEC/INTEL PCI chipsets.
**
@@ -41,6 +41,7 @@
***************************************************************************
*/
+#include "opt_bus.h"
#include "opt_pci.h"
#include "opt_smp.h"
#include "intpm.h"
@@ -50,6 +51,7 @@
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
+#include <sys/bus.h>
#include <pci/pcivar.h>
#include <pci/pcireg.h>
@@ -65,19 +67,7 @@
**---------------------------------------------------------
*/
-static const char* chipset_probe (pcici_t tag, pcidi_t type);
-static void chipset_attach(pcici_t tag, int unit);
-static u_long chipset_count;
-
-static struct pci_device chipset_device = {
- "chip",
- chipset_probe,
- chipset_attach,
- &chipset_count,
- NULL
-};
-
-DATA_SET (pcidevice_set, chipset_device);
+static void chipset_attach(device_t dev, int unit);
struct condmsg {
unsigned char port;
@@ -127,20 +117,22 @@ generic_pci_bridge (pcici_t tag)
*/
static void
-fixbushigh_orion(pcici_t tag)
+fixbushigh_orion(device_t dev)
{
- tag->secondarybus = pci_cfgread(tag, 0x4a, 1);
- tag->subordinatebus = pci_cfgread(tag, 0x4b, 1);
+ pci_set_secondarybus(dev, pci_read_config(dev, 0x4a, 1));
+ pci_set_subordinatebus(dev, pci_read_config(dev, 0x4b, 1));
}
static void
-fixbushigh_i1225(pcici_t tag)
+fixbushigh_i1225(device_t dev)
{
int sublementarybus;
- sublementarybus = pci_cfgread(tag, 0x41, 1);
- if (sublementarybus != 0xff)
- tag->secondarybus = tag->subordinatebus = sublementarybus +1;
+ sublementarybus = pci_read_config(dev, 0x41, 1);
+ if (sublementarybus != 0xff) {
+ pci_set_secondarybus(dev, sublementarybus + 1);
+ pci_set_subordinatebus(dev, sublementarybus + 1);
+ }
}
@@ -158,7 +150,7 @@ fixbushigh_i1225(pcici_t tag)
* most sense.
*/
static void
-fixbushigh_450nx(pcici_t tag)
+fixbushigh_450nx(device_t dev)
{
int subordinatebus;
unsigned long devmap;
@@ -170,7 +162,7 @@ fixbushigh_450nx(pcici_t tag)
* If this doesn't find all the PCI busses, complain to the
* BIOS vendor. There is nothing more we can do.
*/
- devmap = pci_cfgread(tag, 0xd6, 2) & 0x3c;
+ devmap = pci_read_config(dev, 0xd6, 2) & 0x3c;
if (!devmap)
panic("450NX MIOC: No host to PCI bridges marked present.\n");
/*
@@ -178,13 +170,13 @@ fixbushigh_450nx(pcici_t tag)
* find the highest bus, and use those numbers.
*/
if (devmap & 0x20) { /* B1 */
- subordinatebus = pci_cfgread(tag, 0xd5, 1);
+ subordinatebus = pci_read_config(dev, 0xd5, 1);
} else if (devmap & 0x10) { /* A1 */
- subordinatebus = pci_cfgread(tag, 0xd4, 1);
+ subordinatebus = pci_read_config(dev, 0xd4, 1);
} else if (devmap & 0x8) { /* B0 */
- subordinatebus = pci_cfgread(tag, 0xd2, 1);
+ subordinatebus = pci_read_config(dev, 0xd2, 1);
} else /* if (devmap & 0x4) */ { /* A0 */
- subordinatebus = pci_cfgread(tag, 0xd1, 1);
+ subordinatebus = pci_read_config(dev, 0xd1, 1);
}
if (subordinatebus == 255) {
printf("fixbushigh_450nx: bogus highest PCI bus %d",
@@ -201,214 +193,44 @@ fixbushigh_450nx(pcici_t tag)
printf("fixbushigh_450nx: subordinatebus is %d\n",
subordinatebus);
- tag->secondarybus = tag->subordinatebus = subordinatebus;
+ pci_set_secondarybus(dev, subordinatebus);
+ pci_set_subordinatebus(dev, subordinatebus);
}
static void
-fixbushigh_Ross(pcici_t tag)
+fixbushigh_Ross(device_t dev)
{
int secondarybus;
/* just guessing the secondary bus register number ... */
- secondarybus = pci_cfgread(tag, 0x45, 1);
- if (secondarybus != 0)
- tag->secondarybus = tag->subordinatebus = secondarybus + 1;
+ secondarybus = pci_read_config(dev, 0x45, 1);
+ if (secondarybus != 0) {
+ pci_set_secondarybus(dev, secondarybus + 1);
+ pci_set_subordinatebus(dev, secondarybus + 1);
+ }
}
static void
-fixwsc_natoma(pcici_t tag)
+fixwsc_natoma(device_t dev)
{
int pmccfg;
- pmccfg = pci_cfgread(tag, 0x50, 2);
+ pmccfg = pci_read_config(dev, 0x50, 2);
#if defined(SMP)
if (pmccfg & 0x8000) {
printf("Correcting Natoma config for SMP\n");
pmccfg &= ~0x8000;
- pci_cfgwrite(tag, 0x50, 2, pmccfg);
+ pci_write_config(dev, 0x50, 2, pmccfg);
}
#else
if ((pmccfg & 0x8000) == 0) {
printf("Correcting Natoma config for non-SMP\n");
pmccfg |= 0x8000;
- pci_cfgwrite(tag, 0x50, 2, pmccfg);
+ pci_write_config(dev, 0x50, 2, pmccfg);
}
#endif
}
-
-static const char*
-chipset_probe (pcici_t tag, pcidi_t type)
-{
- unsigned rev;
- char *descr;
-
- switch (type) {
- case 0x00088086:
- /* Silently ignore this one! What is it, anyway ??? */
- return ("");
- case 0x04868086:
- return ("Intel 82425EX PCI system controller");
- case 0x04848086:
- rev = (unsigned) pci_conf_read (tag, PCI_CLASS_REG) & 0xff;
- if (rev == 3)
- return ("Intel 82378ZB PCI to ISA bridge");
- return ("Intel 82378IB PCI to ISA bridge");
- case 0x04838086:
- return ("Intel 82424ZX (Saturn) cache DRAM controller");
- case 0x04828086:
- return ("Intel 82375EB PCI-EISA bridge");
- case 0x04a38086:
- rev = (unsigned) pci_conf_read (tag, PCI_CLASS_REG) & 0xff;
- if (rev == 16 || rev == 17)
- return ("Intel 82434NX (Neptune) PCI cache memory controller");
- return ("Intel 82434LX (Mercury) PCI cache memory controller");
- case 0x12258086:
- fixbushigh_i1225(tag);
- return ("Intel 824?? host to PCI bridge");
- case 0x122d8086:
- return ("Intel 82437FX PCI cache memory controller");
- case 0x122e8086:
- return ("Intel 82371FB PCI to ISA bridge");
- case 0x12348086:
- return ("Intel 82371MX mobile PCI I/O IDE accelerator (MPIIX)");
- case 0x12358086:
- return ("Intel 82437MX mobile PCI cache memory controller");
- case 0x12508086:
- return ("Intel 82439");
- case 0x70008086:
- return ("Intel 82371SB PCI to ISA bridge");
- case 0x70308086:
- return ("Intel 82437VX PCI cache memory controller");
- case 0x71008086:
- return ("Intel 82439TX System Controller (MTXC)");
- case 0x71108086:
- return ("Intel 82371AB PCI to ISA bridge");
- case 0x71138086:
-#if NINTPM > 0
- return NULL; /* Need to stop generic_pci_bridge() */
-#else
- return ("Intel 82371AB Power management controller");
-#endif
- case 0x71908086:
- return ("Intel 82443BX host to PCI bridge");
- case 0x71918086:
- return ("Intel 82443BX host to AGP bridge");
- case 0x71928086:
- return ("Intel 82443BX host to PCI bridge (AGP disabled)");
- case 0x12378086:
- fixwsc_natoma(tag);
- return ("Intel 82440FX (Natoma) PCI and memory controller");
- case 0x84c48086:
- fixbushigh_orion(tag);
- return ("Intel 82454KX/GX (Orion) host to PCI bridge");
- case 0x84c58086:
- return ("Intel 82453KX/GX (Orion) PCI memory controller");
- case 0x84ca8086:
- fixbushigh_450nx(tag);
- return ("Intel 82451NX Memory and I/O Controller");
- case 0x84cb8086:
- return ("Intel 82454NX PCI Expander Bridge");
- case 0x00221014:
- return ("IBM 82351 PCI-PCI bridge");
- case 0x00011011:
- return ("DEC 21050 PCI-PCI bridge");
- case 0x124b8086:
- return ("Intel 82380FB mobile PCI to PCI bridge");
- /* SiS -- vendor 0x1039 */
- case 0x04961039:
- return ("SiS 85c496");
- case 0x04061039:
- return ("SiS 85c501");
- case 0x00081039:
- return ("SiS 85c503");
- case 0x06011039:
- return ("SiS 85c601");
-
- /* VLSI -- vendor 0x1004 */
- case 0x00051004:
- return ("VLSI 82C592 Host to PCI bridge");
- case 0x00061004:
- return ("VLSI 82C593 PCI to ISA bridge");
- case 0x01011004:
- return ("VLSI 82C532 Eagle II Peripheral Controller");
- case 0x01021004:
- return ("VLSI 82C534 Eagle II PCI Bus bridge");
- case 0x01031004:
- return ("VLSI 82C538 Eagle II PCI Docking bridge");
- case 0x01041004:
- return ("VLSI 82C535 Eagle II System Controller");
- case 0x01051004:
- return ("VLSI 82C147 IrDA Controller");
-
- /* VIA Technologies -- vendor 0x1106
- * Note that the old Apollo Master chipset is not in here, as VIA
- * does not seem to have any docs on their website for it, and I do
- * not have a Master board in my posession. -LC */
-
- case 0x05851106:
- return("VIA 82C585 (Apollo VP1/VPX) system controller");
- case 0x05861106: /* south bridge section -- IDE is covered in ide_pci.c */
- return("VIA 82C586 PCI-ISA bridge");
- case 0x05951106:
- case 0x15951106:
- return("VIA 82C595 (Apollo VP2) system controller");
- case 0x05971106:
- return("VIA 82C597 (Apollo VP3) system controller");
- /* XXX need info on the MVP3 -- any takers? */
- case 0x30401106:
- return("VIA 82C586B ACPI interface");
- /* XXX Here is MVP3, I got the datasheet but NO M/B to test it */
- /* totally. Please let me know if anything wrong. -F */
- case 0x05981106:
- return("VIA 82C598MVP (Apollo MVP3) host bridge");
- case 0x85981106:
- return("VIA 82C598MVP (Apollo MVP3) PCI-PCI bridge");
-
- /* AcerLabs -- vendor 0x10b9 */
- /* Funny : The datasheet told me vendor id is "10b8",sub-vendor */
- /* id is '10b9" but the register always shows "10b9". -Foxfair */
- case 0x154110b9:
- return("AcerLabs M1541 (Aladdin-V) PCI host bridge");
- case 0x153310b9:
- return("AcerLabs M1533 portable PCI-ISA bridge");
- case 0x154310b9:
- return("AcerLabs M1543 desktop PCI-ISA bridge");
- case 0x524710b9:
- return("AcerLabs M5247 PCI-PCI(AGP Supported) bridge");
- case 0x524310b9:/* 5243 seems like 5247, need more info to divide*/
- return("AcerLabs M5243 PCI-PCI bridge");
- case 0x710110b9:
-#if NALPM > 0
- return NULL; /* Need to stop generic_pci_bridge() */
-#else
- return("AcerLabs M15x3 Power Management Unit");
-#endif
-
- /* NEC -- vendor 0x1033 */
- case 0x00011033:
- return ("NEC 0001 PCI to PC-98 C-bus bridge");
- case 0x00021033:
- return ("NEC 0002 PCI to PC-98 local bus bridge");
- case 0x00161033:
- return ("NEC 0016 PCI to PC-98 local bus bridge");
- case 0x002c1033:
- return ("NEC 002C PCI to PC-98 C-bus bridge");
- case 0x003b1033:
- return ("NEC 003B PCI to PC-98 C-bus bridge");
-
- /* Ross (?) -- vendor 0x1166 */
- case 0x00051166:
- fixbushigh_Ross(tag);
- return ("Ross (?) host to PCI bridge");
- };
-
- if ((descr = generic_pci_bridge(tag)) != NULL)
- return descr;
-
- return NULL;
-}
-
#ifndef PCI_QUIET
#define M_XX 0 /* end of list */
@@ -848,17 +670,8 @@ static const struct condmsg conf82371fb2[] =
{ 0 }
};
-static char confread (pcici_t config_id, int port)
-{
- unsigned long portw = port & ~3;
- unsigned long ports = (port - portw) << 3;
-
- unsigned long l = pci_conf_read (config_id, portw);
- return (l >> ports);
-}
-
static void
-writeconfig (pcici_t config_id, const struct condmsg *tbl)
+writeconfig (device_t dev, const struct condmsg *tbl)
{
while (tbl->flags != M_XX) {
const char *text = 0;
@@ -866,7 +679,7 @@ writeconfig (pcici_t config_id, const struct condmsg *tbl)
if (tbl->flags == M_TR) {
text = tbl->text;
} else {
- unsigned char v = (unsigned char) confread(config_id, tbl->port);
+ unsigned char v = pci_read_config(dev, tbl->port, 1);
switch (tbl->flags) {
case M_EQ:
if ((v & tbl->mask) == tbl->value) text = tbl->text;
@@ -888,14 +701,14 @@ writeconfig (pcici_t config_id, const struct condmsg *tbl)
#ifdef DUMPCONFIGSPACE
static void
-dumpconfigspace (pcici_t tag)
+dumpconfigspace (device_t dev)
{
int reg;
printf ("configuration space registers:");
for (reg = 0; reg < 0x100; reg+=4) {
if ((reg & 0x0f) == 0)
printf ("\n%02x:\t", reg);
- printf ("%08x ", pci_conf_read (tag, reg));
+ printf ("%08x ", pci_read_config(dev, reg, 4));
}
printf ("\n");
}
@@ -904,49 +717,448 @@ dumpconfigspace (pcici_t tag)
#endif /* PCI_QUIET */
static void
-chipset_attach (pcici_t config_id, int unit)
+chipset_attach (device_t dev, int unit)
{
#ifndef PCI_QUIET
if (!bootverbose)
return;
- switch (pci_conf_read (config_id, PCI_ID_REG)) {
+ switch (pci_get_devid(dev)) {
case 0x04868086:
- writeconfig (config_id, conf82425ex);
+ writeconfig (dev, conf82425ex);
break;
case 0x04838086:
- writeconfig (config_id, conf82424zx);
+ writeconfig (dev, conf82424zx);
break;
case 0x04a38086:
- writeconfig (config_id, conf82434lx);
+ writeconfig (dev, conf82434lx);
break;
case 0x04848086:
- writeconfig (config_id, conf82378);
+ writeconfig (dev, conf82378);
break;
case 0x122d8086:
- writeconfig (config_id, conf82437fx);
+ writeconfig (dev, conf82437fx);
break;
case 0x70308086:
- writeconfig (config_id, conf82437vx);
+ writeconfig (dev, conf82437vx);
break;
case 0x70008086:
case 0x122e8086:
- writeconfig (config_id, conf82371fb);
+ writeconfig (dev, conf82371fb);
break;
case 0x70108086:
case 0x12308086:
- writeconfig (config_id, conf82371fb2);
+ writeconfig (dev, conf82371fb2);
break;
#if 0
case 0x00011011: /* DEC 21050 */
case 0x00221014: /* IBM xxx */
- writeconfig (config_id, conf_pci2pci);
+ writeconfig (dev, conf_pci2pci);
break;
#endif
};
#endif /* PCI_QUIET */
}
+static const char *
+pci_bridge_type(device_t dev)
+{
+ char *descr, tmpbuf[120];
+
+ if (pci_get_class(dev) != PCIC_BRIDGE)
+ return NULL;
+
+ switch (pci_get_subclass(dev)) {
+ case PCIS_BRIDGE_HOST: strcpy(tmpbuf, "Host to PCI"); break;
+ case PCIS_BRIDGE_ISA: strcpy(tmpbuf, "PCI to ISA"); break;
+ case PCIS_BRIDGE_EISA: strcpy(tmpbuf, "PCI to EISA"); break;
+ case PCIS_BRIDGE_MCA: strcpy(tmpbuf, "PCI to MCA"); break;
+ case PCIS_BRIDGE_PCI: strcpy(tmpbuf, "PCI to PCI"); break;
+ case PCIS_BRIDGE_PCMCIA: strcpy(tmpbuf, "PCI to PCMCIA"); break;
+ case PCIS_BRIDGE_NUBUS: strcpy(tmpbuf, "PCI to NUBUS"); break;
+ case PCIS_BRIDGE_CARDBUS: strcpy(tmpbuf, "PCI to CardBus"); break;
+ default:
+ snprintf(tmpbuf, sizeof(tmpbuf),
+ "PCI to 0x%x", pci_get_subclass(dev));
+ break;
+ }
+ snprintf(tmpbuf+strlen(tmpbuf), sizeof(tmpbuf)-strlen(tmpbuf),
+ " bridge (vendor=%04x device=%04x)",
+ pci_get_vendor(dev), pci_get_device(dev));
+ descr = malloc (strlen(tmpbuf) +1, M_DEVBUF, M_WAITOK);
+ strcpy(descr, tmpbuf);
+ return descr;
+}
+
+static const char*
+pcib_match(device_t dev)
+{
+ switch (pci_get_devid(dev)) {
+ case 0x84cb8086:
+ return ("Intel 82454NX PCI Expander Bridge");
+ case 0x00221014:
+ return ("IBM 82351 PCI-PCI bridge");
+ case 0x00011011:
+ return ("DEC 21050 PCI-PCI bridge");
+ case 0x124b8086:
+ return ("Intel 82380FB mobile PCI to PCI bridge");
+
+ /* VLSI -- vendor 0x1004 */
+ case 0x01021004:
+ return ("VLSI 82C534 Eagle II PCI Bus bridge");
+ case 0x01031004:
+ return ("VLSI 82C538 Eagle II PCI Docking bridge");
+
+ /* XXX Here is MVP3, I got the datasheet but NO M/B to test it */
+ /* totally. Please let me know if anything wrong. -F */
+ case 0x85981106:
+ return("VIA 82C598MVP (Apollo MVP3) PCI-PCI bridge");
+
+ /* AcerLabs -- vendor 0x10b9 */
+ /* Funny : The datasheet told me vendor id is "10b8",sub-vendor */
+ /* id is '10b9" but the register always shows "10b9". -Foxfair */
+ case 0x524710b9:
+ return("AcerLabs M5247 PCI-PCI(AGP Supported) bridge");
+ case 0x524310b9:/* 5243 seems like 5247, need more info to divide*/
+ return("AcerLabs M5243 PCI-PCI bridge");
+
+ };
+
+ if (pci_get_class(dev) == PCIC_BRIDGE
+ && pci_get_subclass(dev) == PCIS_BRIDGE_PCI)
+ return pci_bridge_type(dev);
+
+ return NULL;
+}
+
+static int pcib_probe(device_t dev)
+{
+ const char *desc;
+
+ desc = pcib_match(dev);
+ if (desc) {
+ device_set_desc_copy(dev, desc);
+ return 0;
+ }
+
+ return ENXIO;
+}
+
+static int pcib_attach(device_t dev)
+{
+ struct pci_devinfo *dinfo;
+ pcicfgregs *cfg;
+
+ dinfo = device_get_ivars(dev);
+ cfg = &dinfo->cfg;
+
+ chipset_attach(dev, device_get_unit(dev));
+
+ if (cfg->secondarybus) {
+ device_add_child(dev, "pci", cfg->secondarybus, 0);
+ return bus_generic_attach(dev);
+ } else
+ return 0;
+}
+
+static device_method_t pcib_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, pcib_probe),
+ DEVMETHOD(device_attach, pcib_attach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+
+ { 0, 0 }
+};
+
+static driver_t pcib_driver = {
+ "pcib",
+ pcib_methods,
+ DRIVER_TYPE_MISC,
+ 1,
+};
+
+static devclass_t pcib_devclass;
+
+DRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, 0, 0);
+
+static const char *
+isab_match(device_t dev)
+{
+ unsigned rev;
+
+ switch (pci_get_devid(dev)) {
+ case 0x04848086:
+ rev = pci_get_revid(dev);
+ if (rev == 3)
+ return ("Intel 82378ZB PCI to ISA bridge");
+ return ("Intel 82378IB PCI to ISA bridge");
+ case 0x04828086:
+ return ("Intel 82375EB PCI-EISA bridge");
+ case 0x122e8086:
+ return ("Intel 82371FB PCI to ISA bridge");
+ case 0x70008086:
+ return ("Intel 82371SB PCI to ISA bridge");
+ case 0x71108086:
+ return ("Intel 82371AB PCI to ISA bridge");
+
+ /* VLSI -- vendor 0x1004 */
+ case 0x00061004:
+ return ("VLSI 82C593 PCI to ISA bridge");
+
+ /* VIA Technologies -- vendor 0x1106
+ * Note that the old Apollo Master chipset is not in here, as VIA
+ * does not seem to have any docs on their website for it, and I do
+ * not have a Master board in my posession. -LC */
+
+ case 0x05861106: /* south bridge section -- IDE is covered in ide_pci.c */
+ return("VIA 82C586 PCI-ISA bridge");
+
+ /* AcerLabs -- vendor 0x10b9 */
+ /* Funny : The datasheet told me vendor id is "10b8",sub-vendor */
+ /* id is '10b9" but the register always shows "10b9". -Foxfair */
+ case 0x153310b9:
+ return("AcerLabs M1533 portable PCI-ISA bridge");
+ case 0x154310b9:
+ return("AcerLabs M1543 desktop PCI-ISA bridge");
+ }
+
+ if (pci_get_class(dev) == PCIC_BRIDGE
+ && (pci_get_subclass(dev) == PCIS_BRIDGE_ISA
+ || pci_get_subclass(dev) == PCIS_BRIDGE_EISA))
+ return pci_bridge_type(dev);
+
+ return NULL;
+}
+
+static int
+isab_probe(device_t dev)
+{
+ const char *desc;
+
+ desc = isab_match(dev);
+ if (desc) {
+ device_set_desc_copy(dev, desc);
+ /* Don't bother adding more than one ISA bus */
+ if (!devclass_get_device(devclass_find("isa"), 0))
+ device_add_child(dev, "isa", -1, 0);
+ return 0;
+ }
+
+ return ENXIO;
+}
+
+static device_method_t isab_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, isab_probe),
+ DEVMETHOD(device_attach, bus_generic_attach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+
+ { 0, 0 }
+};
+
+static driver_t isab_driver = {
+ "isab",
+ isab_methods,
+ DRIVER_TYPE_MISC,
+ 1,
+};
+
+static devclass_t isab_devclass;
+
+DRIVER_MODULE(isab, pci, isab_driver, isab_devclass, 0, 0);
+
+static const char*
+chip_match(device_t dev)
+{
+ unsigned rev;
+
+ switch (pci_get_devid(dev)) {
+ case 0x00088086:
+ /* Silently ignore this one! What is it, anyway ??? */
+ return ("");
+ case 0x71108086:
+ /*
+ * On my laptop (Tecra 8000DVD), this device has a
+ * bogus subclass 0x80 so make sure that it doesn't
+ * match the generic 'chip' driver by accident.
+ */
+ return NULL;
+ case 0x12258086:
+ fixbushigh_i1225(dev);
+ return ("Intel 824?? host to PCI bridge");
+ case 0x71908086:
+ return ("Intel 82443BX host to PCI bridge");
+ case 0x71918086:
+ return ("Intel 82443BX host to AGP bridge");
+ case 0x71928086:
+ return ("Intel 82443BX host to PCI bridge (AGP disabled)");
+ case 0x84c48086:
+ fixbushigh_orion(dev);
+ return ("Intel 82454KX/GX (Orion) host to PCI bridge");
+ case 0x84ca8086:
+ fixbushigh_450nx(dev);
+ return ("Intel 82451NX Memory and I/O Controller");
+ case 0x04868086:
+ return ("Intel 82425EX PCI system controller");
+ case 0x04838086:
+ return ("Intel 82424ZX (Saturn) cache DRAM controller");
+ case 0x04a38086:
+ rev = pci_get_revid(dev);
+ if (rev == 16 || rev == 17)
+ return ("Intel 82434NX (Neptune) PCI cache memory controller");
+ return ("Intel 82434LX (Mercury) PCI cache memory controller");
+ case 0x122d8086:
+ return ("Intel 82437FX PCI cache memory controller");
+ case 0x12348086:
+ return ("Intel 82371MX mobile PCI I/O IDE accelerator (MPIIX)");
+ case 0x12358086:
+ return ("Intel 82437MX mobile PCI cache memory controller");
+ case 0x12508086:
+ return ("Intel 82439");
+ case 0x70308086:
+ return ("Intel 82437VX PCI cache memory controller");
+ case 0x71008086:
+ return ("Intel 82439TX System Controller (MTXC)");
+
+ case 0x71138086:
+ return ("Intel 82371AB Power management controller");
+ case 0x12378086:
+ fixwsc_natoma(dev);
+ return ("Intel 82440FX (Natoma) PCI and memory controller");
+ case 0x84c58086:
+ return ("Intel 82453KX/GX (Orion) PCI memory controller");
+ /* SiS -- vendor 0x1039 */
+ case 0x04961039:
+ return ("SiS 85c496");
+ case 0x04061039:
+ return ("SiS 85c501");
+ case 0x00081039:
+ return ("SiS 85c503");
+ case 0x06011039:
+ return ("SiS 85c601");
+
+ /* VLSI -- vendor 0x1004 */
+ case 0x00051004:
+ return ("VLSI 82C592 Host to PCI bridge");
+ case 0x01011004:
+ return ("VLSI 82C532 Eagle II Peripheral Controller");
+ case 0x01041004:
+ return ("VLSI 82C535 Eagle II System Controller");
+ case 0x01051004:
+ return ("VLSI 82C147 IrDA Controller");
+
+ /* VIA Technologies -- vendor 0x1106
+ * Note that the old Apollo Master chipset is not in here, as VIA
+ * does not seem to have any docs on their website for it, and I do
+ * not have a Master board in my posession. -LC */
+
+ case 0x05851106:
+ return("VIA 82C585 (Apollo VP1/VPX) system controller");
+ case 0x05951106:
+ case 0x15951106:
+ return("VIA 82C595 (Apollo VP2) system controller");
+ case 0x05971106:
+ return("VIA 82C597 (Apollo VP3) system controller");
+ /* XXX Here is MVP3, I got the datasheet but NO M/B to test it */
+ /* totally. Please let me know if anything wrong. -F */
+ /* XXX need info on the MVP3 -- any takers? */
+ case 0x05981106:
+ return("VIA 82C598MVP (Apollo MVP3) host bridge");
+ case 0x30401106:
+ return("VIA 82C586B ACPI interface");
+#if 0
+ /* XXX New info added-in */
+ case 0x05711106:
+ return("VIA 82C586B IDE controller");
+ case 0x30381106:
+ return("VIA 82C586B USB controller");
+#endif
+
+ /* NEC -- vendor 0x1033 */
+ case 0x00011033:
+ return ("NEC 0001 PCI to PC-98 C-bus bridge");
+ case 0x00021033:
+ return ("NEC 0002 PCI to PC-98 local bus bridge");
+ case 0x00161033:
+ return ("NEC 0016 PCI to PC-98 local bus bridge");
+ case 0x002c1033:
+ return ("NEC 002C PCI to PC-98 C-bus bridge");
+ case 0x003b1033:
+ return ("NEC 003B PCI to PC-98 C-bus bridge");
+
+ /* AcerLabs -- vendor 0x10b9 */
+ /* Funny : The datasheet told me vendor id is "10b8",sub-vendor */
+ /* id is '10b9" but the register always shows "10b9". -Foxfair */
+ case 0x154110b9:
+ return("AcerLabs M1541 (Aladdin-V) PCI host bridge");
+ };
+
+ if (pci_get_class(dev) == PCIC_BRIDGE
+ && pci_get_subclass(dev) != PCIS_BRIDGE_PCI
+ && pci_get_subclass(dev) != PCIS_BRIDGE_ISA
+ && pci_get_subclass(dev) != PCIS_BRIDGE_EISA)
+ return pci_bridge_type(dev);
+
+ return NULL;
+}
+
+static int chip_probe(device_t dev)
+{
+ const char *desc;
+
+ desc = chip_match(dev);
+ if (desc) {
+ device_set_desc_copy(dev, desc);
+ return 0;
+ }
+
+ return ENXIO;
+}
+
+static int chip_attach(device_t dev)
+{
+ chipset_attach(dev, device_get_unit(dev));
+
+ return 0;
+}
+
+static device_method_t chip_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, chip_probe),
+ DEVMETHOD(device_attach, chip_attach),
+
+ { 0, 0 }
+};
+
+static driver_t chip_driver = {
+ "chip",
+ chip_methods,
+ DRIVER_TYPE_MISC,
+ 1,
+};
+
+static devclass_t chip_devclass;
+
+DRIVER_MODULE(chip, pci, chip_driver, chip_devclass, 0, 0);
+
/*---------------------------------------------------------
**
** Catchall driver for VGA devices
@@ -957,29 +1169,16 @@ chipset_attach (pcici_t config_id, int unit)
**---------------------------------------------------------
*/
-static const char* vga_probe (pcici_t tag, pcidi_t type);
-static void vga_attach (pcici_t tag, int unit);
-static u_long vga_count;
-
-static struct pci_device vga_device = {
- "vga",
- vga_probe,
- vga_attach,
- &vga_count,
- NULL
-};
-
-DATA_SET (pcidevice_set, vga_device);
-
-static const char* vga_probe (pcici_t tag, pcidi_t typea)
+static const char* vga_match(device_t dev)
{
- int data = pci_conf_read(tag, PCI_CLASS_REG);
- u_int id = pci_conf_read(tag, PCI_ID_REG);
+ /* int data = pci_conf_read(tag, PCI_CLASS_REG); */
+ u_int id = pci_get_devid(dev);
const char *vendor, *chip, *type;
- vendor = chip = type = 0;
+ return 0; /* XXX interferes with syscons */
- switch (id & 0xffff) {
+ vendor = chip = type = 0;
+ switch (id) {
case 0x10c8:
vendor = "NeoMagic";
switch (id >> 16) {
@@ -1209,20 +1408,18 @@ static const char* vga_probe (pcici_t tag, pcidi_t typea)
return buf;
}
- switch (data & PCI_CLASS_MASK) {
+ switch (pci_get_class(dev)) {
- case PCI_CLASS_PREHISTORIC:
- if ((data & PCI_SUBCLASS_MASK)
- != PCI_SUBCLASS_PREHISTORIC_VGA)
+ case PCIC_OLD:
+ if (pci_get_subclass(dev) != PCIS_OLD_VGA)
return 0;
if (type == 0)
type = "VGA-compatible display device";
break;
- case PCI_CLASS_DISPLAY:
+ case PCIC_DISPLAY:
if (type == 0) {
- if ((data & PCI_SUBCLASS_MASK)
- == PCI_SUBCLASS_DISPLAY_VGA)
+ if (pci_get_subclass(dev) != PCIS_DISPLAY_VGA)
type = "VGA-compatible display device";
else {
/*
@@ -1260,7 +1457,20 @@ static const char* vga_probe (pcici_t tag, pcidi_t typea)
return type;
}
-static void vga_attach (pcici_t tag, int unit)
+static int vga_probe(device_t dev)
+{
+ const char *desc;
+
+ desc = vga_match(dev);
+ if (desc) {
+ device_set_desc(dev, desc);
+ return 0;
+ }
+
+ return ENXIO;
+}
+
+static int vga_attach(device_t dev)
{
/*
** If the assigned addresses are remapped,
@@ -1273,42 +1483,27 @@ static void vga_attach (pcici_t tag, int unit)
for (reg = PCI_MAP_REG_START; reg < PCI_MAP_REG_END; reg += 4)
(void) pci_map_mem (tag, reg, &va, &pa);
#endif
+ return 0;
}
-/*---------------------------------------------------------
-**
-** Hook for loadable pci drivers
-**
-**---------------------------------------------------------
-*/
-
-static const char* lkm_probe (pcici_t tag, pcidi_t type);
-static void lkm_attach (pcici_t tag, int unit);
-static u_long lkm_count;
+static device_method_t vga_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, vga_probe),
+ DEVMETHOD(device_attach, vga_attach),
-static struct pci_device lkm_device = {
- "lkm",
- lkm_probe,
- lkm_attach,
- &lkm_count,
- NULL
+ { 0, 0 }
};
-DATA_SET (pcidevice_set, lkm_device);
+static driver_t vga_driver = {
+ "vga",
+ vga_methods,
+ DRIVER_TYPE_MISC,
+ 1,
+};
-static const char*
-lkm_probe (pcici_t tag, pcidi_t type)
-{
- /*
- ** Not yet!
- ** (Should try to load a matching driver)
- */
- return ((char*)0);
-}
+static devclass_t vga_devclass;
-static void
-lkm_attach (pcici_t tag, int unit)
-{}
+DRIVER_MODULE(vga, pci, vga_driver, vga_devclass, 0, 0);
/*---------------------------------------------------------
**
@@ -1317,32 +1512,39 @@ lkm_attach (pcici_t tag, int unit)
**---------------------------------------------------------
*/
-static const char* ign_probe (pcici_t tag, pcidi_t type);
-static void ign_attach (pcici_t tag, int unit);
-static u_long ign_count;
-
-static struct pci_device ign_device = {
- NULL,
- ign_probe,
- ign_attach,
- &ign_count,
- NULL
-};
-
-DATA_SET (pcidevice_set, ign_device);
-
-static const char*
-ign_probe (pcici_t tag, pcidi_t type)
+static int
+ign_probe (device_t dev)
{
- switch (type) {
+ switch (pci_get_devid(dev)) {
case 0x10001042ul: /* wd */
- return ("");
+ return 0;
/* return ("SMC FDC 37c665");*/
};
- return ((char*)0);
+ return ENXIO;
}
-static void
-ign_attach (pcici_t tag, int unit)
-{}
+static int
+ign_attach (device_t dev)
+{
+ return 0;
+}
+
+static device_method_t ign_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ign_probe),
+ DEVMETHOD(device_attach, ign_attach),
+
+ { 0, 0 }
+};
+
+static driver_t ign_driver = {
+ "ign",
+ ign_methods,
+ DRIVER_TYPE_MISC,
+ 1,
+};
+
+static devclass_t ign_devclass;
+
+DRIVER_MODULE(ign, pci, ign_driver, ign_devclass, 0, 0);
diff --git a/sys/pci/pcivar.h b/sys/pci/pcivar.h
index 7843e3a6d656b..55f72a16b875f 100644
--- a/sys/pci/pcivar.h
+++ b/sys/pci/pcivar.h
@@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: pcivar.h,v 1.24 1999/01/13 04:59:19 bde Exp $
+ * $Id: pcivar.h,v 1.25 1999/01/19 23:29:20 se Exp $
*
*/
@@ -67,13 +67,17 @@ typedef struct {
u_int8_t ln2size;
u_int8_t ln2range;
u_int8_t reg; /* offset of map register in config space */
+/* u_int8_t dummy;*/
+ struct resource *res; /* handle from resource manager */
} pcimap;
/* config header information common to all header types */
typedef struct pcicfg {
+ struct device *dev; /* device which owns this */
pcimap *map; /* pointer to array of PCI maps */
void *hdrspec; /* pointer to header type specific data */
+ struct resource *irqres; /* resource descriptor for interrupt mapping */
u_int16_t subvendor; /* card vendor ID */
u_int16_t subdevice; /* card device ID, assigned by card vendor */
@@ -182,6 +186,79 @@ void pci_cfgwrite (pcicfgregs *cfg, int reg, int data, int bytes);
vm_offset_t pci_cvt_to_dense (vm_offset_t);
vm_offset_t pci_cvt_to_bwx (vm_offset_t);
#endif /* __alpha__ */
+
+#ifdef _SYS_BUS_H_
+
+#include "pci_if.h"
+
+enum pci_device_ivars {
+ PCI_IVAR_SUBVENDOR,
+ PCI_IVAR_SUBDEVICE,
+ PCI_IVAR_VENDOR,
+ PCI_IVAR_DEVICE,
+ PCI_IVAR_DEVID,
+ PCI_IVAR_CLASS,
+ PCI_IVAR_SUBCLASS,
+ PCI_IVAR_PROGIF,
+ PCI_IVAR_REVID,
+ PCI_IVAR_INTPIN,
+ PCI_IVAR_IRQ,
+ PCI_IVAR_BUS,
+ PCI_IVAR_SLOT,
+ PCI_IVAR_FUNCTION,
+ PCI_IVAR_SECONDARYBUS,
+ PCI_IVAR_SUBORDINATEBUS,
+};
+
+/*
+ * Simplified accessors for pci devices
+ */
+#define PCI_ACCESSOR(A, B, T) \
+ \
+static __inline T pci_get_ ## A(device_t dev) \
+{ \
+ uintptr_t v; \
+ BUS_READ_IVAR(device_get_parent(dev), dev, PCI_IVAR_ ## B, &v); \
+ return (T) v; \
+} \
+ \
+static __inline void pci_set_ ## A(device_t dev, T t) \
+{ \
+ u_long v = (u_long) t; \
+ BUS_WRITE_IVAR(device_get_parent(dev), dev, PCI_IVAR_ ## B, v); \
+}
+
+PCI_ACCESSOR(subvendor, SUBVENDOR, u_int16_t)
+PCI_ACCESSOR(subdevice, SUBDEVICE, u_int16_t)
+PCI_ACCESSOR(vendor, VENDOR, u_int16_t)
+PCI_ACCESSOR(device, DEVICE, u_int16_t)
+PCI_ACCESSOR(devid, DEVID, u_int32_t)
+PCI_ACCESSOR(class, CLASS, u_int8_t)
+PCI_ACCESSOR(subclass, SUBCLASS, u_int8_t)
+PCI_ACCESSOR(progif, PROGIF, u_int8_t)
+PCI_ACCESSOR(revid, REVID, u_int8_t)
+PCI_ACCESSOR(intpin, INTPIN, u_int8_t)
+PCI_ACCESSOR(irq, IRQ, u_int8_t)
+PCI_ACCESSOR(bus, BUS, u_int8_t)
+PCI_ACCESSOR(slot, SLOT, u_int8_t)
+PCI_ACCESSOR(function, FUNCTION, u_int8_t)
+PCI_ACCESSOR(secondarybus, SECONDARYBUS, u_int8_t)
+PCI_ACCESSOR(subordinatebus, SUBORDINATEBUS, u_int8_t)
+
+static __inline u_int32_t
+pci_read_config(device_t dev, int reg, int width)
+{
+ return PCI_READ_CONFIG(device_get_parent(dev), dev, reg, width);
+}
+
+static __inline void
+pci_write_config(device_t dev, int reg, u_int32_t val, int width)
+{
+ PCI_WRITE_CONFIG(device_get_parent(dev), dev, reg, val, width);
+}
+
+#endif
+
/* for compatibility to FreeBSD-2.2 version of PCI code */
#ifdef PCI_COMPAT
diff --git a/sys/pci/uhci_pci.c b/sys/pci/uhci_pci.c
index 6ed3cee0381f1..4bddf8b327869 100644
--- a/sys/pci/uhci_pci.c
+++ b/sys/pci/uhci_pci.c
@@ -1,4 +1,4 @@
-/* FreeBSD $Id: uhci_pci.c,v 1.4 1999/04/06 23:09:58 n_hibma Exp $ */
+/* FreeBSD $Id: uhci_pci.c,v 1.5 1999/04/11 14:24:20 n_hibma Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -37,6 +37,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include "opt_bus.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -45,23 +47,13 @@
#include <sys/device.h>
#include <sys/proc.h>
#include <sys/queue.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
#include <pci/pcivar.h>
#include <pci/pcireg.h>
-#define PCI_CLASS_SERIALBUS 0x0c000000
-#define PCI_SUBCLASS_COMMUNICATIONS_SERIAL 0x00000000
-#define PCI_SUBCLASS_SERIALBUS_FIREWIRE 0x00000000
-#define PCI_SUBCLASS_SERIALBUS_ACCESS 0x00010000
-#define PCI_SUBCLASS_SERIALBUS_SSA 0x00020000
-#define PCI_SUBCLASS_SERIALBUS_USB 0x00030000
-#define PCI_SUBCLASS_SERIALBUS_FIBER 0x00040000
-
-#define PCI_INTERFACE(d) (((d)>>8)&0xff)
-#define PCI_SUBCLASS(d) ((d)&PCI_SUBCLASS_MASK)
-#define PCI_CLASS(d) ((d)&PCI_CLASS_MASK)
-
-
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdivar.h>
@@ -70,7 +62,6 @@
#include <dev/usb/uhcireg.h>
#include <dev/usb/uhcivar.h>
-
#define PCI_UHCI_VENDORID_INTEL 0x8086
#define PCI_UHCI_VENDORID_VIA 0x1106
@@ -85,26 +76,10 @@ static const char *uhci_device_generic = "UHCI (generic) USB Controller";
#define PCI_UHCI_BASE_REG 0x20
-static const char *uhci_pci_probe __P((pcici_t, pcidi_t));
-static void uhci_pci_attach __P((pcici_t, int));
-
-static u_long uhci_count = 0;
-
-static struct pci_device uhci_pci_device = {
- "uhci",
- uhci_pci_probe,
- uhci_pci_attach,
- &uhci_count,
- NULL
-};
-
-DATA_SET(pcidevice_set, uhci_pci_device);
-
-
static const char *
-uhci_pci_probe(pcici_t config_id, pcidi_t device_id)
+uhci_pci_match(device_t dev)
{
- u_int32_t class;
+ u_int32_t device_id = pci_get_devid(dev);
if (device_id == PCI_UHCI_DEVICEID_PIIX3) {
return (uhci_device_piix3);
@@ -113,10 +88,9 @@ uhci_pci_probe(pcici_t config_id, pcidi_t device_id)
} else if (device_id == PCI_UHCI_DEVICEID_VT83C572) {
return (uhci_device_vt83c572);
} else {
- class = pci_conf_read(config_id, PCI_CLASS_REG);
- if ( PCI_CLASS(class) == PCI_CLASS_SERIALBUS
- && PCI_SUBCLASS(class) == PCI_SUBCLASS_SERIALBUS_USB
- && PCI_INTERFACE(class) == PCI_INTERFACE_UHCI) {
+ if ( pci_get_class(dev) == PCIC_SERIALBUS
+ && pci_get_subclass(dev) == PCIS_SERIALBUS_USB
+ && pci_get_progif(dev) == PCI_INTERFACE_UHCI) {
return (uhci_device_generic);
}
}
@@ -124,42 +98,64 @@ uhci_pci_probe(pcici_t config_id, pcidi_t device_id)
return NULL; /* dunno... */
}
-static void
-uhci_pci_attach(pcici_t config_id, int unit)
+static int
+uhci_pci_probe(device_t dev)
+{
+ const char *desc = uhci_pci_match(dev);
+ if (desc) {
+ device_set_desc(dev, desc);
+ return 0;
+ } else {
+ return ENXIO;
+ }
+}
+
+static int
+uhci_pci_attach(device_t dev)
{
- int id, legsup;
+ int unit = device_get_unit(dev);
+ int legsup;
char *typestr;
usbd_status err;
- uhci_softc_t *sc = NULL;
device_t usbus;
-
- sc = malloc(sizeof(uhci_softc_t), M_DEVBUF, M_NOWAIT);
- /* Do not free it below, intr might use the sc */
- if ( sc == NULL ) {
- printf("uhci%d: could not allocate memory", unit);
- return;
+ uhci_softc_t *sc = device_get_softc(dev);
+ int rid;
+ struct resource *res;
+ void *ih;
+ int error;
+
+ rid = PCI_UHCI_BASE_REG;
+ res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
+ 0, ~0, 1, RF_ACTIVE);
+ if (!res) {
+ device_printf(dev, "could not map ports\n");
+ return ENXIO;
+ }
+
+ sc->iot = rman_get_bustag(res);
+ sc->ioh = rman_get_bushandle(res);
+
+ rid = 0;
+ res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
+ RF_SHAREABLE | RF_ACTIVE);
+ if (res == NULL) {
+ device_printf(dev, "could not allocate irq\n");
+ return ENOMEM;
}
- memset(sc, 0, sizeof(uhci_softc_t));
-
- if ( !pci_map_port(config_id, PCI_UHCI_BASE_REG, &sc->sc_iobase) ) {
- printf("uhci%d: could not map port\n", unit);
- return;
- }
-
- if ( !pci_map_int(config_id, (pci_inthand_t *)uhci_intr,
- (void *) sc, &bio_imask)) {
- printf("uhci%d: could not map irq\n", unit);
- return;
+
+ error = bus_setup_intr(dev, res, (driver_intr_t *) uhci_intr, sc, &ih);
+ if (error) {
+ device_printf(dev, "could not setup irq\n");
+ return error;
}
- usbus = device_add_child(root_bus, "usb", -1, sc);
+ usbus = device_add_child(dev, "usb", -1, sc);
if (!usbus) {
- printf("usb%d: could not add USB device to root bus\n", unit);
- return;
+ printf("usb%d: could not add USB device\n", unit);
+ return ENOMEM;
}
- id = pci_conf_read(config_id, PCI_ID_REG);
- switch (id) {
+ switch (pci_get_devid(dev)) {
case PCI_UHCI_DEVICEID_PIIX3:
device_set_desc(usbus, uhci_device_piix3);
sprintf(sc->sc_vendor, "Intel");
@@ -173,13 +169,13 @@ uhci_pci_attach(pcici_t config_id, int unit)
sprintf(sc->sc_vendor, "VIA");
break;
default:
- printf("(New UHCI DeviceId=0x%08x)\n", id);
+ printf("(New UHCI DeviceId=0x%08x)\n", pci_get_devid(dev));
device_set_desc(usbus, uhci_device_generic);
- sprintf(sc->sc_vendor, "(0x%08x)", id);
+ sprintf(sc->sc_vendor, "(0x%08x)", pci_get_devid(dev));
}
if (bootverbose) {
- switch(pci_conf_read(config_id, PCI_USBREV) & PCI_USBREV_MASK) {
+ switch(pci_read_config(dev, PCI_USBREV, 4) & PCI_USBREV_MASK) {
case PCI_USBREV_PRE_1_0:
typestr = "pre 1.0";
break;
@@ -191,25 +187,53 @@ uhci_pci_attach(pcici_t config_id, int unit)
break;
}
printf("uhci%d: USB version %s, chip rev. %d\n", unit, typestr,
- (int) pci_conf_read(config_id, PCIR_REVID) & 0xff);
+ pci_get_revid(dev));
}
- legsup = pci_conf_read(config_id, PCI_LEGSUP);
+ legsup = pci_read_config(dev, PCI_LEGSUP, 4);
if ( !(legsup & PCI_LEGSUP_USBPIRQDEN) ) {
#if ! (defined(USBVERBOSE) || defined(USB_DEBUG))
if (bootverbose)
#endif
printf("uhci%d: PIRQD enable not set\n", unit);
legsup |= PCI_LEGSUP_USBPIRQDEN;
- pci_conf_write(config_id, PCI_LEGSUP, legsup);
+ pci_write_config(dev, PCI_LEGSUP, legsup, 4);
}
sc->sc_bus.bdev = usbus;
err = uhci_init(sc);
if (err != USBD_NORMAL_COMPLETION) {
printf("uhci%d: init failed, error=%d\n", unit, err);
- device_delete_child(root_bus, usbus);
+ device_delete_child(dev, usbus);
}
- return;
+ return device_probe_and_attach(sc->sc_bus.bdev);
}
+
+static device_method_t uhci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, uhci_pci_probe),
+ DEVMETHOD(device_attach, uhci_pci_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+
+ { 0, 0 }
+};
+
+static driver_t uhci_driver = {
+ "uhci",
+ uhci_methods,
+ DRIVER_TYPE_BIO,
+ sizeof(uhci_softc_t),
+};
+
+static devclass_t uhci_devclass;
+
+DRIVER_MODULE(uhci, pci, uhci_driver, uhci_devclass, 0, 0);