Home | History | Annotate | Line # | Download | only in vsa
vsbus.c revision 1.6
      1 /*	$NetBSD: vsbus.c,v 1.6 1997/03/22 23:05:31 ragge Exp $ */
      2 /*
      3  * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
      4  * All rights reserved.
      5  *
      6  * This code is derived from software contributed to Ludd by Bertram Barth.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *	This product includes software developed at Ludd, University of
     19  *	Lule}, Sweden and its contributors.
     20  * 4. The name of the author may not be used to endorse or promote products
     21  *    derived from this software without specific prior written permission
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     33  */
     34 
     35 #include <sys/param.h>
     36 #include <sys/systm.h>
     37 #include <sys/buf.h>
     38 #include <sys/conf.h>
     39 #include <sys/file.h>
     40 #include <sys/ioctl.h>
     41 #include <sys/proc.h>
     42 #include <sys/user.h>
     43 #include <sys/map.h>
     44 #include <sys/device.h>
     45 #include <sys/dkstat.h>
     46 #include <sys/disklabel.h>
     47 #include <sys/syslog.h>
     48 #include <sys/stat.h>
     49 
     50 #include <machine/pte.h>
     51 #include <machine/sid.h>
     52 #include <machine/scb.h>
     53 #include <machine/cpu.h>
     54 #include <machine/trap.h>
     55 #include <machine/nexus.h>
     56 
     57 #include <machine/uvax.h>
     58 #include <machine/ka410.h>
     59 #include <machine/ka43.h>
     60 
     61 #include <machine/vsbus.h>
     62 
     63 #define trace(x)
     64 #define debug(x)
     65 
     66 int	vsbus_match	__P((struct device *, void *, void *));
     67 void	vsbus_attach	__P((struct device *, struct device *, void *));
     68 int	vsbus_print	__P((void *, const char *));
     69 
     70 void	ka410_attach	__P((struct device *, struct device *, void *));
     71 void	ka43_attach	__P((struct device *, struct device *, void *));
     72 
     73 struct	cfdriver vsbus_cd = {
     74 	NULL, "vsbus", DV_DULL
     75 };
     76 struct	cfattach vsbus_ca = {
     77 	sizeof(struct device), vsbus_match, vsbus_attach
     78 };
     79 
     80 /*
     81 void	vsbus_intr_register __P((struct confargs *ca, int (*)(void*), void*));
     82 void	vsbus_intr_unregister __P((struct confargs *));
     83 */
     84 
     85 void	vsbus_intr_dispatch __P((int i));
     86 
     87 #define VSBUS_MAXDEVS	8
     88 #define VSBUS_MAXINTR	8
     89 
     90 struct confargs *vsbus_devs = NULL;
     91 
     92 #ifdef VAX410
     93 struct confargs ka410_devs[] = {
     94 	/* name		intslot intpri intvec	intbit	ioaddr	*/
     95 	{ "dc",		7,	7,	0x2C0,	(1<<7), KA410_SER_BASE,
     96 			6,	6,	0x2C4,	(1<<6), 0x01,		},
     97 	{ "dc (xmit)",	6,	6,	0x2C4,	(1<<6), KA410_SER_BASE, },
     98 	{ "le",		5,	5,	0x250,	(1<<5), KA410_LAN_BASE,
     99 			KA410_NWA_BASE, 0x00,				},
    100 	{ "ncr",	1,	1,	0x3F8,	(1<<1), KA410_SCS_BASE,
    101 			KA410_SCS_DADR, KA410_SCS_DCNT, KA410_SCS_DDIR,
    102 			KA410_DMA_BASE, KA410_DMA_SIZE, 0x00,	0x07,	},
    103 	{ "hdc",	0,	0,	0x3FC,	(1<<0), KA410_DKC_BASE,
    104 			0, 0, 0,
    105 			KA410_DMA_BASE, KA410_DMA_SIZE, 0x00,		},
    106 #if 0
    107 	{ "dc (recv)",	7,	7,	0x2C0,	(1<<7), KA410_SER_BASE, },
    108 	{ "dc (xmit)",	6,	6,	0x2C4,	(1<<6), KA410_SER_BASE, },
    109 	{ "hdc9224",	0,	0,	0x3FC,	(1<<0), KA410_DKC_BASE, },
    110 	{ "ncr5380",	1,	1,	0x3F8,	(1<<1), KA410_SCS_BASE, },
    111 	{ "am7990",	5,	5,	0x250,	(1<<5), KA410_LAN_BASE, },
    112 	{ "NETOPT",	4,	4,	0x254,	(1<<4), KA410_LAN_BASE, },
    113 #endif
    114 	{ "" },
    115 };
    116 
    117 /*
    118  * It would be better if we could use the (provided) system config
    119  * information for each CPU instead of this.
    120  */
    121 struct confargs ka420_devs[] = {
    122 	{ "le",		5,	5,	0x250,	(1<<5),	KA410_LAN_BASE,
    123 		KA410_NWA_BASE,	0x00,					},
    124 	{ "ncr",	1,	1,	0x3F8,	(1<<1),	KA410_SCS_BASE,
    125 			KA410_SCS_DADR,	KA410_SCS_DCNT,	KA410_SCS_DDIR,
    126 			KA410_DMA_BASE,	KA410_DMA_SIZE,	0x00,	0x07,	},
    127 	{ "ncr",	0,	0,	0x3FC,	(1<<0),	0x200C0180,
    128 			0x200C01A0,	0x200C01C0,	0x200C01C4,
    129 			KA410_DMA_BASE,	KA410_DMA_SIZE,	0x00,	0x07,	},
    130 	{ "" },
    131 };
    132 #endif
    133 
    134 #ifdef VAX43
    135 struct confargs ka43_devs[] = {
    136 	/* name		intslot intpri intvec	intbit	ioaddr	*/
    137 	{ "dc",		7,	7,	0x2C0,	(1<<7), KA43_SER_BASE,
    138 			6,	6,	0x2C4,	(1<<6), 0x01,		},
    139 	{ "dc (xmit)",	6,	6,	0x2C4,	(1<<6), KA43_SER_BASE,	},
    140 	{ "le",		5,	5,	0x250,	(1<<5), KA43_LAN_BASE,
    141 			KA43_NWA_BASE,	0x00,				},
    142 	{ "ncr",	1,	1,	0x3F8,	(1<<1), KA43_SC1_BASE,
    143 			KA43_SC1_DADR,	KA43_SC1_DCNT,	KA43_SC1_DDIR,
    144 			KA43_DMA_BASE,	KA43_DMA_SIZE,	0x01,	0x06,	},
    145 	{ "ncr",	0,	0,	0x3FC,	(1<<0), KA43_SC2_BASE,
    146 			KA43_SC2_DADR,	KA43_SC2_DCNT,	KA43_SC2_DDIR,
    147 			KA43_DMA_BASE,	KA43_DMA_SIZE,	0x01,	0x06,	},
    148 #if 0
    149 	{ "le (2nd)",	4,	4,	0x254,	(1<<4), 0x???,		},
    150 	{ "NETOPT",	4,	4,	0x254,	(1<<4), 0x???,		},
    151 #endif
    152 	{ "" },
    153 };
    154 #endif
    155 
    156 int
    157 vsbus_print(aux, name)
    158 	void *aux;
    159 	const char *name;
    160 {
    161 	struct confargs *ca = aux;
    162 
    163 	trace(("vsbus_print(%x, %s)\n", ca->ca_name, name));
    164 
    165 	if (name) {
    166 		printf ("device %s at %s", ca->ca_name, name);
    167 		return (UNSUPP);
    168 	}
    169 	return (UNCONF);
    170 }
    171 
    172 int
    173 vsbus_match(parent, cf, aux)
    174 	struct	device	*parent;
    175 	void	*cf;
    176 	void	*aux;
    177 {
    178 	struct bp_conf *bp = aux;
    179 
    180 	trace(("vsbus_match: bp->type = \"%s\"\n", bp->type));
    181 
    182 	if (strcmp(bp->type, "vsbus"))
    183 		return 0;
    184 	/*
    185 	 * on machines which can have it, the vsbus is always there
    186 	 */
    187 	if ((vax_bustype & VAX_VSBUS) == 0)
    188 		return (0);
    189 
    190 	return (1);
    191 }
    192 
    193 #if 1	/*------------------------------------------------------------*/
    194 #if 1
    195 #define REG(name)	short name; short X##name##X;
    196 #else
    197 #define REG(name)	int name;
    198 #endif
    199 static volatile struct {/* base address of DZ-controller: 0x200A0000 */
    200   REG(csr);		/* 00 Csr: control/status register */
    201   REG(rbuf);		/* 04 Rbuf/Lpr: receive buffer/line param reg. */
    202   REG(tcr);		/* 08 Tcr: transmit console register */
    203   REG(tdr);		/* 0C Msr/Tdr: modem status reg/transmit data reg */
    204   REG(lpr0);		/* 10 Lpr0: */
    205   REG(lpr1);		/* 14 Lpr0: */
    206   REG(lpr2);		/* 18 Lpr0: */
    207   REG(lpr3);		/* 1C Lpr0: */
    208 } *dz = (void*)0x200A0000;
    209 extern int dzcnrint();
    210 extern int dzcntint();
    211 int hardclock_count = 0;
    212 int
    213 ka410_consintr_enable()
    214 {
    215 	vsbus_intr_enable(&ka410_devs[0]);
    216 	vsbus_intr_enable(&ka410_devs[1]);
    217 }
    218 
    219 int
    220 ka410_consRecv_intr(p)
    221 	void *p;
    222 {
    223   /* printf("ka410_consRecv_intr: hc-count=%d\n", hardclock_count); */
    224   dzcnrint();
    225   /* printf("gencnrint() returned.\n"); */
    226   return(0);
    227 }
    228 
    229 int
    230 ka410_consXmit_intr(p)
    231 	void *p;
    232 {
    233   /* printf("ka410_consXmit_intr: hc-count=%d\n", hardclock_count); */
    234   dzcntint();
    235   /* printf("gencntint() returned.\n"); */
    236   return(0);
    237 }
    238 #endif	/*------------------------------------------------------------*/
    239 
    240 void
    241 vsbus_attach(parent, self, aux)
    242 	struct	device	*parent, *self;
    243 	void	*aux;
    244 {
    245 	struct confargs *ca;
    246 	int i;
    247 
    248 	printf("\n");
    249 	trace (("vsbus_attach()\n"));
    250 
    251 	switch (vax_boardtype) {
    252 	case VAX_BTYP_420:
    253 		vsbus_devs = ka420_devs;
    254 		break;
    255 
    256 	case VAX_BTYP_410:
    257 		vsbus_devs = ka410_devs;
    258 		break;
    259 
    260 	case VAX_BTYP_43:
    261 	case VAX_BTYP_46:
    262 	case VAX_BTYP_49:
    263 #ifdef VAX43
    264 		vsbus_devs = ka43_devs;
    265 #endif
    266 		break;
    267 
    268 	default:
    269 		printf ("unsupported boardtype 0x%x in vsbus_attach()\n",
    270 			vax_boardtype);
    271 		return;
    272 	}
    273 
    274 	/*
    275 	 * first setup interrupt-table, so that devices can register
    276 	 * their interrupt-routines...
    277 	 */
    278 	vsbus_intr_setup();
    279 
    280 	/*
    281 	 * now check for all possible devices on this "bus"
    282 	 */
    283 	for (i=0; i<VSBUS_MAXDEVS; i++) {
    284 		ca = &vsbus_devs[i];
    285 		if (*ca->ca_name == '\0')
    286 			break;
    287 		config_found(self, (void*)ca, vsbus_print);
    288 	}
    289 
    290 	/*
    291 	 * as long as there's no working DZ-driver, we use this dummy
    292 	 */
    293 	vsbus_intr_register(&ka410_devs[0], ka410_consRecv_intr, NULL);
    294 	vsbus_intr_register(&ka410_devs[1], ka410_consXmit_intr, NULL);
    295 }
    296 
    297 #define VSBUS_MAX_INTR	8	/* 64? */
    298 /*
    299  * interrupt service routines are given an int as argument, which is
    300  * pushed onto stack as LITERAL. Thus the value is between 0-63.
    301  * This array of 64 might be oversized for now, but it's all which
    302  * ever will be possible.
    303  */
    304 struct vsbus_ivec {
    305 	struct ivec_dsp intr_vec;		/* this is referenced in SCB */
    306 	int		intr_count;		/* keep track of interrupts */
    307 	int		intr_flags;		/* valid, etc. */
    308 	void		(*enab)(int);		/* enable interrupt */
    309 	void		(*disab)(int);		/* disable interrupt */
    310 	void		(*prep)(int);		/* need pre-processing? */
    311 	int		(*handler)(void*);	/* isr-routine to call */
    312 	void		*hndlarg;		/* args to this routine */
    313 	void		(*postp)(int);		/* need post-processing? */
    314 } vsbus_ivtab[VSBUS_MAX_INTR];
    315 
    316 /*
    317  *
    318  */
    319 int
    320 vsbus_intr_setup()
    321 {
    322 	int i;
    323 	struct vsbus_ivec *ip;
    324 	extern struct ivec_dsp idsptch;		/* subr.s */
    325 
    326 	for (i=0; i<VSBUS_MAX_INTR; i++) {
    327 		ip = &vsbus_ivtab[i];
    328 		bcopy(&idsptch, &ip->intr_vec, sizeof(struct ivec_dsp));
    329 		ip->intr_vec.pushlarg = i;
    330 		ip->intr_vec.hoppaddr = vsbus_intr_dispatch;
    331 		ip->intr_count = 0;
    332 		ip->intr_flags = 0;
    333 		ip->enab = NULL;
    334 		ip->disab = NULL;
    335 		ip->postp = NULL;
    336 	}
    337 	switch (vax_boardtype) {
    338 	case VAX_BTYP_410:
    339 	case VAX_BTYP_420:
    340 	case VAX_BTYP_43:
    341 	case VAX_BTYP_46:
    342 	case VAX_BTYP_49:
    343 		ka410_intr_setup();
    344 		return(0);
    345 	default:
    346 		printf("unsupported board-type 0x%x in vsbus_intr_setup()\n",
    347 			vax_boardtype);
    348 		return(1);
    349 	}
    350 }
    351 
    352 int
    353 vsbus_intr_register(ca, handler, arg)
    354 	struct confargs *ca;
    355 	int (*handler)(void*);
    356 	void *arg;
    357 {
    358 	/* struct device *dev = arg; */
    359 	int i = ca->ca_intslot;
    360 	struct vsbus_ivec *ip = &vsbus_ivtab[i];
    361 
    362 	trace (("vsbus_intr_register(%s/%d)\n", ca->ca_name, ca->ca_intslot));
    363 
    364 	ip->handler = handler;
    365 	ip->hndlarg = arg;
    366 }
    367 
    368 int
    369 vsbus_intr_enable(ca)
    370 	struct confargs *ca;
    371 {
    372 	int i = ca->ca_intslot;
    373 	struct vsbus_ivec *ip = &vsbus_ivtab[i];
    374 
    375 	trace (("vsbus_intr_enable(%s/%d)\n", ca->ca_name, ca->ca_intslot));
    376 
    377 	/* XXX check for valid handler etc. !!! */
    378 	if (ip->handler == NULL) {
    379 		printf("interrupts for \"%s\"(%d) not enabled: null-handler\n",
    380 		      ca->ca_name, ca->ca_intslot);
    381 		return;
    382 	}
    383 
    384 	ip->enab(i);
    385 }
    386 
    387 int
    388 vsbus_intr_disable(ca)
    389 	struct confargs *ca;
    390 {
    391 	int i = ca->ca_intslot;
    392 	struct vsbus_ivec *ip = &vsbus_ivtab[i];
    393 
    394 	trace (("vsbus_intr_disable(%s/%d)\n", ca->ca_name, i));
    395 
    396 	ip->disab(i);
    397 }
    398 
    399 int
    400 vsbus_intr_unregister(ca)
    401 	struct confargs *ca;
    402 {
    403 	int i = ca->ca_intslot;
    404 	struct vsbus_ivec *ip = &vsbus_ivtab[i];
    405 
    406 	trace (("vsbus_intr_unregister(%s/%d)\n", ca->ca_name, i));
    407 
    408 	ip->handler = NULL;
    409 	ip->hndlarg = NULL;
    410 }
    411 
    412 void
    413 vsbus_intr_dispatch(i)
    414 	register int i;
    415 {
    416 	register struct vsbus_ivec *ip = &vsbus_ivtab[i];
    417 
    418 	trace (("vsbus_intr_dispatch(%d)", i));
    419 
    420 	if (i < VSBUS_MAX_INTR && ip->handler != NULL) {
    421 		ip->intr_count++;
    422 		debug (("intr-count[%d] = %d\n", i, ip->intr_count));
    423 		(ip->handler)(ip->hndlarg);
    424 		if (ip->postp)
    425 			(ip->postp)(i);
    426 		return;
    427 	}
    428 
    429 	if (i < 0 || i >= VSBUS_MAX_INTR) {
    430 		printf ("stray interrupt %d on vsbus.\n", i);
    431 		return;
    432 	}
    433 
    434 	if (!ip->handler) {
    435 		printf ("unhandled interrupt %d on vsbus.\n", i);
    436 		return;
    437 	}
    438 }
    439 
    440 /*
    441  * These addresses are invalid and will be updated/corrected by
    442  * ka410_intr_setup(), but having them this way helps debugging
    443  */
    444 static volatile u_char *ka410_intmsk = (void*)KA410_INTMSK;
    445 static volatile u_char *ka410_intreq = (void*)KA410_INTREQ;
    446 static volatile u_char *ka410_intclr = (void*)KA410_INTCLR;
    447 
    448 static void
    449 ka410_intr_enable(i)
    450 	int i;
    451 {
    452 	trace (("ka410_intr_enable(%d)\n", i));
    453 	*ka410_intmsk |= (1<<i);
    454 }
    455 
    456 static void
    457 ka410_intr_disable(i)
    458 	int i;
    459 {
    460 	trace (("ka410_intr_disable(%d)\n", i));
    461 	*ka410_intmsk &= ~(1<<i);
    462 }
    463 
    464 static void
    465 ka410_intr_clear(i)
    466 	int i;
    467 {
    468 	trace (("ka410_intr_clear(%d)\n", i));
    469 	*ka410_intclr = (1<<i);
    470 }
    471 
    472 ka410_intr_setup()
    473 {
    474 	int i;
    475 	struct vsbus_ivec *ip;
    476 	void **scbP = (void*)scb;
    477 
    478 	trace (("ka410_intr_setup()\n"));
    479 
    480 	ka410_intmsk = (void*)uvax_phys2virt(KA410_INTMSK);
    481 	ka410_intreq = (void*)uvax_phys2virt(KA410_INTREQ);
    482 	ka410_intclr = (void*)uvax_phys2virt(KA410_INTCLR);
    483 
    484 	*ka410_intmsk = 0;		/* disable all interrupts */
    485 	*ka410_intclr = 0xFF;		/* clear all old interrupts */
    486 
    487 	/*
    488 	 * insert the VS2000-specific routines into ivec-table...
    489 	 */
    490 	for (i=0; i<8; i++) {
    491 		ip = &vsbus_ivtab[i];
    492 		ip->enab  = ka410_intr_enable;
    493 		ip->disab = ka410_intr_disable;
    494 		/* ip->postp = ka410_intr_clear; bertram XXX */
    495 	}
    496 	/*
    497 	 * ...and register the interrupt-vectors in SCB
    498 	 */
    499 	scbP[IVEC_DC/4] = &vsbus_ivtab[0].intr_vec;
    500 	scbP[IVEC_SC/4] = &vsbus_ivtab[1].intr_vec;
    501 	scbP[IVEC_VS/4] = &vsbus_ivtab[2].intr_vec;
    502 	scbP[IVEC_VF/4] = &vsbus_ivtab[3].intr_vec;
    503 	scbP[IVEC_NS/4] = &vsbus_ivtab[4].intr_vec;
    504 	scbP[IVEC_NP/4] = &vsbus_ivtab[5].intr_vec;
    505 	scbP[IVEC_ST/4] = &vsbus_ivtab[6].intr_vec;
    506 	scbP[IVEC_SR/4] = &vsbus_ivtab[7].intr_vec;
    507 }
    508 
    509 /*
    510  *
    511  *
    512  */
    513 
    514 static volatile struct dma_lock {
    515 	int	dl_locked;
    516 	int	dl_wanted;
    517 	void	*dl_owner;
    518 	int	dl_count;
    519 } dmalock = { 0, 0, NULL, 0 };
    520 
    521 int
    522 vsbus_lockDMA(ca)
    523 	struct confargs *ca;
    524 {
    525 	while (dmalock.dl_locked) {
    526 		dmalock.dl_wanted++;
    527 		sleep((caddr_t)&dmalock, PRIBIO);	/* PLOCK or PRIBIO ? */
    528 		dmalock.dl_wanted--;
    529 	}
    530 	dmalock.dl_locked++;
    531 	dmalock.dl_owner = ca;
    532 
    533 	/*
    534 	 * no checks yet, no timeouts, nothing...
    535 	 */
    536 
    537 #ifdef DEBUG
    538 	if ((++dmalock.dl_count % 1000) == 0)
    539 		printf("%d locks, owner: %s\n", dmalock.dl_count, ca->ca_name);
    540 #endif
    541 	return (0);
    542 }
    543 
    544 int
    545 vsbus_unlockDMA(ca)
    546 	struct confargs *ca;
    547 {
    548 	if (dmalock.dl_locked != 1 || dmalock.dl_owner != ca) {
    549 		printf("locking-problem: %d, %s\n", dmalock.dl_locked,
    550 		       (dmalock.dl_owner ? dmalock.dl_owner : "null"));
    551 		dmalock.dl_locked = 0;
    552 		return (-1);
    553 	}
    554 	dmalock.dl_owner = NULL;
    555 	dmalock.dl_locked = 0;
    556 	if (dmalock.dl_wanted) {
    557 		wakeup((caddr_t)&dmalock);
    558 	}
    559 	return (0);
    560 }
    561 
    562 /*----------------------------------------------------------------------*/
    563 #if 0
    564 /*
    565  * small set of routines needed for mapping when doing pseudo-DMA,
    566  * quasi-DMA or virtual-DMA (choose whatever name you like).
    567  *
    568  * Once I know how VS3100 is doing real DMA (I hope it does), this
    569  * should be rewritten to present a general interface...
    570  *
    571  */
    572 
    573 extern u_long uVAX_physmap;
    574 
    575 u_long
    576 vsdma_mapin(bp, len)
    577 	struct buf *bp;
    578 	int len;
    579 {
    580 	pt_entry_t *pte;	/* pointer to Page-Table-Entry */
    581 	struct pcb *pcb;	/* pointer to Process-Controll-Block */
    582 	pt_entry_t *xpte;
    583 	caddr_t addr;
    584 	int pgoff;		/* offset into 1st page */
    585 	int pgcnt;		/* number of pages needed */
    586 	int pfnum;
    587 	int i;
    588 
    589 	trace(("mapin(bp=%x, bp->data=%x)\n", bp, bp->b_data));
    590 
    591 	addr = bp->b_data;
    592 	pgoff = (int)bp->b_data & PGOFSET;	/* get starting offset */
    593 	pgcnt = btoc(bp->b_bcount + pgoff) + 1; /* one more than needed */
    594 
    595 	/*
    596 	 * Get a pointer to the pte pointing out the first virtual address.
    597 	 * Use different ways in kernel and user space.
    598 	 */
    599 	if ((bp->b_flags & B_PHYS) == 0) {
    600 		pte = kvtopte(addr);
    601 	} else {
    602 		pcb = bp->b_proc->p_vmspace->vm_pmap.pm_pcb;
    603 		pte = uvtopte(addr, pcb);
    604 	}
    605 
    606 	/*
    607 	 * When we are doing DMA to user space, be sure that all pages
    608 	 * we want to transfer to are mapped. WHY DO WE NEED THIS???
    609 	 * SHOULDN'T THEY ALWAYS BE MAPPED WHEN DOING THIS???
    610 	 */
    611 	for (i=0; i<(pgcnt-1); i++) {
    612 		if ((pte + i)->pg_pfn == 0) {
    613 			int rv;
    614 			rv = vm_fault(&bp->b_proc->p_vmspace->vm_map,
    615 				      (unsigned)addr + i * NBPG,
    616 				      VM_PROT_READ|VM_PROT_WRITE, FALSE);
    617 			if (rv)
    618 				panic("vs-DMA to nonexistent page, %d", rv);
    619 		}
    620 	}
    621 
    622 	/*
    623 	 * now insert new mappings for this memory area into kernel's
    624 	 * mapping-table
    625 	 */
    626 	xpte = kvtopte(uVAX_physmap);
    627 	while (--pgcnt > 0) {
    628 		pfnum = pte->pg_pfn;
    629 		if (pfnum == 0)
    630 			panic("vsbus: zero entry");
    631 		*(int *)xpte++ = *(int *)pte++;
    632 	}
    633 	*(int *)xpte = 0;	/* mark last mapped page as invalid! */
    634 
    635 	debug(("uVAX: 0x%x\n", uVAX_physmap + pgoff));
    636 
    637 	return (uVAX_physmap + pgoff);	/* ??? */
    638 }
    639 #endif
    640 /*----------------------------------------------------------------------*/
    641 /*
    642  * Here follows some currently(?) unused stuff. Someday this should be removed
    643  */
    644 
    645 #if 0
    646 /*
    647  * Configure devices on VS2000/KA410 directly attached to vsbus
    648  */
    649 void
    650 ka410_attach(parent, self, aux)
    651 	struct device *parent;
    652 	struct device *self;
    653 	void *aux;
    654 {
    655 	struct confargs *ca;
    656 	int i;
    657 
    658 	for (i=0; i<KA410_MAXDEVS; i++) {
    659 		ca = &ka410_devs[i];
    660 		if (*ca->ca_name == '\0')
    661 			break;
    662 		config_found(self, (void*)ca, vsbus_print);
    663 	}
    664 	/*
    665 	 * as long as there's no real DZ-driver, we used this dummy
    666 	 */
    667 	vsbus_intr_register(&ka410_devs[0], ka410_consRecv_intr, NULL);
    668 	vsbus_intr_register(&ka410_devs[1], ka410_consXmit_intr, NULL);
    669 }
    670 
    671 #endif
    672