xref: /csrg-svn/sys/i386/isa/isa.c (revision 63364)
149115Swilliam /*-
2*63364Sbostic  * Copyright (c) 1991, 1993
3*63364Sbostic  *	The Regents of the University of California.  All rights reserved.
449115Swilliam  *
549115Swilliam  * This code is derived from software contributed to Berkeley by
649115Swilliam  * William Jolitz.
749115Swilliam  *
849617Sbostic  * %sccs.include.redist.c%
949115Swilliam  *
10*63364Sbostic  *	@(#)isa.c	8.1 (Berkeley) 06/11/93
1149115Swilliam  */
1249115Swilliam 
1345546Sbill /*
1445546Sbill  * code to manage AT bus
1545546Sbill  */
1645546Sbill 
1756513Sbostic #include <sys/param.h>
1856513Sbostic #include <sys/systm.h>
1956513Sbostic #include <sys/conf.h>
2056513Sbostic #include <sys/file.h>
2156513Sbostic #include <sys/buf.h>
2256513Sbostic #include <sys/uio.h>
2356513Sbostic #include <sys/syslog.h>
2445546Sbill 
2556513Sbostic #include <machine/segments.h>
2656513Sbostic #include <i386/isa/isa_device.h>
2756513Sbostic #include <i386/isa/icu.h>
2856513Sbostic #include <vm/vm.h>
2956513Sbostic 
3045624Sbill /*
3145624Sbill  * Configure all ISA devices
3245624Sbill  */
isa_configure()3345624Sbill isa_configure() {
3445624Sbill 	struct isa_device *dvp;
3545624Sbill 	struct isa_driver *dp;
3645624Sbill 
3745624Sbill 	splhigh();
3845624Sbill 	INTREN(IRQ_SLAVE);
3945624Sbill 	for (dvp = isa_devtab_bio; config_isadev(dvp,&biomask); dvp++);
4045624Sbill 	for (dvp = isa_devtab_tty; config_isadev(dvp,&ttymask); dvp++);
4145624Sbill 	for (dvp = isa_devtab_net; config_isadev(dvp,&netmask); dvp++);
4245624Sbill 	for (dvp = isa_devtab_null; config_isadev(dvp,0); dvp++);
4345624Sbill #include "sl.h"
4445624Sbill #if NSL > 0
4545624Sbill 	netmask |= ttymask;
4645624Sbill 	ttymask |= netmask;
4745624Sbill #endif
4859802Smckusick 
4959802Smckusick 	/*
5059802Smckusick 	 * The problem is... if netmask == 0, then the loopback
5159802Smckusick 	 * code can do some really ugly things.
5259802Smckusick 	 * workaround for this: if netmask == 0, set it to 0x8000, which
5359802Smckusick 	 * is the value used by splsoftclock.  this is nasty, but it
5459802Smckusick 	 * should work until this interrupt system goes away. -- cgd
5559802Smckusick 	 */
5659802Smckusick 	if (netmask == 0)
5759802Smckusick 		netmask = 0x8000;       /* same as for softclock.  XXX */
5859802Smckusick 
5945624Sbill 	/* biomask |= ttymask ;  can some tty devices use buffers? */
6045624Sbill 	printf("biomask %x ttymask %x netmask %x\n", biomask, ttymask, netmask);
6145624Sbill 	splnone();
6245624Sbill }
6345624Sbill 
6445624Sbill /*
6545624Sbill  * Configure an ISA device.
6645624Sbill  */
6745624Sbill config_isadev(isdp, mp)
6845624Sbill 	struct isa_device *isdp;
6945624Sbill 	int *mp;
7045624Sbill {
7145624Sbill 	struct isa_driver *dp;
7245624Sbill 
7345624Sbill 	if (dp = isdp->id_driver) {
7445624Sbill 		if (isdp->id_maddr) {
7549115Swilliam 			extern int atdevbase;
7645624Sbill 
7745624Sbill 			isdp->id_maddr -= 0xa0000;
7849115Swilliam 			isdp->id_maddr += atdevbase;
7945624Sbill 		}
8045624Sbill 		isdp->id_alive = (*dp->probe)(isdp);
8145624Sbill 		if (isdp->id_alive) {
8245624Sbill 			printf("%s%d", dp->name, isdp->id_unit);
8345624Sbill 			(*dp->attach)(isdp);
8445624Sbill 			printf(" at 0x%x ", isdp->id_iobase);
8545624Sbill 			if(isdp->id_irq) {
8645624Sbill 				int intrno;
8745624Sbill 
8845624Sbill 				intrno = ffs(isdp->id_irq)-1;
8945624Sbill 				printf("irq %d ", intrno);
9045624Sbill 				INTREN(isdp->id_irq);
9145624Sbill 				if(mp)INTRMASK(*mp,isdp->id_irq);
9245624Sbill 				setidt(ICU_OFFSET+intrno, isdp->id_intr,
9345624Sbill 					 SDT_SYS386IGT, SEL_KPL);
9445624Sbill 			}
9545624Sbill 			if (isdp->id_drq != -1) printf("drq %d ", isdp->id_drq);
9645624Sbill 			printf("on isa\n");
9745624Sbill 		}
9845624Sbill 		return (1);
9945624Sbill 	} else	return(0);
10045624Sbill }
10145624Sbill 
10249573Swilliam #define	IDTVEC(name)	__CONCAT(X,name)
10345624Sbill /* default interrupt vector table */
10445624Sbill extern	IDTVEC(intr0), IDTVEC(intr1), IDTVEC(intr2), IDTVEC(intr3),
10545624Sbill 	IDTVEC(intr4), IDTVEC(intr5), IDTVEC(intr6), IDTVEC(intr7),
10645624Sbill 	IDTVEC(intr8), IDTVEC(intr9), IDTVEC(intr10), IDTVEC(intr11),
10745624Sbill 	IDTVEC(intr12), IDTVEC(intr13), IDTVEC(intr14), IDTVEC(intr15);
10845624Sbill 
10945624Sbill /*
11045624Sbill  * Fill in default interrupt table (in case of spuruious interrupt
11145624Sbill  * during configuration of kernel, setup interrupt control unit
11245624Sbill  */
isa_defaultirq()11345624Sbill isa_defaultirq() {
11445624Sbill 
11545624Sbill /* first icu */
11645624Sbill 	setidt(32, &IDTVEC(intr0),  SDT_SYS386IGT, SEL_KPL);
11745624Sbill 	setidt(33, &IDTVEC(intr1),  SDT_SYS386IGT, SEL_KPL);
11845624Sbill 	setidt(34, &IDTVEC(intr2),  SDT_SYS386IGT, SEL_KPL);
11945624Sbill 	setidt(35, &IDTVEC(intr3),  SDT_SYS386IGT, SEL_KPL);
12045624Sbill 	setidt(36, &IDTVEC(intr4),  SDT_SYS386IGT, SEL_KPL);
12145624Sbill 	setidt(37, &IDTVEC(intr5),  SDT_SYS386IGT, SEL_KPL);
12245624Sbill 	setidt(38, &IDTVEC(intr6),  SDT_SYS386IGT, SEL_KPL);
12345624Sbill 	setidt(39, &IDTVEC(intr7),  SDT_SYS386IGT, SEL_KPL);
12445624Sbill 
12545624Sbill /* second icu */
12645624Sbill 	setidt(40, &IDTVEC(intr8),  SDT_SYS386IGT, SEL_KPL);
12745624Sbill 	setidt(41, &IDTVEC(intr9),  SDT_SYS386IGT, SEL_KPL);
12845624Sbill 	setidt(42, &IDTVEC(intr10),  SDT_SYS386IGT, SEL_KPL);
12945624Sbill 	setidt(43, &IDTVEC(intr11),  SDT_SYS386IGT, SEL_KPL);
13045624Sbill 	setidt(44, &IDTVEC(intr12),  SDT_SYS386IGT, SEL_KPL);
13145624Sbill 	setidt(45, &IDTVEC(intr13),  SDT_SYS386IGT, SEL_KPL);
13245624Sbill 	setidt(46, &IDTVEC(intr14),  SDT_SYS386IGT, SEL_KPL);
13345624Sbill 	setidt(47, &IDTVEC(intr15),  SDT_SYS386IGT, SEL_KPL);
13445624Sbill 
13545624Sbill 	/* initialize 8259's */
13645624Sbill 	outb(0xf1,0);
13745624Sbill 	outb(0x20,0x11);
13845624Sbill 	outb(0x21,32);
13945624Sbill 	outb(0x21,4);
14045624Sbill 	outb(0x21,1);
14145624Sbill 	outb(0x21,0xff);
14245624Sbill 
14345624Sbill 	outb(0xa0,0x11);
14445624Sbill 	outb(0xa1,40);
14545624Sbill 	outb(0xa1,2);
14645624Sbill 	outb(0xa1,1);
14745624Sbill 	outb(0xa1,0xff);
14845624Sbill }
14945624Sbill 
15045546Sbill /* stuff needed for virtual to physical calculations */
15145546Sbill 
15245546Sbill struct buf *dma_bounce[8];
15345546Sbill #define MAXDMASZ 512
15445546Sbill 
15549708Swilliam /* XXX temporary crud */
kernel_space(x)15645546Sbill kernel_space(x)
15745546Sbill unsigned long x;
15845546Sbill {
15949708Swilliam 	if (x >= KERNBASE) return 1;
16045546Sbill 	else return 0;
16145546Sbill }
16245546Sbill 
16345546Sbill 
16445546Sbill /****************************************************************************/
16545546Sbill /*                                 at_dma                                   */
16645546Sbill /* set up DMA read/write operation and virtual address addr for nbytes      */
16745546Sbill /****************************************************************************/
at_dma(read,addr,nbytes,chan)16845546Sbill at_dma(read,addr,nbytes, chan)
16945546Sbill int read;
17045546Sbill unsigned long addr;
17145546Sbill int nbytes;
17245546Sbill {
17345546Sbill 	unsigned long phys;
17445546Sbill 	int s,raw;
17545546Sbill 	caddr_t bounce;
17645546Sbill 
17745546Sbill 	if (kernel_space(addr)) raw = 0;
17845546Sbill 	else raw = 1;
17945546Sbill 
18045546Sbill 	if(raw) {
18145546Sbill 		if (dma_bounce[chan] == 0)
18245546Sbill 			dma_bounce[chan] = geteblk(MAXDMASZ);
18345546Sbill 		bounce = dma_bounce[chan]->b_un.b_addr;
18445546Sbill 	}
18545546Sbill 
18645546Sbill 	/* copy bounce buffer on write */
18745546Sbill 	if (raw && !read) bcopy(addr,bounce,nbytes);
18845546Sbill 
18945546Sbill 	/* Set read/write bytes */
19045546Sbill 	if (read) {
19145546Sbill 		outb(0xC,0x46); outb(0xB,0x46);
19245546Sbill 	} else {
19345546Sbill 		outb(0xC,0x4A); outb(0xB,0x4A);
19445546Sbill 	}
19545546Sbill 	/* Send start address */
19645546Sbill 	if (raw) phys = (unsigned long) bounce;
19745546Sbill 	else phys = addr;
19845546Sbill 	/* translate to physical */
19953407Sbostic 	phys = pmap_extract(kernel_pmap, (vm_offset_t)phys);
20045546Sbill 	outb(0x4,phys & 0xFF);
20145546Sbill 	outb(0x4,(phys>>8) & 0xFF);
20245546Sbill 	outb(0x81,(phys>>16) & 0xFF);
20345546Sbill 	/* Send count */
20445546Sbill 	nbytes--;
20545546Sbill 	outb(0x5,nbytes & 0xFF);
20645546Sbill 	outb(0x5,(nbytes>>8) & 0xFF);
20745546Sbill 	/* set channel 2 */
20845546Sbill 	outb(0x0A,chan);
20945546Sbill }
21045624Sbill 
21145624Sbill /*
21245624Sbill  * Handle a NMI, possibly a machine check.
21345624Sbill  * return true to panic system, false to ignore.
21445624Sbill  */
isa_nmi(cd)21545624Sbill isa_nmi(cd) {
21645624Sbill 
21745624Sbill 	log(LOG_CRIT, "\nNMI port 61 %x, port 70 %x\n", inb(0x61), inb(0x70));
21845624Sbill 	return(0);
21945624Sbill }
22045624Sbill 
22145624Sbill /*
22245624Sbill  * Caught a stray interrupt, notify
22345624Sbill  */
isa_strayintr(d)22445624Sbill isa_strayintr(d) {
22545624Sbill 
22645624Sbill 	/* for some reason, we get bursts of intr #7, even if not enabled! */
22745624Sbill 	log(LOG_ERR,"ISA strayintr %d", ffs(d)-1);
22845624Sbill }
229