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