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