1*49115Swilliam /*- 2*49115Swilliam * Copyright (c) 1990 The Regents of the University of California. 3*49115Swilliam * All rights reserved. 4*49115Swilliam * 5*49115Swilliam * This code is derived from software contributed to Berkeley by 6*49115Swilliam * William Jolitz. 7*49115Swilliam * 8*49115Swilliam * %sccs.include.redist% 9*49115Swilliam * 10*49115Swilliam * @(#)isa.c 1.4 (Berkeley) 05/04/91 11*49115Swilliam */ 12*49115Swilliam 1345546Sbill /* 1445546Sbill * code to manage AT bus 1545546Sbill */ 1645546Sbill 1745546Sbill #include "param.h" 1845546Sbill #include "systm.h" 1945546Sbill #include "conf.h" 2045546Sbill #include "file.h" 2145546Sbill #include "user.h" 2245546Sbill #include "buf.h" 2345546Sbill #include "uio.h" 2445624Sbill #include "syslog.h" 2545624Sbill #include "machine/segments.h" 26*49115Swilliam #include "i386/isa/isa_device.h" 27*49115Swilliam #include "i386/isa/icu.h" 2845546Sbill 2945624Sbill /* 3045624Sbill * Configure all ISA devices 3145624Sbill */ 3245624Sbill isa_configure() { 3345624Sbill struct isa_device *dvp; 3445624Sbill struct isa_driver *dp; 3545624Sbill 3645624Sbill splhigh(); 3745624Sbill INTREN(IRQ_SLAVE); 3845624Sbill for (dvp = isa_devtab_bio; config_isadev(dvp,&biomask); dvp++); 3945624Sbill for (dvp = isa_devtab_tty; config_isadev(dvp,&ttymask); dvp++); 4045624Sbill for (dvp = isa_devtab_net; config_isadev(dvp,&netmask); dvp++); 4145624Sbill for (dvp = isa_devtab_null; config_isadev(dvp,0); dvp++); 4245624Sbill #include "sl.h" 4345624Sbill #if NSL > 0 4445624Sbill netmask |= ttymask; 4545624Sbill ttymask |= netmask; 4645624Sbill #endif 4745624Sbill /* biomask |= ttymask ; can some tty devices use buffers? */ 4845624Sbill printf("biomask %x ttymask %x netmask %x\n", biomask, ttymask, netmask); 4945624Sbill splnone(); 5045624Sbill } 5145624Sbill 5245624Sbill /* 5345624Sbill * Configure an ISA device. 5445624Sbill */ 5545624Sbill config_isadev(isdp, mp) 5645624Sbill struct isa_device *isdp; 5745624Sbill int *mp; 5845624Sbill { 5945624Sbill struct isa_driver *dp; 6045624Sbill 6145624Sbill if (dp = isdp->id_driver) { 6245624Sbill if (isdp->id_maddr) { 63*49115Swilliam extern int atdevbase; 6445624Sbill 6545624Sbill isdp->id_maddr -= 0xa0000; 66*49115Swilliam isdp->id_maddr += atdevbase; 6745624Sbill } 6845624Sbill isdp->id_alive = (*dp->probe)(isdp); 6945624Sbill if (isdp->id_alive) { 7045624Sbill printf("%s%d", dp->name, isdp->id_unit); 7145624Sbill (*dp->attach)(isdp); 7245624Sbill printf(" at 0x%x ", isdp->id_iobase); 7345624Sbill if(isdp->id_irq) { 7445624Sbill int intrno; 7545624Sbill 7645624Sbill intrno = ffs(isdp->id_irq)-1; 7745624Sbill printf("irq %d ", intrno); 7845624Sbill INTREN(isdp->id_irq); 7945624Sbill if(mp)INTRMASK(*mp,isdp->id_irq); 8045624Sbill setidt(ICU_OFFSET+intrno, isdp->id_intr, 8145624Sbill SDT_SYS386IGT, SEL_KPL); 8245624Sbill } 8345624Sbill if (isdp->id_drq != -1) printf("drq %d ", isdp->id_drq); 8445624Sbill printf("on isa\n"); 8545624Sbill } 8645624Sbill return (1); 8745624Sbill } else return(0); 8845624Sbill } 8945624Sbill 9045624Sbill #define IDTVEC(name) X/**/name 9145624Sbill /* default interrupt vector table */ 9245624Sbill extern IDTVEC(intr0), IDTVEC(intr1), IDTVEC(intr2), IDTVEC(intr3), 9345624Sbill IDTVEC(intr4), IDTVEC(intr5), IDTVEC(intr6), IDTVEC(intr7), 9445624Sbill IDTVEC(intr8), IDTVEC(intr9), IDTVEC(intr10), IDTVEC(intr11), 9545624Sbill IDTVEC(intr12), IDTVEC(intr13), IDTVEC(intr14), IDTVEC(intr15); 9645624Sbill 9745624Sbill /* 9845624Sbill * Fill in default interrupt table (in case of spuruious interrupt 9945624Sbill * during configuration of kernel, setup interrupt control unit 10045624Sbill */ 10145624Sbill isa_defaultirq() { 10245624Sbill 10345624Sbill /* first icu */ 10445624Sbill setidt(32, &IDTVEC(intr0), SDT_SYS386IGT, SEL_KPL); 10545624Sbill setidt(33, &IDTVEC(intr1), SDT_SYS386IGT, SEL_KPL); 10645624Sbill setidt(34, &IDTVEC(intr2), SDT_SYS386IGT, SEL_KPL); 10745624Sbill setidt(35, &IDTVEC(intr3), SDT_SYS386IGT, SEL_KPL); 10845624Sbill setidt(36, &IDTVEC(intr4), SDT_SYS386IGT, SEL_KPL); 10945624Sbill setidt(37, &IDTVEC(intr5), SDT_SYS386IGT, SEL_KPL); 11045624Sbill setidt(38, &IDTVEC(intr6), SDT_SYS386IGT, SEL_KPL); 11145624Sbill setidt(39, &IDTVEC(intr7), SDT_SYS386IGT, SEL_KPL); 11245624Sbill 11345624Sbill /* second icu */ 11445624Sbill setidt(40, &IDTVEC(intr8), SDT_SYS386IGT, SEL_KPL); 11545624Sbill setidt(41, &IDTVEC(intr9), SDT_SYS386IGT, SEL_KPL); 11645624Sbill setidt(42, &IDTVEC(intr10), SDT_SYS386IGT, SEL_KPL); 11745624Sbill setidt(43, &IDTVEC(intr11), SDT_SYS386IGT, SEL_KPL); 11845624Sbill setidt(44, &IDTVEC(intr12), SDT_SYS386IGT, SEL_KPL); 11945624Sbill setidt(45, &IDTVEC(intr13), SDT_SYS386IGT, SEL_KPL); 12045624Sbill setidt(46, &IDTVEC(intr14), SDT_SYS386IGT, SEL_KPL); 12145624Sbill setidt(47, &IDTVEC(intr15), SDT_SYS386IGT, SEL_KPL); 12245624Sbill 12345624Sbill /* initialize 8259's */ 12445624Sbill outb(0xf1,0); 12545624Sbill outb(0x20,0x11); 12645624Sbill outb(0x21,32); 12745624Sbill outb(0x21,4); 12845624Sbill outb(0x21,1); 12945624Sbill outb(0x21,0xff); 13045624Sbill 13145624Sbill outb(0xa0,0x11); 13245624Sbill outb(0xa1,40); 13345624Sbill outb(0xa1,2); 13445624Sbill outb(0xa1,1); 13545624Sbill outb(0xa1,0xff); 13645624Sbill } 13745624Sbill 13845546Sbill /* stuff needed for virtual to physical calculations */ 13945546Sbill extern char Sysbase; 14045546Sbill static unsigned long sbase = (unsigned long) &Sysbase; 14145546Sbill 14245546Sbill struct buf *dma_bounce[8]; 14345546Sbill #define MAXDMASZ 512 14445546Sbill 14545546Sbill /* XXX temporary */ 14645546Sbill kernel_space(x) 14745546Sbill unsigned long x; 14845546Sbill { 14945546Sbill if ((x >= sbase) & (x < sbase + 0x800000)) return 1; 15045546Sbill else return 0; 15145546Sbill } 15245546Sbill 15345546Sbill 15445546Sbill /****************************************************************************/ 15545546Sbill /* at_dma */ 15645546Sbill /* set up DMA read/write operation and virtual address addr for nbytes */ 15745546Sbill /****************************************************************************/ 15845546Sbill at_dma(read,addr,nbytes, chan) 15945546Sbill int read; 16045546Sbill unsigned long addr; 16145546Sbill int nbytes; 16245546Sbill { 16345546Sbill unsigned long phys; 16445546Sbill int s,raw; 16545546Sbill caddr_t bounce; 16645546Sbill 16745546Sbill if (kernel_space(addr)) raw = 0; 16845546Sbill else raw = 1; 16945546Sbill 17045546Sbill if(raw) { 17145546Sbill if (dma_bounce[chan] == 0) 17245546Sbill dma_bounce[chan] = geteblk(MAXDMASZ); 17345546Sbill bounce = dma_bounce[chan]->b_un.b_addr; 17445546Sbill } 17545546Sbill 17645546Sbill /* copy bounce buffer on write */ 17745546Sbill if (raw && !read) bcopy(addr,bounce,nbytes); 17845546Sbill 17945546Sbill /* Set read/write bytes */ 18045546Sbill if (read) { 18145546Sbill outb(0xC,0x46); outb(0xB,0x46); 18245546Sbill } else { 18345546Sbill outb(0xC,0x4A); outb(0xB,0x4A); 18445546Sbill } 18545546Sbill /* Send start address */ 18645546Sbill if (raw) phys = (unsigned long) bounce; 18745546Sbill else phys = addr; 18845546Sbill /* translate to physical */ 18945546Sbill phys = phys - sbase; 19045546Sbill outb(0x4,phys & 0xFF); 19145546Sbill outb(0x4,(phys>>8) & 0xFF); 19245546Sbill outb(0x81,(phys>>16) & 0xFF); 19345546Sbill /* Send count */ 19445546Sbill nbytes--; 19545546Sbill outb(0x5,nbytes & 0xFF); 19645546Sbill outb(0x5,(nbytes>>8) & 0xFF); 19745546Sbill /* set channel 2 */ 19845546Sbill outb(0x0A,chan); 19945546Sbill } 20045624Sbill 20145624Sbill /* 20245624Sbill * Handle a NMI, possibly a machine check. 20345624Sbill * return true to panic system, false to ignore. 20445624Sbill */ 20545624Sbill isa_nmi(cd) { 20645624Sbill 20745624Sbill log(LOG_CRIT, "\nNMI port 61 %x, port 70 %x\n", inb(0x61), inb(0x70)); 20845624Sbill return(0); 20945624Sbill } 21045624Sbill 21145624Sbill /* 21245624Sbill * Caught a stray interrupt, notify 21345624Sbill */ 21445624Sbill isa_strayintr(d) { 21545624Sbill 21645624Sbill /* for some reason, we get bursts of intr #7, even if not enabled! */ 21745624Sbill log(LOG_ERR,"ISA strayintr %d", ffs(d)-1); 21845624Sbill } 219