|
|
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.2 (Berkeley) 2/19/87
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 "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: biodone(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: extern int cold;
134:
135: loop:
136: /*
137: * Look for an operation at the front of the queue.
138: */
139: if ((mi = mhp->mh_actf) == NULL) {
140: return;
141: }
142: if ((bp = mi->mi_tab.b_actf) == NULL) {
143: mhp->mh_actf = mi->mi_forw;
144: goto loop;
145: }
146: /*
147: * If this device isn't present and on-line, then
148: * we screwed up, and can't really do the operation.
149: * Only check for non-tapes because tape drivers check
150: * ONLINE themselves and because TU78 registers are
151: * different.
152: * No complaints during autoconfiguration,
153: * when we try to read disk labels from anything on line.
154: */
155: if (((com = mi->mi_drv->mbd_dt) & MBDT_TAP) == 0)
156: if ((mi->mi_drv->mbd_ds & MBDS_DREADY) != MBDS_DREADY) {
157: if (!cold) {
158: if ((com & MBDT_TYPE) == 0) {
159: mi->mi_alive = 0;
160: printf("%s%d: nonexistent\n", mi->mi_driver->md_dname,
161: mbunit(bp->b_dev));
162: } else
163: printf("%s%d: not ready\n", mi->mi_driver->md_dname,
164: mbunit(bp->b_dev));
165: }
166: mi->mi_tab.b_actf = bp->av_forw;
167: mi->mi_tab.b_errcnt = 0;
168: mi->mi_tab.b_active = 0;
169: bp->b_flags |= B_ERROR;
170: biodone(bp);
171: goto loop;
172: }
173: /*
174: * We can do the operation; mark the massbus active
175: * and let the device start routine setup any necessary
176: * device state for the transfer (e.g. desired cylinder, etc
177: * on disks).
178: */
179: mhp->mh_active = 1;
180: if (mi->mi_driver->md_start == (int (*)())0 ||
181: (com = (*mi->mi_driver->md_start)(mi)) == 0)
182: com = (bp->b_flags & B_READ) ? MB_RCOM|MB_GO : MB_WCOM|MB_GO;
183:
184: /*
185: * Setup the massbus control and map registers and start
186: * the transfer.
187: */
188: mbp = mi->mi_mba;
189: mbp->mba_sr = -1; /* conservative */
190: if (bp->b_bcount >= 0) {
191: mbp->mba_var = mbasetup(mi) + mi->mi_tab.b_bdone;
192: mbp->mba_bcr = -(bp->b_bcount - mi->mi_tab.b_bdone);
193: } else {
194: mbp->mba_var = mbasetup(mi) - bp->b_bcount - mi->mi_tab.b_bdone - 1;
195: mbp->mba_bcr = bp->b_bcount + mi->mi_tab.b_bdone;
196: }
197: mi->mi_drv->mbd_cs1 = com;
198: if (mi->mi_dk >= 0) {
199: dk_busy |= 1 << mi->mi_dk;
200: dk_xfer[mi->mi_dk]++;
201: if (bp->b_bcount >= 0)
202: dk_wds[mi->mi_dk] += bp->b_bcount >> 6;
203: else
204: dk_wds[mi->mi_dk] += -(bp->b_bcount) >> 6;
205: }
206: }
207:
208: /*
209: * Take an interrupt off of massbus mbanum,
210: * and dispatch to drivers as appropriate.
211: */
212: mbintr(mbanum)
213: int mbanum;
214: {
215: register struct mba_hd *mhp = &mba_hd[mbanum];
216: register struct mba_regs *mbp = mhp->mh_mba;
217: register struct mba_device *mi;
218: register struct buf *bp;
219: register int drive;
220: int mbasr, as;
221: extern struct mba_device *mbaconfig();
222:
223: /*
224: * Read out the massbus status register
225: * and attention status register and clear
226: * the bits in same by writing them back.
227: */
228: mbasr = mbp->mba_sr;
229: mbp->mba_sr = mbasr;
230: #if VAX750
231: if (mbasr&MBSR_CBHUNG) {
232: printf("mba%d: control bus hung\n", mbanum);
233: panic("cbhung");
234: }
235: #endif
236: /* note: the mbd_as register is shared between drives */
237: as = mbp->mba_drv[0].mbd_as & 0xff;
238: mbp->mba_drv[0].mbd_as = as;
239:
240: /*
241: * If the mba was active, process the data transfer
242: * complete interrupt; otherwise just process units which
243: * are now finished.
244: */
245: if (mhp->mh_active) {
246: /*
247: * Clear attention status for drive whose data
248: * transfer related operation completed,
249: * and give the dtint driver
250: * routine a chance to say what is next.
251: */
252: mi = mhp->mh_actf;
253: as &= ~(1 << mi->mi_drive);
254: dk_busy &= ~(1 << mi->mi_dk);
255: bp = mi->mi_tab.b_actf;
256: switch ((*mi->mi_driver->md_dtint)(mi, mbasr)) {
257:
258: case MBD_DONE: /* all done, for better or worse */
259: /*
260: * Flush request from drive queue.
261: */
262: mi->mi_tab.b_errcnt = 0;
263: mi->mi_tab.b_actf = bp->av_forw;
264: biodone(bp);
265: /* fall into... */
266: case MBD_RETRY: /* attempt the operation again */
267: /*
268: * Dequeue data transfer from massbus queue;
269: * if there is still a i/o request on the device
270: * queue then start the next operation on the device.
271: * (Common code for DONE and RETRY).
272: */
273: mhp->mh_active = 0;
274: mi->mi_tab.b_active = 0;
275: mhp->mh_actf = mi->mi_forw;
276: if (mi->mi_tab.b_actf)
277: mbustart(mi);
278: break;
279:
280: case MBD_REPOSITION: /* driver started repositioning */
281: /*
282: * Drive is repositioning, not doing data transfer.
283: * Free controller, but don't have to restart drive.
284: */
285: mhp->mh_active = 0;
286: mhp->mh_actf = mi->mi_forw;
287: break;
288:
289: case MBD_RESTARTED: /* driver restarted op (ecc, e.g.) */
290: /*
291: * Note that mhp->mh_active is still on.
292: */
293: break;
294:
295: default:
296: panic("mbintr");
297: }
298: }
299: /*
300: * Service drives which require attention
301: * after non-data-transfer operations.
302: */
303: while (drive = ffs((long)as)) {
304: drive--; /* was 1 origin */
305: as &= ~(1 << drive);
306: mi = mhp->mh_mbip[drive];
307: if (mi == NULL || mi->mi_alive == 0) {
308: struct mba_device fnd;
309: struct mba_drv *mbd = &mhp->mh_mba->mba_drv[drive];
310: int dt = mbd->mbd_dt & 0xffff;
311:
312: if (dt == 0 || dt == MBDT_MOH)
313: continue;
314: fnd.mi_mba = mhp->mh_mba;
315: fnd.mi_mbanum = mbanum;
316: fnd.mi_drive = drive;
317: if ((mi = mbaconfig(&fnd, dt)) == NULL)
318: continue;
319: /*
320: * If a tape, poke the slave attach routines.
321: * Otherwise, could be a disk which we want
322: * to swap on, so make a pass over the swap
323: * configuration table in case the size of
324: * the swap area must be determined by drive type.
325: */
326: if (dt & MBDT_TAP)
327: mbaddtape(mi, drive);
328: else
329: swapconf();
330: }
331: /*
332: * If driver has a handler for non-data transfer
333: * interrupts, give it a chance to tell us what to do.
334: */
335: if (mi->mi_driver->md_ndint) {
336: switch ((*mi->mi_driver->md_ndint)(mi)) {
337:
338: case MBN_DONE: /* operation completed */
339: mi->mi_tab.b_active = 0;
340: mi->mi_tab.b_errcnt = 0;
341: bp = mi->mi_tab.b_actf;
342: mi->mi_tab.b_actf = bp->av_forw;
343: biodone(bp);
344: /* fall into common code */
345: case MBN_RETRY: /* operation continues */
346: if (mi->mi_tab.b_actf)
347: mbustart(mi);
348: break;
349: case MBN_SKIP: /* ignore unsol. interrupt */
350: break;
351: default:
352: panic("mbintr");
353: }
354: } else
355: /*
356: * If there is no non-data transfer interrupt
357: * routine, then we should just
358: * restart the unit, leading to a mbstart() soon.
359: */
360: mbustart(mi);
361: }
362: /*
363: * If there is an operation available and
364: * the massbus isn't active, get it going.
365: */
366: if (mhp->mh_actf && !mhp->mh_active)
367: mbstart(mhp);
368: /* THHHHATS all folks... */
369: }
370:
371: /*
372: * For autoconfig'ng tape drives on the fly.
373: */
374: mbaddtape(mi, drive)
375: struct mba_device *mi;
376: int drive;
377: {
378: register struct mba_slave *ms;
379:
380: for (ms = mbsinit; ms->ms_driver; ms++)
381: if (ms->ms_driver == mi->mi_driver && ms->ms_alive == 0 &&
382: (ms->ms_ctlr == mi->mi_unit ||
383: ms->ms_ctlr == '?')) {
384: if ((*ms->ms_driver->md_slave)(mi, ms, drive)) {
385: printf("%s%d at %s%d slave %d\n",
386: ms->ms_driver->md_sname,
387: ms->ms_unit,
388: mi->mi_driver->md_dname,
389: mi->mi_unit,
390: ms->ms_slave);
391: ms->ms_alive = 1;
392: ms->ms_ctlr = mi->mi_unit;
393: }
394: }
395: }
396:
397: /*
398: * Setup the mapping registers for a transfer.
399: */
400: mbasetup(mi)
401: register struct mba_device *mi;
402: {
403: register struct mba_regs *mbap = mi->mi_mba;
404: struct buf *bp = mi->mi_tab.b_actf;
405: register int npf;
406: unsigned v;
407: register struct pte *pte, *io;
408: int o;
409: struct proc *rp;
410:
411: v = btop(bp->b_un.b_addr);
412: o = (int)(bp->b_un.b_addr) & PGOFSET;
413: if (bp->b_bcount >= 0)
414: npf = btoc(bp->b_bcount + o);
415: else
416: npf = btoc(-(bp->b_bcount) + o);
417: rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc;
418: if ((bp->b_flags & B_PHYS) == 0)
419: pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)];
420: else if (bp->b_flags & B_UAREA)
421: pte = &rp->p_addr[v];
422: else if (bp->b_flags & B_PAGET)
423: pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];
424: else
425: pte = vtopte(rp, v);
426: io = mbap->mba_map;
427: while (--npf >= 0) {
428: if (pte->pg_pfnum == 0)
429: panic("mba, zero entry");
430: *(int *)io++ = pte++->pg_pfnum | PG_V;
431: }
432: *(int *)io++ = 0;
433: return (o);
434: }
435:
436: #if notdef
437: /*
438: * Init and interrupt enable a massbus adapter.
439: */
440: mbainit(mp)
441: struct mba_regs *mp;
442: {
443:
444: mp->mba_cr = MBCR_INIT;
445: mp->mba_cr = MBCR_IE;
446: }
447: #endif
448: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.