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