change printf error messages to tprintf's.
[unix-history] / usr / src / sys / vax / mba / mba.c
CommitLineData
c0bb0291 1/* mba.c 6.3 84/09/25 */
b81fd3e8 2
443c8066
BJ
3#include "mba.h"
4#if NMBA > 0
b81fd3e8 5/*
d565635a 6 * Massbus driver, arbitrates a massbus among attached devices.
c0bb0291
KM
7 *
8 * OPTION:
9 * MTRDREV - Enable mag tape read backwards error recovery
b81fd3e8 10 */
961945a8
SL
11#include "../machine/pte.h"
12
969e52ef
JB
13#include "param.h"
14#include "systm.h"
15#include "dk.h"
16#include "buf.h"
17#include "conf.h"
18#include "dir.h"
19#include "user.h"
20#include "proc.h"
21#include "map.h"
c895c266 22#include "../vax/mtpr.h"
969e52ef 23#include "vm.h"
b5ad10c3 24
969e52ef
JB
25#include "mbareg.h"
26#include "mbavar.h"
c895c266 27
d565635a 28char mbsr_bits[] = MBSR_BITS;
b5ad10c3 29/*
b81fd3e8 30 * Start activity on a massbus device.
89bd2f01 31 * We are given the device's mba_device structure and activate
b81fd3e8
BJ
32 * the device via the unit start routine. The unit start
33 * routine may indicate that it is finished (e.g. if the operation
34 * was a ``sense'' on a tape drive), that the (multi-ported) unit
35 * is busy (we will get an interrupt later), that it started the
36 * unit (e.g. for a non-data transfer operation), or that it has
37 * set up a data transfer operation and we should start the massbus adaptor.
b5ad10c3 38 */
b81fd3e8 39mbustart(mi)
89bd2f01 40 register struct mba_device *mi;
b81fd3e8 41{
b81fd3e8
BJ
42 register struct buf *bp; /* i/o operation at head of queue */
43 register struct mba_hd *mhp; /* header for mba device is on */
44
b81fd3e8
BJ
45loop:
46 /*
47 * Get the first thing to do off device queue.
48 */
49 bp = mi->mi_tab.b_actf;
50 if (bp == NULL)
51 return;
0d7a9a27
SL
52 /*
53 * Make sure the drive is still there before starting it up.
54 */
55 if ((mi->mi_drv->mbd_dt & MBDT_TYPE) == 0) {
56 printf("%s%d: nonexistent\n", mi->mi_driver->md_dname,
57 dkunit(bp));
58 mi->mi_alive = 0;
59 mi->mi_tab.b_actf = bp->av_forw;
60 mi->mi_tab.b_active = 0;
61 mi->mi_tab.b_errcnt = 0;
62 bp->b_flags |= B_ERROR;
63 iodone(bp);
64 goto loop;
65 }
b81fd3e8
BJ
66 /*
67 * Let the drivers unit start routine have at it
68 * and then process the request further, per its instructions.
69 */
70 switch ((*mi->mi_driver->md_ustart)(mi)) {
71
72 case MBU_NEXT: /* request is complete (e.g. ``sense'') */
b81fd3e8 73 mi->mi_tab.b_active = 0;
cda4cdd4 74 mi->mi_tab.b_errcnt = 0;
b81fd3e8
BJ
75 mi->mi_tab.b_actf = bp->av_forw;
76 iodone(bp);
77 goto loop;
78
79 case MBU_DODATA: /* all ready to do data transfer */
b81fd3e8 80 /*
89bd2f01 81 * Queue the device mba_device structure on the massbus
b81fd3e8
BJ
82 * mba_hd structure for processing as soon as the
83 * data path is available.
84 */
85 mhp = mi->mi_hd;
86 mi->mi_forw = NULL;
87 if (mhp->mh_actf == NULL)
88 mhp->mh_actf = mi;
89 else
90 mhp->mh_actl->mi_forw = mi;
91 mhp->mh_actl = mi;
92 /*
93 * If data path is idle, start transfer now.
94 * In any case the device is ``active'' waiting for the
95 * data to transfer.
96 */
3dbaa9da 97 mi->mi_tab.b_active = 1;
b81fd3e8
BJ
98 if (mhp->mh_active == 0)
99 mbstart(mhp);
b81fd3e8
BJ
100 return;
101
102 case MBU_STARTED: /* driver started a non-data transfer */
b81fd3e8
BJ
103 /*
104 * Mark device busy during non-data transfer
105 * and count this as a ``seek'' on the device.
106 */
fc4d0a69 107 if (mi->mi_dk >= 0) {
b81fd3e8 108 dk_seek[mi->mi_dk]++;
fc4d0a69
BJ
109 dk_busy |= (1 << mi->mi_dk);
110 }
b81fd3e8
BJ
111 mi->mi_tab.b_active = 1;
112 return;
113
114 case MBU_BUSY: /* dual port drive busy */
b81fd3e8
BJ
115 /*
116 * We mark the device structure so that when an
117 * interrupt occurs we will know to restart the unit.
118 */
119 mi->mi_tab.b_flags |= B_BUSY;
120 return;
121
122 default:
123 panic("mbustart");
124 }
e1e57888 125}
b81fd3e8
BJ
126
127/*
128 * Start an i/o operation on the massbus specified by the argument.
129 * We peel the first operation off its queue and insure that the drive
130 * is present and on-line. We then use the drivers start routine
131 * (if any) to prepare the drive, setup the massbus map for the transfer
132 * and start the transfer.
133 */
134mbstart(mhp)
135 register struct mba_hd *mhp;
136{
89bd2f01 137 register struct mba_device *mi;
b81fd3e8 138 struct buf *bp;
b81fd3e8 139 register struct mba_regs *mbp;
7bd5c7e4 140 register int com;
b81fd3e8 141
b81fd3e8
BJ
142loop:
143 /*
144 * Look for an operation at the front of the queue.
145 */
cda4cdd4 146 if ((mi = mhp->mh_actf) == NULL) {
b81fd3e8 147 return;
cda4cdd4 148 }
b81fd3e8 149 if ((bp = mi->mi_tab.b_actf) == NULL) {
b81fd3e8
BJ
150 mhp->mh_actf = mi->mi_forw;
151 goto loop;
152 }
153 /*
154 * If this device isn't present and on-line, then
155 * we screwed up, and can't really do the operation.
64614526
BJ
156 * Only check for non-tapes because tape drivers check
157 * ONLINE themselves and because TU78 registers are
158 * different.
b81fd3e8 159 */
0d7a9a27 160 if (((com = mi->mi_drv->mbd_dt) & MBDT_TAP) == 0)
d565635a 161 if ((mi->mi_drv->mbd_ds & MBDS_DREADY) != MBDS_DREADY) {
0d7a9a27
SL
162 if ((com & MBDT_TYPE) == 0) {
163 mi->mi_alive = 0;
164 printf("%s%d: nonexistent\n", mi->mi_driver->md_dname,
165 dkunit(bp));
166 } else
167 printf("%s%d: not ready\n", mi->mi_driver->md_dname,
168 dkunit(bp));
b81fd3e8 169 mi->mi_tab.b_actf = bp->av_forw;
3dbaa9da
BJ
170 mi->mi_tab.b_errcnt = 0;
171 mi->mi_tab.b_active = 0;
b81fd3e8
BJ
172 bp->b_flags |= B_ERROR;
173 iodone(bp);
174 goto loop;
175 }
176 /*
177 * We can do the operation; mark the massbus active
178 * and let the device start routine setup any necessary
179 * device state for the transfer (e.g. desired cylinder, etc
180 * on disks).
181 */
182 mhp->mh_active = 1;
7bd5c7e4
BJ
183 if (mi->mi_driver->md_start) {
184 if ((com = (*mi->mi_driver->md_start)(mi)) == 0)
185 com = (bp->b_flags & B_READ) ?
186 MB_RCOM|MB_GO : MB_WCOM|MB_GO;
187 } else
188 com = (bp->b_flags & B_READ) ? MB_RCOM|MB_GO : MB_WCOM|MB_GO;
b81fd3e8
BJ
189
190 /*
191 * Setup the massbus control and map registers and start
192 * the transfer.
193 */
b81fd3e8
BJ
194 mbp = mi->mi_mba;
195 mbp->mba_sr = -1; /* conservative */
c0bb0291
KM
196#ifdef MTRDREV
197 if (bp->b_bcount >= 0) {
198 mbp->mba_var = mbasetup(mi);
199 mbp->mba_bcr = -bp->b_bcount;
200 } else {
201 mbp->mba_var = mbasetup(mi) - bp->b_bcount - 1;
202 mbp->mba_bcr = bp->b_bcount;
203 }
204#else
b81fd3e8
BJ
205 mbp->mba_var = mbasetup(mi);
206 mbp->mba_bcr = -bp->b_bcount;
c0bb0291 207#endif
7bd5c7e4 208 mi->mi_drv->mbd_cs1 = com;
b81fd3e8
BJ
209 if (mi->mi_dk >= 0) {
210 dk_busy |= 1 << mi->mi_dk;
211 dk_xfer[mi->mi_dk]++;
c0bb0291
KM
212#ifdef MTRDREV
213 if (bp->b_bcount >= 0)
214 dk_wds[mi->mi_dk] += bp->b_bcount >> 6;
215 else
216 dk_wds[mi->mi_dk] += -(bp->b_bcount) >> 6;
217#else
b81fd3e8 218 dk_wds[mi->mi_dk] += bp->b_bcount >> 6;
c0bb0291 219#endif
b81fd3e8
BJ
220 }
221}
b5ad10c3 222
b81fd3e8
BJ
223/*
224 * Take an interrupt off of massbus mbanum,
225 * and dispatch to drivers as appropriate.
226 */
227mbintr(mbanum)
228 int mbanum;
229{
230 register struct mba_hd *mhp = &mba_hd[mbanum];
231 register struct mba_regs *mbp = mhp->mh_mba;
89bd2f01 232 register struct mba_device *mi;
80e7c811 233 register struct buf *bp;
b81fd3e8 234 register int drive;
cda4cdd4 235 int mbasr, as;
0d7a9a27 236 extern struct mba_device *mbaconfig();
b81fd3e8
BJ
237
238 /*
239 * Read out the massbus status register
240 * and attention status register and clear
241 * the bits in same by writing them back.
242 */
cda4cdd4
BJ
243 mbasr = mbp->mba_sr;
244 mbp->mba_sr = mbasr;
c9e9b65b 245#if VAX750
d565635a 246 if (mbasr&MBSR_CBHUNG) {
16e4017f
BJ
247 printf("mba%d: control bus hung\n", mbanum);
248 panic("cbhung");
249 }
c9e9b65b 250#endif
b81fd3e8 251 /* note: the mbd_as register is shared between drives */
cda4cdd4 252 as = mbp->mba_drv[0].mbd_as & 0xff;
b81fd3e8 253 mbp->mba_drv[0].mbd_as = as;
b81fd3e8 254
b81fd3e8
BJ
255 /*
256 * If the mba was active, process the data transfer
257 * complete interrupt; otherwise just process units which
258 * are now finished.
259 */
260 if (mhp->mh_active) {
b81fd3e8
BJ
261 /*
262 * Clear attention status for drive whose data
d565635a
BJ
263 * transfer related operation completed,
264 * and give the dtint driver
b81fd3e8
BJ
265 * routine a chance to say what is next.
266 */
267 mi = mhp->mh_actf;
268 as &= ~(1 << mi->mi_drive);
269 dk_busy &= ~(1 << mi->mi_dk);
270 bp = mi->mi_tab.b_actf;
d565635a 271 switch ((*mi->mi_driver->md_dtint)(mi, mbasr)) {
b81fd3e8
BJ
272
273 case MBD_DONE: /* all done, for better or worse */
b81fd3e8
BJ
274 /*
275 * Flush request from drive queue.
276 */
277 mi->mi_tab.b_errcnt = 0;
278 mi->mi_tab.b_actf = bp->av_forw;
279 iodone(bp);
280 /* fall into... */
281 case MBD_RETRY: /* attempt the operation again */
b81fd3e8
BJ
282 /*
283 * Dequeue data transfer from massbus queue;
284 * if there is still a i/o request on the device
285 * queue then start the next operation on the device.
286 * (Common code for DONE and RETRY).
287 */
288 mhp->mh_active = 0;
289 mi->mi_tab.b_active = 0;
290 mhp->mh_actf = mi->mi_forw;
291 if (mi->mi_tab.b_actf)
292 mbustart(mi);
293 break;
294
295 case MBD_RESTARTED: /* driver restarted op (ecc, e.g.)
b81fd3e8 296 /*
3dbaa9da 297 * Note that mhp->mh_active is still on.
b81fd3e8
BJ
298 */
299 break;
300
301 default:
c9e9b65b 302 panic("mbintr");
b81fd3e8 303 }
b81fd3e8 304 }
b81fd3e8
BJ
305 /*
306 * Service drives which require attention
307 * after non-data-transfer operations.
308 */
cda4cdd4
BJ
309 while (drive = ffs(as)) {
310 drive--; /* was 1 origin */
311 as &= ~(1 << drive);
89bd2f01 312 mi = mhp->mh_mbip[drive];
0d7a9a27
SL
313 if (mi == NULL || mi->mi_alive == 0) {
314 struct mba_device fnd;
0d7a9a27
SL
315 struct mba_drv *mbd = &mhp->mh_mba->mba_drv[drive];
316 int dt = mbd->mbd_dt & 0xffff;
317
318 if (dt == 0 || dt == MBDT_MOH)
319 continue;
320 fnd.mi_mba = mhp->mh_mba;
321 fnd.mi_mbanum = mbanum;
322 fnd.mi_drive = drive;
323 if ((mi = mbaconfig(&fnd, dt)) == NULL)
324 continue;
bc1b7985
SL
325 /*
326 * If a tape, poke the slave attach routines.
327 * Otherwise, could be a disk which we want
328 * to swap on, so make a pass over the swap
329 * configuration table in case the size of
330 * the swap area must be determined by drive type.
331 */
332 if (dt & MBDT_TAP)
333 mbaddtape(mi, drive);
334 else
335 swapconf();
0d7a9a27 336 }
cda4cdd4 337 /*
89bd2f01 338 * If driver has a handler for non-data transfer
d565635a 339 * interrupts, give it a chance to tell us what to do.
cda4cdd4 340 */
cda4cdd4 341 if (mi->mi_driver->md_ndint) {
cda4cdd4 342 switch ((*mi->mi_driver->md_ndint)(mi)) {
b81fd3e8 343
d565635a 344 case MBN_DONE: /* operation completed */
0d7a9a27 345 mi->mi_tab.b_active = 0;
cda4cdd4 346 mi->mi_tab.b_errcnt = 0;
89bd2f01 347 bp = mi->mi_tab.b_actf;
cda4cdd4
BJ
348 mi->mi_tab.b_actf = bp->av_forw;
349 iodone(bp);
d565635a
BJ
350 /* fall into common code */
351 case MBN_RETRY: /* operation continues */
cda4cdd4
BJ
352 if (mi->mi_tab.b_actf)
353 mbustart(mi);
354 break;
d565635a 355 case MBN_SKIP: /* ignore unsol. interrupt */
89bd2f01 356 break;
cda4cdd4
BJ
357 default:
358 panic("mbintr");
359 }
360 } else
d565635a
BJ
361 /*
362 * If there is no non-data transfer interrupt
363 * routine, then we should just
364 * restart the unit, leading to a mbstart() soon.
365 */
cda4cdd4
BJ
366 mbustart(mi);
367 }
b81fd3e8
BJ
368 /*
369 * If there is an operation available and
370 * the massbus isn't active, get it going.
371 */
372 if (mhp->mh_actf && !mhp->mh_active)
373 mbstart(mhp);
d565635a 374 /* THHHHATS all folks... */
b81fd3e8
BJ
375}
376
bc1b7985
SL
377/*
378 * For autoconfig'ng tape drives on the fly.
379 */
bc1b7985
SL
380mbaddtape(mi, drive)
381 struct mba_device *mi;
382 int drive;
383{
384 register struct mba_slave *ms;
385
386 for (ms = mbsinit; ms->ms_driver; ms++)
387 if (ms->ms_driver == mi->mi_driver && ms->ms_alive == 0 &&
388 (ms->ms_ctlr == mi->mi_unit ||
389 ms->ms_ctlr == '?')) {
390 if ((*ms->ms_driver->md_slave)(mi, ms, drive)) {
391 printf("%s%d at %s%d slave %d\n",
392 ms->ms_driver->md_sname,
393 ms->ms_unit,
394 mi->mi_driver->md_dname,
395 mi->mi_unit,
396 ms->ms_slave);
397 ms->ms_alive = 1;
398 ms->ms_ctlr = mi->mi_unit;
399 }
400 }
401}
402
b81fd3e8
BJ
403/*
404 * Setup the mapping registers for a transfer.
405 */
406mbasetup(mi)
89bd2f01 407 register struct mba_device *mi;
b5ad10c3 408{
b81fd3e8
BJ
409 register struct mba_regs *mbap = mi->mi_mba;
410 struct buf *bp = mi->mi_tab.b_actf;
309cfbf4 411 register int npf;
b5ad10c3
BJ
412 unsigned v;
413 register struct pte *pte, *io;
414 int o;
b5ad10c3 415 struct proc *rp;
b5ad10c3 416
f9b6e695
BJ
417 v = btop(bp->b_un.b_addr);
418 o = (int)bp->b_un.b_addr & PGOFSET;
c0bb0291
KM
419#ifdef MTRDREV
420 if (bp->b_bcount >= 0)
421 npf = btoc(bp->b_bcount + o);
422 else
423 npf = btoc(-(bp->b_bcount) + o);
424#else
f9b6e695 425 npf = btoc(bp->b_bcount + o);
c0bb0291 426#endif
f9b6e695 427 rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc;
309cfbf4 428 if ((bp->b_flags & B_PHYS) == 0)
f9b6e695 429 pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)];
309cfbf4
BJ
430 else if (bp->b_flags & B_UAREA)
431 pte = &rp->p_addr[v];
432 else if (bp->b_flags & B_PAGET)
433 pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];
434 else
435 pte = vtopte(rp, v);
436 io = mbap->mba_map;
437 while (--npf >= 0) {
438 if (pte->pg_pfnum == 0)
439 panic("mba, zero entry");
440 *(int *)io++ = pte++->pg_pfnum | PG_V;
b5ad10c3 441 }
f9b6e695 442 *(int *)io++ = 0;
309cfbf4 443 return (o);
b5ad10c3 444}
16e4017f 445
a42d8a6b 446#if notdef
d565635a
BJ
447/*
448 * Init and interrupt enable a massbus adapter.
449 */
16e4017f
BJ
450mbainit(mp)
451 struct mba_regs *mp;
452{
453
d565635a
BJ
454 mp->mba_cr = MBCR_INIT;
455 mp->mba_cr = MBCR_IE;
16e4017f 456}
443c8066 457#endif
2752c877 458#endif