1 /* $NetBSD: rd.c,v 1.88 2008/06/17 21:08:08 he Exp $ */
4 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Copyright (c) 1982, 1990, 1993
34 * The Regents of the University of California. All rights reserved.
36 * This code is derived from software contributed to Berkeley by
37 * the Systems Programming Group of the University of Utah Computer
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * from: Utah $Hdr: rd.c 1.44 92/12/26$
66 * @(#)rd.c 8.2 (Berkeley) 5/19/94
69 * Copyright (c) 1988 University of Utah.
71 * This code is derived from software contributed to Berkeley by
72 * the Systems Programming Group of the University of Utah Computer
75 * Redistribution and use in source and binary forms, with or without
76 * modification, are permitted provided that the following conditions
78 * 1. Redistributions of source code must retain the above copyright
79 * notice, this list of conditions and the following disclaimer.
80 * 2. Redistributions in binary form must reproduce the above copyright
81 * notice, this list of conditions and the following disclaimer in the
82 * documentation and/or other materials provided with the distribution.
83 * 3. All advertising materials mentioning features or use of this software
84 * must display the following acknowledgement:
85 * This product includes software developed by the University of
86 * California, Berkeley and its contributors.
87 * 4. Neither the name of the University nor the names of its contributors
88 * may be used to endorse or promote products derived from this software
89 * without specific prior written permission.
91 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
92 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
94 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
95 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
96 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
97 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
98 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
99 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
100 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
103 * from: Utah $Hdr: rd.c 1.44 92/12/26$
105 * @(#)rd.c 8.2 (Berkeley) 5/19/94
109 * CS80/SS80 disk driver
112 #include <sys/cdefs.h>
113 __KERNEL_RCSID(0, "$NetBSD: rd.c,v 1.88 2008/06/17 21:08:08 he Exp $");
115 #include "opt_useleds.h"
118 #include <sys/param.h>
119 #include <sys/systm.h>
121 #include <sys/bufq.h>
122 #include <sys/conf.h>
123 #include <sys/device.h>
124 #include <sys/disk.h>
125 #include <sys/disklabel.h>
126 #include <sys/fcntl.h>
127 #include <sys/ioctl.h>
128 #include <sys/proc.h>
129 #include <sys/stat.h>
135 #include <hp300/dev/hpibvar.h>
137 #include <hp300/dev/rdreg.h>
138 #include <hp300/dev/rdvar.h>
141 #include <hp300/hp300/leds.h>
146 int rderrthresh
= RDRETRY
-1; /* when to start reporting errors */
149 /* error message tables */
150 static const char *err_reject
[] = {
152 "channel parity error", /* 0x2000 */
154 "illegal opcode", /* 0x0400 */
155 "module addressing", /* 0x0200 */
156 "address bounds", /* 0x0100 */
157 "parameter bounds", /* 0x0080 */
158 "illegal parameter", /* 0x0040 */
159 "message sequence", /* 0x0020 */
161 "message length", /* 0x0008 */
165 static const char *err_fault
[] = {
167 "cross unit", /* 0x4000 */
169 "controller fault", /* 0x1000 */
171 "unit fault", /* 0x0200 */
173 "diagnostic result", /* 0x0080 */
175 "operator release request", /* 0x0020 */
176 "diagnostic release request", /* 0x0010 */
177 "internal maintenance release request", /* 0x0008 */
179 "power fail", /* 0x0002 */
180 "retransmit" /* 0x0001 */
183 static const char *err_access
[] = {
184 "illegal parallel operation", /* 0x8000 */
185 "uninitialized media", /* 0x4000 */
186 "no spares available", /* 0x2000 */
187 "not ready", /* 0x1000 */
188 "write protect", /* 0x0800 */
189 "no data found", /* 0x0400 */
191 "unrecoverable data overflow", /* 0x0080 */
192 "unrecoverable data", /* 0x0040 */
194 "end of file", /* 0x0010 */
195 "end of volume", /* 0x0008 */
199 static const char *err_info
[] = {
200 "operator release request", /* 0x8000 */
201 "diagnostic release request", /* 0x4000 */
202 "internal maintenance release request", /* 0x2000 */
203 "media wear", /* 0x1000 */
204 "latency induced", /* 0x0800 */
206 "auto sparing invoked", /* 0x0100 */
208 "recoverable data overflow", /* 0x0040 */
209 "marginal data", /* 0x0020 */
210 "recoverable data", /* 0x0010 */
212 "maintenance track overflow", /* 0x0004 */
217 #define RDB_FOLLOW 0x01
218 #define RDB_STATUS 0x02
219 #define RDB_IDENT 0x04
221 #define RDB_ASYNC 0x10
222 #define RDB_ERROR 0x80
226 * Misc. HW description, indexed by sc_type.
227 * Nothing really critical here, could do without it.
229 static const struct rdidentinfo rdidentinfo
[] = {
230 { RD7946AID
, 0, "7945A", NRD7945ABPT
,
231 NRD7945ATRK
, 968, 108416 },
233 { RD9134DID
, 1, "9134D", NRD9134DBPT
,
234 NRD9134DTRK
, 303, 29088 },
236 { RD9134LID
, 1, "9122S", NRD9122SBPT
,
237 NRD9122STRK
, 77, 1232 },
239 { RD7912PID
, 0, "7912P", NRD7912PBPT
,
240 NRD7912PTRK
, 572, 128128 },
242 { RD7914PID
, 0, "7914P", NRD7914PBPT
,
243 NRD7914PTRK
, 1152, 258048 },
245 { RD7958AID
, 0, "7958A", NRD7958ABPT
,
246 NRD7958ATRK
, 1013, 255276 },
248 { RD7957AID
, 0, "7957A", NRD7957ABPT
,
249 NRD7957ATRK
, 1036, 159544 },
251 { RD7933HID
, 0, "7933H", NRD7933HBPT
,
252 NRD7933HTRK
, 1321, 789958 },
254 { RD9134LID
, 1, "9134L", NRD9134LBPT
,
255 NRD9134LTRK
, 973, 77840 },
257 { RD7936HID
, 0, "7936H", NRD7936HBPT
,
258 NRD7936HTRK
, 698, 600978 },
260 { RD7937HID
, 0, "7937H", NRD7937HBPT
,
261 NRD7937HTRK
, 698, 1116102 },
263 { RD7914CTID
, 0, "7914CT", NRD7914PBPT
,
264 NRD7914PTRK
, 1152, 258048 },
266 { RD7946AID
, 0, "7946A", NRD7945ABPT
,
267 NRD7945ATRK
, 968, 108416 },
269 { RD9134LID
, 1, "9122D", NRD9122SBPT
,
270 NRD9122STRK
, 77, 1232 },
272 { RD7957BID
, 0, "7957B", NRD7957BBPT
,
273 NRD7957BTRK
, 1269, 159894 },
275 { RD7958BID
, 0, "7958B", NRD7958BBPT
,
276 NRD7958BTRK
, 786, 297108 },
278 { RD7959BID
, 0, "7959B", NRD7959BBPT
,
279 NRD7959BTRK
, 1572, 594216 },
281 { RD2200AID
, 0, "2200A", NRD2200ABPT
,
282 NRD2200ATRK
, 1449, 654948 },
284 { RD2203AID
, 0, "2203A", NRD2203ABPT
,
285 NRD2203ATRK
, 1449, 1309896 }
287 static const int numrdidentinfo
= __arraycount(rdidentinfo
);
289 static int rdident(struct device
*, struct rd_softc
*,
290 struct hpibbus_attach_args
*);
291 static void rdreset(struct rd_softc
*);
292 static void rdustart(struct rd_softc
*);
293 static int rdgetinfo(dev_t
);
294 static void rdrestart(void *);
295 static struct buf
*rdfinish(struct rd_softc
*, struct buf
*);
297 static void rdgetdefaultlabel(struct rd_softc
*, struct disklabel
*);
298 static void rdrestart(void *);
299 static void rdustart(struct rd_softc
*);
300 static struct buf
*rdfinish(struct rd_softc
*, struct buf
*);
301 static void rdstart(void *);
302 static void rdgo(void *);
303 static void rdintr(void *);
304 static int rdstatus(struct rd_softc
*);
305 static int rderror(int);
307 static void rdprinterr(const char *, short, const char **);
310 static int rdmatch(device_t
, cfdata_t
, void *);
311 static void rdattach(device_t
, device_t
, void *);
313 CFATTACH_DECL_NEW(rd
, sizeof(struct rd_softc
),
314 rdmatch
, rdattach
, NULL
, NULL
);
316 static dev_type_open(rdopen
);
317 static dev_type_close(rdclose
);
318 static dev_type_read(rdread
);
319 static dev_type_write(rdwrite
);
320 static dev_type_ioctl(rdioctl
);
321 static dev_type_strategy(rdstrategy
);
322 static dev_type_dump(rddump
);
323 static dev_type_size(rdsize
);
325 const struct bdevsw rd_bdevsw
= {
326 rdopen
, rdclose
, rdstrategy
, rdioctl
, rddump
, rdsize
, D_DISK
329 const struct cdevsw rd_cdevsw
= {
330 rdopen
, rdclose
, rdread
, rdwrite
, rdioctl
,
331 nostop
, notty
, nopoll
, nommap
, nokqfilter
, D_DISK
335 rdmatch(device_t parent
, cfdata_t cf
, void *aux
)
337 struct hpibbus_attach_args
*ha
= aux
;
340 * Set punit if operator specified one in the kernel
341 * configuration file.
343 if (cf
->hpibbuscf_punit
!= HPIBBUSCF_PUNIT_DEFAULT
&&
344 cf
->hpibbuscf_punit
< HPIB_NPUNITS
)
345 ha
->ha_punit
= cf
->hpibbuscf_punit
;
347 if (rdident(parent
, NULL
, ha
) == 0) {
349 * XXX Some aging HP-IB drives are slow to
350 * XXX respond; give them a chance to catch
351 * XXX up and probe them again.
354 ha
->ha_id
= hpibid(device_unit(parent
), ha
->ha_slave
);
355 return rdident(parent
, NULL
, ha
);
361 rdattach(device_t parent
, device_t self
, void *aux
)
363 struct rd_softc
*sc
= device_private(self
);
364 struct hpibbus_attach_args
*ha
= aux
;
367 bufq_alloc(&sc
->sc_tab
, "disksort", BUFQ_SORT_RAWBLOCK
);
369 if (rdident(parent
, sc
, ha
) == 0) {
370 aprint_error(": didn't respond to describe command!\n");
375 * Initialize and attach the disk structure.
377 memset(&sc
->sc_dkdev
, 0, sizeof(sc
->sc_dkdev
));
378 disk_init(&sc
->sc_dkdev
, device_xname(sc
->sc_dev
), NULL
);
379 disk_attach(&sc
->sc_dkdev
);
381 sc
->sc_slave
= ha
->ha_slave
;
382 sc
->sc_punit
= ha
->ha_punit
;
384 callout_init(&sc
->sc_restart_ch
, 0);
386 /* Initialize the hpib job queue entry */
387 sc
->sc_hq
.hq_softc
= sc
;
388 sc
->sc_hq
.hq_slave
= sc
->sc_slave
;
389 sc
->sc_hq
.hq_start
= rdstart
;
390 sc
->sc_hq
.hq_go
= rdgo
;
391 sc
->sc_hq
.hq_intr
= rdintr
;
393 sc
->sc_flags
= RDF_ALIVE
;
395 /* always report errors */
396 if (rddebug
& RDB_ERROR
)
401 * attach the device into the random source list
403 rnd_attach_source(&sc
->rnd_source
, device_xname(sc
->sc_dev
),
409 rdident(device_t parent
, struct rd_softc
*sc
, struct hpibbus_attach_args
*ha
)
411 struct rd_describe
*desc
= sc
!= NULL
? &sc
->sc_rddesc
: NULL
;
414 int i
, id
, n
, ctlr
, slave
;
416 ctlr
= device_unit(parent
);
417 slave
= ha
->ha_slave
;
419 /* Verify that we have a CS80 device. */
420 if ((ha
->ha_id
& 0x200) == 0)
423 /* Is it one of the disks we support? */
424 for (id
= 0; id
< numrdidentinfo
; id
++)
425 if (ha
->ha_id
== rdidentinfo
[id
].ri_hwid
)
427 if (id
== numrdidentinfo
|| ha
->ha_punit
> rdidentinfo
[id
].ri_maxunum
)
431 * If we're just probing for the device, that's all the
432 * work we need to do.
438 * Reset device and collect description
441 cmd
[0] = C_SUNIT(ha
->ha_punit
);
444 hpibsend(ctlr
, slave
, C_CMD
, cmd
, sizeof(cmd
));
445 hpibrecv(ctlr
, slave
, C_EXEC
, desc
, 37);
446 hpibrecv(ctlr
, slave
, C_QSTAT
, &stat
, sizeof(stat
));
447 memset(name
, 0, sizeof(name
));
450 for (i
= 5; i
>= 0; i
--) {
451 name
[i
] = (n
& 0xf) + '0';
457 if (rddebug
& RDB_IDENT
) {
459 aprint_debug_dev(sc
->sc_dev
, "name: %x ('%s')\n",
461 aprint_debug(" iuw %x, maxxfr %d, ctype %d\n",
462 desc
->d_iuw
, desc
->d_cmaxxfr
, desc
->d_ctype
);
463 aprint_debug(" utype %d, bps %d, blkbuf %d, burst %d,"
465 desc
->d_utype
, desc
->d_sectsize
,
466 desc
->d_blkbuf
, desc
->d_burstsize
, desc
->d_blocktime
);
467 aprint_debug(" avxfr %d, ort %d, atp %d, maxint %d, fv %x"
469 desc
->d_uavexfr
, desc
->d_retry
, desc
->d_access
,
470 desc
->d_maxint
, desc
->d_fvbyte
, desc
->d_rvbyte
);
471 aprint_debug(" maxcyl/head/sect %d/%d/%d, maxvsect %d,"
473 desc
->d_maxcyl
, desc
->d_maxhead
, desc
->d_maxsect
,
474 desc
->d_maxvsectl
, desc
->d_interleave
);
475 aprint_normal("%s", device_xname(sc
->sc_dev
));
480 * Take care of a couple of anomolies:
481 * 1. 7945A and 7946A both return same HW id
482 * 2. 9122S and 9134D both return same HW id
483 * 3. 9122D and 9134L both return same HW id
487 if (memcmp(name
, "079450", 6) == 0)
494 if (memcmp(name
, "091340", 6) == 0)
501 if (memcmp(name
, "091220", 6) == 0)
511 * XXX We use DEV_BSIZE instead of the sector size value pulled
512 * XXX off the driver because all of this code assumes 512 byte
515 aprint_normal(": %s\n", rdidentinfo
[id
].ri_desc
);
516 aprint_normal_dev(sc
->sc_dev
, "%d cylinders, %d heads, %d blocks,"
518 rdidentinfo
[id
].ri_ncyl
,
519 rdidentinfo
[id
].ri_ntpc
, rdidentinfo
[id
].ri_nblocks
,
526 rdreset(struct rd_softc
*sc
)
528 int ctlr
= device_unit(device_parent(sc
->sc_dev
));
529 int slave
= sc
->sc_slave
;
532 sc
->sc_clear
.c_unit
= C_SUNIT(sc
->sc_punit
);
533 sc
->sc_clear
.c_cmd
= C_CLEAR
;
534 hpibsend(ctlr
, slave
, C_TCMD
, &sc
->sc_clear
, sizeof(sc
->sc_clear
));
535 hpibswait(ctlr
, slave
);
536 hpibrecv(ctlr
, slave
, C_QSTAT
, &stat
, sizeof(stat
));
538 sc
->sc_src
.c_unit
= C_SUNIT(RDCTLR
);
539 sc
->sc_src
.c_nop
= C_NOP
;
540 sc
->sc_src
.c_cmd
= C_SREL
;
541 sc
->sc_src
.c_param
= C_REL
;
542 hpibsend(ctlr
, slave
, C_CMD
, &sc
->sc_src
, sizeof(sc
->sc_src
));
543 hpibswait(ctlr
, slave
);
544 hpibrecv(ctlr
, slave
, C_QSTAT
, &stat
, sizeof(stat
));
546 sc
->sc_ssmc
.c_unit
= C_SUNIT(sc
->sc_punit
);
547 sc
->sc_ssmc
.c_cmd
= C_SSM
;
548 sc
->sc_ssmc
.c_refm
= REF_MASK
;
549 sc
->sc_ssmc
.c_fefm
= FEF_MASK
;
550 sc
->sc_ssmc
.c_aefm
= AEF_MASK
;
551 sc
->sc_ssmc
.c_iefm
= IEF_MASK
;
552 hpibsend(ctlr
, slave
, C_CMD
, &sc
->sc_ssmc
, sizeof(sc
->sc_ssmc
));
553 hpibswait(ctlr
, slave
);
554 hpibrecv(ctlr
, slave
, C_QSTAT
, &stat
, sizeof(stat
));
556 sc
->sc_stats
.rdresets
++;
561 * Read or construct a disklabel
566 struct rd_softc
*sc
= device_lookup_private(&rd_cd
, rdunit(dev
));
567 struct disklabel
*lp
= sc
->sc_dkdev
.dk_label
;
568 struct partition
*pi
;
572 * Set some default values to use while reading the label
573 * or to use if there isn't a label.
575 memset((void *)lp
, 0, sizeof *lp
);
576 rdgetdefaultlabel(sc
, lp
);
579 * Now try to read the disklabel
581 msg
= readdisklabel(rdlabdev(dev
), rdstrategy
, lp
, NULL
);
585 pi
= lp
->d_partitions
;
586 printf("%s: WARNING: %s\n", device_xname(sc
->sc_dev
), msg
);
588 pi
[2].p_size
= rdidentinfo
[sc
->sc_type
].ri_nblocks
;
589 /* XXX reset other info since readdisklabel screws with it */
590 lp
->d_npartitions
= 3;
597 rdopen(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
600 int error
, mask
, part
;
602 sc
= device_lookup_private(&rd_cd
, rdunit(dev
));
606 if ((sc
->sc_flags
& RDF_ALIVE
) == 0)
610 * Wait for any pending opens/closes to complete
612 while (sc
->sc_flags
& (RDF_OPENING
|RDF_CLOSING
))
613 (void) tsleep(sc
, PRIBIO
, "rdopen", 0);
616 * On first open, get label and partition info.
617 * We may block reading the label, so be careful
618 * to stop any other opens.
620 if (sc
->sc_dkdev
.dk_openmask
== 0) {
621 sc
->sc_flags
|= RDF_OPENING
;
622 error
= rdgetinfo(dev
);
623 sc
->sc_flags
&= ~RDF_OPENING
;
632 /* Check that the partition exists. */
633 if (part
!= RAW_PART
&&
634 (part
> sc
->sc_dkdev
.dk_label
->d_npartitions
||
635 sc
->sc_dkdev
.dk_label
->d_partitions
[part
].p_fstype
== FS_UNUSED
))
638 /* Ensure only one open at a time. */
641 sc
->sc_dkdev
.dk_copenmask
|= mask
;
644 sc
->sc_dkdev
.dk_bopenmask
|= mask
;
647 sc
->sc_dkdev
.dk_openmask
=
648 sc
->sc_dkdev
.dk_copenmask
| sc
->sc_dkdev
.dk_bopenmask
;
654 rdclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
656 struct rd_softc
*sc
= device_lookup_private(&rd_cd
, rdunit(dev
));
657 struct disk
*dk
= &sc
->sc_dkdev
;
660 mask
= 1 << rdpart(dev
);
662 dk
->dk_copenmask
&= ~mask
;
664 dk
->dk_bopenmask
&= ~mask
;
665 dk
->dk_openmask
= dk
->dk_copenmask
| dk
->dk_bopenmask
;
667 * On last close, we wait for all activity to cease since
668 * the label/parition info will become invalid. Since we
669 * might sleep, we must block any opens while we are here.
670 * Note we don't have to about other closes since we know
671 * we are the last one.
673 if (dk
->dk_openmask
== 0) {
674 sc
->sc_flags
|= RDF_CLOSING
;
676 while (sc
->sc_active
) {
677 sc
->sc_flags
|= RDF_WANTED
;
678 (void) tsleep(&sc
->sc_tab
, PRIBIO
, "rdclose", 0);
681 sc
->sc_flags
&= ~(RDF_CLOSING
|RDF_WLABEL
);
688 rdstrategy(struct buf
*bp
)
690 struct rd_softc
*sc
= device_lookup_private(&rd_cd
, rdunit(bp
->b_dev
));
691 struct partition
*pinfo
;
697 if (rddebug
& RDB_FOLLOW
)
698 printf("rdstrategy(%p): dev %x, bn %llx, bcount %x, %c\n",
699 bp
, bp
->b_dev
, bp
->b_blkno
, bp
->b_bcount
,
700 (bp
->b_flags
& B_READ
) ? 'R' : 'W');
703 sz
= howmany(bp
->b_bcount
, DEV_BSIZE
);
704 pinfo
= &sc
->sc_dkdev
.dk_label
->d_partitions
[rdpart(bp
->b_dev
)];
706 /* Don't perform partition translation on RAW_PART. */
707 offset
= (rdpart(bp
->b_dev
) == RAW_PART
) ? 0 : pinfo
->p_offset
;
709 if (rdpart(bp
->b_dev
) != RAW_PART
) {
711 * XXX This block of code belongs in
712 * XXX bounds_check_with_label()
715 if (bn
< 0 || bn
+ sz
> pinfo
->p_size
) {
716 sz
= pinfo
->p_size
- bn
;
718 bp
->b_resid
= bp
->b_bcount
;
722 bp
->b_error
= EINVAL
;
725 bp
->b_bcount
= dbtob(sz
);
728 * Check for write to write protected label
730 if (bn
+ offset
<= LABELSECTOR
&&
732 bn
+ offset
+ sz
> LABELSECTOR
&&
734 !(bp
->b_flags
& B_READ
) && !(sc
->sc_flags
& RDF_WLABEL
)) {
739 bp
->b_rawblkno
= bn
+ offset
;
741 bufq_put(sc
->sc_tab
, bp
);
742 if (sc
->sc_active
== 0) {
753 * Called from timeout() when handling maintenance releases
759 rdustart((struct rd_softc
*)arg
);
764 rdustart(struct rd_softc
*sc
)
768 bp
= bufq_peek(sc
->sc_tab
);
769 sc
->sc_addr
= bp
->b_data
;
770 sc
->sc_resid
= bp
->b_bcount
;
771 if (hpibreq(device_parent(sc
->sc_dev
), &sc
->sc_hq
))
776 rdfinish(struct rd_softc
*sc
, struct buf
*bp
)
780 (void)bufq_get(sc
->sc_tab
);
783 hpibfree(device_parent(sc
->sc_dev
), &sc
->sc_hq
);
784 if ((bp
= bufq_peek(sc
->sc_tab
)) != NULL
)
787 if (sc
->sc_flags
& RDF_WANTED
) {
788 sc
->sc_flags
&= ~RDF_WANTED
;
789 wakeup((void *)&sc
->sc_tab
);
797 struct rd_softc
*sc
= arg
;
798 struct buf
*bp
= bufq_peek(sc
->sc_tab
);
799 int part
, ctlr
, slave
;
801 ctlr
= device_unit(device_parent(sc
->sc_dev
));
802 slave
= sc
->sc_slave
;
806 if (rddebug
& RDB_FOLLOW
)
807 printf("rdstart(%s): bp %p, %c\n", device_xname(sc
->sc_dev
), bp
,
808 (bp
->b_flags
& B_READ
) ? 'R' : 'W');
810 part
= rdpart(bp
->b_dev
);
811 sc
->sc_flags
|= RDF_SEEK
;
812 sc
->sc_ioc
.c_unit
= C_SUNIT(sc
->sc_punit
);
813 sc
->sc_ioc
.c_volume
= C_SVOL(0);
814 sc
->sc_ioc
.c_saddr
= C_SADDR
;
815 sc
->sc_ioc
.c_hiaddr
= 0;
816 sc
->sc_ioc
.c_addr
= RDBTOS(bp
->b_rawblkno
);
817 sc
->sc_ioc
.c_nop2
= C_NOP
;
818 sc
->sc_ioc
.c_slen
= C_SLEN
;
819 sc
->sc_ioc
.c_len
= sc
->sc_resid
;
820 sc
->sc_ioc
.c_cmd
= bp
->b_flags
& B_READ
? C_READ
: C_WRITE
;
822 if (rddebug
& RDB_IO
)
823 printf("rdstart: hpibsend(%x, %x, %x, %p, %x)\n",
825 &sc
->sc_ioc
.c_unit
, sizeof(sc
->sc_ioc
) - 2);
827 if (hpibsend(ctlr
, slave
, C_CMD
, &sc
->sc_ioc
.c_unit
,
828 sizeof(sc
->sc_ioc
) - 2) == sizeof(sc
->sc_ioc
) - 2) {
830 /* Instrumentation. */
831 disk_busy(&sc
->sc_dkdev
);
832 iostat_seek(sc
->sc_dkdev
.dk_stats
);
835 if (rddebug
& RDB_IO
)
836 printf("rdstart: hpibawait(%x)\n", ctlr
);
842 * Experience has shown that the hpibwait in this hpibsend will
843 * occasionally timeout. It appears to occur mostly on old 7914
844 * drives with full maintenance tracks. We should probably
845 * integrate this with the backoff code in rderror.
848 if (rddebug
& RDB_ERROR
)
849 printf("%s: rdstart: cmd %x adr %lx blk %lld len %d ecnt %d\n",
850 device_xname(sc
->sc_dev
),
851 sc
->sc_ioc
.c_cmd
, sc
->sc_ioc
.c_addr
,
852 bp
->b_blkno
, sc
->sc_resid
, sc
->sc_errcnt
);
853 sc
->sc_stats
.rdretries
++;
855 sc
->sc_flags
&= ~RDF_SEEK
;
857 if (sc
->sc_errcnt
++ < RDRETRY
)
859 printf("%s: rdstart err: cmd 0x%x sect %ld blk %" PRId64
" len %d\n",
860 device_xname(sc
->sc_dev
), sc
->sc_ioc
.c_cmd
, sc
->sc_ioc
.c_addr
,
861 bp
->b_blkno
, sc
->sc_resid
);
863 bp
= rdfinish(sc
, bp
);
865 sc
->sc_addr
= bp
->b_data
;
866 sc
->sc_resid
= bp
->b_bcount
;
867 if (hpibreq(device_parent(sc
->sc_dev
), &sc
->sc_hq
))
875 struct rd_softc
*sc
= arg
;
876 struct buf
*bp
= bufq_peek(sc
->sc_tab
);
879 ctlr
= device_unit(device_parent(sc
->sc_dev
));
880 slave
= sc
->sc_slave
;
882 rw
= bp
->b_flags
& B_READ
;
884 /* Instrumentation. */
885 disk_busy(&sc
->sc_dkdev
);
888 ledcontrol(0, 0, LED_DISK
);
890 hpibgo(ctlr
, slave
, C_EXEC
, sc
->sc_addr
, sc
->sc_resid
, rw
, rw
!= 0);
897 struct rd_softc
*sc
= arg
;
898 int unit
= device_unit(sc
->sc_dev
);
899 struct buf
*bp
= bufq_peek(sc
->sc_tab
);
900 u_char stat
= 13; /* in case hpibrecv fails */
901 int rv
, restart
, ctlr
, slave
;
903 ctlr
= device_unit(device_parent(sc
->sc_dev
));
904 slave
= sc
->sc_slave
;
907 if (rddebug
& RDB_FOLLOW
)
908 printf("rdintr(%d): bp %p, %c, flags %x\n", unit
, bp
,
909 (bp
->b_flags
& B_READ
) ? 'R' : 'W', sc
->sc_flags
);
911 printf("%s: bp == NULL\n", device_xname(sc
->sc_dev
));
915 disk_unbusy(&sc
->sc_dkdev
, (bp
->b_bcount
- bp
->b_resid
),
916 (bp
->b_flags
& B_READ
));
918 if (sc
->sc_flags
& RDF_SEEK
) {
919 sc
->sc_flags
&= ~RDF_SEEK
;
920 if (hpibustart(ctlr
))
924 if ((sc
->sc_flags
& RDF_SWAIT
) == 0) {
926 sc
->sc_stats
.rdpolltries
++;
928 if (hpibpptest(ctlr
, slave
) == 0) {
930 sc
->sc_stats
.rdpollwaits
++;
933 /* Instrumentation. */
934 disk_busy(&sc
->sc_dkdev
);
935 sc
->sc_flags
|= RDF_SWAIT
;
940 sc
->sc_flags
&= ~RDF_SWAIT
;
941 rv
= hpibrecv(ctlr
, slave
, C_QSTAT
, &stat
, 1);
942 if (rv
!= 1 || stat
) {
944 if (rddebug
& RDB_ERROR
)
945 printf("rdintr: recv failed or bad stat %d\n", stat
);
947 restart
= rderror(unit
);
949 sc
->sc_stats
.rdretries
++;
951 if (sc
->sc_errcnt
++ < RDRETRY
) {
958 if (rdfinish(sc
, bp
))
961 rnd_add_uint32(&sc
->rnd_source
, bp
->b_blkno
);
966 rdstatus(struct rd_softc
*sc
)
972 c
= device_unit(device_parent(sc
->sc_dev
));
974 sc
->sc_rsc
.c_unit
= C_SUNIT(sc
->sc_punit
);
975 sc
->sc_rsc
.c_sram
= C_SRAM
;
976 sc
->sc_rsc
.c_ram
= C_RAM
;
977 sc
->sc_rsc
.c_cmd
= C_STATUS
;
978 memset((void *)&sc
->sc_stat
, 0, sizeof(sc
->sc_stat
));
979 rv
= hpibsend(c
, s
, C_CMD
, &sc
->sc_rsc
, sizeof(sc
->sc_rsc
));
980 if (rv
!= sizeof(sc
->sc_rsc
)) {
982 if (rddebug
& RDB_STATUS
)
983 printf("rdstatus: send C_CMD failed %d != %d\n",
984 rv
, sizeof(sc
->sc_rsc
));
988 rv
= hpibrecv(c
, s
, C_EXEC
, &sc
->sc_stat
, sizeof(sc
->sc_stat
));
989 if (rv
!= sizeof(sc
->sc_stat
)) {
991 if (rddebug
& RDB_STATUS
)
992 printf("rdstatus: send C_EXEC failed %d != %d\n",
993 rv
, sizeof(sc
->sc_stat
));
997 rv
= hpibrecv(c
, s
, C_QSTAT
, &stat
, 1);
998 if (rv
!= 1 || stat
) {
1000 if (rddebug
& RDB_STATUS
)
1001 printf("rdstatus: recv failed %d or bad stat %d\n",
1011 * Returns 1 if request should be restarted,
1012 * 0 if we should just quietly give up.
1017 struct rd_softc
*sc
= device_lookup_private(&rd_cd
,unit
);
1021 char *hexstr(int, int); /* XXX */
1025 printf("%s: couldn't get status\n", device_xname(sc
->sc_dev
));
1031 if (sp
->c_fef
& FEF_REXMT
)
1033 if (sp
->c_fef
& FEF_PF
) {
1038 * Unit requests release for internal maintenance.
1039 * We just delay awhile and try again later. Use expontially
1040 * increasing backoff ala ethernet drivers since we don't really
1041 * know how long the maintenance will take. With RDWAITC and
1042 * RDRETRY as defined, the range is 1 to 32 seconds.
1044 if (sp
->c_fef
& FEF_IMR
) {
1046 int rdtimo
= RDWAITC
<< sc
->sc_errcnt
;
1048 printf("%s: internal maintenance, %d second timeout\n",
1049 device_xname(sc
->sc_dev
), rdtimo
);
1050 sc
->sc_stats
.rdtimeouts
++;
1052 hpibfree(device_parent(sc
->sc_dev
), &sc
->sc_hq
);
1053 callout_reset(&sc
->sc_restart_ch
, rdtimo
* hz
, rdrestart
, sc
);
1057 * Only report error if we have reached the error reporting
1058 * threshhold. By default, this will only report after the
1059 * retry limit has been exceeded.
1061 if (sc
->sc_errcnt
< rderrthresh
)
1065 * First conjure up the block number at which the error occurred.
1066 * Note that not all errors report a block number, in that case
1067 * we just use b_blkno.
1069 bp
= bufq_peek(sc
->sc_tab
);
1070 pbn
= sc
->sc_dkdev
.dk_label
->d_partitions
[rdpart(bp
->b_dev
)].p_offset
;
1071 if ((sp
->c_fef
& FEF_CU
) || (sp
->c_fef
& FEF_DR
) ||
1072 (sp
->c_ief
& IEF_RRMASK
)) {
1073 hwbn
= RDBTOS(pbn
+ bp
->b_blkno
);
1077 pbn
= RDSTOB(hwbn
) - pbn
;
1080 * Now output a generic message suitable for badsect.
1081 * Note that we don't use harderr cuz it just prints
1082 * out b_blkno which is just the beginning block number
1083 * of the transfer, not necessary where the error occurred.
1085 printf("%s%c: hard error sn%" PRId64
"\n", device_xname(sc
->sc_dev
),
1086 'a'+rdpart(bp
->b_dev
), pbn
);
1088 * Now report the status as returned by the hardware with
1089 * attempt at interpretation (unless debugging).
1091 printf("%s %s error:", device_xname(sc
->sc_dev
),
1092 (bp
->b_flags
& B_READ
) ? "read" : "write");
1094 if (rddebug
& RDB_ERROR
) {
1096 printf("\n volume: %d, unit: %d\n",
1097 (sp
->c_vu
>>4)&0xF, sp
->c_vu
&0xF);
1098 rdprinterr("reject", sp
->c_ref
, err_reject
);
1099 rdprinterr("fault", sp
->c_fef
, err_fault
);
1100 rdprinterr("access", sp
->c_aef
, err_access
);
1101 rdprinterr("info", sp
->c_ief
, err_info
);
1102 printf(" block: %lld, P1-P10: ", hwbn
);
1103 printf("0x%x", *(u_int
*)&sp
->c_raw
[0]);
1104 printf("0x%x", *(u_int
*)&sp
->c_raw
[4]);
1105 printf("0x%x\n", *(u_short
*)&sp
->c_raw
[8]);
1108 printf("0x%x", *(u_int
*)&sc
->sc_ioc
.c_pad
);
1109 printf("0x%x", *(u_short
*)&sc
->sc_ioc
.c_hiaddr
);
1110 printf("0x%x", *(u_int
*)&sc
->sc_ioc
.c_addr
);
1111 printf("0x%x", *(u_short
*)&sc
->sc_ioc
.c_nop2
);
1112 printf("0x%x", *(u_int
*)&sc
->sc_ioc
.c_len
);
1113 printf("0x%x\n", *(u_short
*)&sc
->sc_ioc
.c_cmd
);
1117 printf(" v%d u%d, R0x%x F0x%x A0x%x I0x%x\n",
1118 (sp
->c_vu
>>4)&0xF, sp
->c_vu
&0xF,
1119 sp
->c_ref
, sp
->c_fef
, sp
->c_aef
, sp
->c_ief
);
1121 printf("0x%x", *(u_int
*)&sp
->c_raw
[0]);
1122 printf("0x%x", *(u_int
*)&sp
->c_raw
[4]);
1123 printf("0x%x\n", *(u_short
*)&sp
->c_raw
[8]);
1128 rdread(dev_t dev
, struct uio
*uio
, int flags
)
1131 return physio(rdstrategy
, NULL
, dev
, B_READ
, minphys
, uio
);
1135 rdwrite(dev_t dev
, struct uio
*uio
, int flags
)
1138 return physio(rdstrategy
, NULL
, dev
, B_WRITE
, minphys
, uio
);
1142 rdioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
1144 struct rd_softc
*sc
= device_lookup_private(&rd_cd
, rdunit(dev
));
1145 struct disklabel
*lp
= sc
->sc_dkdev
.dk_label
;
1150 *(struct disklabel
*)data
= *lp
;
1154 ((struct partinfo
*)data
)->disklab
= lp
;
1155 ((struct partinfo
*)data
)->part
=
1156 &lp
->d_partitions
[rdpart(dev
)];
1160 if ((flag
& FWRITE
) == 0)
1163 sc
->sc_flags
|= RDF_WLABEL
;
1165 sc
->sc_flags
&= ~RDF_WLABEL
;
1169 if ((flag
& FWRITE
) == 0)
1171 return setdisklabel(lp
, (struct disklabel
*)data
,
1172 (sc
->sc_flags
& RDF_WLABEL
) ? 0 : sc
->sc_dkdev
.dk_openmask
,
1176 if ((flag
& FWRITE
) == 0)
1178 error
= setdisklabel(lp
, (struct disklabel
*)data
,
1179 (sc
->sc_flags
& RDF_WLABEL
) ? 0 : sc
->sc_dkdev
.dk_openmask
,
1183 flags
= sc
->sc_flags
;
1184 sc
->sc_flags
= RDF_ALIVE
| RDF_WLABEL
;
1185 error
= writedisklabel(rdlabdev(dev
), rdstrategy
, lp
, NULL
);
1186 sc
->sc_flags
= flags
;
1190 rdgetdefaultlabel(sc
, (struct disklabel
*)data
);
1197 rdgetdefaultlabel(struct rd_softc
*sc
, struct disklabel
*lp
)
1199 int type
= sc
->sc_type
;
1201 memset((void *)lp
, 0, sizeof(struct disklabel
));
1203 lp
->d_type
= DTYPE_HPIB
;
1204 lp
->d_secsize
= DEV_BSIZE
;
1205 lp
->d_nsectors
= rdidentinfo
[type
].ri_nbpt
;
1206 lp
->d_ntracks
= rdidentinfo
[type
].ri_ntpc
;
1207 lp
->d_ncylinders
= rdidentinfo
[type
].ri_ncyl
;
1208 lp
->d_secperunit
= rdidentinfo
[type
].ri_nblocks
;
1209 lp
->d_secpercyl
= lp
->d_ntracks
* lp
->d_nsectors
;
1211 strlcpy(lp
->d_typename
, rdidentinfo
[type
].ri_desc
,
1212 sizeof(lp
->d_typename
));
1213 strlcpy(lp
->d_packname
, "fictitious", sizeof(lp
->d_packname
));
1215 lp
->d_interleave
= 1;
1218 lp
->d_partitions
[RAW_PART
].p_offset
= 0;
1219 lp
->d_partitions
[RAW_PART
].p_size
=
1220 lp
->d_secperunit
* (lp
->d_secsize
/ DEV_BSIZE
);
1221 lp
->d_partitions
[RAW_PART
].p_fstype
= FS_UNUSED
;
1222 lp
->d_npartitions
= RAW_PART
+ 1;
1224 lp
->d_magic
= DISKMAGIC
;
1225 lp
->d_magic2
= DISKMAGIC
;
1226 lp
->d_checksum
= dkcksum(lp
);
1232 struct rd_softc
*sc
;
1233 int psize
, didopen
= 0;
1235 sc
= device_lookup_private(&rd_cd
, rdunit(dev
));
1239 if ((sc
->sc_flags
& RDF_ALIVE
) == 0)
1243 * We get called very early on (via swapconf)
1244 * without the device being open so we may need
1245 * to handle it here.
1247 if (sc
->sc_dkdev
.dk_openmask
== 0) {
1248 if (rdopen(dev
, FREAD
|FWRITE
, S_IFBLK
, NULL
))
1252 psize
= sc
->sc_dkdev
.dk_label
->d_partitions
[rdpart(dev
)].p_size
*
1253 (sc
->sc_dkdev
.dk_label
->d_secsize
/ DEV_BSIZE
);
1255 (void)rdclose(dev
, FREAD
|FWRITE
, S_IFBLK
, NULL
);
1261 rdprinterr(const char *str
, short err
, const char **tab
)
1268 printf(" %s error %d field:", str
, err
);
1270 for (i
= 0; i
< 16; i
++)
1271 if (err
& (0x8000 >> i
))
1272 printf("%s%s", printed
++ ? " + " : " ", tab
[i
]);
1277 static int rddoingadump
; /* simple mutex */
1280 * Non-interrupt driven, non-DMA dump routine.
1283 rddump(dev_t dev
, daddr_t blkno
, void *va
, size_t size
)
1285 int sectorsize
; /* size of a disk sector */
1286 int nsects
; /* number of sectors in partition */
1287 int sectoff
; /* sector offset of partition */
1288 int totwrt
; /* total number of sectors left to write */
1289 int nwrt
; /* current number of sectors to write */
1292 struct rd_softc
*sc
;
1293 struct disklabel
*lp
;
1296 /* Check for recursive dump; if so, punt. */
1301 /* Decompose unit and partition. */
1305 /* Make sure dump device is ok. */
1306 sc
= device_lookup_private(&rd_cd
, rdunit(dev
));
1310 if ((sc
->sc_flags
& RDF_ALIVE
) == 0)
1313 ctlr
= device_unit(device_parent(sc
->sc_dev
));
1314 slave
= sc
->sc_slave
;
1317 * Convert to disk sectors. Request must be a multiple of size.
1319 lp
= sc
->sc_dkdev
.dk_label
;
1320 sectorsize
= lp
->d_secsize
;
1321 if ((size
% sectorsize
) != 0)
1323 totwrt
= size
/ sectorsize
;
1324 blkno
= dbtob(blkno
) / sectorsize
; /* blkno in DEV_BSIZE units */
1326 nsects
= lp
->d_partitions
[part
].p_size
;
1327 sectoff
= lp
->d_partitions
[part
].p_offset
;
1329 /* Check transfer bounds against partition size. */
1330 if ((blkno
< 0) || (blkno
+ totwrt
) > nsects
)
1333 /* Offset block number to start of partition. */
1336 while (totwrt
> 0) {
1337 nwrt
= totwrt
; /* XXX */
1338 #ifndef RD_DUMP_NOT_TRUSTED
1340 * Fill out and send HPIB command.
1342 sc
->sc_ioc
.c_unit
= C_SUNIT(sc
->sc_punit
);
1343 sc
->sc_ioc
.c_volume
= C_SVOL(0);
1344 sc
->sc_ioc
.c_saddr
= C_SADDR
;
1345 sc
->sc_ioc
.c_hiaddr
= 0;
1346 sc
->sc_ioc
.c_addr
= RDBTOS(blkno
);
1347 sc
->sc_ioc
.c_nop2
= C_NOP
;
1348 sc
->sc_ioc
.c_slen
= C_SLEN
;
1349 sc
->sc_ioc
.c_len
= nwrt
* sectorsize
;
1350 sc
->sc_ioc
.c_cmd
= C_WRITE
;
1351 hpibsend(ctlr
, slave
, C_CMD
, &sc
->sc_ioc
.c_unit
,
1352 sizeof(sc
->sc_ioc
) - 2);
1353 if (hpibswait(ctlr
, slave
))
1359 hpibsend(ctlr
, slave
, C_EXEC
, va
, nwrt
* sectorsize
);
1360 (void) hpibswait(ctlr
, slave
);
1361 hpibrecv(ctlr
, slave
, C_QSTAT
, &stat
, 1);
1364 #else /* RD_DUMP_NOT_TRUSTED */
1365 /* Let's just talk about this first... */
1366 printf("%s: dump addr %p, blk %d\n", device_xname(sc
->sc_dev
),
1368 delay(500 * 1000); /* half a second */
1369 #endif /* RD_DUMP_NOT_TRUSTED */
1371 /* update block count */
1374 va
= (char *)va
+ sectorsize
* nwrt
;