Home | History | Annotate | Line # | Download | only in pci
apecs.c revision 1.1
      1 /*	$NetBSD: apecs.c,v 1.1 1995/06/28 01:25:18 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 void
     84 apecsattach(parent, self, aux)
     85 	struct device *parent, *self;
     86 	void *aux;
     87 {
     88 	struct confargs *ca = aux;
     89 	struct confargs nca;
     90 	int pass2_comanche, widemem, pass2_epic;
     91 
     92 	pass2_comanche = (REGVAL(COMANCHE_ED) & COMANCHE_ED_PASS2) != 0;
     93 	widemem = (REGVAL(COMANCHE_GCR) & COMANCHE_GCR_WIDEMEM) != 0;
     94 	pass2_epic = (REGVAL(EPIC_DCSR) & EPIC_DCSR_PASS2) != 0;
     95 
     96 	sgmap = (struct sgmapent *)malloc(1024 * sizeof(struct sgmapent),
     97 	    M_DEVBUF, M_WAITOK);
     98 
     99 	printf(": DECchip %s Core Logic chipset\n",
    100 	    widemem ? "21072" : "21071");
    101 	printf("%s: DC21071-CA pass %d, %d-bit memory bus\n",
    102 	    self->dv_xname, pass2_comanche ? 2 : 1, widemem ? 128 : 64);
    103 	printf("%s: DC21071-DA pass %d\n", self->dv_xname, pass2_epic ? 2 : 1);
    104 	/* XXX print bcache size */
    105 
    106 	if (!pass2_epic)
    107 		printf("WARNING: 21071-DA NOT PASS2... NO BETS...\n");
    108 
    109 	/* set up the chipset's functions */
    110 	isadma_fcns = &apecs_isadma_fcns;
    111 	isa_pio_fcns = &apecs_pio_fcns;
    112 	if (!pass2_epic)
    113 		pci_cs_fcns = &apecs_p1e_cs_fcns;
    114 	else
    115 		pci_cs_fcns = &apecs_p2e_cs_fcns;
    116 
    117 	switch (hwrpb->rpb_type) {
    118 #if defined(DEC_2100_A50)
    119 	case ST_DEC_2100_A50:
    120 		pci_2100_a50_pickintr();
    121 		break;
    122 #endif
    123 	default:
    124 		panic("apecsattach: shouldn't be here, really...");
    125 	}
    126 
    127 	/* attach the PCI bus that hangs off of it... */
    128 	nca.ca_name = "pci";
    129 	nca.ca_slot = 0;
    130 	nca.ca_offset = 0;
    131 	nca.ca_bus = NULL;
    132 	if (!config_found(self, &nca, apecsprint))
    133 		panic("apecsattach: couldn't attach PCI bus");
    134 }
    135 
    136 static int
    137 apecsprint(aux, pnp)
    138 	void *aux;
    139 	char *pnp;
    140 {
    141         register struct confargs *ca = aux;
    142 
    143         if (pnp)
    144                 printf("%s at %s", ca->ca_name, pnp);
    145         return (UNCONF);
    146 }
    147 
    148 vm_offset_t						/* XXX? */
    149 apecs_sgmap_alloc(va, npg, nocross, waitok)
    150 	caddr_t	va;
    151 	int npg;
    152 	vm_size_t nocross;
    153 	int waitok;
    154 {
    155 	int s;
    156 	int base, i, stride;
    157 
    158 #ifdef DIAGNOSTIC
    159 	/* Quick sanity checks. */
    160 	if ((vm_offset_t)va & PGOFSET)
    161 		panic("apecs_sgmap_alloc: va not page aligned");
    162 	if ((nocross & (nocross - 1)) != 0 || nocross == 0)
    163 		panic("apecs_sgmap_alloc: bogus alignment 0x%lx", nocross);
    164 	if (npg <= 0)
    165 		panic("apecs_sgmap_alloc: not allocating anything");
    166 	if (npg > nsgmapent)
    167 		panic("apecs_sgmap_alloc: insane allocation");
    168 	if (ptoa(npg) > nocross)
    169 		panic("apecs_sgmap_alloc: must cross boundary");
    170 #endif
    171 
    172 	stride = atop(nocross);
    173 #ifdef DIAGNOSTIC
    174 	if (stride > nsgmapent)
    175 		panic("apecs_sgmap_alloc: cheesy implementation loses");
    176 #endif
    177 
    178 top:
    179 	s = splhigh();
    180 	for (base = 0; base < nsgmapent; base += stride) {
    181 		for (i = base; i < base + npg; i++)
    182 			if (isset(sgbitmap, i))
    183 				goto nextstride;
    184 		break;
    185 nextstride:
    186 	}
    187 	if (base < nsgmapent)		/* found a free chunk, claim it */
    188 		for (i = base; i < base + npg; i++)
    189 			setbit(sgbitmap, i);
    190 	splx(s);
    191 
    192 	if (base >= nsgmapent) {	/* didn't find a free chunk */
    193 		if (!waitok)
    194 			return 0;
    195 		tsleep(&sgmap, PRIBIO+1, "sgmap", 0);
    196 		goto top;
    197 	}
    198 
    199 	for (i = base; i < base + npg; i++) {
    200 #ifdef DIAGNOSTIC
    201 		if ((sgmap[i].val & SGMAPENT_EVAL) != 0)
    202 			panic("apecs_sgmap_alloc: unallocated entry valid");
    203 #endif
    204 		sgmap[i].val = SGMAP_MAKEENTRY(atop(vtophys(va)));
    205 		va += PAGE_SIZE;
    206 	}
    207 
    208 	/* Invalidate old cached entries. */
    209 	REGVAL(EPIC_TBIA) = 1;
    210 
    211 	/* Return the PCI address. */
    212 	return (ptoa(base) + sgmap_pci_base);
    213 }
    214 
    215 void
    216 apecs_sgmap_dealloc(pa, npg)
    217 	vm_offset_t pa;
    218 	int npg;
    219 {
    220 	int i, pfn;
    221 
    222 #ifdef DIAGNOSTIC
    223 	/* Quick sanity checks. */
    224 	if (pa & PGOFSET)
    225 		panic("apecs_sgmap_dealloc: pa not page aligned");
    226 	if (npg <= 0)
    227 		panic("apecs_sgmap_dealloc: not deallocating anything");
    228 	if (npg > nsgmapent)
    229 		panic("apecs_sgmap_dealloc: insane deallocation");
    230 #endif
    231 
    232 	pfn = atop(pa - sgmap_pci_base);
    233 #ifdef DIAGNOSTIC
    234 	/* Bounds check the deallocation range.  Paranoid about wraparound. */
    235 	if (pfn < 0 || pfn >= nsgmapent || (pfn + npg) >= nsgmapent)
    236 		panic("apecs_sgmap_dealloc: pa out of range (%s)",
    237 			pfn < 0 ? "too low" : "too high");
    238 #endif
    239 
    240 	for (i = 0; i < npg; i++) {
    241 #ifdef DIAGNOSTIC
    242 		/* Make sure it's actually allocated. */
    243 		if (isclr(sgbitmap, i + pfn))
    244 			panic("apecs_sgmap_dealloc: multiple frees: entry %d",
    245 			    i + pfn);
    246 #endif
    247 
    248 		/* Clear the entries and the allocation map bits. */
    249 		clrbit(sgbitmap, i + pfn);
    250 		sgmap[i + pfn].val &= ~SGMAPENT_EVAL;
    251 	}
    252 
    253 	/* Invalidate old cached entries. */
    254 	REGVAL(EPIC_TBIA) = 1;
    255 
    256 	/* Wake up anybody waiting for map entries. */
    257 	wakeup(&sgmap);
    258 }
    259