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