Annotation of sys/arch/hp300/dev/hd.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: hd.c,v 1.53 2007/06/21 20:23:07 miod Exp $ */
2: /* $NetBSD: rd.c,v 1.33 1997/07/10 18:14:08 kleink Exp $ */
3:
4: /*
5: * Copyright (c) 1996, 1997 Jason R. Thorpe. All rights reserved.
6: * Copyright (c) 1988 University of Utah.
7: * Copyright (c) 1982, 1990, 1993
8: * The Regents of the University of California. All rights reserved.
9: *
10: * This code is derived from software contributed to Berkeley by
11: * the Systems Programming Group of the University of Utah Computer
12: * Science Department.
13: *
14: * Redistribution and use in source and binary forms, with or without
15: * modification, are permitted provided that the following conditions
16: * are met:
17: * 1. Redistributions of source code must retain the above copyright
18: * notice, this list of conditions and the following disclaimer.
19: * 2. Redistributions in binary form must reproduce the above copyright
20: * notice, this list of conditions and the following disclaimer in the
21: * documentation and/or other materials provided with the distribution.
22: * 3. Neither the name of the University nor the names of its contributors
23: * may be used to endorse or promote products derived from this software
24: * without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36: * SUCH DAMAGE.
37: *
38: * from: Utah $Hdr: rd.c 1.44 92/12/26$
39: *
40: * @(#)rd.c 8.2 (Berkeley) 5/19/94
41: */
42:
43: /*
44: * CS80/SS80 disk driver
45: */
46:
47: #include <sys/param.h>
48: #include <sys/systm.h>
49: #include <sys/buf.h>
50: #include <sys/conf.h>
51: #include <sys/device.h>
52: #include <sys/disk.h>
53: #include <sys/disklabel.h>
54: #include <sys/fcntl.h>
55: #include <sys/ioctl.h>
56: #include <sys/kernel.h>
57: #include <sys/proc.h>
58: #include <sys/stat.h>
59: #include <sys/syslog.h>
60:
61: #include <ufs/ffs/fs.h> /* for BBSIZE and SBSIZE */
62:
63: #include <hp300/dev/hpibvar.h>
64:
65: #include <hp300/dev/hdreg.h>
66: #include <hp300/dev/hdvar.h>
67:
68: #ifdef USELEDS
69: #include <hp300/hp300/leds.h>
70: #endif
71:
72: #ifndef HDRETRY
73: #define HDRETRY 5
74: #endif
75:
76: #ifndef HDWAITC
77: #define HDWAITC 1 /* min time for timeout in seconds */
78: #endif
79:
80: int hderrthresh = HDRETRY - 1; /* when to start reporting errors */
81:
82: #ifdef DEBUG
83: /* error message tables */
84: const char *err_reject[16] = {
85: NULL,
86: NULL,
87: "channel parity error", /* 0x2000 */
88: NULL,
89: NULL,
90: "illegal opcode", /* 0x0400 */
91: "module addressing", /* 0x0200 */
92: "address bounds", /* 0x0100 */
93: "parameter bounds", /* 0x0080 */
94: "illegal parameter", /* 0x0040 */
95: "message sequence", /* 0x0020 */
96: NULL,
97: "message length", /* 0x0008 */
98: NULL,
99: NULL,
100: NULL
101: };
102:
103: const char *err_fault[16] = {
104: NULL,
105: "cross unit", /* 0x4000 */
106: NULL,
107: "controller fault", /* 0x1000 */
108: NULL,
109: NULL,
110: "unit fault", /* 0x0200 */
111: NULL,
112: "diagnostic result", /* 0x0080 */
113: NULL,
114: "operator release request", /* 0x0020 */
115: "diagnostic release request", /* 0x0010 */
116: "internal maintenance release request", /* 0x0008 */
117: NULL,
118: "power fail", /* 0x0002 */
119: "retransmit" /* 0x0001 */
120: };
121:
122: const char *err_access[16] = {
123: "illegal parallel operation", /* 0x8000 */
124: "uninitialized media", /* 0x4000 */
125: "no spares available", /* 0x2000 */
126: "not ready", /* 0x1000 */
127: "write protect", /* 0x0800 */
128: "no data found", /* 0x0400 */
129: NULL,
130: NULL,
131: "unrecoverable data overflow", /* 0x0080 */
132: "unrecoverable data", /* 0x0040 */
133: NULL,
134: "end of file", /* 0x0010 */
135: "end of volume", /* 0x0008 */
136: NULL,
137: NULL,
138: NULL
139: };
140:
141: const char *err_info[16] = {
142: "operator release request", /* 0x8000 */
143: "diagnostic release request", /* 0x4000 */
144: "internal maintenance release request", /* 0x2000 */
145: "media wear", /* 0x1000 */
146: "latency induced", /* 0x0800 */
147: NULL,
148: NULL,
149: "auto sparing invoked", /* 0x0100 */
150: NULL,
151: "recoverable data overflow", /* 0x0040 */
152: "marginal data", /* 0x0020 */
153: "recoverable data", /* 0x0010 */
154: NULL,
155: "maintenance track overflow", /* 0x0004 */
156: NULL,
157: NULL
158: };
159:
160: #define HDB_FOLLOW 0x01
161: #define HDB_STATUS 0x02
162: #define HDB_IDENT 0x04
163: #define HDB_IO 0x08
164: #define HDB_ASYNC 0x10
165: #define HDB_ERROR 0x80
166: int hddebug = HDB_ERROR | HDB_IDENT;
167: #endif
168:
169: /*
170: * Misc. HW description, indexed by sc_type.
171: * Nothing really critical here, could do without it.
172: */
173: const struct hdidentinfo hdidentinfo[] = {
174: { HD7946AID, 0, "7945A", NHD7945ABPT,
175: NHD7945ATRK, 968, 108416 },
176:
177: { HD9134DID, 1, "9134D", NHD9134DBPT,
178: NHD9134DTRK, 303, 29088 },
179:
180: { HD9134LID, 1, "9122S", NHD9122SBPT,
181: NHD9122STRK, 77, 1232 },
182:
183: { HD7912PID, 0, "7912P", NHD7912PBPT,
184: NHD7912PTRK, 572, 128128 },
185:
186: { HD7914PID, 0, "7914P", NHD7914PBPT,
187: NHD7914PTRK, 1152, 258048 },
188:
189: { HD7958AID, 0, "7958A", NHD7958ABPT,
190: NHD7958ATRK, 1013, 255276 },
191:
192: { HD7957AID, 0, "7957A", NHD7957ABPT,
193: NHD7957ATRK, 1036, 159544 },
194:
195: { HD7933HID, 0, "7933H", NHD7933HBPT,
196: NHD7933HTRK, 1321, 789958 },
197:
198: { HD9134LID, 1, "9134L", NHD9134LBPT,
199: NHD9134LTRK, 973, 77840 },
200:
201: { HD7936HID, 0, "7936H", NHD7936HBPT,
202: NHD7936HTRK, 698, 600978 },
203:
204: { HD7937HID, 0, "7937H", NHD7937HBPT,
205: NHD7937HTRK, 698, 1116102 },
206:
207: { HD7914CTID, 0, "7914CT", NHD7914PBPT,
208: NHD7914PTRK, 1152, 258048 },
209:
210: { HD7946AID, 0, "7946A", NHD7945ABPT,
211: NHD7945ATRK, 968, 108416 },
212:
213: { HD9134LID, 1, "9122D", NHD9122SBPT,
214: NHD9122STRK, 77, 1232 },
215:
216: { HD7957BID, 0, "7957B", NHD7957BBPT,
217: NHD7957BTRK, 1269, 159894 },
218:
219: { HD7958BID, 0, "7958B", NHD7958BBPT,
220: NHD7958BTRK, 786, 297108 },
221:
222: { HD7959BID, 0, "7959B", NHD7959BBPT,
223: NHD7959BTRK, 1572, 594216 },
224:
225: { HD2200AID, 0, "2200A", NHD2200ABPT,
226: NHD2200ATRK, 1449, 654948 },
227:
228: { HD2203AID, 0, "2203A", NHD2203ABPT,
229: NHD2203ATRK, 1449, 1309896 }
230: };
231: const int numhdidentinfo = sizeof(hdidentinfo) / sizeof(hdidentinfo[0]);
232:
233: bdev_decl(hd);
234: cdev_decl(hd);
235:
236: int hdident(struct device *, struct hd_softc *,
237: struct hpibbus_attach_args *);
238: void hdreset(int, int, int);
239: void hdustart(struct hd_softc *);
240: void hdgetdisklabel(dev_t, struct hd_softc *, struct disklabel *, int);
241: void hdrestart(void *);
242: struct buf *hdfinish(struct hd_softc *, struct buf *);
243:
244: void hdstart(void *);
245: void hdinterrupt(void *);
246: void hdgo(void *);
247: int hdstatus(struct hd_softc *);
248: int hderror(int);
249: #ifdef DEBUG
250: void hdprinterr(const char *, short, const char **);
251: #endif
252:
253: int hdmatch(struct device *, void *, void *);
254: void hdattach(struct device *, struct device *, void *);
255:
256: struct cfattach hd_ca = {
257: sizeof(struct hd_softc), hdmatch, hdattach
258: };
259:
260: struct cfdriver hd_cd = {
261: NULL, "hd", DV_DISK
262: };
263:
264: #define hdlock(rs) disk_lock(&(rs)->sc_dkdev)
265: #define hdunlock(rs) disk_unlock(&(rs)->sc_dkdev)
266: #define hdlookup(unit) (struct hd_softc *)device_lookup(&hd_cd, (unit))
267:
268: int
269: hdmatch(parent, match, aux)
270: struct device *parent;
271: void *match, *aux;
272: {
273: struct hpibbus_attach_args *ha = aux;
274:
275: return (hdident(parent, NULL, ha));
276: }
277:
278: void
279: hdattach(parent, self, aux)
280: struct device *parent, *self;
281: void *aux;
282: {
283: struct hd_softc *sc = (struct hd_softc *)self;
284: struct hpibbus_attach_args *ha = aux;
285:
286: if (hdident(parent, sc, ha) == 0) {
287: printf("\n%s: didn't respond to describe command!\n",
288: sc->sc_dev.dv_xname);
289: return;
290: }
291:
292: /*
293: * Initialize and attach the disk structure.
294: */
295: bzero(&sc->sc_dkdev, sizeof(sc->sc_dkdev));
296: sc->sc_dkdev.dk_name = sc->sc_dev.dv_xname;
297: disk_attach(&sc->sc_dkdev);
298:
299: sc->sc_slave = ha->ha_slave;
300: sc->sc_punit = ha->ha_punit;
301:
302: /* Initialize the hpib job queue entry */
303: sc->sc_hq.hq_softc = sc;
304: sc->sc_hq.hq_slave = sc->sc_slave;
305: sc->sc_hq.hq_start = hdstart;
306: sc->sc_hq.hq_go = hdgo;
307: sc->sc_hq.hq_intr = hdinterrupt;
308:
309: #ifdef DEBUG
310: /* always report errors */
311: if (hddebug & HDB_ERROR)
312: hderrthresh = 0;
313: #endif
314:
315: /* Initialize timeout structure */
316: timeout_set(&sc->sc_timeout, hdrestart, sc);
317: }
318:
319: int
320: hdident(parent, sc, ha)
321: struct device *parent;
322: struct hd_softc *sc;
323: struct hpibbus_attach_args *ha;
324: {
325: struct cs80_describe desc;
326: u_char stat, cmd[3];
327: char name[7];
328: int i, id, n, ctlr, slave;
329:
330: ctlr = parent->dv_unit;
331: slave = ha->ha_slave;
332:
333: /* Verify that we have a CS80 device. */
334: if ((ha->ha_id & 0x200) == 0)
335: return (0);
336:
337: /* Is it one of the disks we support? */
338: for (id = 0; id < numhdidentinfo; id++)
339: if (ha->ha_id == hdidentinfo[id].ri_hwid &&
340: ha->ha_punit <= hdidentinfo[id].ri_maxunum)
341: break;
342: if (id == numhdidentinfo)
343: return (0);
344:
345: /*
346: * Reset device and collect description
347: */
348: bzero(&desc, sizeof(desc));
349: stat = 0;
350: hdreset(ctlr, slave, ha->ha_punit);
351: cmd[0] = C_SUNIT(ha->ha_punit);
352: cmd[1] = C_SVOL(0);
353: cmd[2] = C_DESC;
354: hpibsend(ctlr, slave, C_CMD, cmd, sizeof(cmd));
355: hpibrecv(ctlr, slave, C_EXEC, &desc, sizeof(desc));
356: hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
357:
358: if (desc.d_name == 0 && stat != 0)
359: return (0);
360:
361: /*
362: * If we're just probing for the device, that's all the
363: * work we need to do.
364: */
365: if (sc == NULL)
366: return (1);
367:
368: bzero(name, sizeof(name));
369: n = desc.d_name;
370: for (i = 5; i >= 0; i--) {
371: name[i] = (n & 0xf) + '0';
372: n >>= 4;
373: }
374:
375: #ifdef DEBUG
376: if (hddebug & HDB_IDENT) {
377: printf(": stat %d name: %x ('%s')\n", stat, desc.d_name, name);
378: printf(" iuw %x, maxxfr %d, ctype %d\n",
379: desc.d_iuw, desc.d_cmaxxfr, desc.d_ctype);
380: printf(" utype %d, bps %d, blkbuf %d, burst %d, blktime %d\n",
381: desc.d_utype, desc.d_sectsize,
382: desc.d_blkbuf, desc.d_burstsize, desc.d_blocktime);
383: printf(" avxfr %d, ort %d, atp %d, maxint %d, fv %x, rv %x\n",
384: desc.d_uavexfr, desc.d_retry, desc.d_access,
385: desc.d_maxint, desc.d_fvbyte, desc.d_rvbyte);
386: printf(" maxcyl/head/sect %d/%d/%d, maxvsect %d, inter %d\n",
387: desc.d_maxcyl, desc.d_maxhead, desc.d_maxsect,
388: desc.d_maxvsectl, desc.d_interleave);
389: printf("%s:", sc->sc_dev.dv_xname);
390: }
391: #endif
392:
393: /*
394: * Take care of a couple of anomalies:
395: * 1. 7945A and 7946A both return same HW id
396: * 2. 9122S and 9134D both return same HW id
397: * 3. 9122D and 9134L both return same HW id
398: */
399: switch (ha->ha_id) {
400: case HD7946AID:
401: if (bcmp(name, "079450", 6) == 0)
402: id = HD7945A;
403: else
404: id = HD7946A;
405: break;
406:
407: case HD9134LID:
408: if (bcmp(name, "091340", 6) == 0)
409: id = HD9134L;
410: else
411: id = HD9122D;
412: break;
413:
414: case HD9134DID:
415: if (bcmp(name, "091220", 6) == 0)
416: id = HD9122S;
417: else
418: id = HD9134D;
419: break;
420: }
421:
422: sc->sc_type = id;
423:
424: /*
425: * XXX We use DEV_BSIZE instead of the sector size value pulled
426: * XXX off the driver because all of this code assumes 512 byte
427: * XXX blocks. ICK!
428: */
429: printf(": %s\n", hdidentinfo[id].ri_desc);
430: printf("%s: %luMB, %lu cyl, %lu head, %lu sec, %lu bytes/sec, %lu sec total\n",
431: sc->sc_dev.dv_xname,
432: hdidentinfo[id].ri_nblocks / (1048576 / DEV_BSIZE),
433: hdidentinfo[id].ri_ncyl, hdidentinfo[id].ri_ntpc,
434: hdidentinfo[id].ri_nbpt, DEV_BSIZE, hdidentinfo[id].ri_nblocks);
435:
436: return (1);
437: }
438:
439: void
440: hdreset(ctlr, slave, punit)
441: int ctlr, slave, punit;
442: {
443: struct hd_ssmcmd ssmc;
444: struct hd_srcmd src;
445: struct hd_clearcmd clear;
446: u_char stat;
447:
448: bzero(&clear, sizeof(clear));
449: clear.c_unit = C_SUNIT(punit);
450: clear.c_cmd = C_CLEAR;
451: hpibsend(ctlr, slave, C_TCMD, &clear, sizeof(clear));
452: hpibswait(ctlr, slave);
453: hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
454:
455: bzero(&src, sizeof(src));
456: src.c_unit = C_SUNIT(HDCTLR);
457: src.c_nop = C_NOP;
458: src.c_cmd = C_SREL;
459: src.c_param = C_REL;
460: hpibsend(ctlr, slave, C_CMD, &src, sizeof(src));
461: hpibswait(ctlr, slave);
462: hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
463:
464: bzero(&ssmc, sizeof(ssmc));
465: ssmc.c_unit = C_SUNIT(punit);
466: ssmc.c_cmd = C_SSM;
467: ssmc.c_refm = REF_MASK;
468: ssmc.c_fefm = FEF_MASK;
469: ssmc.c_aefm = AEF_MASK;
470: ssmc.c_iefm = IEF_MASK;
471: hpibsend(ctlr, slave, C_CMD, &ssmc, sizeof(ssmc));
472: hpibswait(ctlr, slave);
473: hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
474: }
475:
476: /*
477: * Read or construct a disklabel
478: */
479: void
480: hdgetdisklabel(dev, rs, lp, spoofonly)
481: dev_t dev;
482: struct hd_softc *rs;
483: struct disklabel *lp;
484: int spoofonly;
485: {
486: char *errstring;
487:
488: bzero(lp, sizeof(struct disklabel));
489:
490: /*
491: * Create a default disk label based on geometry.
492: * This will get overridden if there is a real label on the disk.
493: */
494: lp->d_secsize = DEV_BSIZE;
495: lp->d_ntracks = hdidentinfo[rs->sc_type].ri_ntpc;
496: lp->d_nsectors = hdidentinfo[rs->sc_type].ri_nbpt;
497: lp->d_ncylinders = hdidentinfo[rs->sc_type].ri_ncyl;
498: lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
499: if (lp->d_secpercyl == 0) {
500: lp->d_secpercyl = 100;
501: /* as long as it's not 0 - readdisklabel divides by it */
502: }
503:
504: lp->d_type = DTYPE_HPIB;
505: strncpy(lp->d_typename, hdidentinfo[rs->sc_type].ri_desc,
506: sizeof(lp->d_typename));
507: strncpy(lp->d_packname, "fictitious", sizeof lp->d_packname);
508:
509: DL_SETDSIZE(lp, hdidentinfo[rs->sc_type].ri_nblocks);
510: lp->d_rpm = 3600;
511: lp->d_interleave = 1;
512: lp->d_flags = 0;
513: lp->d_version = 1;
514:
515: /* XXX - these values for BBSIZE and SBSIZE assume ffs */
516: lp->d_bbsize = BBSIZE;
517: lp->d_sbsize = SBSIZE;
518:
519: lp->d_magic = DISKMAGIC;
520: lp->d_magic2 = DISKMAGIC;
521: lp->d_checksum = dkcksum(lp);
522:
523: /*
524: * Now try to read the disklabel
525: */
526: errstring = readdisklabel(DISKLABELDEV(dev), hdstrategy, lp,
527: spoofonly);
528: if (errstring) {
529: /* printf("%s: %s\n", rs->sc_dev.dv_xname, errstring); */
530: return;
531: }
532: }
533:
534: int
535: hdopen(dev, flags, mode, p)
536: dev_t dev;
537: int flags, mode;
538: struct proc *p;
539: {
540: int unit = DISKUNIT(dev);
541: struct hd_softc *rs;
542: int mask, part;
543: int error;
544:
545: rs = hdlookup(unit);
546: if (rs == NULL)
547: return (ENXIO);
548:
549: if ((error = hdlock(rs)) != 0) {
550: device_unref(&rs->sc_dev);
551: return (error);
552: }
553:
554: /*
555: * On first open, get label and partition info.
556: * We may block reading the label, so be careful
557: * to stop any other opens.
558: */
559: if (rs->sc_dkdev.dk_openmask == 0) {
560: rs->sc_flags |= HDF_OPENING;
561: hdgetdisklabel(dev, rs, rs->sc_dkdev.dk_label, 0);
562: rs->sc_flags &= ~HDF_OPENING;
563: }
564:
565: part = DISKPART(dev);
566: mask = 1 << part;
567:
568: /* Check that the partition exists. */
569: if (part != RAW_PART &&
570: (part > rs->sc_dkdev.dk_label->d_npartitions ||
571: rs->sc_dkdev.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
572: error = ENXIO;
573: goto out;
574: }
575:
576: /* Ensure only one open at a time. */
577: switch (mode) {
578: case S_IFCHR:
579: rs->sc_dkdev.dk_copenmask |= mask;
580: break;
581: case S_IFBLK:
582: rs->sc_dkdev.dk_bopenmask |= mask;
583: break;
584: }
585: rs->sc_dkdev.dk_openmask =
586: rs->sc_dkdev.dk_copenmask | rs->sc_dkdev.dk_bopenmask;
587:
588: error = 0;
589: out:
590: hdunlock(rs);
591: device_unref(&rs->sc_dev);
592: return (error);
593: }
594:
595: int
596: hdclose(dev, flag, mode, p)
597: dev_t dev;
598: int flag, mode;
599: struct proc *p;
600: {
601: int unit = DISKUNIT(dev);
602: struct hd_softc *rs;
603: struct disk *dk;
604: int mask, s;
605: int error;
606:
607: rs = hdlookup(unit);
608: if (rs == NULL)
609: return (ENXIO);
610:
611: if ((error = hdlock(rs)) != 0) {
612: device_unref(&rs->sc_dev);
613: return (error);
614: }
615:
616: mask = 1 << DISKPART(dev);
617: dk = &rs->sc_dkdev;
618: switch (mode) {
619: case S_IFCHR:
620: dk->dk_copenmask &= ~mask;
621: break;
622: case S_IFBLK:
623: dk->dk_bopenmask &= ~mask;
624: break;
625: }
626: dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask;
627:
628: /*
629: * On last close, we wait for all activity to cease since
630: * the label/parition info will become invalid.
631: * Note we don't have to about other closes since we know
632: * we are the last one.
633: */
634: if (dk->dk_openmask == 0) {
635: rs->sc_flags |= HDF_CLOSING;
636: s = splbio();
637: while (rs->sc_tab.b_active) {
638: rs->sc_flags |= HDF_WANTED;
639: tsleep((caddr_t)&rs->sc_tab, PRIBIO, "hdclose", 0);
640: }
641: splx(s);
642: rs->sc_flags &= ~(HDF_CLOSING);
643: }
644:
645: hdunlock(rs);
646: device_unref(&rs->sc_dev);
647: return (0);
648: }
649:
650: void
651: hdstrategy(bp)
652: struct buf *bp;
653: {
654: int unit = DISKUNIT(bp->b_dev);
655: struct hd_softc *rs;
656: struct buf *dp;
657: struct disklabel *lp;
658: int s;
659:
660: rs = hdlookup(unit);
661: if (rs == NULL) {
662: bp->b_error = ENXIO;
663: goto bad;
664: }
665:
666: #ifdef DEBUG
667: if (hddebug & HDB_FOLLOW)
668: printf("hdstrategy(%x): dev %x, bn %x, bcount %lx, %c\n",
669: bp, bp->b_dev, bp->b_blkno, bp->b_bcount,
670: (bp->b_flags & B_READ) ? 'R' : 'W');
671: #endif
672:
673: lp = rs->sc_dkdev.dk_label;
674:
675: /*
676: * If it's a null transfer, return immediately
677: */
678: if (bp->b_bcount == 0)
679: goto done;
680:
681: /*
682: * The transfer must be a whole number of blocks.
683: */
684: if ((bp->b_bcount % lp->d_secsize) != 0) {
685: bp->b_error = EINVAL;
686: goto bad;
687: }
688:
689: /*
690: * Do bounds checking, adjust transfer. if error, process;
691: * If end of partition, just return.
692: */
693: if (bounds_check_with_label(bp, lp,
694: (rs->sc_flags & HDF_WLABEL) != 0) <= 0)
695: goto done;
696:
697: s = splbio();
698: dp = &rs->sc_tab;
699: disksort(dp, bp);
700: if (dp->b_active == 0) {
701: dp->b_active = 1;
702: hdustart(rs);
703: }
704: splx(s);
705:
706: device_unref(&rs->sc_dev);
707: return;
708: bad:
709: bp->b_flags |= B_ERROR;
710: done:
711: /*
712: * Correctly set the buf to indicate a completed xfer
713: */
714: bp->b_resid = bp->b_bcount;
715: s = splbio();
716: biodone(bp);
717: splx(s);
718: if (rs != NULL)
719: device_unref(&rs->sc_dev);
720: }
721:
722: /*
723: * Called via timeout(9) when handling maintenance releases
724: */
725: void
726: hdrestart(arg)
727: void *arg;
728: {
729: int s = splbio();
730: hdustart((struct hd_softc *)arg);
731: splx(s);
732: }
733:
734: void
735: hdustart(rs)
736: struct hd_softc *rs;
737: {
738: struct buf *bp;
739:
740: bp = rs->sc_tab.b_actf;
741: rs->sc_addr = bp->b_data;
742: rs->sc_resid = bp->b_bcount;
743: if (hpibreq(rs->sc_dev.dv_parent, &rs->sc_hq))
744: hdstart(rs);
745: }
746:
747: struct buf *
748: hdfinish(rs, bp)
749: struct hd_softc *rs;
750: struct buf *bp;
751: {
752: struct buf *dp = &rs->sc_tab;
753: int s;
754:
755: rs->sc_errcnt = 0;
756: dp->b_actf = bp->b_actf;
757: bp->b_resid = 0;
758: s = splbio();
759: biodone(bp);
760: splx(s);
761: hpibfree(rs->sc_dev.dv_parent, &rs->sc_hq);
762: if (dp->b_actf)
763: return (dp->b_actf);
764: dp->b_active = 0;
765: if (rs->sc_flags & HDF_WANTED) {
766: rs->sc_flags &= ~HDF_WANTED;
767: wakeup((caddr_t)dp);
768: }
769: return (NULL);
770: }
771:
772: void
773: hdstart(arg)
774: void *arg;
775: {
776: struct hd_softc *rs = arg;
777: struct disklabel *lp;
778: struct buf *bp = rs->sc_tab.b_actf;
779: int ctlr, slave;
780: daddr64_t bn;
781:
782: ctlr = rs->sc_dev.dv_parent->dv_unit;
783: slave = rs->sc_slave;
784:
785: again:
786: #ifdef DEBUG
787: if (hddebug & HDB_FOLLOW)
788: printf("hdstart(%s): bp %p, %c\n", rs->sc_dev.dv_xname, bp,
789: (bp->b_flags & B_READ) ? 'R' : 'W');
790: #endif
791: lp = rs->sc_dkdev.dk_label;
792: bn = bp->b_blkno +
793: DL_GETPOFFSET(&lp->d_partitions[DISKPART(bp->b_dev)]);
794:
795: rs->sc_flags |= HDF_SEEK;
796: rs->sc_ioc.c_unit = C_SUNIT(rs->sc_punit);
797: rs->sc_ioc.c_volume = C_SVOL(0);
798: rs->sc_ioc.c_saddr = C_SADDR;
799: rs->sc_ioc.c_hiaddr = 0;
800: rs->sc_ioc.c_addr = HDBTOS(bn);
801: rs->sc_ioc.c_nop2 = C_NOP;
802: rs->sc_ioc.c_slen = C_SLEN;
803: rs->sc_ioc.c_len = rs->sc_resid;
804: rs->sc_ioc.c_cmd = bp->b_flags & B_READ ? C_READ : C_WRITE;
805: #ifdef DEBUG
806: if (hddebug & HDB_IO)
807: printf("hdstart: hpibsend(%x, %x, %x, %p, %x)\n",
808: ctlr, slave, C_CMD,
809: &rs->sc_ioc.c_unit, sizeof(rs->sc_ioc)-2);
810: #endif
811: if (hpibsend(ctlr, slave, C_CMD, &rs->sc_ioc.c_unit,
812: sizeof(rs->sc_ioc)-2) == sizeof(rs->sc_ioc)-2) {
813:
814: /* Instrumentation. */
815: disk_busy(&rs->sc_dkdev);
816: rs->sc_dkdev.dk_seek++;
817:
818: #ifdef DEBUG
819: if (hddebug & HDB_IO)
820: printf("hdstart: hpibawait(%x)\n", ctlr);
821: #endif
822: hpibawait(ctlr);
823: return;
824: }
825: /*
826: * Experience has shown that the hpibwait in this hpibsend will
827: * occasionally timeout. It appears to occur mostly on old 7914
828: * drives with full maintenance tracks. We should probably
829: * integrate this with the backoff code in hderror.
830: */
831: #ifdef DEBUG
832: if (hddebug & HDB_ERROR)
833: printf("%s: hdstart: cmd %x adr %lx blk %d len %d ecnt %ld\n",
834: rs->sc_dev.dv_xname, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr,
835: bp->b_blkno, rs->sc_resid, rs->sc_errcnt);
836: rs->sc_stats.hdretries++;
837: #endif
838: rs->sc_flags &= ~HDF_SEEK;
839: hdreset(rs->sc_dev.dv_parent->dv_unit, rs->sc_slave, rs->sc_punit);
840: if (rs->sc_errcnt++ < HDRETRY)
841: goto again;
842: printf("%s: hdstart err: err: cmd 0x%x sect %ld blk %d len %d\n",
843: rs->sc_dev.dv_xname, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr,
844: bp->b_blkno, rs->sc_resid);
845: bp->b_flags |= B_ERROR;
846: bp->b_error = EIO;
847: bp = hdfinish(rs, bp);
848: if (bp) {
849: rs->sc_addr = bp->b_data;
850: rs->sc_resid = bp->b_bcount;
851: if (hpibreq(rs->sc_dev.dv_parent, &rs->sc_hq))
852: goto again;
853: }
854: }
855:
856: void
857: hdgo(arg)
858: void *arg;
859: {
860: struct hd_softc *rs = arg;
861: struct buf *bp = rs->sc_tab.b_actf;
862: int rw, ctlr, slave;
863:
864: ctlr = rs->sc_dev.dv_parent->dv_unit;
865: slave = rs->sc_slave;
866:
867: rw = bp->b_flags & B_READ;
868:
869: /* Instrumentation. */
870: disk_busy(&rs->sc_dkdev);
871:
872: #ifdef USELEDS
873: ledcontrol(0, 0, LED_DISK);
874: #endif
875: hpibgo(ctlr, slave, C_EXEC, rs->sc_addr, rs->sc_resid, rw, rw != 0);
876: }
877:
878: /* ARGSUSED */
879: void
880: hdinterrupt(arg)
881: void *arg;
882: {
883: struct hd_softc *rs = arg;
884: int unit = rs->sc_dev.dv_unit;
885: struct buf *bp = rs->sc_tab.b_actf;
886: u_char stat = 13; /* in case hpibrecv fails */
887: int rv, restart, ctlr, slave;
888:
889: ctlr = rs->sc_dev.dv_parent->dv_unit;
890: slave = rs->sc_slave;
891:
892: #ifdef DEBUG
893: if (hddebug & HDB_FOLLOW)
894: printf("hdinterrupt(%d): bp %p, %c, flags %x\n", unit, bp,
895: (bp->b_flags & B_READ) ? 'R' : 'W', rs->sc_flags);
896: if (bp == NULL) {
897: printf("%s: bp == NULL\n", rs->sc_dev.dv_xname);
898: return;
899: }
900: #endif
901: disk_unbusy(&rs->sc_dkdev, (bp->b_bcount - bp->b_resid),
902: (bp->b_flags & B_READ));
903:
904: if (rs->sc_flags & HDF_SEEK) {
905: rs->sc_flags &= ~HDF_SEEK;
906: if (hpibustart(ctlr))
907: hdgo(rs);
908: return;
909: }
910: if ((rs->sc_flags & HDF_SWAIT) == 0) {
911: #ifdef DEBUG
912: rs->sc_stats.hdpolltries++;
913: #endif
914: if (hpibpptest(ctlr, slave) == 0) {
915: #ifdef DEBUG
916: rs->sc_stats.hdpollwaits++;
917: #endif
918:
919: /* Instrumentation. */
920: disk_busy(&rs->sc_dkdev);
921: rs->sc_flags |= HDF_SWAIT;
922: hpibawait(ctlr);
923: return;
924: }
925: } else
926: rs->sc_flags &= ~HDF_SWAIT;
927: rv = hpibrecv(ctlr, slave, C_QSTAT, &stat, 1);
928: if (rv != 1 || stat) {
929: #ifdef DEBUG
930: if (hddebug & HDB_ERROR)
931: printf("hdinterrupt: recv failed or bad stat %d\n", stat);
932: #endif
933: restart = hderror(unit);
934: #ifdef DEBUG
935: rs->sc_stats.hdretries++;
936: #endif
937: if (rs->sc_errcnt++ < HDRETRY) {
938: if (restart)
939: hdstart(rs);
940: return;
941: }
942: bp->b_flags |= B_ERROR;
943: bp->b_error = EIO;
944: }
945: if (hdfinish(rs, bp))
946: hdustart(rs);
947: }
948:
949: int
950: hdstatus(rs)
951: struct hd_softc *rs;
952: {
953: int c, s;
954: u_char stat;
955: int rv;
956:
957: c = rs->sc_dev.dv_parent->dv_unit;
958: s = rs->sc_slave;
959: rs->sc_rsc.c_unit = C_SUNIT(rs->sc_punit);
960: rs->sc_rsc.c_sram = C_SRAM;
961: rs->sc_rsc.c_ram = C_RAM;
962: rs->sc_rsc.c_cmd = C_STATUS;
963: bzero((caddr_t)&rs->sc_stat, sizeof(rs->sc_stat));
964: rv = hpibsend(c, s, C_CMD, &rs->sc_rsc, sizeof(rs->sc_rsc));
965: if (rv != sizeof(rs->sc_rsc)) {
966: #ifdef DEBUG
967: if (hddebug & HDB_STATUS)
968: printf("hdstatus: send C_CMD failed %d != %d\n",
969: rv, sizeof(rs->sc_rsc));
970: #endif
971: return(1);
972: }
973: rv = hpibrecv(c, s, C_EXEC, &rs->sc_stat, sizeof(rs->sc_stat));
974: if (rv != sizeof(rs->sc_stat)) {
975: #ifdef DEBUG
976: if (hddebug & HDB_STATUS)
977: printf("hdstatus: send C_EXEC failed %d != %d\n",
978: rv, sizeof(rs->sc_stat));
979: #endif
980: return(1);
981: }
982: rv = hpibrecv(c, s, C_QSTAT, &stat, 1);
983: if (rv != 1 || stat) {
984: #ifdef DEBUG
985: if (hddebug & HDB_STATUS)
986: printf("hdstatus: recv failed %d or bad stat %d\n",
987: rv, stat);
988: #endif
989: return(1);
990: }
991: return(0);
992: }
993:
994: /*
995: * Deal with errors.
996: * Returns 1 if request should be restarted,
997: * 0 if we should just quietly give up.
998: */
999: int
1000: hderror(unit)
1001: int unit;
1002: {
1003: struct hd_softc *rs = hd_cd.cd_devs[unit];
1004: struct hd_stat *sp;
1005: struct buf *bp;
1006: daddr64_t hwbn, pbn;
1007:
1008: if (hdstatus(rs)) {
1009: #ifdef DEBUG
1010: printf("%s: couldn't get status\n", rs->sc_dev.dv_xname);
1011: #endif
1012: hdreset(rs->sc_dev.dv_parent->dv_unit,
1013: rs->sc_slave, rs->sc_punit);
1014: return(1);
1015: }
1016: sp = &rs->sc_stat;
1017: if (sp->c_fef & FEF_REXMT)
1018: return(1);
1019: if (sp->c_fef & FEF_PF) {
1020: hdreset(rs->sc_dev.dv_parent->dv_unit,
1021: rs->sc_slave, rs->sc_punit);
1022: return(1);
1023: }
1024: /*
1025: * Unit requests release for internal maintenance.
1026: * We just delay a while and try again later. Use exponentially
1027: * increasing backoff a la ethernet drivers since we don't really
1028: * know how long the maintenance will take. With HDWAITC and
1029: * HDRETRY as defined, the range is 1 to 32 seconds.
1030: */
1031: if (sp->c_fef & FEF_IMR) {
1032: int hdtimo = HDWAITC << rs->sc_errcnt;
1033: #ifdef DEBUG
1034: printf("%s: internal maintenance, %d second timeout\n",
1035: rs->sc_dev.dv_xname, hdtimo);
1036: rs->sc_stats.hdtimeouts++;
1037: #endif
1038: hpibfree(rs->sc_dev.dv_parent, &rs->sc_hq);
1039: timeout_add(&rs->sc_timeout, hdtimo * hz);
1040: return(0);
1041: }
1042: /*
1043: * Only report error if we have reached the error reporting
1044: * threshold. By default, this will only report after the
1045: * retry limit has been exceeded.
1046: */
1047: if (rs->sc_errcnt < hderrthresh)
1048: return(1);
1049:
1050: /*
1051: * First conjure up the block number at which the error occurred.
1052: * Note that not all errors report a block number, in that case
1053: * we just use b_blkno.
1054: */
1055: bp = rs->sc_tab.b_actf;
1056: pbn = DL_GETPOFFSET(&rs->sc_dkdev.dk_label->d_partitions[DISKPART(bp->b_dev)]);
1057: if ((sp->c_fef & FEF_CU) || (sp->c_fef & FEF_DR) ||
1058: (sp->c_ief & IEF_RRMASK)) {
1059: hwbn = HDBTOS(pbn + bp->b_blkno);
1060: pbn = bp->b_blkno;
1061: } else {
1062: hwbn = sp->c_blk;
1063: pbn = HDSTOB(hwbn) - pbn;
1064: }
1065:
1066: diskerr(bp, hd_cd.cd_name, "hard error", LOG_PRINTF,
1067: pbn - bp->b_blkno, rs->sc_dkdev.dk_label);
1068: printf("\n%s%c: ", rs->sc_dev.dv_xname, 'a' + DISKPART(bp->b_dev));
1069:
1070: #ifdef DEBUG
1071: if (hddebug & HDB_ERROR) {
1072: /* status info */
1073: printf("volume: %d, unit: %d\n",
1074: (sp->c_vu>>4)&0xF, sp->c_vu&0xF);
1075: hdprinterr("reject", sp->c_ref, err_reject);
1076: hdprinterr("fault", sp->c_fef, err_fault);
1077: hdprinterr("access", sp->c_aef, err_access);
1078: hdprinterr("info", sp->c_ief, err_info);
1079: printf(" block: %d, P1-P10: ", hwbn);
1080: printf("0x%04x", *(u_int *)&sp->c_raw[0]);
1081: printf("%04x", *(u_int *)&sp->c_raw[4]);
1082: printf("%02x\n", *(u_short *)&sp->c_raw[8]);
1083: /* command */
1084: printf(" ioc: ");
1085: printf("0x%x", *(u_int *)&rs->sc_ioc.c_pad);
1086: printf("0x%x", *(u_short *)&rs->sc_ioc.c_hiaddr);
1087: printf("0x%x", *(u_int *)&rs->sc_ioc.c_addr);
1088: printf("0x%x", *(u_short *)&rs->sc_ioc.c_nop2);
1089: printf("0x%x", *(u_int *)&rs->sc_ioc.c_len);
1090: printf("0x%x\n", *(u_short *)&rs->sc_ioc.c_cmd);
1091: } else
1092: #endif
1093: {
1094: printf("v%d u%d, R0x%x F0x%x A0x%x I0x%x",
1095: (sp->c_vu>>4)&0xF, sp->c_vu&0xF,
1096: sp->c_ref, sp->c_fef, sp->c_aef, sp->c_ief);
1097: printf(" P1-P10: 0x%04x%04x%02x\n",
1098: *(u_int *)&sp->c_raw[0], *(u_int *)&sp->c_raw[4],
1099: *(u_short *)&sp->c_raw[8]);
1100: }
1101: return (1);
1102: }
1103:
1104: int
1105: hdread(dev, uio, flags)
1106: dev_t dev;
1107: struct uio *uio;
1108: int flags;
1109: {
1110:
1111: return (physio(hdstrategy, NULL, dev, B_READ, minphys, uio));
1112: }
1113:
1114: int
1115: hdwrite(dev, uio, flags)
1116: dev_t dev;
1117: struct uio *uio;
1118: int flags;
1119: {
1120:
1121: return (physio(hdstrategy, NULL, dev, B_WRITE, minphys, uio));
1122: }
1123:
1124: int
1125: hdioctl(dev, cmd, data, flag, p)
1126: dev_t dev;
1127: u_long cmd;
1128: caddr_t data;
1129: int flag;
1130: struct proc *p;
1131: {
1132: int unit = DISKUNIT(dev);
1133: struct hd_softc *sc;
1134: int error = 0;
1135:
1136: sc = hdlookup(unit);
1137: if (sc == NULL)
1138: return (ENXIO);
1139:
1140: switch (cmd) {
1141: case DIOCGPDINFO:
1142: hdgetdisklabel(dev, sc, (struct disklabel *)data, 1);
1143: goto exit;
1144:
1145: case DIOCGDINFO:
1146: *(struct disklabel *)data = *sc->sc_dkdev.dk_label;
1147: goto exit;
1148:
1149: case DIOCGPART:
1150: ((struct partinfo *)data)->disklab = sc->sc_dkdev.dk_label;
1151: ((struct partinfo *)data)->part =
1152: &sc->sc_dkdev.dk_label->d_partitions[DISKPART(dev)];
1153: goto exit;
1154:
1155: case DIOCWLABEL:
1156: if ((flag & FWRITE) == 0) {
1157: error = EBADF;
1158: goto exit;
1159: }
1160: if (*(int *)data)
1161: sc->sc_flags |= HDF_WLABEL;
1162: else
1163: sc->sc_flags &= ~HDF_WLABEL;
1164: goto exit;
1165:
1166: case DIOCWDINFO:
1167: case DIOCSDINFO:
1168: if ((flag & FWRITE) == 0) {
1169: error = EBADF;
1170: goto exit;
1171: }
1172:
1173: if ((error = hdlock(sc)) != 0)
1174: goto exit;
1175: sc->sc_flags |= HDF_WLABEL;
1176:
1177: error = setdisklabel(sc->sc_dkdev.dk_label,
1178: (struct disklabel *)data, /* sc->sc_dkdev.dk_openmask */ 0);
1179: if (error == 0) {
1180: if (cmd == DIOCWDINFO)
1181: error = writedisklabel(DISKLABELDEV(dev),
1182: hdstrategy, sc->sc_dkdev.dk_label);
1183: }
1184:
1185: sc->sc_flags &= ~HDF_WLABEL;
1186: hdunlock(sc);
1187: goto exit;
1188:
1189: default:
1190: error = EINVAL;
1191: break;
1192: }
1193:
1194: exit:
1195: device_unref(&sc->sc_dev);
1196: return (error);
1197: }
1198:
1199: daddr64_t
1200: hdsize(dev)
1201: dev_t dev;
1202: {
1203: struct hd_softc *rs;
1204: int unit = DISKUNIT(dev);
1205: int part, omask;
1206: int size;
1207:
1208: rs = hdlookup(unit);
1209: if (rs == NULL)
1210: return (-1);
1211:
1212: part = DISKPART(dev);
1213: omask = rs->sc_dkdev.dk_openmask & (1 << part);
1214:
1215: /*
1216: * We get called very early on (via swapconf)
1217: * without the device being open so we may need
1218: * to handle it here.
1219: */
1220: if (omask == 0 && hdopen(dev, FREAD | FWRITE, S_IFBLK, NULL) != 0) {
1221: size = -1;
1222: goto out;
1223: }
1224:
1225: if (rs->sc_dkdev.dk_label->d_partitions[part].p_fstype != FS_SWAP)
1226: size = -1;
1227: else
1228: size = DL_GETPSIZE(&rs->sc_dkdev.dk_label->d_partitions[part]) *
1229: (rs->sc_dkdev.dk_label->d_secsize / DEV_BSIZE);
1230:
1231: if (hdclose(dev, FREAD | FWRITE, S_IFBLK, NULL) != 0)
1232: size = -1;
1233:
1234: out:
1235: device_unref(&rs->sc_dev);
1236: return (size);
1237: }
1238:
1239: #ifdef DEBUG
1240: void
1241: hdprinterr(str, err, tab)
1242: const char *str;
1243: short err;
1244: const char **tab;
1245: {
1246: int i;
1247: int printed;
1248:
1249: if (err == 0)
1250: return;
1251: printf(" %s error %d field:", str, err);
1252: printed = 0;
1253: for (i = 0; i < 16; i++)
1254: if (err & (0x8000 >> i))
1255: printf("%s%s", printed++ ? " + " : " ", tab[i]);
1256: printf("\n");
1257: }
1258: #endif
1259:
1260: static int hddoingadump; /* simple mutex */
1261:
1262: /*
1263: * Non-interrupt driven, non-dma dump routine.
1264: */
1265: int
1266: hddump(dev, blkno, va, size)
1267: dev_t dev;
1268: daddr64_t blkno;
1269: caddr_t va;
1270: size_t size;
1271: {
1272: int sectorsize; /* size of a disk sector */
1273: daddr64_t nsects; /* number of sectors in partition */
1274: daddr64_t sectoff; /* sector offset of partition */
1275: int totwrt; /* total number of sectors left to write */
1276: int nwrt; /* current number of sectors to write */
1277: int unit, part;
1278: int ctlr, slave;
1279: struct hd_softc *rs;
1280: struct disklabel *lp;
1281: char stat;
1282:
1283: /* Check for recursive dump; if so, punt. */
1284: if (hddoingadump)
1285: return (EFAULT);
1286: hddoingadump = 1;
1287:
1288: /* Decompose unit and partition. */
1289: unit = DISKUNIT(dev);
1290: part = DISKPART(dev);
1291:
1292: /* Make sure dump device is ok. */
1293: rs = hdlookup(unit);
1294: if (rs == NULL)
1295: return (ENXIO);
1296: device_unref(&rs->sc_dev);
1297:
1298: ctlr = rs->sc_dev.dv_parent->dv_unit;
1299: slave = rs->sc_slave;
1300:
1301: /*
1302: * Convert to disk sectors. Request must be a multiple of size.
1303: */
1304: lp = rs->sc_dkdev.dk_label;
1305: sectorsize = lp->d_secsize;
1306: if ((size % sectorsize) != 0)
1307: return (EFAULT);
1308: totwrt = size / sectorsize;
1309: blkno = dbtob(blkno) / sectorsize; /* blkno in DEV_BSIZE units */
1310:
1311: nsects = DL_GETPSIZE(&lp->d_partitions[part]);
1312: sectoff = DL_GETPOFFSET(&lp->d_partitions[part]);
1313:
1314: /* Check transfer bounds against partition size. */
1315: if ((blkno < 0) || (blkno + totwrt) > nsects)
1316: return (EINVAL);
1317:
1318: /* Offset block number to start of partition. */
1319: blkno += sectoff;
1320:
1321: while (totwrt > 0) {
1322: nwrt = totwrt; /* XXX */
1323: #ifndef HD_DUMP_NOT_TRUSTED
1324: /*
1325: * Fill out and send HPIB command.
1326: */
1327: rs->sc_ioc.c_unit = C_SUNIT(rs->sc_punit);
1328: rs->sc_ioc.c_volume = C_SVOL(0);
1329: rs->sc_ioc.c_saddr = C_SADDR;
1330: rs->sc_ioc.c_hiaddr = 0;
1331: rs->sc_ioc.c_addr = HDBTOS(blkno);
1332: rs->sc_ioc.c_nop2 = C_NOP;
1333: rs->sc_ioc.c_slen = C_SLEN;
1334: rs->sc_ioc.c_len = nwrt * sectorsize;
1335: rs->sc_ioc.c_cmd = C_WRITE;
1336: hpibsend(ctlr, slave, C_CMD, &rs->sc_ioc.c_unit,
1337: sizeof(rs->sc_ioc)-2);
1338: if (hpibswait(ctlr, slave))
1339: return (EIO);
1340:
1341: /*
1342: * Send the data.
1343: */
1344: hpibsend(ctlr, slave, C_EXEC, va, nwrt * sectorsize);
1345: (void) hpibswait(ctlr, slave);
1346: hpibrecv(ctlr, slave, C_QSTAT, &stat, 1);
1347: if (stat)
1348: return (EIO);
1349: #else /* HD_DUMP_NOT_TRUSTED */
1350: /* Let's just talk about this first... */
1351: printf("%s: dump addr %p, blk %d\n", sc->sc_dev.dv_xname,
1352: va, blkno);
1353: delay(500 * 1000); /* half a second */
1354: #endif /* HD_DUMP_NOT_TRUSTED */
1355:
1356: /* update block count */
1357: totwrt -= nwrt;
1358: blkno += nwrt;
1359: va += sectorsize * nwrt;
1360: }
1361: hddoingadump = 0;
1362: return (0);
1363: }
CVSweb