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