diff options
author | David Greenman <dg@FreeBSD.org> | 1995-02-02 13:12:18 +0000 |
---|---|---|
committer | David Greenman <dg@FreeBSD.org> | 1995-02-02 13:12:18 +0000 |
commit | 6398cf311391af65694520c14dd5fd802fda9806 (patch) | |
tree | 8d1b00d546148364ba291540f1d0241cc58fde5e /sys/pci | |
parent | 77e50733d821b6eaaece214ce20890dda262cf92 (diff) | |
download | src-6398cf311391af65694520c14dd5fd802fda9806.tar.gz src-6398cf311391af65694520c14dd5fd802fda9806.zip |
Reapplied all of Stefan's changes. What a mess - the files were modified
and moved at the same time. This made it *very* difficult to fix the
revision log lossage that happend when the files were moved. SIGH.
Notes
Notes:
svn path=/head/; revision=6132
Diffstat (limited to 'sys/pci')
-rw-r--r-- | sys/pci/aic7870.c | 8 | ||||
-rw-r--r-- | sys/pci/if_de.c | 15 | ||||
-rw-r--r-- | sys/pci/ncr.c | 192 | ||||
-rw-r--r-- | sys/pci/ncrreg.h | 3 | ||||
-rw-r--r-- | sys/pci/pci.c | 313 | ||||
-rw-r--r-- | sys/pci/pcireg.h | 287 | ||||
-rw-r--r-- | sys/pci/pcisupport.c | 25 |
7 files changed, 380 insertions, 463 deletions
diff --git a/sys/pci/aic7870.c b/sys/pci/aic7870.c index 6c565faf7546..edac4a2c3dfa 100644 --- a/sys/pci/aic7870.c +++ b/sys/pci/aic7870.c @@ -19,7 +19,7 @@ * 4. Modifications may be freely made to this file if the above conditions * are met. * - * $Id: aic7870.c,v 1.3 1995/01/22 00:47:50 gibbs Exp $ + * $Id: aic7870.c,v 1.4 1995/02/02 12:36:14 davidg Exp $ */ #include <pci.h> @@ -29,6 +29,7 @@ #include <scsi/scsi_all.h> #include <scsi/scsiconf.h> #include <pci/pcireg.h> +#include <pci/pcivar.h> #include <i386/scsi/aic7xxx.h> #define PCI_BASEADR0 PCI_MAP_REG_START @@ -40,12 +41,15 @@ void aic7870_attach __P((pcici_t config_id, int unit)); static u_long aic7870_count; -struct pci_driver ahc_device = { +struct pci_device ahc_device = { + "ahc", aic7870_probe, aic7870_attach, &aic7870_count }; +DATA_SET (pcidevice_set, ahc_device); + static char* aic7870_probe (pcici_t tag, pcidi_t type) { diff --git a/sys/pci/if_de.c b/sys/pci/if_de.c index 78840277c40e..c7887a23d7da 100644 --- a/sys/pci/if_de.c +++ b/sys/pci/if_de.c @@ -21,7 +21,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: if_de.c,v 1.13 1994/12/22 23:42:25 davidg Exp $ + * $Id: if_de.c,v 1.14 1995/02/02 12:36:15 davidg Exp $ * */ @@ -46,6 +46,8 @@ #include <sys/ioctl.h> #include <sys/errno.h> #include <sys/malloc.h> +#include <sys/kernel.h> +#include <machine/clock.h> #include <net/if.h> #include <net/if_types.h> @@ -78,9 +80,9 @@ #include <pci.h> #if NPCI > 0 -#include <pci/pcireg.h> +#include <pci/pcivar.h> #endif -#include <i386/isa/icu.h> + #include <pci/dc21040.h> /* @@ -840,6 +842,8 @@ tulip_addr_filter( } } +/*extern void arp_ifinit(struct arpcom *, struct ifaddr*);*/ + static int tulip_ioctl( struct ifnet *ifp, @@ -1041,12 +1045,15 @@ static char* tulip_pci_probe (pcici_t config_id, pcidi_t device_id); static void tulip_pci_attach(pcici_t config_id, int unit); static u_long tulip_count; -struct pci_driver dedevice = { +struct pci_device dedevice = { + "de", tulip_pci_probe, tulip_pci_attach, &tulip_count, }; +DATA_SET (pcidevice_set, dedevice); + #define PCI_CFID 0x00 /* Configuration ID */ #define PCI_CFCS 0x04 /* Configurtion Command/Status */ #define PCI_CFRV 0x08 /* Configuration Revision */ diff --git a/sys/pci/ncr.c b/sys/pci/ncr.c index bf6ab03934dc..d21664c3761a 100644 --- a/sys/pci/ncr.c +++ b/sys/pci/ncr.c @@ -1,6 +1,6 @@ /************************************************************************** ** -** $Id: ncr.c,v 1.14 1995/01/12 14:01:13 se Exp $ +** $Id: ncr.c,v 1.15 1995/02/02 12:36:16 davidg Exp $ ** ** Device driver for the NCR 53C810 PCI-SCSI-Controller. ** @@ -44,15 +44,21 @@ *************************************************************************** */ +#define NCR_PATCHLEVEL "pl4 95/01/27" + #define NCR_VERSION (2) #define MAX_UNITS (16) +#ifndef LDSC + /* belongs to sstat2 in ncrreg.h */ + #define LDSC 0x02 /* sta: disconnect & reconnect */ +#endif /*========================================================== ** ** Configuration and Debugging ** -** May be overwritten in <i386/conf/XXXXX> +** May be overwritten in <arch/conf/XXXXX> ** **========================================================== */ @@ -139,12 +145,6 @@ */ #define MAX_SIZE ((MAX_SCATTER-1) * NBPG) - -/* -** Write disk status information to dkstat ? -*/ - -/* #define DK */ /*========================================================== ** @@ -163,19 +163,23 @@ #include <sys/malloc.h> #include <sys/buf.h> #include <sys/kernel.h> -#ifdef DK -#include <sys/dkstat.h> -#endif /* DK */ +#ifndef __NetBSD__ +#include <machine/clock.h> +#endif #include <vm/vm.h> #endif /* KERNEL */ -#include <pci/ncrreg.h> -#ifdef __NetBSD__ +#ifndef __NetBSD__ +#include <pci/pcivar.h> +#include <pci/pcireg.h> +#include <pci/ncrreg.h> +#else #include <sys/device.h> +#include <i386/pci/ncrreg.h> #include <i386/pci/pcivar.h> +#include <i386/pci/pcireg.h> #endif /* __NetBSD */ -#include <pci/pcireg.h> #include <scsi/scsi_all.h> #include <scsi/scsiconf.h> @@ -1152,7 +1156,7 @@ struct script { ncrcmd data_in [MAX_SCATTER * 4 + 7]; ncrcmd data_out [MAX_SCATTER * 4 + 7]; ncrcmd aborttag [ 4]; - ncrcmd abort [ 20]; + ncrcmd abort [ 22]; ncrcmd snooptest [ 11]; }; @@ -1222,7 +1226,7 @@ static void ncr_attach (pcici_t tag, int unit); static char ident[] = - "\n$Id: ncr.c,v 1.14 1995/01/12 14:01:13 se Exp $\n"; + "\n$Id: ncr.c,v 1.15 1995/02/02 12:36:16 davidg Exp $\n"; u_long ncr_version = NCR_VERSION + (u_long) sizeof (struct ncb) @@ -1258,7 +1262,6 @@ static u_char rs_cmd [6] = */ #define NCR_810_ID (0x00011000ul) -#define NCR_815_ID (0x00041000ul) #define NCR_825_ID (0x00031000ul) #ifdef __NetBSD__ @@ -1271,12 +1274,15 @@ struct cfdriver ncrcd = { static u_long ncr_count; -struct pci_driver ncr_device = { +struct pci_device ncr_device = { + "ncr", ncr_probe, ncr_attach, &ncr_count }; +DATA_SET (pcidevice_set, ncr_device); + #endif /* !__NetBSD__ */ #ifndef ANCIENT @@ -2345,7 +2351,8 @@ static struct script script0 = { /* ** DISCONNECTing ... ** - ** Disable the "unexpected disconnect" feature. + ** disable the "unexpected disconnect" feature, + ** and remove the ACK signal. */ SCR_REG_REG (scntl2, SCR_AND, 0x7f), 0, @@ -2383,8 +2390,6 @@ static struct script script0 = { }/*-------------------------< MSG_OUT >-------------------*/,{ /* ** The target requests a message. - ** First remove ATN so the target will - ** not continue fetching messages. */ SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, NADDR (msgout), @@ -2824,6 +2829,8 @@ static struct script script0 = { SCR_COPY (1), RADDR (sfbr), NADDR (lastmsg), + SCR_CLR (SCR_ACK), + 0, SCR_WAIT_DISC, 0, SCR_JUMP, @@ -3119,7 +3126,6 @@ ncr_probe(parent, self, aux) if (!pci_targmatch(cf, pa)) return 0; if (pa->pa_id != NCR_810_ID && - pa->pa_id != NCR_815_ID && pa->pa_id != NCR_825_ID) return 0; @@ -3136,9 +3142,6 @@ static char* ncr_probe (pcici_t tag, pcidi_t type) case NCR_810_ID: return ("ncr 53c810 scsi"); - case NCR_815_ID: - return ("ncr 53c815 scsi"); - case NCR_825_ID: return ("ncr 53c825 wide scsi"); } @@ -3247,7 +3250,6 @@ static void ncr_attach (pcici_t config_id, int unit) case NCR_810_ID: np->maxwide = 0; break; - case NCR_815_ID: case NCR_825_ID: np->maxwide = 1; break; @@ -3296,6 +3298,31 @@ static void ncr_attach (pcici_t config_id, int unit) OUTB (nc_istat, SRST); OUTB (nc_istat, 0 ); +#ifdef NCR_DUMP_REG + /* + ** Log the initial register contents + */ + { + int reg; +#ifdef __NetBSD__ + u_long config_id = pa->pa_tag; +#endif + for (reg=0; reg<256; reg+=4) { + if (reg%16==0) printf ("reg[%2x]", reg); + printf (" %08x", (int)pci_conf_read (config_id, reg)); + if (reg%16==12) printf ("\n"); + } + } + + /* + ** Reset chip, once again. + */ + + OUTB (nc_istat, SRST); + OUTB (nc_istat, 0 ); + +#endif NCR_DUMP_REG + /* ** Now check the cache handling of the pci chipset. */ @@ -3333,8 +3360,12 @@ static void ncr_attach (pcici_t config_id, int unit) ncr_name (np)); DELAY (1000000); #endif - printf ("%s scanning for targets 0..%d ($Revision: 1.14 $)\n", - ncr_name (np), MAX_TARGET-1); +#ifdef NCR_PATCHLEVEL + printf ("%s scanning for targets 0..%d (V%d " NCR_PATCHLEVEL ")\n", +#else + printf ("%s scanning for targets 0..%d (V%d)\n", +#endif + ncr_name (np), MAX_TARGET-1, NCR_VERSION); /* ** Now let the generic SCSI driver @@ -3668,7 +3699,22 @@ static INT32 ncr_start (struct scsi_xfer * xp) **---------------------------------------------------- */ - idmsg = (cp==&np->ccb ? 0x80 : 0xc0) | xp->LUN; +#ifndef NCR_NO_DISCONNECT + idmsg = (cp==&np->ccb ? M_IDENTIFY : 0xc0) | xp->LUN; +#else + /*--------------------------------------------------------------------- + ** Some users have problems with this driver. + ** I assume that the current problems relate to a conflict between + ** a disconnect and an immediately following reconnect operation. + ** With this option you can prevent the driver from using disconnects. + ** If this removes the problems, I would know where to search further.. + ** Of course this is no solution. + ** Without disconnects the performance will be severely degraded. + ** But it may help to trace down the core problem. + **--------------------------------------------------------------------- + */ + idmsg = M_IDENTIFY | xp->LUN; +#endif cp -> scsi_smsg [0] = idmsg; msglen=1; @@ -3957,7 +4003,7 @@ void ncr_complete (ncb_p np, ccb_p cp) ** Sanity check */ - if (!cp || !cp->magic || !cp->xfer) return; + if (!cp || (cp->magic!=CCB_MAGIC) || !cp->xfer) return; cp->magic = 1; cp->tlimit= 0; @@ -4084,12 +4130,6 @@ void ncr_complete (ncb_p np, ccb_p cp) ncr_opennings (np, lp, xp); }; -#ifdef DK - dk_xfer[DK] ++; - dk_wds [DK] += xp->datalen/64; - dk_wpms[DK] = 1000000; -#endif /* DK */ - tp->bytes += xp->datalen; tp->transfers ++; @@ -4306,7 +4346,7 @@ void ncr_init (ncb_p np, char * msg, u_long code) OUTB (nc_scntl0, 0xca ); /* full arb., ena parity, par->ATN */ OUTB (nc_scntl1, 0x00 ); /* odd parity, and remove CRST!! */ OUTB (nc_scntl3, np->rv_scntl3);/* timing prescaler */ - OUTB (nc_scid , 0x40|np->myaddr);/* host adapter SCSI address */ + OUTB (nc_scid , RRE|np->myaddr);/* host adapter SCSI address */ OUTW (nc_respid, 1ul<<np->myaddr);/* id to respond to */ OUTB (nc_istat , SIGP ); /* Signal Process */ OUTB (nc_dmode , 0xc0 ); /* Burst length = 16 transfer */ @@ -4684,6 +4724,10 @@ static void ncr_timeout (ncb_p np) ccb_p cp; if (np->lasttime != thistime) { + /* + ** block ncr interupts + */ + int oldspl = splbio(); np->lasttime = thistime; ncr_usercmd (np); @@ -4781,12 +4825,9 @@ static void ncr_timeout (ncb_p np) /* ** wakeup this ccb. */ - { - int oldspl = splbio(); - ncr_complete (np, cp); - splx (oldspl); - }; + ncr_complete (np, cp); }; + splx (oldspl); } timeout (TIMEOUT ncr_timeout, (caddr_t) np, step ? step : 1); @@ -4819,6 +4860,7 @@ void ncr_exception (ncb_p np) u_char istat, dstat; u_short sist; u_long dsp; + int i; /* ** interrupt on the fly ? @@ -4935,13 +4977,47 @@ void ncr_exception (ncb_p np) np->regdump.nc_dstat = dstat; np->regdump.nc_sist = sist; }; + + /*========================================= + ** log message for real hard errors + **========================================= - printf ("%s targ %d?: ERROR (%x:%x:%x) (%x/%x) @ (%x:%x).\n", + "ncr0 targ 0?: ERROR (ds:si) (so-si-sd) (sxfer/scntl3) @ (dsp:dbc)." + " reg: r0 r1 r2 r3 r4 r5 r6 ..... rf." + + exception register: + ds: dstat + si: sist + + SCSI bus lines: + so: control lines as driver by NCR. + si: control lines as seen by NCR. + sd: scsi data lines as seen by NCR. + + wide/fastmode: + sxfer: (see the manual) + scntl3: (see the manual) + + current script command: + dsp: script adress (relative to start of script). + dbc: first word of script command. + + First 16 register of the chip: + r0..rf + + ============================================= + */ + + printf ("%s targ %d?: ERROR (%x:%x) (%x-%x-%x) (%x/%x) @ (%x:%x).\n", ncr_name (np), INB (nc_ctest0)&7, dstat, sist, - INB (nc_sbcl), + INB (nc_socl), INB (nc_sbcl), INB (nc_sbdl), INB (nc_sxfer),INB (nc_scntl3), - (unsigned) (dsp = INL (nc_dsp)), + ((unsigned) (dsp = INL (nc_dsp))) - (unsigned) np->p_script, (unsigned) INL (nc_dbc)); + printf (" reg:"); + for (i=0; i<16;i++) + printf (" %x", ((u_char*)np->reg)[i]); + printf (".\n"); /*---------------------------------------- ** clean up the dma fifo @@ -4980,15 +5056,27 @@ void ncr_exception (ncb_p np) !(dstat & (MDPE|BF|ABRT|SIR)) && ((INL(nc_dbc) & 0xf8000000) == SCR_WAIT_DISC)) { /* - ** Data cycles while waiting for disconnect. - ** Force disconnect. + ** Unexpected data cycle while waiting for disconnect. */ - OUTB (nc_scntl1, 0); + if (INB(nc_sstat2) & LDSC) { + /* + ** It's an early reconnect. + ** Let's continue ... + */ + OUTB (nc_dcntl, (STD|NOCOM)); + /* + ** info message + */ + printf ("%s: XXX INFO: LDSC while IID.\n", + ncr_name (np)); + return; + }; + printf ("%s: target %d? doesn't release the bus.\n", + ncr_name (np), INB (nc_ctest0)&7); /* - ** System may hang, but timeout will handle that. - ** In fact, timeout can handle ALL problems :-) + ** return without restarting the NCR. + ** timeout will do the real work. */ - OUTB (nc_dcntl, (STD|NOCOM)); return; }; @@ -5914,7 +6002,7 @@ static ccb_p ncr_get_ccb while (cp->magic) { if (flags & SCSI_NOSLEEP) break; - if (tsleep ((caddr_t)cp, PZERO|PCATCH, "ncr", 0)) + if (tsleep ((caddr_t)cp, PRIBIO|PCATCH, "ncr", 0)) break; }; diff --git a/sys/pci/ncrreg.h b/sys/pci/ncrreg.h index 1a22aee38d24..d5800612a5ed 100644 --- a/sys/pci/ncrreg.h +++ b/sys/pci/ncrreg.h @@ -1,6 +1,6 @@ /************************************************************************** ** -** $Id: ncrreg.h,v 2.3 94/10/09 21:10:34 wolf Oct11 $ +** $Id: ncrreg.h,v 1.1 1994/10/12 02:21:56 se Exp $ ** ** Device driver for the NCR 53C810 PCI-SCSI-Controller. ** @@ -123,6 +123,7 @@ struct ncr_reg { #define ILF1 0x80 /* sta: data in SIDL register msb[W]*/ #define ORF1 0x40 /* sta: data in SODR register msb[W]*/ #define OLF1 0x20 /* sta: data in SODL register msb[W]*/ + #define LDSC 0x02 /* sta: disconnect & reconnect */ /*10*/ u_long nc_dsa; /* --> Base page */ diff --git a/sys/pci/pci.c b/sys/pci/pci.c index 8bbd36ea3eae..61e546f68986 100644 --- a/sys/pci/pci.c +++ b/sys/pci/pci.c @@ -1,6 +1,6 @@ /************************************************************************** ** -** $Id: pci.c,v 1.9 1994/11/02 23:47:13 se Exp $ +** $Id: pci.c,v 1.10 1995/02/02 12:36:18 davidg Exp $ ** ** General subroutines for the PCI bus on 80*86 systems. ** pci_configure () @@ -56,62 +56,38 @@ #include <sys/systm.h> #include <sys/malloc.h> #include <sys/errno.h> +#include <sys/kernel.h> #include <vm/vm.h> #include <vm/vm_param.h> -#include <i386/isa/isa.h> -#include <i386/isa/isa_device.h> -#include <i386/isa/icu.h> +#include <pci/pcivar.h> #include <pci/pcireg.h> +#include <pci/pcibus.h> #ifdef __FreeBSD2__ #include <sys/devconf.h> - + struct pci_devconf { struct kern_devconf pdc_kdc; struct pci_info pdc_pi; }; -#endif + +static int +pci_externalize (struct proc *, struct kern_devconf *, void *, size_t); + +static int +pci_internalize (struct proc *, struct kern_devconf *, void *, size_t); +#else /* __FreeBSD2__ */ /* ** Function prototypes missing in system headers */ -#ifndef __FreeBSD2__ extern pmap_t pmap_kernel(void); static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize); +#endif /* __FreeBSD2__ */ -/* - * Type of the first (asm) part of an interrupt handler. - */ -typedef void inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss)); - -/* - * Usual type of the second (C) part of an interrupt handler. Some bogus - * ones need the arg to be the interrupt frame (and not a copy of it, which - * is all that is possible in C). - */ -typedef void inthand2_t __P((int unit)); - -/* -** XXX @FreeBSD2@ -** -** Unfortunately, the mptr argument is _no_ pointer in 2.0 FreeBSD. -** We would prefer a pointer because it enables us to install -** new interrupt handlers at any time. -** (This is just going to be changed ... <se> :) -** In 2.0 FreeBSD later installed interrupt handlers may change -** the xyz_imask, but this would not be recognized by handlers -** which are installed before. -*/ - -static int -register_intr __P((int intr, int device_id, unsigned int flags, - inthand2_t *handler, unsigned int * mptr, int unit)); -extern unsigned intr_mask[ICU_LEN]; - -#endif /* !__FreeBSD2__ */ /*======================================================== ** @@ -140,6 +116,20 @@ static vm_offset_t pci_paddr = PCI_PMEM_START; /*-------------------------------------------------------- ** +** The pci ports can be mapped to any address. +** As default we start at 0x400 +** +**-------------------------------------------------------- +*/ + +#ifndef PCI_PORT_START +#define PCI_PORT_START 0x0400 +#endif + +static u_short pci_ioaddr = PCI_PORT_START; + +/*-------------------------------------------------------- +** ** The pci device interrupt lines should have been ** assigned by the bios. But if the bios failed to ** to it, we set it. @@ -172,15 +162,6 @@ static unsigned long pci_seen[NPCI]; static int pci_conf_count; -#ifdef __FreeBSD2__ -static int -pci_externalize (struct proc *, struct kern_devconf *, void *, size_t); - -static int -pci_internalize (struct proc *, struct kern_devconf *, void *, size_t); - -#endif /* __FreeBSD2__ */ - void pci_configure() { u_char device,last_device; @@ -194,19 +175,28 @@ void pci_configure() int irq; char* name=0; vm_offset_t old_addr=pci_paddr; + u_short old_ioaddr=pci_ioaddr; - struct pci_driver *drp=0; - struct pci_device *dvp; + int dvi; + struct pci_device *dvp=0; #ifdef __FreeBSD2__ struct pci_devconf *pdcp; #endif /* + ** first check pci bus driver available + */ + + if (pcibus_set.ls_length <= 0) + return; + +#define pcibus (*((struct pcibus*) pcibus_set.ls_items[0])) + /* ** check pci bus present */ - pci_mechanism = pci_conf_mode (); + pci_mechanism = pcibus.pb_mode (); if (!pci_mechanism) return; last_device = pci_mechanism==1 ? 31 : 15; @@ -217,16 +207,16 @@ void pci_configure() for (bus=0;bus<NPCI;bus++) { #ifndef PCI_QUIET - printf ("pci%d: scanning device 0..%d, mechanism=%d.\n", - bus, last_device, pci_mechanism); + printf ("%s%d: scanning device 0..%d, mechanism=%d.\n", + pcibus.pb_name, bus, last_device, pci_mechanism); #endif for (device=0; device<=last_device; device ++) { if (pci_seen[bus] & (1ul << device)) continue; - tag = pcitag (bus, device, 0); - type = pci_conf_read (tag, PCI_ID_REG); + tag = pcibus.pb_tag (bus, device, 0); + type = pcibus.pb_read (tag, PCI_ID_REG); if ((!type) || (type==0xfffffffful)) continue; @@ -234,19 +224,18 @@ void pci_configure() ** lookup device in ioconfiguration: */ - for (dvp = pci_devtab; dvp->pd_name; dvp++) { - drp = dvp->pd_driver; - if (!drp) - continue; - if ((name=(*drp->probe)(tag, type))) + for (dvi=0; dvi<pcidevice_set.ls_length; dvi++) { + dvp = (struct pci_device*) pcidevice_set.ls_items[dvi]; + if ((name=(*dvp->pd_probe)(tag, type))) break; + dvp = NULL; }; - if (!dvp->pd_name) { + if (dvp==NULL) { #ifndef PCI_QUIET if (pci_conf_count) continue; - printf("pci%d:%d: ", bus, device); + printf("%s%d:%d: ", pcibus.pb_name, bus, device); not_supported (tag, type); #endif continue; @@ -257,7 +246,7 @@ void pci_configure() ** Get and increment the unit. */ - unit = (*drp->count)++; + unit = (*dvp->pd_count)++; /* ** ignore device ? @@ -276,7 +265,7 @@ void pci_configure() ** from the pci configuration space. */ - data = pci_conf_read (tag, PCI_INTERRUPT_REG); + data = pcibus.pb_read (tag, PCI_INTERRUPT_REG); pciint = PCI_INTERRUPT_PIN_EXTRACT(data); if (pciint) { @@ -295,7 +284,7 @@ void pci_configure() data = PCI_INTERRUPT_LINE_INSERT(data, irq); printf (" (config)"); - pci_conf_write (tag, PCI_INTERRUPT_REG, data); + pcibus.pb_write (tag, PCI_INTERRUPT_REG, data); }; irq = PCI_INTERRUPT_LINE_EXTRACT(data); @@ -315,10 +304,10 @@ void pci_configure() ** enable memory access */ - data = (pci_conf_read (tag, PCI_COMMAND_STATUS_REG) + data = (pcibus.pb_read (tag, PCI_COMMAND_STATUS_REG) & 0xffff) | PCI_COMMAND_MEM_ENABLE; - pci_conf_write (tag, (u_char) PCI_COMMAND_STATUS_REG, data); + pcibus.pb_write (tag, (u_char) PCI_COMMAND_STATUS_REG, data); /* ** show pci slot. @@ -333,7 +322,7 @@ void pci_configure() */ pdcp = (struct pci_devconf *) - malloc (sizeof (struct pci_devconf),M_DEVBUF,M_WAITOK); + malloc (sizeof (struct pci_devconf),M_DEVBUF,M_WAITOK); /* ** Fill in. @@ -378,7 +367,7 @@ void pci_configure() ** i.e. when installing subdevices. */ - (*drp->attach) (tag, unit); + (*dvp->pd_attach) (tag, unit); }; }; @@ -386,10 +375,43 @@ void pci_configure() if (pci_paddr != old_addr) printf ("pci uses physical addresses from 0x%lx to 0x%lx\n", (u_long)PCI_PMEM_START, (u_long)pci_paddr); + if (pci_ioaddr != old_ioaddr) + printf ("pci devices use ioports from 0x%x to 0x%x\n", + (unsigned)PCI_PORT_START, (unsigned)pci_ioaddr); #endif pci_conf_count++; } +/*----------------------------------------------------------------- +** +** The following functions are provided for the device driver +** to read/write the configuration space. +** +** pci_conf_read(): +** Read a long word from the pci configuration space. +** Requires a tag (from pcitag) and the register +** number (should be a long word alligned one). +** +** pci_conf_write(): +** Writes a long word to the pci configuration space. +** Requires a tag (from pcitag), the register number +** (should be a long word alligned one), and a value. +** +**----------------------------------------------------------------- +*/ + +u_long +pci_conf_read (pcici_t tag, u_long reg) +{ + return (pcibus.pb_read (tag, reg)); +} + +void +pci_conf_write (pcici_t tag, u_long reg, u_long data) +{ + pcibus.pb_write (tag, reg, data); +} + /*----------------------------------------------------------------------- ** ** Map device into port space. @@ -401,11 +423,78 @@ void pci_configure() int pci_map_port (pcici_t tag, u_long reg, u_short* pa) { + u_long data; + u_short size; + /* - ** @MAPIO@ not yet implemented. + ** sanity check */ - printf ("pci_map_port failed: not yet implemented\n"); - return (0); + + if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) { + printf ("pci_map_port failed: bad register=0x%x\n", + (unsigned)reg); + return (0); + }; + + /* + ** get size and type of port + ** + ** type is in the lowest two bits. + ** If device requires 2^n bytes, the next + ** n-2 bits are hardwired as 0. + */ + + pcibus.pb_write (tag, reg, 0xfffffffful); + data = pcibus.pb_read (tag, reg); + + switch (data & 0x03) { + + case PCI_MAP_IO: + break; + + default: /* unknown */ + printf ("pci_map_port failed: bad port type=0x%x\n", + (unsigned) data); + return (0); + }; + + /* + ** get the size + */ + + size = -(data & PCI_MAP_IO_ADDRESS_MASK); + + if (!size) return (0); + + /* + ** align physical address to virtual size + */ + + if ((data = pci_ioaddr % size)) + pci_ioaddr += size - data; + +#ifndef PCI_QUIET + /* + ** display values. + */ + + printf ("\treg%d: ioaddr=0x%x size=0x%x\n", + (unsigned) reg, (unsigned) pci_ioaddr, (unsigned) size); +#endif + + /* + ** return them to the driver + */ + + *pa = pci_ioaddr; + + /* + ** and don't forget to increment pci_ioaddr + */ + + pci_ioaddr += size; + + return (1); } /*----------------------------------------------------------------------- @@ -427,10 +516,10 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa) ** sanity check */ - if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) { - printf ("pci_map_mem failed: bad register=0x%x\n", - (unsigned)reg); - return (0); + if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) { + printf ("pci_map_mem failed: bad register=0x%x\n", + (unsigned)reg); + return (0); }; /* @@ -441,8 +530,8 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa) ** n-4 bits are read as 0. */ - pci_conf_write (tag, reg, 0xfffffffful); - data = pci_conf_read (tag, reg); + pcibus.pb_write (tag, reg, 0xfffffffful); + data = pcibus.pb_read (tag, reg); switch (data & 0x0f) { @@ -450,9 +539,9 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa) break; default: /* unknown */ - printf ("pci_map_mem failed: bad memory type=0x%x\n", - (unsigned) data); - return (0); + printf ("pci_map_mem failed: bad memory type=0x%x\n", + (unsigned) data); + return (0); }; /* @@ -496,7 +585,7 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa) ** set device address */ - pci_conf_write (tag, reg, pci_paddr); + pcibus.pb_write (tag, reg, pci_paddr); /* ** and don't forget to increment pci_paddr @@ -519,29 +608,29 @@ pci_externalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t l) { struct pci_externalize_buffer buffer; struct pci_info * pip = kdcp->kdc_parentdata; - pcici_t tag; + pcici_t tag; int i; if (l < sizeof buffer) { - return ENOMEM; + return ENOMEM; }; - tag = pcitag (pip->pi_bus, pip->pi_device, 0); + tag = pcibus.pb_tag (pip->pi_bus, pip->pi_device, 0); buffer.peb_pci_info = *pip; for (i=0; i<PCI_EXT_CONF_LEN; i++) { - buffer.peb_config[i] = pci_conf_read (tag, i*4); + buffer.peb_config[i] = pcibus.pb_read (tag, i*4); }; - return copyout(&buffer, u, sizeof buffer); + return copyout(&buffer, u, sizeof buffer); } static int pci_internalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t s) { - return EOPNOTSUPP; + return EOPNOTSUPP; } /*----------------------------------------------------------------------- @@ -551,60 +640,24 @@ pci_internalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t s) **----------------------------------------------------------------------- */ -static unsigned int pci_int_mask [16]; - int pci_map_int (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr) { - int irq; - unsigned mask; + int irq, result; irq = PCI_INTERRUPT_LINE_EXTRACT( - pci_conf_read (tag, PCI_INTERRUPT_REG)); + pcibus.pb_read (tag, PCI_INTERRUPT_REG)); if (irq >= 16 || irq <= 0) { printf ("pci_map_int failed: no int line set.\n"); return (0); } - mask = 1ul << irq; - - if (!maskptr) - maskptr = &pci_int_mask[irq]; - - INTRMASK (*maskptr, mask); - - register_intr( - irq, /* isa irq */ - 0, /* deviced?? */ - 0, /* flags? */ - (inthand2_t*) func, /* handler */ - maskptr, /* mask pointer */ - (int) arg); /* handler arg */ + result = pcibus.pb_regint (tag, func, arg, maskptr); -#ifdef __FreeBSD2__ - /* - ** XXX See comment at beginning of file. - ** - ** Have to update all the interrupt masks ... Grrrrr!!! - */ - { - unsigned * mp = &intr_mask[0]; - /* - ** update the isa interrupt masks. - */ - for (mp=&intr_mask[0]; mp<&intr_mask[ICU_LEN]; mp++) - if (*mp & *maskptr) - *mp |= mask; - /* - ** update the pci interrupt masks. - */ - for (mp=&pci_int_mask[0]; mp<&pci_int_mask[16]; mp++) - if (*mp & *maskptr) - *mp |= mask; + if (!result) { + printf ("pci_map_int failed.\n"); + return (0); }; -#endif - - INTREN (mask); return (1); } @@ -659,14 +712,14 @@ void not_supported (pcici_t tag, u_long type) printf (", device=0x%lx", type >> 16); - data = (pci_conf_read(tag, PCI_CLASS_REG) >> 24) & 0xff; + data = (pcibus.pb_read(tag, PCI_CLASS_REG) >> 24) & 0xff; if (data < sizeof(majclasses) / sizeof(majclasses[0])) printf(", class=%s", majclasses[data]); printf (" [not supported]\n"); for (reg=PCI_MAP_REG_START; reg<PCI_MAP_REG_END; reg+=4) { - data = pci_conf_read (tag, reg); + data = pcibus.pb_read (tag, reg); if (!data) continue; switch (data&7) { diff --git a/sys/pci/pcireg.h b/sys/pci/pcireg.h index dd1f1ccf3280..595e59f172af 100644 --- a/sys/pci/pcireg.h +++ b/sys/pci/pcireg.h @@ -1,10 +1,12 @@ /************************************************************************** ** -** $Id: pcireg.h,v 1.1 1994/10/12 02:25:03 se Exp $ +** $Id: pcireg.h,v 1.1 1995/02/01 22:56:50 se Exp $ ** -** Declarations for pci bus drivers. +** Names for PCI configuration space registers. ** -** 386bsd / FreeBSD +** Copyright (c) 1994 Charles Hannum. All rights reserved. +** +** FreeBSD ** **------------------------------------------------------------------------- ** @@ -38,271 +40,16 @@ #ifndef __PCI_REG_H__ #define __PCI_REG_H__ -/*----------------------------------------------------------------- -** -** main pci initialization function. -** called at boot time from autoconf.c -** -**----------------------------------------------------------------- -*/ - -void pci_configure (void); - -/*----------------------------------------------------------------- -** -** The pci configuration id describes a pci device on the bus. -** It is constructed from: bus, device & function numbers. -** -**----------------------------------------------------------------- -*/ - -typedef union { - u_long cfg1; - struct { - u_char enable; - u_char forward; - u_short port; - } cfg2; - } pcici_t; - -/*----------------------------------------------------------------- -** -** Each pci device has an unique device id. -** It is used to find a matching driver. -** -**----------------------------------------------------------------- -*/ - -typedef u_long pcidi_t; - -/*----------------------------------------------------------------- -** -** The pci driver structure. -** -** probe: Checks if the driver can support a device -** with this type. The tag may be used to get -** more info with pci_read_conf(). See below. -** It returns a string with the devices name, -** or a NULL pointer, if the driver cannot -** support this device. -** -** attach: Allocate a control structure and prepare -** it. This function may use the pci mapping -** functions. See below. -** (configuration id) or type. -** -** count: A pointer to a unit counter. -** It's used by the pci configurator to -** allocate unit numbers. -** -**----------------------------------------------------------------- -*/ - -struct pci_driver { - char* (*probe ) (pcici_t tag, pcidi_t type); - void (*attach) (pcici_t tag, int unit); - u_long *count; -}; - -/*----------------------------------------------------------------- -** -** The pci-devconf interface. -** -**----------------------------------------------------------------- -*/ - -struct pci_info { - u_short pi_bus; - u_short pi_device; -}; - -#define PCI_EXT_CONF_LEN (16) -#define PCI_EXTERNAL_LEN (sizeof(struct pci_externalize_buffer)) - -struct pci_externalize_buffer { - struct pci_info peb_pci_info; - u_long peb_config[PCI_EXT_CONF_LEN]; -}; - - -/*----------------------------------------------------------------- -** -** Per device structure. -** -** An array of this structure should be created by the -** config utility and live in "ioconf.c". -** -** At the moment it's created by hand and lives in -** pci_config.c -** -** pd_driver: -** a pointer to the driver structure. -** -** pd_name: -** the name of the devices which are supported -** by this driver for kernel messages. -** -** pd_flags: -** for further study. -** -**----------------------------------------------------------------- -*/ - -struct pci_device { - struct - pci_driver* pd_driver; - const char * pd_name; - int pd_flags; -}; - -/*----------------------------------------------------------------- -** -** This table should be generated in file "ioconf.c" -** by the config program. -** It is used at boot time by the configuration function -** pci_configure() -** -**----------------------------------------------------------------- -*/ - -extern struct pci_device pci_devtab[]; - -/*----------------------------------------------------------------- -** -** Map a pci device to physical and virtual memory. -** -** The va and pa addresses are "in/out" parameters. -** If they are 0 on entry, the function assigns an address. -** -** Entry selects the register in the pci configuration -** space, which supplies the size of the region, and -** receives the physical address. -** -** If there is any error, a message is written, and -** the function returns with zero. -** Else it returns with a value different to zero. -** -**----------------------------------------------------------------- -*/ - -int pci_map_mem (pcici_t tag, u_long entry, u_long * va, u_long * pa); - -/*----------------------------------------------------------------- -** -** Map a pci device to an io port area. -** -** *pa is an "in/out" parameter. -** If it's 0 on entry, the function assigns an port number.. -** -** Entry selects the register in the pci configuration -** space, which supplies the size of the region, and -** receives the port number. -** -** If there is any error, a message is written, and -** the function returns with zero. -** Else it returns with a value different to zero. -** -**----------------------------------------------------------------- -*/ - -int pci_map_port(pcici_t tag, u_long entry, u_short * pa); - -/*----------------------------------------------------------------- -** -** Map a pci interrupt to an isa irq line, -** and enable the interrupt. -** -** func is the interrupt handler, arg is the argument -** to this function. -** -** The maskptr argument should be &bio_imask, -** &net_imask etc. or NULL. -** -** If there is any error, a message is written, and -** the function returns with zero. -** Else it returns with a value different to zero. -** -** A word of caution for FreeBSD 2.0: -** -** We use the register_intr() function. -** -** The interrupt line of the selected device is included -** into the supplied mask: after the corresponding splXXX -** this drivers interrupts are blocked. -** -** But in the interrupt handlers startup code ONLY -** the interrupt of the driver is blocked, and NOT -** all interrupts of the spl group. -** -** It may be required to additional block the group -** interrupts by splXXX() inside the interrupt handler. -** -** In pre 2.0 kernels we emulate the register_intr -** function. The emulating function blocks all interrupts -** of the group in the interrupt handler prefix code. -** -**----------------------------------------------------------------- -*/ - -int pci_map_int (pcici_t tag, int (*func)(), void* arg, unsigned * maskptr); - -/*----------------------------------------------------------------- -** -** The following functions are provided by the pci bios. -** They are used only by the pci configuration. -** -** pci_conf_mode(): -** Probes for a pci system. -** Returns 1 or 2 for pci configuration mechanism. -** Returns 0 if no pci system. -** -** pcitag(): -** Gets a handle for accessing the pci configuration -** space. -** This handle is given to the mapping functions (see -** above) or to the read/write functions. -** -** pci_conf_read(): -** Read a long word from the pci configuration space. -** Requires a tag (from pcitag) and the register -** number (should be a long word alligned one). -** -** pci_conf_write(): -** Writes a long word to the pci configuration space. -** Requires a tag (from pcitag), the register number -** (should be a long word alligned one), and a value. -** -**----------------------------------------------------------------- -*/ - -int pci_conf_mode (void); - -pcici_t pcitag (unsigned char bus, - unsigned char device, - unsigned char func); - -u_long pci_conf_read (pcici_t tag, u_long reg ); -void pci_conf_write (pcici_t tag, u_long reg, u_long data); - - -/*------------------------------------------------------------------ -** -** Names for PCI configuration space registers. -** -** Copyright (c) 1994 Charles Hannum. All rights reserved. -** -**------------------------------------------------------------------ -*/ /* - * Device identification register; contains a vendor ID and a device ID. - * We have little need to distinguish the two parts. - */ +** Device identification register; contains a vendor ID and a device ID. +** We have little need to distinguish the two parts. +*/ #define PCI_ID_REG 0x00 /* - * Command and status register. - */ +** Command and status register. +*/ #define PCI_COMMAND_STATUS_REG 0x04 #define PCI_COMMAND_IO_ENABLE 0x00000001 @@ -329,8 +76,8 @@ void pci_conf_write (pcici_t tag, u_long reg, u_long data); #define PCI_STATUS_PARITY_DETECT 0x80000000 /* - * Class register; defines basic type of device. - */ +** Class register; defines basic type of device. +*/ #define PCI_CLASS_REG 0x08 #define PCI_CLASS_MASK 0xff000000 @@ -388,8 +135,8 @@ void pci_conf_write (pcici_t tag, u_long reg, u_long data); #define PCI_SUBCLASS_BRIDGE_MISC 0x00800000 /* - * Mapping registers - */ +** Mapping registers +*/ #define PCI_MAP_REG_START 0x10 #define PCI_MAP_REG_END 0x28 @@ -403,9 +150,11 @@ void pci_conf_write (pcici_t tag, u_long reg, u_long data); #define PCI_MAP_MEMORY_CACHABLE 0x00000008 #define PCI_MAP_MEMORY_ADDRESS_MASK 0xfffffff0 +#define PCI_MAP_IO_ADDRESS_MASK 0xfffffffc + /* - * Interrupt configuration register - */ +** Interrupt configuration register +*/ #define PCI_INTERRUPT_REG 0x3c #define PCI_INTERRUPT_PIN_MASK 0x0000ff00 diff --git a/sys/pci/pcisupport.c b/sys/pci/pcisupport.c index 16694653bc0d..933ca54a460a 100644 --- a/sys/pci/pcisupport.c +++ b/sys/pci/pcisupport.c @@ -1,6 +1,6 @@ /************************************************************************** ** -** $Id: pcisupport.c,v 1.6 1994/12/22 21:20:39 se Exp $ +** $Id: pcisupport.c,v 1.7 1995/02/02 12:36:19 davidg Exp $ ** ** Device driver for INTEL PCI chipsets. ** @@ -50,7 +50,10 @@ */ #include <sys/types.h> +#include <sys/param.h> +#include <sys/kernel.h> +#include <pci/pcivar.h> #include <pci/pcireg.h> extern void printf(); @@ -69,12 +72,15 @@ static char* chipset_probe (pcici_t tag, pcidi_t type); static void chipset_attach(pcici_t tag, int unit); static u_long chipset_count; -struct pci_driver chipset_device = { +struct pci_device chipset_device = { + "chip", chipset_probe, chipset_attach, &chipset_count }; +DATA_SET (pcidevice_set, chipset_device); + static char confread(pcici_t config_id, int port); struct condmsg { @@ -296,12 +302,15 @@ static char* vga_probe (pcici_t tag, pcidi_t type); static void vga_attach(pcici_t tag, int unit); static u_long vga_count; -struct pci_driver vga_device = { +struct pci_device vga_device = { + "vga", vga_probe, vga_attach, &vga_count }; +DATA_SET (pcidevice_set, vga_device); + static char* vga_probe (pcici_t tag, pcidi_t type) { int data = pci_conf_read(tag, PCI_CLASS_REG); @@ -345,12 +354,15 @@ static char* lkm_probe (pcici_t tag, pcidi_t type); static void lkm_attach(pcici_t tag, int unit); static u_long lkm_count; -struct pci_driver lkm_device = { +struct pci_device lkm_device = { + "lkm", lkm_probe, lkm_attach, &lkm_count }; +DATA_SET (pcidevice_set, lkm_device); + static char* lkm_probe (pcici_t tag, pcidi_t type) { /* @@ -375,12 +387,15 @@ static char* ign_probe (pcici_t tag, pcidi_t type); static void ign_attach(pcici_t tag, int unit); static u_long ign_count; -struct pci_driver ign_device = { +struct pci_device ign_device = { + NULL, ign_probe, ign_attach, &ign_count }; +DATA_SET (pcidevice_set, ign_device); + static char* ign_probe (pcici_t tag, pcidi_t type) { switch (type) { |