1 /*
2 * Copyright (c) 1988 University of Utah.
3 * Copyright (c) 1982, 1990, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * the Systems Programming Group of the University of Utah Computer
8 * Science Department.
9 *
10 * %sccs.include.redist.c%
11 *
12 * from: Utah $Hdr: rd.c 1.44 92/12/26$
13 *
14 * @(#)rd.c 8.5 (Berkeley) 05/14/95
15 */
16
17 /*
18 * CS80/SS80 disk driver
19 */
20 #include "rd.h"
21 #if NRD > 0
22
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/buf.h>
26 #include <sys/stat.h>
27 #include <sys/dkstat.h>
28 #include <sys/disklabel.h>
29 #include <sys/ioctl.h>
30 #include <sys/fcntl.h>
31
32 #include <hp/dev/device.h>
33 #include <hp300/dev/rdreg.h>
34 #include <hp300/dev/rdvar.h>
35 #ifdef USELEDS
36 #include <hp300/hp300/led.h>
37 #endif
38
39 #include <vm/vm.h>
40
41 int rdinit(), rdstart(), rdgo(), rdintr();
42 void rdstrategy();
43 struct driver rddriver = {
44 rdinit, "rd", rdstart, rdgo, rdintr,
45 };
46
47 struct rd_softc rd_softc[NRD];
48 struct buf rdtab[NRD];
49 int rderrthresh = RDRETRY-1; /* when to start reporting errors */
50
51 #ifdef DEBUG
52 /* error message tables */
53 char *err_reject[] = {
54 0, 0,
55 "channel parity error", /* 0x2000 */
56 0, 0,
57 "illegal opcode", /* 0x0400 */
58 "module addressing", /* 0x0200 */
59 "address bounds", /* 0x0100 */
60 "parameter bounds", /* 0x0080 */
61 "illegal parameter", /* 0x0040 */
62 "message sequence", /* 0x0020 */
63 0,
64 "message length", /* 0x0008 */
65 0, 0, 0
66 };
67
68 char *err_fault[] = {
69 0,
70 "cross unit", /* 0x4000 */
71 0,
72 "controller fault", /* 0x1000 */
73 0, 0,
74 "unit fault", /* 0x0200 */
75 0,
76 "diagnostic result", /* 0x0080 */
77 0,
78 "operator release request", /* 0x0020 */
79 "diagnostic release request", /* 0x0010 */
80 "internal maintenance release request", /* 0x0008 */
81 0,
82 "power fail", /* 0x0002 */
83 "retransmit" /* 0x0001 */
84 };
85
86 char *err_access[] = {
87 "illegal parallel operation", /* 0x8000 */
88 "uninitialized media", /* 0x4000 */
89 "no spares available", /* 0x2000 */
90 "not ready", /* 0x1000 */
91 "write protect", /* 0x0800 */
92 "no data found", /* 0x0400 */
93 0, 0,
94 "unrecoverable data overflow", /* 0x0080 */
95 "unrecoverable data", /* 0x0040 */
96 0,
97 "end of file", /* 0x0010 */
98 "end of volume", /* 0x0008 */
99 0, 0, 0
100 };
101
102 char *err_info[] = {
103 "operator release request", /* 0x8000 */
104 "diagnostic release request", /* 0x4000 */
105 "internal maintenance release request", /* 0x2000 */
106 "media wear", /* 0x1000 */
107 "latency induced", /* 0x0800 */
108 0, 0,
109 "auto sparing invoked", /* 0x0100 */
110 0,
111 "recoverable data overflow", /* 0x0040 */
112 "marginal data", /* 0x0020 */
113 "recoverable data", /* 0x0010 */
114 0,
115 "maintenance track overflow", /* 0x0004 */
116 0, 0
117 };
118
119 struct rdstats rdstats[NRD];
120 int rddebug = 0x80;
121 #define RDB_FOLLOW 0x01
122 #define RDB_STATUS 0x02
123 #define RDB_IDENT 0x04
124 #define RDB_IO 0x08
125 #define RDB_ASYNC 0x10
126 #define RDB_ERROR 0x80
127 #endif
128
129 /*
130 * Misc. HW description, indexed by sc_type.
131 * Nothing really critical here, could do without it.
132 */
133 struct rdidentinfo rdidentinfo[] = {
134 { RD7946AID, 0, "7945A", 108416 },
135 { RD9134DID, 1, "9134D", 29088 },
136 { RD9134LID, 1, "9122S", 1232 },
137 { RD7912PID, 0, "7912P", 128128 },
138 { RD7914PID, 0, "7914P", 258048 },
139 { RD7958AID, 0, "7958A", 255276 },
140 { RD7957AID, 0, "7957A", 159544 },
141 { RD7933HID, 0, "7933H", 789958 },
142 { RD9134LID, 1, "9134L", 77840 },
143 { RD7936HID, 0, "7936H", 600978 },
144 { RD7937HID, 0, "7937H", 1116102 },
145 { RD7914CTID, 0, "7914CT", 258048 },
146 { RD7946AID, 0, "7946A", 108416 },
147 { RD9134LID, 1, "9122D", 1232 },
148 { RD7957BID, 0, "7957B", 159894 },
149 { RD7958BID, 0, "7958B", 297108 },
150 { RD7959BID, 0, "7959B", 594216 },
151 { RD2200AID, 0, "2200A", 654948 },
152 { RD2203AID, 0, "2203A", 1309896 }
153 };
154 int numrdidentinfo = sizeof(rdidentinfo) / sizeof(rdidentinfo[0]);
155
rdinit(hd)156 rdinit(hd)
157 register struct hp_device *hd;
158 {
159 register struct rd_softc *rs = &rd_softc[hd->hp_unit];
160
161 rs->sc_hd = hd;
162 rs->sc_punit = rdpunit(hd->hp_flags);
163 rs->sc_type = rdident(rs, hd);
164 if (rs->sc_type < 0)
165 return(0);
166 rs->sc_dq.dq_ctlr = hd->hp_ctlr;
167 rs->sc_dq.dq_unit = hd->hp_unit;
168 rs->sc_dq.dq_slave = hd->hp_slave;
169 rs->sc_dq.dq_driver = &rddriver;
170 rs->sc_flags = RDF_ALIVE;
171 #ifdef DEBUG
172 /* always report errors */
173 if (rddebug & RDB_ERROR)
174 rderrthresh = 0;
175 #endif
176 return(1);
177 }
178
179 rdident(rs, hd)
180 struct rd_softc *rs;
181 struct hp_device *hd;
182 {
183 struct rd_describe desc;
184 u_char stat, cmd[3];
185 int unit, lunit;
186 char name[7];
187 register int ctlr, slave, id, i;
188
189 ctlr = hd->hp_ctlr;
190 slave = hd->hp_slave;
191 unit = rs->sc_punit;
192 lunit = hd->hp_unit;
193
194 /*
195 * Grab device id and make sure:
196 * 1. It is a CS80 device.
197 * 2. It is one of the types we support.
198 * 3. If it is a 7946, we are accessing the disk unit (0)
199 */
200 id = hpibid(ctlr, slave);
201 #ifdef DEBUG
202 if (rddebug & RDB_IDENT)
203 printf("hpibid(%d, %d) -> %x\n", ctlr, slave, id);
204 #endif
205 if ((id & 0x200) == 0)
206 return(-1);
207 for (i = 0; i < numrdidentinfo; i++)
208 if (id == rdidentinfo[i].ri_hwid)
209 break;
210 if (i == numrdidentinfo || unit > rdidentinfo[i].ri_maxunum)
211 return(-1);
212 id = i;
213
214 /*
215 * Reset drive and collect device description.
216 * Don't really use the description info right now but
217 * might come in handy in the future (for disk labels).
218 */
219 rdreset(rs, hd);
220 cmd[0] = C_SUNIT(unit);
221 cmd[1] = C_SVOL(0);
222 cmd[2] = C_DESC;
223 hpibsend(ctlr, slave, C_CMD, cmd, sizeof(cmd));
224 hpibrecv(ctlr, slave, C_EXEC, &desc, 37);
225 hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
226 bzero(name, sizeof(name));
227 if (!stat) {
228 register int n = desc.d_name;
229 for (i = 5; i >= 0; i--) {
230 name[i] = (n & 0xf) + '0';
231 n >>= 4;
232 }
233 /* use drive characteristics to calculate xfer rate */
234 rs->sc_wpms = 1000000 * (desc.d_sectsize/2) / desc.d_blocktime;
235 }
236 #ifdef DEBUG
237 if (rddebug & RDB_IDENT) {
238 printf("rd%d: name: %x ('%s')\n",
239 lunit, desc.d_name, name);
240 printf(" iuw %x, maxxfr %d, ctype %d\n",
241 desc.d_iuw, desc.d_cmaxxfr, desc.d_ctype);
242 printf(" utype %d, bps %d, blkbuf %d, burst %d, blktime %d\n",
243 desc.d_utype, desc.d_sectsize,
244 desc.d_blkbuf, desc.d_burstsize, desc.d_blocktime);
245 printf(" avxfr %d, ort %d, atp %d, maxint %d, fv %x, rv %x\n",
246 desc.d_uavexfr, desc.d_retry, desc.d_access,
247 desc.d_maxint, desc.d_fvbyte, desc.d_rvbyte);
248 printf(" maxcyl/head/sect %d/%d/%d, maxvsect %d, inter %d\n",
249 desc.d_maxcyl, desc.d_maxhead, desc.d_maxsect,
250 desc.d_maxvsectl, desc.d_interleave);
251 }
252 #endif
253 /*
254 * Take care of a couple of anomolies:
255 * 1. 7945A and 7946A both return same HW id
256 * 2. 9122S and 9134D both return same HW id
257 * 3. 9122D and 9134L both return same HW id
258 */
259 switch (rdidentinfo[id].ri_hwid) {
260 case RD7946AID:
261 if (bcmp(name, "079450", 6) == 0)
262 id = RD7945A;
263 else
264 id = RD7946A;
265 break;
266
267 case RD9134LID:
268 if (bcmp(name, "091340", 6) == 0)
269 id = RD9134L;
270 else
271 id = RD9122D;
272 break;
273
274 case RD9134DID:
275 if (bcmp(name, "091220", 6) == 0)
276 id = RD9122S;
277 else
278 id = RD9134D;
279 break;
280 }
281 printf("rd%d: %s\n", lunit, rdidentinfo[id].ri_desc);
282 return(id);
283 }
284
rdreset(rs,hd)285 rdreset(rs, hd)
286 register struct rd_softc *rs;
287 register struct hp_device *hd;
288 {
289 u_char stat;
290
291 rs->sc_clear.c_unit = C_SUNIT(rs->sc_punit);
292 rs->sc_clear.c_cmd = C_CLEAR;
293 hpibsend(hd->hp_ctlr, hd->hp_slave, C_TCMD, &rs->sc_clear,
294 sizeof(rs->sc_clear));
295 hpibswait(hd->hp_ctlr, hd->hp_slave);
296 hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
297 rs->sc_src.c_unit = C_SUNIT(RDCTLR);
298 rs->sc_src.c_nop = C_NOP;
299 rs->sc_src.c_cmd = C_SREL;
300 rs->sc_src.c_param = C_REL;
301 hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &rs->sc_src,
302 sizeof(rs->sc_src));
303 hpibswait(hd->hp_ctlr, hd->hp_slave);
304 hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
305 rs->sc_ssmc.c_unit = C_SUNIT(rs->sc_punit);
306 rs->sc_ssmc.c_cmd = C_SSM;
307 rs->sc_ssmc.c_refm = REF_MASK;
308 rs->sc_ssmc.c_fefm = FEF_MASK;
309 rs->sc_ssmc.c_aefm = AEF_MASK;
310 rs->sc_ssmc.c_iefm = IEF_MASK;
311 hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &rs->sc_ssmc,
312 sizeof(rs->sc_ssmc));
313 hpibswait(hd->hp_ctlr, hd->hp_slave);
314 hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
315 #ifdef DEBUG
316 rdstats[hd->hp_unit].rdresets++;
317 #endif
318 }
319
320 /*
321 * Read or constuct a disklabel
322 */
323 int
rdgetinfo(dev)324 rdgetinfo(dev)
325 dev_t dev;
326 {
327 int unit = rdunit(dev);
328 register struct rd_softc *rs = &rd_softc[unit];
329 register struct disklabel *lp = &rs->sc_info.ri_label;
330 register struct partition *pi;
331 char *msg, *readdisklabel();
332
333 /*
334 * Set some default values to use while reading the label
335 * or to use if there isn't a label.
336 */
337 bzero((caddr_t)lp, sizeof *lp);
338 lp->d_type = DTYPE_HPIB;
339 lp->d_secsize = DEV_BSIZE;
340 lp->d_nsectors = 32;
341 lp->d_ntracks = 20;
342 lp->d_ncylinders = 1;
343 lp->d_secpercyl = 32*20;
344 lp->d_npartitions = 3;
345 lp->d_partitions[2].p_offset = 0;
346 lp->d_partitions[2].p_size = LABELSECTOR+1;
347
348 /*
349 * Now try to read the disklabel
350 */
351 msg = readdisklabel(rdlabdev(dev), rdstrategy, lp);
352 if (msg == NULL)
353 return(0);
354
355 pi = lp->d_partitions;
356 printf("rd%d: WARNING: %s, ", unit, msg);
357 #ifdef COMPAT_NOLABEL
358 printf("using old default partitioning\n");
359 rdmakedisklabel(unit, lp);
360 #else
361 printf("defining `c' partition as entire disk\n");
362 pi[2].p_size = rdidentinfo[rs->sc_type].ri_nblocks;
363 /* XXX reset other info since readdisklabel screws with it */
364 lp->d_npartitions = 3;
365 pi[0].p_size = 0;
366 #endif
367 return(0);
368 }
369
370 int
rdopen(dev,flags,mode,p)371 rdopen(dev, flags, mode, p)
372 dev_t dev;
373 int flags, mode;
374 struct proc *p;
375 {
376 register int unit = rdunit(dev);
377 register struct rd_softc *rs = &rd_softc[unit];
378 int error, mask;
379
380 if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
381 return(ENXIO);
382
383 /*
384 * Wait for any pending opens/closes to complete
385 */
386 while (rs->sc_flags & (RDF_OPENING|RDF_CLOSING))
387 sleep((caddr_t)rs, PRIBIO);
388
389 /*
390 * On first open, get label and partition info.
391 * We may block reading the label, so be careful
392 * to stop any other opens.
393 */
394 if (rs->sc_info.ri_open == 0) {
395 rs->sc_flags |= RDF_OPENING;
396 error = rdgetinfo(dev);
397 rs->sc_flags &= ~RDF_OPENING;
398 wakeup((caddr_t)rs);
399 if (error)
400 return(error);
401 }
402 if (rs->sc_hd->hp_dk >= 0) {
403 /* guess at xfer rate based on 3600 rpm (60 rps) */
404 if (rs->sc_wpms == 0)
405 rs->sc_wpms = 60 * rs->sc_info.ri_label.d_nsectors
406 * DEV_BSIZE / 2;
407 dk_wpms[rs->sc_hd->hp_dk] = rs->sc_wpms;
408 }
409
410 mask = 1 << rdpart(dev);
411 if (mode == S_IFCHR)
412 rs->sc_info.ri_copen |= mask;
413 else
414 rs->sc_info.ri_bopen |= mask;
415 rs->sc_info.ri_open |= mask;
416 return(0);
417 }
418
419 int
rdclose(dev,flag,mode,p)420 rdclose(dev, flag, mode, p)
421 dev_t dev;
422 int flag, mode;
423 struct proc *p;
424 {
425 int unit = rdunit(dev);
426 register struct rd_softc *rs = &rd_softc[unit];
427 register struct rdinfo *ri = &rs->sc_info;
428 int mask, s;
429
430 mask = 1 << rdpart(dev);
431 if (mode == S_IFCHR)
432 ri->ri_copen &= ~mask;
433 else
434 ri->ri_bopen &= ~mask;
435 ri->ri_open = ri->ri_bopen | ri->ri_copen;
436 /*
437 * On last close, we wait for all activity to cease since
438 * the label/parition info will become invalid. Since we
439 * might sleep, we must block any opens while we are here.
440 * Note we don't have to about other closes since we know
441 * we are the last one.
442 */
443 if (ri->ri_open == 0) {
444 rs->sc_flags |= RDF_CLOSING;
445 s = splbio();
446 while (rdtab[unit].b_active) {
447 rs->sc_flags |= RDF_WANTED;
448 sleep((caddr_t)&rdtab[unit], PRIBIO);
449 }
450 splx(s);
451 rs->sc_flags &= ~(RDF_CLOSING|RDF_WLABEL);
452 wakeup((caddr_t)rs);
453 }
454 return(0);
455 }
456
457 void
rdstrategy(bp)458 rdstrategy(bp)
459 register struct buf *bp;
460 {
461 int unit = rdunit(bp->b_dev);
462 register struct rd_softc *rs = &rd_softc[unit];
463 register struct buf *dp = &rdtab[unit];
464 register struct partition *pinfo;
465 register daddr_t bn;
466 register int sz, s;
467
468 #ifdef DEBUG
469 if (rddebug & RDB_FOLLOW)
470 printf("rdstrategy(%x): dev %x, bn %x, bcount %x, %c\n",
471 bp, bp->b_dev, bp->b_blkno, bp->b_bcount,
472 (bp->b_flags & B_READ) ? 'R' : 'W');
473 #endif
474 bn = bp->b_blkno;
475 sz = howmany(bp->b_bcount, DEV_BSIZE);
476 pinfo = &rs->sc_info.ri_label.d_partitions[rdpart(bp->b_dev)];
477 if (bn < 0 || bn + sz > pinfo->p_size) {
478 sz = pinfo->p_size - bn;
479 if (sz == 0) {
480 bp->b_resid = bp->b_bcount;
481 goto done;
482 }
483 if (sz < 0) {
484 bp->b_error = EINVAL;
485 goto bad;
486 }
487 bp->b_bcount = dbtob(sz);
488 }
489 /*
490 * Check for write to write protected label
491 */
492 if (bn + pinfo->p_offset <= LABELSECTOR &&
493 #if LABELSECTOR != 0
494 bn + pinfo->p_offset + sz > LABELSECTOR &&
495 #endif
496 !(bp->b_flags & B_READ) && !(rs->sc_flags & RDF_WLABEL)) {
497 bp->b_error = EROFS;
498 goto bad;
499 }
500 bp->b_cylin = bn + pinfo->p_offset;
501 s = splbio();
502 disksort(dp, bp);
503 if (dp->b_active == 0) {
504 dp->b_active = 1;
505 rdustart(unit);
506 }
507 splx(s);
508 return;
509 bad:
510 bp->b_flags |= B_ERROR;
511 done:
512 biodone(bp);
513 }
514
515 /*
516 * Called from timeout() when handling maintenance releases
517 */
518 void
rdrestart(arg)519 rdrestart(arg)
520 void *arg;
521 {
522 int s = splbio();
523 rdustart((int)arg);
524 splx(s);
525 }
526
rdustart(unit)527 rdustart(unit)
528 register int unit;
529 {
530 register struct buf *bp;
531 register struct rd_softc *rs = &rd_softc[unit];
532
533 bp = rdtab[unit].b_actf;
534 rs->sc_addr = bp->b_un.b_addr;
535 rs->sc_resid = bp->b_bcount;
536 if (hpibreq(&rs->sc_dq))
537 rdstart(unit);
538 }
539
540 struct buf *
rdfinish(unit,rs,bp)541 rdfinish(unit, rs, bp)
542 int unit;
543 register struct rd_softc *rs;
544 register struct buf *bp;
545 {
546 register struct buf *dp = &rdtab[unit];
547
548 dp->b_errcnt = 0;
549 dp->b_actf = bp->b_actf;
550 bp->b_resid = 0;
551 biodone(bp);
552 hpibfree(&rs->sc_dq);
553 if (dp->b_actf)
554 return(dp->b_actf);
555 dp->b_active = 0;
556 if (rs->sc_flags & RDF_WANTED) {
557 rs->sc_flags &= ~RDF_WANTED;
558 wakeup((caddr_t)dp);
559 }
560 return(NULL);
561 }
562
rdstart(unit)563 rdstart(unit)
564 register int unit;
565 {
566 register struct rd_softc *rs = &rd_softc[unit];
567 register struct buf *bp = rdtab[unit].b_actf;
568 register struct hp_device *hp = rs->sc_hd;
569 register int part;
570
571 again:
572 #ifdef DEBUG
573 if (rddebug & RDB_FOLLOW)
574 printf("rdstart(%d): bp %x, %c\n", unit, bp,
575 (bp->b_flags & B_READ) ? 'R' : 'W');
576 #endif
577 part = rdpart(bp->b_dev);
578 rs->sc_flags |= RDF_SEEK;
579 rs->sc_ioc.c_unit = C_SUNIT(rs->sc_punit);
580 rs->sc_ioc.c_volume = C_SVOL(0);
581 rs->sc_ioc.c_saddr = C_SADDR;
582 rs->sc_ioc.c_hiaddr = 0;
583 rs->sc_ioc.c_addr = RDBTOS(bp->b_cylin);
584 rs->sc_ioc.c_nop2 = C_NOP;
585 rs->sc_ioc.c_slen = C_SLEN;
586 rs->sc_ioc.c_len = rs->sc_resid;
587 rs->sc_ioc.c_cmd = bp->b_flags & B_READ ? C_READ : C_WRITE;
588 #ifdef DEBUG
589 if (rddebug & RDB_IO)
590 printf("rdstart: hpibsend(%x, %x, %x, %x, %x)\n",
591 hp->hp_ctlr, hp->hp_slave, C_CMD,
592 &rs->sc_ioc.c_unit, sizeof(rs->sc_ioc)-2);
593 #endif
594 if (hpibsend(hp->hp_ctlr, hp->hp_slave, C_CMD, &rs->sc_ioc.c_unit,
595 sizeof(rs->sc_ioc)-2) == sizeof(rs->sc_ioc)-2) {
596 if (hp->hp_dk >= 0) {
597 dk_busy |= 1 << hp->hp_dk;
598 dk_seek[hp->hp_dk]++;
599 }
600 #ifdef DEBUG
601 if (rddebug & RDB_IO)
602 printf("rdstart: hpibawait(%x)\n", hp->hp_ctlr);
603 #endif
604 hpibawait(hp->hp_ctlr);
605 return;
606 }
607 /*
608 * Experience has shown that the hpibwait in this hpibsend will
609 * occasionally timeout. It appears to occur mostly on old 7914
610 * drives with full maintenance tracks. We should probably
611 * integrate this with the backoff code in rderror.
612 */
613 #ifdef DEBUG
614 if (rddebug & RDB_ERROR)
615 printf("rd%d: rdstart: cmd %x adr %d blk %d len %d ecnt %d\n",
616 unit, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr,
617 bp->b_blkno, rs->sc_resid, rdtab[unit].b_errcnt);
618 rdstats[unit].rdretries++;
619 #endif
620 rs->sc_flags &= ~RDF_SEEK;
621 rdreset(rs, hp);
622 if (rdtab[unit].b_errcnt++ < RDRETRY)
623 goto again;
624 printf("rd%d: rdstart err: cmd 0x%x sect %d blk %d len %d\n",
625 unit, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr,
626 bp->b_blkno, rs->sc_resid);
627 bp->b_flags |= B_ERROR;
628 bp->b_error = EIO;
629 bp = rdfinish(unit, rs, bp);
630 if (bp) {
631 rs->sc_addr = bp->b_un.b_addr;
632 rs->sc_resid = bp->b_bcount;
633 if (hpibreq(&rs->sc_dq))
634 goto again;
635 }
636 }
637
rdgo(unit)638 rdgo(unit)
639 register int unit;
640 {
641 register struct rd_softc *rs = &rd_softc[unit];
642 register struct hp_device *hp = rs->sc_hd;
643 struct buf *bp = rdtab[unit].b_actf;
644
645 if (hp->hp_dk >= 0) {
646 dk_busy |= 1 << hp->hp_dk;
647 dk_xfer[hp->hp_dk]++;
648 dk_wds[hp->hp_dk] += rs->sc_resid >> 6;
649 }
650 #ifdef USELEDS
651 if (inledcontrol == 0)
652 ledcontrol(0, 0, LED_DISK);
653 #endif
654 hpibgo(hp->hp_ctlr, hp->hp_slave, C_EXEC,
655 rs->sc_addr, rs->sc_resid, bp->b_flags & B_READ);
656 }
657
rdintr(unit)658 rdintr(unit)
659 register int unit;
660 {
661 register struct rd_softc *rs = &rd_softc[unit];
662 register struct buf *bp = rdtab[unit].b_actf;
663 register struct hp_device *hp = rs->sc_hd;
664 u_char stat = 13; /* in case hpibrecv fails */
665 int rv, restart;
666
667 #ifdef DEBUG
668 if (rddebug & RDB_FOLLOW)
669 printf("rdintr(%d): bp %x, %c, flags %x\n", unit, bp,
670 (bp->b_flags & B_READ) ? 'R' : 'W', rs->sc_flags);
671 if (bp == NULL) {
672 printf("rd%d: bp == NULL\n", unit);
673 return;
674 }
675 #endif
676 if (hp->hp_dk >= 0)
677 dk_busy &= ~(1 << hp->hp_dk);
678 if (rs->sc_flags & RDF_SEEK) {
679 rs->sc_flags &= ~RDF_SEEK;
680 if (hpibustart(hp->hp_ctlr))
681 rdgo(unit);
682 return;
683 }
684 if ((rs->sc_flags & RDF_SWAIT) == 0) {
685 #ifdef DEBUG
686 rdstats[unit].rdpolltries++;
687 #endif
688 if (hpibpptest(hp->hp_ctlr, hp->hp_slave) == 0) {
689 #ifdef DEBUG
690 rdstats[unit].rdpollwaits++;
691 #endif
692 if (hp->hp_dk >= 0)
693 dk_busy |= 1 << hp->hp_dk;
694 rs->sc_flags |= RDF_SWAIT;
695 hpibawait(hp->hp_ctlr);
696 return;
697 }
698 } else
699 rs->sc_flags &= ~RDF_SWAIT;
700 rv = hpibrecv(hp->hp_ctlr, hp->hp_slave, C_QSTAT, &stat, 1);
701 if (rv != 1 || stat) {
702 #ifdef DEBUG
703 if (rddebug & RDB_ERROR)
704 printf("rdintr: recv failed or bad stat %d\n", stat);
705 #endif
706 restart = rderror(unit);
707 #ifdef DEBUG
708 rdstats[unit].rdretries++;
709 #endif
710 if (rdtab[unit].b_errcnt++ < RDRETRY) {
711 if (restart)
712 rdstart(unit);
713 return;
714 }
715 bp->b_flags |= B_ERROR;
716 bp->b_error = EIO;
717 }
718 if (rdfinish(unit, rs, bp))
719 rdustart(unit);
720 }
721
rdstatus(rs)722 rdstatus(rs)
723 register struct rd_softc *rs;
724 {
725 register int c, s;
726 u_char stat;
727 int rv;
728
729 c = rs->sc_hd->hp_ctlr;
730 s = rs->sc_hd->hp_slave;
731 rs->sc_rsc.c_unit = C_SUNIT(rs->sc_punit);
732 rs->sc_rsc.c_sram = C_SRAM;
733 rs->sc_rsc.c_ram = C_RAM;
734 rs->sc_rsc.c_cmd = C_STATUS;
735 bzero((caddr_t)&rs->sc_stat, sizeof(rs->sc_stat));
736 rv = hpibsend(c, s, C_CMD, &rs->sc_rsc, sizeof(rs->sc_rsc));
737 if (rv != sizeof(rs->sc_rsc)) {
738 #ifdef DEBUG
739 if (rddebug & RDB_STATUS)
740 printf("rdstatus: send C_CMD failed %d != %d\n",
741 rv, sizeof(rs->sc_rsc));
742 #endif
743 return(1);
744 }
745 rv = hpibrecv(c, s, C_EXEC, &rs->sc_stat, sizeof(rs->sc_stat));
746 if (rv != sizeof(rs->sc_stat)) {
747 #ifdef DEBUG
748 if (rddebug & RDB_STATUS)
749 printf("rdstatus: send C_EXEC failed %d != %d\n",
750 rv, sizeof(rs->sc_stat));
751 #endif
752 return(1);
753 }
754 rv = hpibrecv(c, s, C_QSTAT, &stat, 1);
755 if (rv != 1 || stat) {
756 #ifdef DEBUG
757 if (rddebug & RDB_STATUS)
758 printf("rdstatus: recv failed %d or bad stat %d\n",
759 rv, stat);
760 #endif
761 return(1);
762 }
763 return(0);
764 }
765
766 /*
767 * Deal with errors.
768 * Returns 1 if request should be restarted,
769 * 0 if we should just quietly give up.
770 */
rderror(unit)771 rderror(unit)
772 int unit;
773 {
774 struct rd_softc *rs = &rd_softc[unit];
775 register struct rd_stat *sp;
776 struct buf *bp;
777 daddr_t hwbn, pbn;
778
779 if (rdstatus(rs)) {
780 #ifdef DEBUG
781 printf("rd%d: couldn't get status\n", unit);
782 #endif
783 rdreset(rs, rs->sc_hd);
784 return(1);
785 }
786 sp = &rs->sc_stat;
787 if (sp->c_fef & FEF_REXMT)
788 return(1);
789 if (sp->c_fef & FEF_PF) {
790 rdreset(rs, rs->sc_hd);
791 return(1);
792 }
793 /*
794 * Unit requests release for internal maintenance.
795 * We just delay awhile and try again later. Use expontially
796 * increasing backoff ala ethernet drivers since we don't really
797 * know how long the maintenance will take. With RDWAITC and
798 * RDRETRY as defined, the range is 1 to 32 seconds.
799 */
800 if (sp->c_fef & FEF_IMR) {
801 extern int hz;
802 int rdtimo = RDWAITC << rdtab[unit].b_errcnt;
803 #ifdef DEBUG
804 printf("rd%d: internal maintenance, %d second timeout\n",
805 unit, rdtimo);
806 rdstats[unit].rdtimeouts++;
807 #endif
808 hpibfree(&rs->sc_dq);
809 timeout(rdrestart, (void *)unit, rdtimo * hz);
810 return(0);
811 }
812 /*
813 * Only report error if we have reached the error reporting
814 * threshhold. By default, this will only report after the
815 * retry limit has been exceeded.
816 */
817 if (rdtab[unit].b_errcnt < rderrthresh)
818 return(1);
819
820 /*
821 * First conjure up the block number at which the error occured.
822 * Note that not all errors report a block number, in that case
823 * we just use b_blkno.
824 */
825 bp = rdtab[unit].b_actf;
826 pbn = rs->sc_info.ri_label.d_partitions[rdpart(bp->b_dev)].p_offset;
827 if ((sp->c_fef & FEF_CU) || (sp->c_fef & FEF_DR) ||
828 (sp->c_ief & IEF_RRMASK)) {
829 hwbn = RDBTOS(pbn + bp->b_blkno);
830 pbn = bp->b_blkno;
831 } else {
832 hwbn = sp->c_blk;
833 pbn = RDSTOB(hwbn) - pbn;
834 }
835 /*
836 * Now output a generic message suitable for badsect.
837 * Note that we don't use harderr cuz it just prints
838 * out b_blkno which is just the beginning block number
839 * of the transfer, not necessary where the error occured.
840 */
841 printf("rd%d%c: hard error sn%d\n",
842 rdunit(bp->b_dev), 'a'+rdpart(bp->b_dev), pbn);
843 /*
844 * Now report the status as returned by the hardware with
845 * attempt at interpretation (unless debugging).
846 */
847 printf("rd%d %s error:",
848 unit, (bp->b_flags & B_READ) ? "read" : "write");
849 #ifdef DEBUG
850 if (rddebug & RDB_ERROR) {
851 /* status info */
852 printf("\n volume: %d, unit: %d\n",
853 (sp->c_vu>>4)&0xF, sp->c_vu&0xF);
854 rdprinterr("reject", sp->c_ref, err_reject);
855 rdprinterr("fault", sp->c_fef, err_fault);
856 rdprinterr("access", sp->c_aef, err_access);
857 rdprinterr("info", sp->c_ief, err_info);
858 printf(" block: %d, P1-P10: ", hwbn);
859 printf("%s", hexstr(*(u_int *)&sp->c_raw[0], 8));
860 printf("%s", hexstr(*(u_int *)&sp->c_raw[4], 8));
861 printf("%s\n", hexstr(*(u_short *)&sp->c_raw[8], 4));
862 /* command */
863 printf(" ioc: ");
864 printf("%s", hexstr(*(u_int *)&rs->sc_ioc.c_pad, 8));
865 printf("%s", hexstr(*(u_short *)&rs->sc_ioc.c_hiaddr, 4));
866 printf("%s", hexstr(*(u_int *)&rs->sc_ioc.c_addr, 8));
867 printf("%s", hexstr(*(u_short *)&rs->sc_ioc.c_nop2, 4));
868 printf("%s", hexstr(*(u_int *)&rs->sc_ioc.c_len, 8));
869 printf("%s\n", hexstr(*(u_short *)&rs->sc_ioc.c_cmd, 4));
870 return(1);
871 }
872 #endif
873 printf(" v%d u%d, R0x%x F0x%x A0x%x I0x%x\n",
874 (sp->c_vu>>4)&0xF, sp->c_vu&0xF,
875 sp->c_ref, sp->c_fef, sp->c_aef, sp->c_ief);
876 printf("P1-P10: ");
877 printf("%s", hexstr(*(u_int *)&sp->c_raw[0], 8));
878 printf("%s", hexstr(*(u_int *)&sp->c_raw[4], 8));
879 printf("%s\n", hexstr(*(u_short *)&sp->c_raw[8], 4));
880 return(1);
881 }
882
883 int
rdread(dev,uio,flags)884 rdread(dev, uio, flags)
885 dev_t dev;
886 struct uio *uio;
887 int flags;
888 {
889
890 return (physio(rdstrategy, NULL, dev, B_READ, minphys, uio));
891 }
892
893 int
rdwrite(dev,uio,flags)894 rdwrite(dev, uio, flags)
895 dev_t dev;
896 struct uio *uio;
897 int flags;
898 {
899
900 return (physio(rdstrategy, NULL, dev, B_WRITE, minphys, uio));
901 }
902
903 int
rdioctl(dev,cmd,data,flag,p)904 rdioctl(dev, cmd, data, flag, p)
905 dev_t dev;
906 u_long cmd;
907 caddr_t data;
908 int flag;
909 struct proc *p;
910 {
911 int unit = rdunit(dev);
912 register struct rd_softc *sc = &rd_softc[unit];
913 register struct disklabel *lp = &sc->sc_info.ri_label;
914 int error, flags;
915
916 switch (cmd) {
917 case DIOCGDINFO:
918 *(struct disklabel *)data = *lp;
919 return (0);
920
921 case DIOCGPART:
922 ((struct partinfo *)data)->disklab = lp;
923 ((struct partinfo *)data)->part =
924 &lp->d_partitions[rdpart(dev)];
925 return (0);
926
927 case DIOCWLABEL:
928 if ((flag & FWRITE) == 0)
929 return (EBADF);
930 if (*(int *)data)
931 sc->sc_flags |= RDF_WLABEL;
932 else
933 sc->sc_flags &= ~RDF_WLABEL;
934 return (0);
935
936 case DIOCSDINFO:
937 if ((flag & FWRITE) == 0)
938 return (EBADF);
939 return (setdisklabel(lp, (struct disklabel *)data,
940 (sc->sc_flags & RDF_WLABEL) ? 0
941 : sc->sc_info.ri_open));
942
943 case DIOCWDINFO:
944 if ((flag & FWRITE) == 0)
945 return (EBADF);
946 error = setdisklabel(lp, (struct disklabel *)data,
947 (sc->sc_flags & RDF_WLABEL) ? 0
948 : sc->sc_info.ri_open);
949 if (error)
950 return (error);
951 flags = sc->sc_flags;
952 sc->sc_flags = RDF_ALIVE | RDF_WLABEL;
953 error = writedisklabel(rdlabdev(dev), rdstrategy, lp);
954 sc->sc_flags = flags;
955 return (error);
956 }
957 return(EINVAL);
958 }
959
960 int
rdsize(dev)961 rdsize(dev)
962 dev_t dev;
963 {
964 register int unit = rdunit(dev);
965 register struct rd_softc *rs = &rd_softc[unit];
966 int psize, didopen = 0;
967
968 if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
969 return(-1);
970
971 /*
972 * We get called very early on (via swapconf)
973 * without the device being open so we may need
974 * to handle it here.
975 */
976 if (rs->sc_info.ri_open == 0) {
977 if (rdopen(dev, FREAD|FWRITE, S_IFBLK, NULL))
978 return(-1);
979 didopen = 1;
980 }
981 psize = rs->sc_info.ri_label.d_partitions[rdpart(dev)].p_size;
982 if (didopen)
983 (void) rdclose(dev, FREAD|FWRITE, S_IFBLK, NULL);
984 return (psize);
985 }
986
987 #ifdef DEBUG
rdprinterr(str,err,tab)988 rdprinterr(str, err, tab)
989 char *str;
990 short err;
991 char *tab[];
992 {
993 register int i;
994 int printed;
995
996 if (err == 0)
997 return;
998 printf(" %s error field:", str, err);
999 printed = 0;
1000 for (i = 0; i < 16; i++)
1001 if (err & (0x8000 >> i))
1002 printf("%s%s", printed++ ? " + " : " ", tab[i]);
1003 printf("\n");
1004 }
1005 #endif
1006
1007 /*
1008 * Non-interrupt driven, non-dma dump routine.
1009 */
1010 int
rddump(dev)1011 rddump(dev)
1012 dev_t dev;
1013 {
1014 int part = rdpart(dev);
1015 int unit = rdunit(dev);
1016 register struct rd_softc *rs = &rd_softc[unit];
1017 register struct hp_device *hp = rs->sc_hd;
1018 register struct partition *pinfo;
1019 register daddr_t baddr;
1020 register int maddr, pages, i;
1021 char stat;
1022 extern int lowram, dumpsize;
1023 #ifdef DEBUG
1024 extern int pmapdebug;
1025 pmapdebug = 0;
1026 #endif
1027
1028 /* is drive ok? */
1029 if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
1030 return (ENXIO);
1031 pinfo = &rs->sc_info.ri_label.d_partitions[part];
1032 /* dump parameters in range? */
1033 if (dumplo < 0 || dumplo >= pinfo->p_size ||
1034 pinfo->p_fstype != FS_SWAP)
1035 return (EINVAL);
1036 pages = dumpsize;
1037 if (dumplo + ctod(pages) > pinfo->p_size)
1038 pages = dtoc(pinfo->p_size - dumplo);
1039 maddr = lowram;
1040 baddr = dumplo + pinfo->p_offset;
1041 /* HPIB idle? */
1042 if (!hpibreq(&rs->sc_dq)) {
1043 hpibreset(hp->hp_ctlr);
1044 rdreset(rs, rs->sc_hd);
1045 printf("[ drive %d reset ] ", unit);
1046 }
1047 for (i = 0; i < pages; i++) {
1048 #define NPGMB (1024*1024/NBPG)
1049 /* print out how many Mbs we have dumped */
1050 if (i && (i % NPGMB) == 0)
1051 printf("%d ", i / NPGMB);
1052 #undef NPBMG
1053 rs->sc_ioc.c_unit = C_SUNIT(rs->sc_punit);
1054 rs->sc_ioc.c_volume = C_SVOL(0);
1055 rs->sc_ioc.c_saddr = C_SADDR;
1056 rs->sc_ioc.c_hiaddr = 0;
1057 rs->sc_ioc.c_addr = RDBTOS(baddr);
1058 rs->sc_ioc.c_nop2 = C_NOP;
1059 rs->sc_ioc.c_slen = C_SLEN;
1060 rs->sc_ioc.c_len = NBPG;
1061 rs->sc_ioc.c_cmd = C_WRITE;
1062 hpibsend(hp->hp_ctlr, hp->hp_slave, C_CMD,
1063 &rs->sc_ioc.c_unit, sizeof(rs->sc_ioc)-2);
1064 if (hpibswait(hp->hp_ctlr, hp->hp_slave))
1065 return (EIO);
1066 pmap_enter(kernel_pmap, (vm_offset_t)vmmap, maddr,
1067 VM_PROT_READ, TRUE);
1068 hpibsend(hp->hp_ctlr, hp->hp_slave, C_EXEC, vmmap, NBPG);
1069 (void) hpibswait(hp->hp_ctlr, hp->hp_slave);
1070 hpibrecv(hp->hp_ctlr, hp->hp_slave, C_QSTAT, &stat, 1);
1071 if (stat)
1072 return (EIO);
1073 maddr += NBPG;
1074 baddr += ctod(1);
1075 }
1076 return (0);
1077 }
1078 #endif
1079