Home | History | Annotate | Line # | Download | only in pci
apecs.c revision 1.2
      1  1.2  cgd /*	$NetBSD: apecs.c,v 1.2 1995/08/03 00:44:57 cgd Exp $	*/
      2  1.1  cgd 
      3  1.1  cgd /*
      4  1.1  cgd  * Copyright (c) 1994, 1995 Carnegie-Mellon University.
      5  1.1  cgd  * All rights reserved.
      6  1.1  cgd  *
      7  1.1  cgd  * Author: Chris G. Demetriou
      8  1.1  cgd  *
      9  1.1  cgd  * Permission to use, copy, modify and distribute this software and
     10  1.1  cgd  * its documentation is hereby granted, provided that both the copyright
     11  1.1  cgd  * notice and this permission notice appear in all copies of the
     12  1.1  cgd  * software, derivative works or modified versions, and any portions
     13  1.1  cgd  * thereof, and that both notices appear in supporting documentation.
     14  1.1  cgd  *
     15  1.1  cgd  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     16  1.1  cgd  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
     17  1.1  cgd  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     18  1.1  cgd  *
     19  1.1  cgd  * Carnegie Mellon requests users of this software to return to
     20  1.1  cgd  *
     21  1.1  cgd  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     22  1.1  cgd  *  School of Computer Science
     23  1.1  cgd  *  Carnegie Mellon University
     24  1.1  cgd  *  Pittsburgh PA 15213-3890
     25  1.1  cgd  *
     26  1.1  cgd  * any improvements or extensions that they make and grant Carnegie the
     27  1.1  cgd  * rights to redistribute these changes.
     28  1.1  cgd  */
     29  1.1  cgd 
     30  1.1  cgd #include <sys/param.h>
     31  1.1  cgd #include <sys/systm.h>
     32  1.1  cgd #include <sys/kernel.h>
     33  1.1  cgd #include <sys/malloc.h>
     34  1.1  cgd #include <sys/device.h>
     35  1.1  cgd #include <vm/vm.h>
     36  1.1  cgd 
     37  1.1  cgd #include <machine/autoconf.h>
     38  1.1  cgd #include <machine/pio.h>
     39  1.1  cgd #include <machine/rpb.h>
     40  1.1  cgd 
     41  1.1  cgd #include <dev/isa/isareg.h>
     42  1.1  cgd #include <dev/isa/isavar.h>
     43  1.1  cgd #include <alpha/isa/isa_dma.h>
     44  1.1  cgd 
     45  1.1  cgd #include <dev/pci/pcireg.h>
     46  1.1  cgd #include <dev/pci/pcivar.h>
     47  1.1  cgd #include <alpha/pci/pci_chipset.h>
     48  1.1  cgd #include <alpha/pci/apecsreg.h>
     49  1.1  cgd 
     50  1.1  cgd int	apecsmatch __P((struct device *, void *, void *));
     51  1.1  cgd void	apecsattach __P((struct device *, struct device *, void *));
     52  1.1  cgd 
     53  1.1  cgd struct cfdriver apecscd = {
     54  1.1  cgd 	NULL, "apecs", apecsmatch, apecsattach, DV_DULL, sizeof(struct device)
     55  1.1  cgd };
     56  1.1  cgd 
     57  1.1  cgd static int	apecsprint __P((void *, char *pnp));
     58  1.1  cgd 
     59  1.1  cgd #ifdef DEC_2100_A50
     60  1.1  cgd extern void	pci_2100_a50_pickintr __P((void));
     61  1.1  cgd #endif
     62  1.1  cgd 
     63  1.1  cgd #define	REGVAL(r)	(*(int32_t *)phystok0seg(r))
     64  1.1  cgd 
     65  1.1  cgd static int		nsgmapent = 1024;
     66  1.1  cgd static vm_offset_t	sgmap_pci_base = 0x800000;
     67  1.1  cgd /*static */struct sgmapent	*sgmap;
     68  1.1  cgd static char		/* * */ sgbitmap[1024 / NBBY];
     69  1.1  cgd 
     70  1.1  cgd int
     71  1.1  cgd apecsmatch(parent, match, aux)
     72  1.1  cgd 	struct device *parent;
     73  1.1  cgd 	void *match, *aux;
     74  1.1  cgd {
     75  1.1  cgd 	struct cfdata *cf = match;
     76  1.1  cgd 	struct confargs *pa = aux;
     77  1.1  cgd 
     78  1.1  cgd 	/* XXX */
     79  1.1  cgd 
     80  1.1  cgd 	return (1);
     81  1.1  cgd }
     82  1.1  cgd 
     83  1.2  cgd /*
     84  1.2  cgd  * Set up the chipset's function pointers.
     85  1.2  cgd  */
     86  1.2  cgd void
     87  1.2  cgd apecs_init()
     88  1.2  cgd {
     89  1.2  cgd 	int pass2_epic;
     90  1.2  cgd 
     91  1.2  cgd 	pass2_epic = (REGVAL(EPIC_DCSR) & EPIC_DCSR_PASS2) != 0;
     92  1.2  cgd 
     93  1.2  cgd 	isadma_fcns = &apecs_isadma_fcns;
     94  1.2  cgd 	isa_pio_fcns = &apecs_pio_fcns;
     95  1.2  cgd 	if (!pass2_epic)
     96  1.2  cgd 		pci_cs_fcns = &apecs_p1e_cs_fcns;
     97  1.2  cgd 	else
     98  1.2  cgd 		pci_cs_fcns = &apecs_p2e_cs_fcns;
     99  1.2  cgd }
    100  1.2  cgd 
    101  1.1  cgd void
    102  1.1  cgd apecsattach(parent, self, aux)
    103  1.1  cgd 	struct device *parent, *self;
    104  1.1  cgd 	void *aux;
    105  1.1  cgd {
    106  1.1  cgd 	struct confargs *ca = aux;
    107  1.1  cgd 	struct confargs nca;
    108  1.1  cgd 	int pass2_comanche, widemem, pass2_epic;
    109  1.1  cgd 
    110  1.1  cgd 	pass2_comanche = (REGVAL(COMANCHE_ED) & COMANCHE_ED_PASS2) != 0;
    111  1.1  cgd 	widemem = (REGVAL(COMANCHE_GCR) & COMANCHE_GCR_WIDEMEM) != 0;
    112  1.1  cgd 	pass2_epic = (REGVAL(EPIC_DCSR) & EPIC_DCSR_PASS2) != 0;
    113  1.1  cgd 
    114  1.1  cgd 	sgmap = (struct sgmapent *)malloc(1024 * sizeof(struct sgmapent),
    115  1.1  cgd 	    M_DEVBUF, M_WAITOK);
    116  1.1  cgd 
    117  1.1  cgd 	printf(": DECchip %s Core Logic chipset\n",
    118  1.1  cgd 	    widemem ? "21072" : "21071");
    119  1.1  cgd 	printf("%s: DC21071-CA pass %d, %d-bit memory bus\n",
    120  1.1  cgd 	    self->dv_xname, pass2_comanche ? 2 : 1, widemem ? 128 : 64);
    121  1.1  cgd 	printf("%s: DC21071-DA pass %d\n", self->dv_xname, pass2_epic ? 2 : 1);
    122  1.1  cgd 	/* XXX print bcache size */
    123  1.1  cgd 
    124  1.1  cgd 	if (!pass2_epic)
    125  1.1  cgd 		printf("WARNING: 21071-DA NOT PASS2... NO BETS...\n");
    126  1.1  cgd 
    127  1.1  cgd 	/* set up the chipset's functions */
    128  1.2  cgd 	apecs_init();
    129  1.1  cgd 
    130  1.1  cgd 	switch (hwrpb->rpb_type) {
    131  1.1  cgd #if defined(DEC_2100_A50)
    132  1.1  cgd 	case ST_DEC_2100_A50:
    133  1.1  cgd 		pci_2100_a50_pickintr();
    134  1.1  cgd 		break;
    135  1.1  cgd #endif
    136  1.1  cgd 	default:
    137  1.1  cgd 		panic("apecsattach: shouldn't be here, really...");
    138  1.1  cgd 	}
    139  1.1  cgd 
    140  1.1  cgd 	/* attach the PCI bus that hangs off of it... */
    141  1.1  cgd 	nca.ca_name = "pci";
    142  1.1  cgd 	nca.ca_slot = 0;
    143  1.1  cgd 	nca.ca_offset = 0;
    144  1.1  cgd 	nca.ca_bus = NULL;
    145  1.1  cgd 	if (!config_found(self, &nca, apecsprint))
    146  1.1  cgd 		panic("apecsattach: couldn't attach PCI bus");
    147  1.1  cgd }
    148  1.1  cgd 
    149  1.1  cgd static int
    150  1.1  cgd apecsprint(aux, pnp)
    151  1.1  cgd 	void *aux;
    152  1.1  cgd 	char *pnp;
    153  1.1  cgd {
    154  1.1  cgd         register struct confargs *ca = aux;
    155  1.1  cgd 
    156  1.1  cgd         if (pnp)
    157  1.1  cgd                 printf("%s at %s", ca->ca_name, pnp);
    158  1.1  cgd         return (UNCONF);
    159  1.1  cgd }
    160  1.1  cgd 
    161  1.1  cgd vm_offset_t						/* XXX? */
    162  1.1  cgd apecs_sgmap_alloc(va, npg, nocross, waitok)
    163  1.1  cgd 	caddr_t	va;
    164  1.1  cgd 	int npg;
    165  1.1  cgd 	vm_size_t nocross;
    166  1.1  cgd 	int waitok;
    167  1.1  cgd {
    168  1.1  cgd 	int s;
    169  1.1  cgd 	int base, i, stride;
    170  1.1  cgd 
    171  1.1  cgd #ifdef DIAGNOSTIC
    172  1.1  cgd 	/* Quick sanity checks. */
    173  1.1  cgd 	if ((vm_offset_t)va & PGOFSET)
    174  1.1  cgd 		panic("apecs_sgmap_alloc: va not page aligned");
    175  1.1  cgd 	if ((nocross & (nocross - 1)) != 0 || nocross == 0)
    176  1.1  cgd 		panic("apecs_sgmap_alloc: bogus alignment 0x%lx", nocross);
    177  1.1  cgd 	if (npg <= 0)
    178  1.1  cgd 		panic("apecs_sgmap_alloc: not allocating anything");
    179  1.1  cgd 	if (npg > nsgmapent)
    180  1.1  cgd 		panic("apecs_sgmap_alloc: insane allocation");
    181  1.1  cgd 	if (ptoa(npg) > nocross)
    182  1.1  cgd 		panic("apecs_sgmap_alloc: must cross boundary");
    183  1.1  cgd #endif
    184  1.1  cgd 
    185  1.1  cgd 	stride = atop(nocross);
    186  1.1  cgd #ifdef DIAGNOSTIC
    187  1.1  cgd 	if (stride > nsgmapent)
    188  1.1  cgd 		panic("apecs_sgmap_alloc: cheesy implementation loses");
    189  1.1  cgd #endif
    190  1.1  cgd 
    191  1.1  cgd top:
    192  1.1  cgd 	s = splhigh();
    193  1.1  cgd 	for (base = 0; base < nsgmapent; base += stride) {
    194  1.1  cgd 		for (i = base; i < base + npg; i++)
    195  1.1  cgd 			if (isset(sgbitmap, i))
    196  1.1  cgd 				goto nextstride;
    197  1.1  cgd 		break;
    198  1.1  cgd nextstride:
    199  1.1  cgd 	}
    200  1.1  cgd 	if (base < nsgmapent)		/* found a free chunk, claim it */
    201  1.1  cgd 		for (i = base; i < base + npg; i++)
    202  1.1  cgd 			setbit(sgbitmap, i);
    203  1.1  cgd 	splx(s);
    204  1.1  cgd 
    205  1.1  cgd 	if (base >= nsgmapent) {	/* didn't find a free chunk */
    206  1.1  cgd 		if (!waitok)
    207  1.1  cgd 			return 0;
    208  1.1  cgd 		tsleep(&sgmap, PRIBIO+1, "sgmap", 0);
    209  1.1  cgd 		goto top;
    210  1.1  cgd 	}
    211  1.1  cgd 
    212  1.1  cgd 	for (i = base; i < base + npg; i++) {
    213  1.1  cgd #ifdef DIAGNOSTIC
    214  1.1  cgd 		if ((sgmap[i].val & SGMAPENT_EVAL) != 0)
    215  1.1  cgd 			panic("apecs_sgmap_alloc: unallocated entry valid");
    216  1.1  cgd #endif
    217  1.1  cgd 		sgmap[i].val = SGMAP_MAKEENTRY(atop(vtophys(va)));
    218  1.1  cgd 		va += PAGE_SIZE;
    219  1.1  cgd 	}
    220  1.1  cgd 
    221  1.1  cgd 	/* Invalidate old cached entries. */
    222  1.1  cgd 	REGVAL(EPIC_TBIA) = 1;
    223  1.1  cgd 
    224  1.1  cgd 	/* Return the PCI address. */
    225  1.1  cgd 	return (ptoa(base) + sgmap_pci_base);
    226  1.1  cgd }
    227  1.1  cgd 
    228  1.1  cgd void
    229  1.1  cgd apecs_sgmap_dealloc(pa, npg)
    230  1.1  cgd 	vm_offset_t pa;
    231  1.1  cgd 	int npg;
    232  1.1  cgd {
    233  1.1  cgd 	int i, pfn;
    234  1.1  cgd 
    235  1.1  cgd #ifdef DIAGNOSTIC
    236  1.1  cgd 	/* Quick sanity checks. */
    237  1.1  cgd 	if (pa & PGOFSET)
    238  1.1  cgd 		panic("apecs_sgmap_dealloc: pa not page aligned");
    239  1.1  cgd 	if (npg <= 0)
    240  1.1  cgd 		panic("apecs_sgmap_dealloc: not deallocating anything");
    241  1.1  cgd 	if (npg > nsgmapent)
    242  1.1  cgd 		panic("apecs_sgmap_dealloc: insane deallocation");
    243  1.1  cgd #endif
    244  1.1  cgd 
    245  1.1  cgd 	pfn = atop(pa - sgmap_pci_base);
    246  1.1  cgd #ifdef DIAGNOSTIC
    247  1.1  cgd 	/* Bounds check the deallocation range.  Paranoid about wraparound. */
    248  1.1  cgd 	if (pfn < 0 || pfn >= nsgmapent || (pfn + npg) >= nsgmapent)
    249  1.1  cgd 		panic("apecs_sgmap_dealloc: pa out of range (%s)",
    250  1.1  cgd 			pfn < 0 ? "too low" : "too high");
    251  1.1  cgd #endif
    252  1.1  cgd 
    253  1.1  cgd 	for (i = 0; i < npg; i++) {
    254  1.1  cgd #ifdef DIAGNOSTIC
    255  1.1  cgd 		/* Make sure it's actually allocated. */
    256  1.1  cgd 		if (isclr(sgbitmap, i + pfn))
    257  1.1  cgd 			panic("apecs_sgmap_dealloc: multiple frees: entry %d",
    258  1.1  cgd 			    i + pfn);
    259  1.1  cgd #endif
    260  1.1  cgd 
    261  1.1  cgd 		/* Clear the entries and the allocation map bits. */
    262  1.1  cgd 		clrbit(sgbitmap, i + pfn);
    263  1.1  cgd 		sgmap[i + pfn].val &= ~SGMAPENT_EVAL;
    264  1.1  cgd 	}
    265  1.1  cgd 
    266  1.1  cgd 	/* Invalidate old cached entries. */
    267  1.1  cgd 	REGVAL(EPIC_TBIA) = 1;
    268  1.1  cgd 
    269  1.1  cgd 	/* Wake up anybody waiting for map entries. */
    270  1.1  cgd 	wakeup(&sgmap);
    271  1.1  cgd }
    272