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