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