xref: /csrg-svn/sys/vax/mba/mba.c (revision 2423)
1 /*	mba.c	4.6	81/02/15	*/
2 
3 /*
4  * Massbus driver; arbitrates massbusses through device driver routines
5  * and provides common functions.
6  */
7 int	mbadebug = 0;
8 #define	dprintf if (mbadebug) printf
9 
10 #include "../h/param.h"
11 #include "../h/systm.h"
12 #include "../h/dk.h"
13 #include "../h/buf.h"
14 #include "../h/conf.h"
15 #include "../h/dir.h"
16 #include "../h/user.h"
17 #include "../h/proc.h"
18 #include "../h/map.h"
19 #include "../h/pte.h"
20 #include "../h/mba.h"
21 #include "../h/mtpr.h"
22 #include "../h/vm.h"
23 
24 /*
25  * Start activity on a massbus device.
26  * We are given the device's mba_info 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_info *mi;
36 {
37 	register struct mba_drv *mdp;	/* drive registers */
38 	register struct buf *bp;	/* i/o operation at head of queue */
39 	register struct mba_hd *mhp;	/* header for mba device is on */
40 
41 	dprintf("enter mbustart\n");
42 loop:
43 	/*
44 	 * Get the first thing to do off device queue.
45 	 */
46 	bp = mi->mi_tab.b_actf;
47 	if (bp == NULL)
48 		return;
49 	mdp = mi->mi_drv;
50 	/*
51 	 * Since we clear attentions on the drive when we are
52 	 * finished processing it, the fact that an attention
53 	 * status shows indicated confusion in the hardware or our logic.
54 	 */
55 	if (mdp->mbd_as & (1 << mi->mi_drive)) {
56 		printf("mbustart: ata on for %d\n", mi->mi_drive);
57 		mdp->mbd_as = 1 << mi->mi_drive;
58 	}
59 	/*
60 	 * Let the drivers unit start routine have at it
61 	 * and then process the request further, per its instructions.
62 	 */
63 	switch ((*mi->mi_driver->md_ustart)(mi)) {
64 
65 	case MBU_NEXT:		/* request is complete (e.g. ``sense'') */
66 		dprintf("mbu_next\n");
67 		mi->mi_tab.b_active = 0;
68 		mi->mi_tab.b_actf = bp->av_forw;
69 		iodone(bp);
70 		goto loop;
71 
72 	case MBU_DODATA:	/* all ready to do data transfer */
73 		dprintf("mbu_dodata\n");
74 		/*
75 		 * Queue the device mba_info structure on the massbus
76 		 * mba_hd structure for processing as soon as the
77 		 * data path is available.
78 		 */
79 		mhp = mi->mi_hd;
80 		mi->mi_forw = NULL;
81 		if (mhp->mh_actf == NULL)
82 			mhp->mh_actf = mi;
83 		else
84 			mhp->mh_actl->mi_forw = mi;
85 		mhp->mh_actl = mi;
86 		/*
87 		 * If data path is idle, start transfer now.
88 		 * In any case the device is ``active'' waiting for the
89 		 * data to transfer.
90 		 */
91 		if (mhp->mh_active == 0)
92 			mbstart(mhp);
93 		mi->mi_tab.b_active = 1;
94 		return;
95 
96 	case MBU_STARTED:	/* driver started a non-data transfer */
97 		dprintf("mbu_started\n");
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 		mi->mi_tab.b_active = 1;
105 		return;
106 
107 	case MBU_BUSY:		/* dual port drive busy */
108 		dprintf("mbu_busy\n");
109 		/*
110 		 * We mark the device structure so that when an
111 		 * interrupt occurs we will know to restart the unit.
112 		 */
113 		mi->mi_tab.b_flags |= B_BUSY;
114 		return;
115 
116 	default:
117 		panic("mbustart");
118 	}
119 }
120 
121 /*
122  * Start an i/o operation on the massbus specified by the argument.
123  * We peel the first operation off its queue and insure that the drive
124  * is present and on-line.  We then use the drivers start routine
125  * (if any) to prepare the drive, setup the massbus map for the transfer
126  * and start the transfer.
127  */
128 mbstart(mhp)
129 	register struct mba_hd *mhp;
130 {
131 	register struct mba_info *mi;
132 	struct buf *bp;
133 	register struct mba_drv *daddr;
134 	register struct mba_regs *mbp;
135 
136 	dprintf("mbstart\n");
137 loop:
138 	/*
139 	 * Look for an operation at the front of the queue.
140 	 */
141 	if ((mi = mhp->mh_actf) == NULL) {
142 		dprintf("nothing to do\n");
143 		return;
144 	}
145 	if ((bp = mi->mi_tab.b_actf) == NULL) {
146 		dprintf("nothing on actf\n");
147 		mhp->mh_actf = mi->mi_forw;
148 		goto loop;
149 	}
150 	/*
151 	 * If this device isn't present and on-line, then
152 	 * we screwed up, and can't really do the operation.
153 	 */
154 	if ((mi->mi_drv->mbd_ds & (MBD_DPR|MBD_MOL)) != (MBD_DPR|MBD_MOL)) {
155 		dprintf("not on line ds %x\n", mi->mi_drv->mbd_ds);
156 		mi->mi_tab.b_actf = bp->av_forw;
157 		bp->b_flags |= B_ERROR;
158 		iodone(bp);
159 		goto loop;
160 	}
161 	/*
162 	 * We can do the operation; mark the massbus active
163 	 * and let the device start routine setup any necessary
164 	 * device state for the transfer (e.g. desired cylinder, etc
165 	 * on disks).
166 	 */
167 	mhp->mh_active = 1;
168 	if (mi->mi_driver->md_start) {
169 		dprintf("md_start\n");
170 		(*mi->mi_driver->md_start)(mi);
171 	}
172 
173 	/*
174 	 * Setup the massbus control and map registers and start
175 	 * the transfer.
176 	 */
177 	dprintf("start mba\n");
178 	mbp = mi->mi_mba;
179 	mbp->mba_sr = -1;	/* conservative */
180 	mbp->mba_var = mbasetup(mi);
181 	mbp->mba_bcr = -bp->b_bcount;
182 	mi->mi_drv->mbd_cs1 =
183 	    (bp->b_flags & B_READ) ? MBD_RCOM|MBD_GO : MBD_WCOM|MBD_GO;
184 	if (mi->mi_dk >= 0) {
185 		dk_busy |= 1 << mi->mi_dk;
186 		dk_xfer[mi->mi_dk]++;
187 		dk_wds[mi->mi_dk] += bp->b_bcount >> 6;
188 	}
189 }
190 
191 /*
192  * Take an interrupt off of massbus mbanum,
193  * and dispatch to drivers as appropriate.
194  */
195 mbintr(mbanum)
196 	int mbanum;
197 {
198 	register struct mba_hd *mhp = &mba_hd[mbanum];
199 	register struct mba_regs *mbp = mhp->mh_mba;
200 	register struct mba_info *mi;
201 	register struct buf *bp;
202 	register int drive;
203 	int mbastat, as;
204 
205 	/*
206 	 * Read out the massbus status register
207 	 * and attention status register and clear
208 	 * the bits in same by writing them back.
209 	 */
210 	mbastat = mbp->mba_sr;
211 	mbp->mba_sr = mbastat;
212 	/* note: the mbd_as register is shared between drives */
213 	as = mbp->mba_drv[0].mbd_as;
214 	mbp->mba_drv[0].mbd_as = as;
215 	dprintf("mbintr mbastat %x as %x\n", mbastat, as);
216 
217 	/*
218 	 * Disable interrupts from the massbus adapter
219 	 * for the duration of the operation of the massbus
220 	 * driver, so that spurious interrupts won't be generated.
221 	 */
222 	mbp->mba_cr &= ~MBAIE;
223 
224 	/*
225 	 * If the mba was active, process the data transfer
226 	 * complete interrupt; otherwise just process units which
227 	 * are now finished.
228 	 */
229 	if (mhp->mh_active) {
230 		if ((mbastat & MBS_DTCMP) == 0) {
231 			printf("mbintr(%d),b_active,no DTCMP!\n", mbanum);
232 			goto doattn;
233 		}
234 		/*
235 		 * Clear attention status for drive whose data
236 		 * transfer completed, and give the dtint driver
237 		 * routine a chance to say what is next.
238 		 */
239 		mi = mhp->mh_actf;
240 		as &= ~(1 << mi->mi_drive);
241 		dk_busy &= ~(1 << mi->mi_dk);
242 		bp = mi->mi_tab.b_actf;
243 		switch((*mi->mi_driver->md_dtint)(mi, mbastat)) {
244 
245 		case MBD_DONE:		/* all done, for better or worse */
246 			dprintf("mbd_done\n");
247 			/*
248 			 * Flush request from drive queue.
249 			 */
250 			mi->mi_tab.b_errcnt = 0;
251 			mi->mi_tab.b_actf = bp->av_forw;
252 			iodone(bp);
253 			/* fall into... */
254 		case MBD_RETRY:		/* attempt the operation again */
255 			dprintf("mbd_retry\n");
256 			/*
257 			 * Dequeue data transfer from massbus queue;
258 			 * if there is still a i/o request on the device
259 			 * queue then start the next operation on the device.
260 			 * (Common code for DONE and RETRY).
261 			 */
262 			mhp->mh_active = 0;
263 			mi->mi_tab.b_active = 0;
264 			mhp->mh_actf = mi->mi_forw;
265 			if (mi->mi_tab.b_actf)
266 				mbustart(mi);
267 			break;
268 
269 		case MBD_RESTARTED:	/* driver restarted op (ecc, e.g.)
270 			dprintf("mbd_restarted\n");
271 			/*
272 			 * Note that mp->b_active is still on.
273 			 */
274 			break;
275 
276 		default:
277 			panic("mbaintr");
278 		}
279 	} else {
280 		dprintf("!dtcmp\n");
281 		if (mbastat & MBS_DTCMP)
282 			printf("mbaintr,DTCMP,!b_active\n");
283 	}
284 doattn:
285 	/*
286 	 * Service drives which require attention
287 	 * after non-data-transfer operations.
288 	 */
289 	for (drive = 0; as && drive < 8; drive++)
290 		if (as & (1 << drive)) {
291 			dprintf("service as %d\n", drive);
292 			as &= ~(1 << drive);
293 			/*
294 			 * Consistency check the implied attention,
295 			 * to make sure the drive should have interrupted.
296 			 */
297 			mi = mhp->mh_mbip[drive];
298 			if (mi == NULL)
299 				goto random;		/* no such drive */
300 			if (mi->mi_tab.b_active == 0 &&
301 			    (mi->mi_tab.b_flags&B_BUSY) == 0)
302 				goto random;		/* not active */
303 			if ((bp = mi->mi_tab.b_actf) == NULL) {
304 							/* nothing doing */
305 random:
306 				printf("random mbaintr %d %d\n",mbanum,drive);
307 				continue;
308 			}
309 			/*
310 			 * If this interrupt wasn't a notification that
311 			 * a dual ported drive is available, and if the
312 			 * driver has a handler for non-data transfer
313 			 * interrupts, give it a chance to tell us that
314 			 * the operation needs to be redone
315 			 */
316 			if ((mi->mi_tab.b_flags&B_BUSY) == 0 &&
317 			    mi->mi_driver->md_ndint) {
318 				mi->mi_tab.b_active = 0;
319 				switch((*mi->mi_driver->md_ndint)(mi)) {
320 
321 				case MBN_DONE:
322 					dprintf("mbn_done\n");
323 					/*
324 					 * Non-data transfer interrupt
325 					 * completed i/o request's processing.
326 					 */
327 					mi->mi_tab.b_errcnt = 0;
328 					mi->mi_tab.b_actf = bp->av_forw;
329 					iodone(bp);
330 					/* fall into... */
331 				case MBN_RETRY:
332 					dprintf("mbn_retry\n");
333 					if (mi->mi_tab.b_actf)
334 						mbustart(mi);
335 					break;
336 
337 				default:
338 					panic("mbintr ndint");
339 				}
340 			} else
341 				mbustart(mi);
342 		}
343 	/*
344 	 * If there is an operation available and
345 	 * the massbus isn't active, get it going.
346 	 */
347 	if (mhp->mh_actf && !mhp->mh_active)
348 		mbstart(mhp);
349 	mbp->mba_cr |= MBAIE;
350 }
351 
352 /*
353  * Setup the mapping registers for a transfer.
354  */
355 mbasetup(mi)
356 	register struct mba_info *mi;
357 {
358 	register struct mba_regs *mbap = mi->mi_mba;
359 	struct buf *bp = mi->mi_tab.b_actf;
360 	register int i;
361 	int npf;
362 	unsigned v;
363 	register struct pte *pte, *io;
364 	int o;
365 	int vaddr;
366 	struct proc *rp;
367 
368 	io = mbap->mba_map;
369 	v = btop(bp->b_un.b_addr);
370 	o = (int)bp->b_un.b_addr & PGOFSET;
371 	npf = btoc(bp->b_bcount + o);
372 	rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc;
373 	vaddr = o;
374 	if (bp->b_flags & B_UAREA) {
375 		for (i = 0; i < UPAGES; i++) {
376 			if (rp->p_addr[i].pg_pfnum == 0)
377 				panic("mba: zero upage");
378 			*(int *)io++ = rp->p_addr[i].pg_pfnum | PG_V;
379 		}
380 	} else if ((bp->b_flags & B_PHYS) == 0) {
381 		pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)];
382 		while (--npf >= 0)
383 			*(int *)io++ = pte++->pg_pfnum | PG_V;
384 	} else {
385 		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 		while (--npf >= 0) {
390 			if (pte->pg_pfnum == 0)
391 				panic("mba, zero entry");
392 			*(int *)io++ = pte++->pg_pfnum | PG_V;
393 		}
394 	}
395 	*(int *)io++ = 0;
396 	return (vaddr);
397 }
398