mscp.c revision 1.10 1 /* $NetBSD: mscp.c,v 1.10 1999/05/29 19:11:02 ragge Exp $ */
2
3 /*
4 * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
5 * Copyright (c) 1988 Regents of the University of California.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Chris Torek.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * @(#)mscp.c 7.5 (Berkeley) 12/16/90
40 */
41
42 /*
43 * MSCP generic driver routines
44 */
45
46 #include <sys/param.h>
47 #include <sys/buf.h>
48 #include <sys/malloc.h>
49 #include <sys/device.h>
50 #include <sys/proc.h>
51 #include <sys/systm.h>
52
53 #include <vax/mscp/mscp.h>
54 #include <vax/mscp/mscpvar.h>
55
56 #define PCMD PSWP /* priority for command packet waits */
57
58 /*
59 * During transfers, mapping info is saved in the buffer's b_resid.
60 */
61 #define b_info b_resid
62
63 /*
64 * Get a command packet. Second argument is true iff we are
65 * to wait if necessary. Return NULL if none are available and
66 * we cannot wait.
67 */
68 struct mscp *
69 mscp_getcp(mi, canwait)
70 register struct mscp_softc *mi;
71 int canwait;
72 {
73 #define mri (&mi->mi_cmd)
74 register struct mscp *mp;
75 register int i;
76 int s = splbio();
77
78 again:
79 /*
80 * Ensure that we have some command credits, and
81 * that the next command packet is free.
82 */
83 if (mi->mi_credits <= MSCP_MINCREDITS) {
84 if (!canwait) {
85 splx(s);
86 return (NULL);
87 }
88 mi->mi_wantcredits = 1;
89 sleep((caddr_t) &mi->mi_wantcredits, PCMD);
90 goto again;
91 }
92 i = mri->mri_next;
93 if (mri->mri_desc[i] & MSCP_OWN) {
94 if (!canwait) {
95 splx(s);
96 return (NULL);
97 }
98 mi->mi_wantcmd = 1;
99 sleep((caddr_t) &mi->mi_wantcmd, PCMD);
100 goto again;
101 }
102 mi->mi_credits--;
103 mri->mri_desc[i] &= ~MSCP_INT;
104 mri->mri_next = (mri->mri_next + 1) % mri->mri_size;
105 splx(s);
106 mp = &mri->mri_ring[i];
107
108 /*
109 * Initialise some often-zero fields.
110 * ARE THE LAST TWO NECESSARY IN GENERAL? IT SURE WOULD BE
111 * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
112 */
113 mp->mscp_msglen = MSCP_MSGLEN;
114 mp->mscp_flags = 0;
115 mp->mscp_modifier = 0;
116 mp->mscp_seq.seq_bytecount = 0;
117 mp->mscp_seq.seq_buffer = 0;
118 mp->mscp_seq.seq_mapbase = 0;
119 /*???*/ mp->mscp_sccc.sccc_errlgfl = 0;
120 /*???*/ mp->mscp_sccc.sccc_copyspd = 0;
121 return (mp);
122 #undef mri
123 }
124
125 #ifdef AVOID_EMULEX_BUG
126 int mscp_aeb_xor = 0x8000bb80;
127 #endif
128
129 /*
130 * Handle a response ring transition.
131 */
132 void
133 mscp_dorsp(mi)
134 register struct mscp_softc *mi;
135 {
136 struct device *drive;
137 struct mscp_device *me = mi->mi_me;
138 struct mscp_ctlr *mc = mi->mi_mc;
139 register struct buf *bp;
140 register struct mscp *mp;
141 register int nextrsp;
142 int st, error, info;
143 extern int cold;
144 extern struct mscp slavereply;
145
146 nextrsp = mi->mi_rsp.mri_next;
147 loop:
148 if (mi->mi_rsp.mri_desc[nextrsp] & MSCP_OWN) {
149 /*
150 * No more responses. Remember the next expected
151 * response index. Check to see if we have some
152 * credits back, and wake up sleepers if so.
153 */
154 mi->mi_rsp.mri_next = nextrsp;
155 if (mi->mi_wantcredits && mi->mi_credits > MSCP_MINCREDITS) {
156 mi->mi_wantcredits = 0;
157 wakeup((caddr_t) &mi->mi_wantcredits);
158 }
159 return;
160 }
161
162 mp = &mi->mi_rsp.mri_ring[nextrsp];
163 mi->mi_credits += MSCP_CREDITS(mp->mscp_msgtc);
164 /*
165 * Controllers are allowed to interrupt as any drive, so we
166 * must check the command before checking for a drive.
167 */
168 if (mp->mscp_opcode == (M_OP_SETCTLRC | M_OP_END)) {
169 if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS) {
170 mi->mi_flags |= MSC_READY;
171 } else {
172 printf("%s: SETCTLRC failed: %d ",
173 mi->mi_dev.dv_xname, mp->mscp_status);
174 mscp_printevent(mp);
175 }
176 goto done;
177 }
178
179 /*
180 * Found a response. Update credit information. If there is
181 * nothing else to do, jump to `done' to get the next response.
182 */
183 if (mp->mscp_unit >= mi->mi_driveno) { /* Must expand drive table */
184 int tmpno = ((mp->mscp_unit + 32) & 0xffe0) * sizeof(void *);
185 struct device **tmp = (struct device **)
186 malloc(tmpno, M_DEVBUF, M_NOWAIT);
187 bzero(tmp, tmpno);
188 if (mi->mi_driveno) {
189 bcopy(mi->mi_dp, tmp, mi->mi_driveno);
190 free(mi->mi_dp, mi->mi_driveno);
191 }
192 mi->mi_driveno = tmpno;
193 mi->mi_dp = tmp;
194 }
195
196 drive = mi->mi_dp[mp->mscp_unit];
197
198 switch (MSCP_MSGTYPE(mp->mscp_msgtc)) {
199
200 case MSCPT_SEQ:
201 break;
202
203 case MSCPT_DATAGRAM:
204 (*me->me_dgram)(drive, mp, mi);
205 goto done;
206
207 case MSCPT_CREDITS:
208 goto done;
209
210 case MSCPT_MAINTENANCE:
211 default:
212 printf("%s: unit %d: unknown message type 0x%x ignored\n",
213 mi->mi_dev.dv_xname, mp->mscp_unit,
214 MSCP_MSGTYPE(mp->mscp_msgtc));
215 goto done;
216 }
217
218 /*
219 * Handle individual responses.
220 */
221 st = mp->mscp_status & M_ST_MASK;
222 error = 0;
223 switch (mp->mscp_opcode) {
224
225 case M_OP_END:
226 /*
227 * The controller presents a bogus END packet when
228 * a read/write command is given with an illegal
229 * block number. This is contrary to the MSCP
230 * specification (ENDs are to be given only for
231 * invalid commands), but that is the way of it.
232 */
233 if (st == M_ST_INVALCMD && mp->mscp_cmdref != 0) {
234 printf("%s: bad lbn (%d)?\n", drive->dv_xname,
235 (int)mp->mscp_seq.seq_lbn);
236 error = EIO;
237 goto rwend;
238 }
239 goto unknown;
240
241 case M_OP_ONLINE | M_OP_END:
242 /*
243 * Finished an ON LINE request. Call the driver to
244 * find out whether it succeeded. If so, mark it on
245 * line.
246 */
247 (*me->me_online)(drive, mp);
248 break;
249
250 case M_OP_GETUNITST | M_OP_END:
251 /*
252 * Got unit status. If we are autoconfiguring, save
253 * the mscp struct so that mscp_attach know what to do.
254 * If the drive isn't configured, call config_found()
255 * to set it up, otherwise it's just a "normal" unit
256 * status.
257 */
258 if (cold)
259 bcopy(mp, &slavereply, sizeof(struct mscp));
260
261 if (mp->mscp_status == (M_ST_OFFLINE|M_OFFLINE_UNKNOWN))
262 break;
263
264 if (drive == 0) {
265 struct drive_attach_args da;
266
267 da.da_mp = (struct mscp *)mp;
268 da.da_typ = mi->mi_type;
269 config_found(&mi->mi_dev, (void *)&da, mscp_print);
270 } else
271 /* Hack to avoid complaints */
272 if (!(((mp->mscp_event & M_ST_MASK) == M_ST_AVAILABLE)
273 && cold))
274 (*me->me_gotstatus)(drive, mp);
275 break;
276
277 case M_OP_AVAILATTN:
278 /*
279 * The drive went offline and we did not notice.
280 * Mark it off line now, to force an on line request
281 * next, so we can make sure it is still the same
282 * drive.
283 *
284 * IF THE UDA DRIVER HAS A COMMAND AWAITING UNIBUS
285 * RESOURCES, THAT COMMAND MAY GO OUT BEFORE THE ON
286 * LINE. IS IT WORTH FIXING??
287 */
288 #ifdef notyet
289 (*md->md_offline)(ui, mp);
290 #endif
291 break;
292
293 case M_OP_POS | M_OP_END:
294 case M_OP_WRITM | M_OP_END:
295 case M_OP_AVAILABLE | M_OP_END:
296 /*
297 * A non-data transfer operation completed.
298 */
299 (*me->me_cmddone)(drive, mp);
300 break;
301
302 case M_OP_READ | M_OP_END:
303 case M_OP_WRITE | M_OP_END:
304 /*
305 * A transfer finished. Get the buffer, and release its
306 * map registers via ubadone(). If the command finished
307 * with an off line or available status, the drive went
308 * off line (the idiot controller does not tell us until
309 * it comes back *on* line, or until we try to use it).
310 */
311 rwend:
312 #ifdef DIAGNOSTIC
313 if (mp->mscp_cmdref == 0) {
314 /*
315 * No buffer means there is a bug somewhere!
316 */
317 printf("%s: io done, but no buffer?\n",
318 drive->dv_xname);
319 mscp_hexdump(mp);
320 break;
321 }
322 #endif
323 bp = (struct buf *) mp->mscp_cmdref;
324
325 if (mp->mscp_cmdref == -1) {
326 (*me->me_cmddone)(drive, mp);
327 break;
328 }
329 /*
330 * Mark any error-due-to-bad-LBN (via `goto rwend').
331 * WHAT STATUS WILL THESE HAVE? IT SURE WOULD BE NICE
332 * IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
333 */
334 if (error) {
335 bp->b_flags |= B_ERROR;
336 bp->b_error = error;
337 }
338 if (st == M_ST_OFFLINE || st == M_ST_AVAILABLE) {
339 #ifdef notyet
340 (*md->md_offline)(ui, mp);
341 #endif
342 }
343
344 /*
345 * Unlink the transfer from the wait queue.
346 */
347 _remque(&bp->b_actf);
348
349 /*
350 * If the transfer has something to do with bad
351 * block forwarding, let the driver handle the
352 * rest.
353 */
354 if ((bp->b_flags & B_BAD) != 0 && me->me_bb != NULL) {
355 (*me->me_bb)(drive, mp, bp);
356 goto out;
357 }
358
359 /*
360 * If the transfer failed, give the driver a crack
361 * at fixing things up.
362 */
363 if (st != M_ST_SUCCESS) {
364 switch ((*me->me_ioerr)(drive, mp, bp)) {
365
366 case MSCP_DONE: /* fixed */
367 break;
368
369 case MSCP_RESTARTED: /* still working on it */
370 goto out;
371
372 case MSCP_FAILED: /* no luck */
373 /* XXX must move to ra.c */
374 mscp_printevent(mp);
375 break;
376 }
377 }
378
379 /*
380 * Set the residual count and mark the transfer as
381 * done. If the I/O wait queue is now empty, release
382 * the shared BDP, if any.
383 */
384 info = bp->b_info; /* we are about to clobber it */
385 bp->b_resid = bp->b_bcount - mp->mscp_seq.seq_bytecount;
386
387 (*mc->mc_ctlrdone)(mi->mi_dev.dv_parent, info);
388 (*me->me_iodone)(drive, bp);
389 out:
390 break;
391
392 case M_OP_REPLACE | M_OP_END:
393 /*
394 * A replace operation finished. Just let the driver
395 * handle it (if it does replaces).
396 */
397 if (me->me_replace == NULL)
398 printf("%s: bogus REPLACE end\n", drive->dv_xname);
399 else
400 (*me->me_replace)(drive, mp);
401 break;
402
403 default:
404 /*
405 * If it is not one of the above, we cannot handle it.
406 * (And we should not have received it, for that matter.)
407 */
408 unknown:
409 printf("%s: unknown opcode 0x%x status 0x%x ignored\n",
410 drive->dv_xname, mp->mscp_opcode, mp->mscp_status);
411 #ifdef DIAGNOSTIC
412 mscp_hexdump(mp);
413 #endif
414 break;
415 }
416
417 /*
418 * If the drive needs to be put back in the controller queue,
419 * do that now. (`bp' below ought to be `dp', but they are all
420 * struct buf *.) Note that b_active was cleared in the driver;
421 * we presume that there is something to be done, hence reassert it.
422 */
423 #ifdef notyet /* XXX */
424 if (ui->ui_flags & UNIT_REQUEUE) {
425 bp = &md->md_utab[ui->ui_unit];
426 if (bp->b_active) panic("mscp_dorsp requeue");
427 MSCP_APPEND(bp, mi->mi_XXXtab, b_hash.le_next);
428 /* Was: MSCP_APPEND(bp, mi->mi_XXXtab, b_forw); */
429 bp->b_active = 1;
430 ui->ui_flags &= ~UNIT_REQUEUE;
431 }
432 #endif
433 done:
434 /*
435 * Give back the response packet, and take a look at the next.
436 */
437 mp->mscp_msglen = MSCP_MSGLEN;
438 mi->mi_rsp.mri_desc[nextrsp] |= MSCP_OWN;
439 nextrsp = (nextrsp + 1) % mi->mi_rsp.mri_size;
440 goto loop;
441 }
442
443 /*
444 * Requeue outstanding transfers, e.g., after bus reset.
445 * Also requeue any drives that have on line or unit status
446 * info pending.
447 */
448 void
449 mscp_requeue(mi)
450 struct mscp_softc *mi;
451 {
452 #if 0
453 register struct mscp_device *me = mi->mi_me;
454 register struct buf *bp, *dp;
455 register int unit;
456 struct buf *nextbp;
457 #endif
458
459 panic("mscp_requeue");
460 /*
461 * Clear the controller chain. Mark everything un-busy; we
462 * will soon fix any that are in fact busy.
463 */
464 #ifdef notyet /* XXX */
465 mi->mi_XXXtab->b_actf = NULL;
466 mi->mi_XXXtab->b_active = 0;
467 for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) {
468 ui = md->md_dinfo[unit];
469 if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr)
470 continue; /* not ours */
471 dp->b_hash.le_next = NULL;
472 dp->b_active = 0;
473 }
474 /*
475 * Scan the wait queue, linking buffers onto drive queues.
476 * Note that these must be put at the front of the drive queue,
477 * lest we reorder I/O operations.
478 */
479 for (bp = *mi->mi_XXXwtab.b_actb; bp != &mi->mi_XXXwtab; bp = nextbp) {
480 nextbp = *bp->b_actb;
481 dp = &md->md_utab[minor(bp->b_dev) >> md->md_unitshift];
482 bp->b_actf = dp->b_actf;
483 if (dp->b_actf == NULL)
484 dp->b_actb = (void *)bp;
485 dp->b_actf = bp;
486 }
487 mi->mi_XXXwtab.b_actf = *mi->mi_XXXwtab.b_actb = &mi->mi_XXXwtab;
488
489 /*
490 * Scan for drives waiting for on line or status responses,
491 * and for drives with pending transfers. Put these on the
492 * controller queue, and mark the controller busy.
493 */
494 for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) {
495 ui = md->md_dinfo[unit];
496 if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr)
497 continue;
498 ui->ui_flags &= ~(UNIT_HAVESTATUS | UNIT_ONLINE);
499 if ((ui->ui_flags & UNIT_REQUEUE) == 0 && dp->b_actf == NULL)
500 continue;
501 ui->ui_flags &= ~UNIT_REQUEUE;
502 MSCP_APPEND(dp, mi->mi_XXXtab, b_hash.le_next);
503
504 dp->b_active = 1;
505 mi->mi_XXXtab->b_active = 1;
506 }
507
508 #endif
509 #ifdef AVOID_EMULEX_BUG
510 /*
511 * ... and clear the index-to-buffer table.
512 */
513 for (unit = 0; unit < AEB_MAX_BP; unit++)
514 mi->mi_bp[unit] = 0;
515 #endif
516 }
517
518