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