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