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