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