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