1 /*
2 * Copyright (c) 1992, 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 * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
7 *
8 * %sccs.include.redist.c%
9 *
10 * from: $Hdr: iop.c,v 4.300 91/06/09 06:42:37 root Rel41 $ SONY
11 *
12 * @(#)iop.c 8.1 (Berkeley) 06/11/93
13 */
14
15 /*
16 * iop.c / hb.c ver 0.0
17 */
18
19 #include <machine/machConst.h>
20
21 #include <sys/param.h>
22 #include <sys/systm.h>
23 #include <sys/map.h>
24 #include <sys/buf.h>
25 #include <sys/proc.h>
26 #include <sys/user.h>
27 #include <sys/conf.h>
28 #include <sys/dkstat.h>
29 #include <sys/kernel.h>
30 #include <sys/malloc.h>
31
32 #include <machine/pte.h>
33 #include <machine/cpu.h>
34
35 #include <news3400/iodev/scsireg.h>
36
37 #ifdef CPU_DOUBLE
38 #include "../iop/iopvar.h"
39 #endif
40
41 #ifdef CPU_SINGLE
42 #include <news3400/hbdev/hbvar.h>
43 #include <news3400/hbdev/scsic.h>
44 struct scsi_stat scsi_stat;
45 #endif
46
47 /*
48 * dual processor ===> single processor
49 */
50 #ifdef CPU_SINGLE
51 # define iopreset hbreset
52 # define iopbuf hbbuf
53 # define iopalloc hballoc
54 # define iopsetup hbsetup
55 # define iop_ctlr hb_ctlr
56 # define iop_device hb_device
57 # define iopgo hbgo
58
59 # define im_driver hm_driver
60 # define im_ctlr hm_ctlr
61 # define im_alive hm_alive
62 # define im_addr hm_addr
63 # define im_intr hm_intr
64 # define im_scnum hm_scnum
65 # define im_hd hm_hd
66 # define im_hbinfo hm_hbinfo
67 # define im_tab hm_tab
68
69 # define ii_driver hi_driver
70 # define ii_unit hi_unit
71 # define ii_ctlr hi_ctlr
72 # define ii_slave hi_slave
73 # define ii_addr hi_addr
74 # define ii_intr hi_intr
75 # define ii_dk hi_dk
76 # define ii_flags hi_flags
77 # define ii_alive hi_alive
78 # define ii_type hi_type
79 # define ii_forw hi_forw
80 # define ii_mi hi_mi
81 # define ii_hd hi_hd
82
83 # define id_dgo hd_dgo
84 #endif /* CPU_SINGLE */
85
iopgo(ii,map)86 iopgo(ii, map)
87 register struct iop_device *ii;
88 struct sc_map *map;
89 {
90 register struct iop_ctlr *im = ii->ii_mi;
91 register int unit;
92 int s;
93
94 s = spl6();
95 if (map)
96 (void)iopsetup(im->im_tab.b_actf->b_actf, map, NSCMAP);
97 splx(s);
98 if (ii->ii_dk >= 0) {
99 unit = ii->ii_dk;
100 dk_busy |= 1<<unit;
101 dk_xfer[unit]++;
102 dk_wds[unit] += im->im_tab.b_actf->b_actf->b_bcount>>6;
103 }
104 if (im->im_driver->id_dgo)
105 (*im->im_driver->id_dgo)(im);
106 }
107
iopsetup(bp,map,nmap)108 iopsetup(bp, map, nmap)
109 register struct buf *bp;
110 struct sc_map *map;
111 int nmap;
112 {
113 register struct pte *pte;
114 register unsigned *io;
115 int o, npf;
116
117 o = (int)bp->b_un.b_addr & PGOFSET;
118 map->mp_offset = o;
119 npf = btoc(bp->b_bcount + o);
120 if (npf > nmap)
121 panic("sc_map setup: bcount too large");
122 map->mp_pages = npf;
123 io = map->mp_addr;
124 #ifdef mips
125 if (MACH_IS_UNMAPPED(bp->b_un.b_addr)) {
126 int i;
127
128 for (i = 0; npf-- > 0; i++)
129 *io++ = ((MACH_UNMAPPED_TO_PHYS(bp->b_un.b_addr))
130 >> PGSHIFT) + i;
131 return (1);
132 }
133 else if ((bp->b_un.b_addr >= (caddr_t)VM_MIN_KERNEL_ADDRESS) &&
134 (bp->b_un.b_addr < (caddr_t)VM_MAX_KERNEL_ADDRESS)) {
135 pte = (struct pte*)kvtopte(bp->b_un.b_addr);
136 while (--npf >= 0) {
137 if (pte->pg_pfnum == 0)
138 panic("sc_map setup: zero pfnum");
139 *io++ = pte++->pg_pfnum;
140 }
141 return (1);
142 }
143 else {
144 panic("iopsetup: user address is not allowed");
145 }
146 #else /* mips */
147 ERROR! This code does not work. /* KU:XXX */
148 pte = buftopte(bp);
149 while (--npf >= 0) {
150 if (pte->pg_pfnum == 0)
151 panic("sc_map setup: zero pfnum");
152 *io++ = pte++->pg_pfnum;
153 }
154 return (1);
155 #endif /* mips */
156 }
157
iopalloc(addr,bcnt,map,nmap)158 iopalloc(addr, bcnt, map, nmap)
159 caddr_t addr;
160 int bcnt, nmap;
161 struct sc_map *map;
162 {
163 struct buf iopbuf;
164
165 iopbuf.b_un.b_addr = addr;
166 iopbuf.b_flags = B_BUSY;
167 iopbuf.b_bcount = bcnt;
168 /* that's all the fields iopsetup() needs */
169 return (iopsetup(&iopbuf, map, nmap));
170 }
171
iopreset()172 iopreset()
173 {
174 register struct cdevsw *cdp;
175 int s;
176
177 #ifdef CPU_DOUBLE
178 s = spl6();
179 printf("iop: reset");
180 for (cdp = cdevsw; cdp < cdevsw + nchrdev; cdp++)
181 (*cdp->d_reset)();
182 printf("\n");
183 splx(s);
184 #endif
185 #ifdef CPU_SINGLE
186 printf("hb: reset");
187 for (cdp = cdevsw; cdp < cdevsw + nchrdev; cdp++)
188 (*cdp->d_reset)();
189 printf("\n");
190 #endif
191 }
192
193 #ifdef CPU_SINGLE
scsend(chan,flag,sc)194 scsend(chan, flag, sc)
195 int chan;
196 int flag;
197 struct scsi *sc;
198 {
199 register int i;
200
201 sc_send(chan, flag, sc);
202 if (flag & SCSI_NOTWAIT)
203 return;
204 if ((flag & SCSI_INTEN) == 0) {
205 for (i = 0; i < 2000000; i++)
206 if (!sc_busy(chan))
207 return;
208 printf("SCSI: scsend() timeout: intr=0x%x, ie=0x%x, sc=0x%x\n",
209 chan, flag, sc);
210 }
211 }
212 #endif /* CPU_SINGLE */
213
214 #ifdef CPU_SINGLE
215 /*kos000*/
216 int
217 on_iobusintr2(func, arg, pri)
218 int (*func)();
219 int arg;
220 int pri;
221 {
222 register_hb_intr2(func, arg, pri);
223 }
224
225 int
226 on_iobusintr4(func, arg, pri)
227 int (*func)();
228 int arg;
229 int pri;
230 {
231 register_hb_intr4(func, arg, pri);
232 }
233 /*kos000*/
234
235 /*kos111*/
236 struct hb_intr {
237 struct hb_intr *forw;
238 struct hb_intr *back;
239 int pri;
240 int (*func)();
241 int arg;
242 };
243
244 struct hb_intr hb_intr2;
245 struct hb_intr hb_intr4;
246
init_hb_intr()247 init_hb_intr()
248 {
249 init_hb_intr2();
250 init_hb_intr4();
251 }
252
init_hb_intr2()253 init_hb_intr2()
254 {
255 hb_intr2.forw = hb_intr2.back = &hb_intr2;
256 hb_intr2.pri = 32767;
257 hb_intr2.func = 0;
258 hb_intr2.arg = 0;
259 }
260
init_hb_intr4()261 init_hb_intr4()
262 {
263 hb_intr4.forw = hb_intr4.back = &hb_intr4;
264 hb_intr4.pri = 32767;
265 hb_intr4.func = 0;
266 hb_intr4.arg = 0;
267 }
268
269 register_hb_intr2(func, arg, pri)
270 int (*func)();
271 int arg;
272 int pri;
273 {
274 register struct hb_intr *p, *q;
275 register int s = splclock();
276
277 p = malloc(sizeof (struct hb_intr), M_DEVBUF, M_WAITOK);
278 p->pri = pri;
279 p->func = func;
280 p->arg = arg;
281
282 for (q = hb_intr2.forw; q != &hb_intr2; q = q->forw)
283 if (p->pri < q->pri)
284 break;
285 insque(p, q->back);
286
287 splx(s);
288 }
289
290 unregister_hb_intr2(func)
291 int (*func)();
292 {
293 register struct hb_intr *p, *q;
294 register int s = splclock();
295
296 for (p = hb_intr2.forw; p != &hb_intr2; p = p->forw) {
297 if (p->func == func) {
298 remque(p);
299 free((caddr_t)p, M_DEVBUF);
300 break;
301 }
302 }
303
304 splx(s);
305 }
306
307 register_hb_intr4(func, arg, pri)
308 int (*func)();
309 int arg;
310 int pri;
311 {
312 register struct hb_intr *p, *q;
313 register int s = splclock();
314
315 p = malloc(sizeof (struct hb_intr), M_DEVBUF, M_WAITOK);
316 p->pri = pri;
317 p->func = func;
318 p->arg = arg;
319
320 for (q = hb_intr4.forw; q != &hb_intr4; q = q->forw)
321 if (p->pri < q->pri)
322 break;
323 insque(p, q->back);
324
325 splx(s);
326 }
327
328 unregister_hb_intr4(func)
329 int (*func)();
330 {
331 register struct hb_intr *p, *q;
332 register int s = splclock();
333
334 for (p = hb_intr4.forw; p != &hb_intr4; p = p->forw) {
335 if (p->func == func) {
336 remque(p);
337 free((caddr_t)p, M_DEVBUF);
338 break;
339 }
340 }
341
342 splx(s);
343 }
344
345 extern struct vmmeter cnt;
346
exec_hb_intr2()347 exec_hb_intr2()
348 {
349 register struct hb_intr *p;
350
351 for (p = hb_intr2.forw; p != &hb_intr2; p = p->forw) {
352 if ((int)p->func == 0)
353 goto out;
354
355 if ((*(p->func))(p->arg)) {
356 cnt.v_intr++; /* statistics info. */
357 return;
358 }
359 }
360 out:
361 #ifdef news3400
362 return;
363 #else
364 printf("stray hb intr 2\n");
365 #endif
366 }
367
exec_hb_intr4()368 exec_hb_intr4()
369 {
370 register struct hb_intr *p;
371
372 for (p = hb_intr4.forw; p != &hb_intr4; p = p->forw) {
373 if ((int)p->func == 0)
374 goto out;
375
376 if ((*(p->func))(p->arg)) {
377 cnt.v_intr++; /* statistics info. */
378 return;
379 }
380 }
381 out:
382 #ifdef news3400
383 return;
384 #else
385 printf("stray hb intr 4\n");
386 #endif
387 }
388 /*kos111*/
389 #endif /* CPU_SINGLE */
390