1 /*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * William Jolitz.
7 *
8 * %sccs.include.redist.c%
9 *
10 * @(#)isa.c 8.1 (Berkeley) 06/11/93
11 */
12
13 /*
14 * code to manage AT bus
15 */
16
17 #include <sys/param.h>
18 #include <sys/systm.h>
19 #include <sys/conf.h>
20 #include <sys/file.h>
21 #include <sys/buf.h>
22 #include <sys/uio.h>
23 #include <sys/syslog.h>
24
25 #include <machine/segments.h>
26 #include <i386/isa/isa_device.h>
27 #include <i386/isa/icu.h>
28 #include <vm/vm.h>
29
30 /*
31 * Configure all ISA devices
32 */
isa_configure()33 isa_configure() {
34 struct isa_device *dvp;
35 struct isa_driver *dp;
36
37 splhigh();
38 INTREN(IRQ_SLAVE);
39 for (dvp = isa_devtab_bio; config_isadev(dvp,&biomask); dvp++);
40 for (dvp = isa_devtab_tty; config_isadev(dvp,&ttymask); dvp++);
41 for (dvp = isa_devtab_net; config_isadev(dvp,&netmask); dvp++);
42 for (dvp = isa_devtab_null; config_isadev(dvp,0); dvp++);
43 #include "sl.h"
44 #if NSL > 0
45 netmask |= ttymask;
46 ttymask |= netmask;
47 #endif
48
49 /*
50 * The problem is... if netmask == 0, then the loopback
51 * code can do some really ugly things.
52 * workaround for this: if netmask == 0, set it to 0x8000, which
53 * is the value used by splsoftclock. this is nasty, but it
54 * should work until this interrupt system goes away. -- cgd
55 */
56 if (netmask == 0)
57 netmask = 0x8000; /* same as for softclock. XXX */
58
59 /* biomask |= ttymask ; can some tty devices use buffers? */
60 printf("biomask %x ttymask %x netmask %x\n", biomask, ttymask, netmask);
61 splnone();
62 }
63
64 /*
65 * Configure an ISA device.
66 */
67 config_isadev(isdp, mp)
68 struct isa_device *isdp;
69 int *mp;
70 {
71 struct isa_driver *dp;
72
73 if (dp = isdp->id_driver) {
74 if (isdp->id_maddr) {
75 extern int atdevbase;
76
77 isdp->id_maddr -= 0xa0000;
78 isdp->id_maddr += atdevbase;
79 }
80 isdp->id_alive = (*dp->probe)(isdp);
81 if (isdp->id_alive) {
82 printf("%s%d", dp->name, isdp->id_unit);
83 (*dp->attach)(isdp);
84 printf(" at 0x%x ", isdp->id_iobase);
85 if(isdp->id_irq) {
86 int intrno;
87
88 intrno = ffs(isdp->id_irq)-1;
89 printf("irq %d ", intrno);
90 INTREN(isdp->id_irq);
91 if(mp)INTRMASK(*mp,isdp->id_irq);
92 setidt(ICU_OFFSET+intrno, isdp->id_intr,
93 SDT_SYS386IGT, SEL_KPL);
94 }
95 if (isdp->id_drq != -1) printf("drq %d ", isdp->id_drq);
96 printf("on isa\n");
97 }
98 return (1);
99 } else return(0);
100 }
101
102 #define IDTVEC(name) __CONCAT(X,name)
103 /* default interrupt vector table */
104 extern IDTVEC(intr0), IDTVEC(intr1), IDTVEC(intr2), IDTVEC(intr3),
105 IDTVEC(intr4), IDTVEC(intr5), IDTVEC(intr6), IDTVEC(intr7),
106 IDTVEC(intr8), IDTVEC(intr9), IDTVEC(intr10), IDTVEC(intr11),
107 IDTVEC(intr12), IDTVEC(intr13), IDTVEC(intr14), IDTVEC(intr15);
108
109 /*
110 * Fill in default interrupt table (in case of spuruious interrupt
111 * during configuration of kernel, setup interrupt control unit
112 */
isa_defaultirq()113 isa_defaultirq() {
114
115 /* first icu */
116 setidt(32, &IDTVEC(intr0), SDT_SYS386IGT, SEL_KPL);
117 setidt(33, &IDTVEC(intr1), SDT_SYS386IGT, SEL_KPL);
118 setidt(34, &IDTVEC(intr2), SDT_SYS386IGT, SEL_KPL);
119 setidt(35, &IDTVEC(intr3), SDT_SYS386IGT, SEL_KPL);
120 setidt(36, &IDTVEC(intr4), SDT_SYS386IGT, SEL_KPL);
121 setidt(37, &IDTVEC(intr5), SDT_SYS386IGT, SEL_KPL);
122 setidt(38, &IDTVEC(intr6), SDT_SYS386IGT, SEL_KPL);
123 setidt(39, &IDTVEC(intr7), SDT_SYS386IGT, SEL_KPL);
124
125 /* second icu */
126 setidt(40, &IDTVEC(intr8), SDT_SYS386IGT, SEL_KPL);
127 setidt(41, &IDTVEC(intr9), SDT_SYS386IGT, SEL_KPL);
128 setidt(42, &IDTVEC(intr10), SDT_SYS386IGT, SEL_KPL);
129 setidt(43, &IDTVEC(intr11), SDT_SYS386IGT, SEL_KPL);
130 setidt(44, &IDTVEC(intr12), SDT_SYS386IGT, SEL_KPL);
131 setidt(45, &IDTVEC(intr13), SDT_SYS386IGT, SEL_KPL);
132 setidt(46, &IDTVEC(intr14), SDT_SYS386IGT, SEL_KPL);
133 setidt(47, &IDTVEC(intr15), SDT_SYS386IGT, SEL_KPL);
134
135 /* initialize 8259's */
136 outb(0xf1,0);
137 outb(0x20,0x11);
138 outb(0x21,32);
139 outb(0x21,4);
140 outb(0x21,1);
141 outb(0x21,0xff);
142
143 outb(0xa0,0x11);
144 outb(0xa1,40);
145 outb(0xa1,2);
146 outb(0xa1,1);
147 outb(0xa1,0xff);
148 }
149
150 /* stuff needed for virtual to physical calculations */
151
152 struct buf *dma_bounce[8];
153 #define MAXDMASZ 512
154
155 /* XXX temporary crud */
kernel_space(x)156 kernel_space(x)
157 unsigned long x;
158 {
159 if (x >= KERNBASE) return 1;
160 else return 0;
161 }
162
163
164 /****************************************************************************/
165 /* at_dma */
166 /* set up DMA read/write operation and virtual address addr for nbytes */
167 /****************************************************************************/
at_dma(read,addr,nbytes,chan)168 at_dma(read,addr,nbytes, chan)
169 int read;
170 unsigned long addr;
171 int nbytes;
172 {
173 unsigned long phys;
174 int s,raw;
175 caddr_t bounce;
176
177 if (kernel_space(addr)) raw = 0;
178 else raw = 1;
179
180 if(raw) {
181 if (dma_bounce[chan] == 0)
182 dma_bounce[chan] = geteblk(MAXDMASZ);
183 bounce = dma_bounce[chan]->b_un.b_addr;
184 }
185
186 /* copy bounce buffer on write */
187 if (raw && !read) bcopy(addr,bounce,nbytes);
188
189 /* Set read/write bytes */
190 if (read) {
191 outb(0xC,0x46); outb(0xB,0x46);
192 } else {
193 outb(0xC,0x4A); outb(0xB,0x4A);
194 }
195 /* Send start address */
196 if (raw) phys = (unsigned long) bounce;
197 else phys = addr;
198 /* translate to physical */
199 phys = pmap_extract(kernel_pmap, (vm_offset_t)phys);
200 outb(0x4,phys & 0xFF);
201 outb(0x4,(phys>>8) & 0xFF);
202 outb(0x81,(phys>>16) & 0xFF);
203 /* Send count */
204 nbytes--;
205 outb(0x5,nbytes & 0xFF);
206 outb(0x5,(nbytes>>8) & 0xFF);
207 /* set channel 2 */
208 outb(0x0A,chan);
209 }
210
211 /*
212 * Handle a NMI, possibly a machine check.
213 * return true to panic system, false to ignore.
214 */
isa_nmi(cd)215 isa_nmi(cd) {
216
217 log(LOG_CRIT, "\nNMI port 61 %x, port 70 %x\n", inb(0x61), inb(0x70));
218 return(0);
219 }
220
221 /*
222 * Caught a stray interrupt, notify
223 */
isa_strayintr(d)224 isa_strayintr(d) {
225
226 /* for some reason, we get bursts of intr #7, even if not enabled! */
227 log(LOG_ERR,"ISA strayintr %d", ffs(d)-1);
228 }
229