1 /* $NetBSD: xd.c,v 1.66 2009/01/12 08:27:26 cegger Exp $ */
5 * Copyright (c) 1995 Charles D. Cranor
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Charles D. Cranor.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 * x d . c x y l o g i c s 7 5 3 / 7 0 5 3 v m e / s m d d r i v e r
38 * author: Chuck Cranor <chuck@ccrc.wustl.edu>
39 * id: &Id: xd.c,v 1.9 1995/09/25 20:12:44 chuck Exp &
41 * references: [1] Xylogics Model 753 User's Manual
42 * part number: 166-753-001, Revision B, May 21, 1988.
43 * "Your Partner For Performance"
44 * [2] other NetBSD disk device drivers
46 * Special thanks go to Scott E. Campbell of Xylogics, Inc. for taking
47 * the time to answer some of my questions about the 753/7053.
49 * note: the 753 and the 7053 are programmed the same way, but are
50 * different sizes. the 753 is a 6U VME card, while the 7053 is a 9U
51 * VME card (found in many VME based suns).
54 #include <sys/cdefs.h>
55 __KERNEL_RCSID(0, "$NetBSD: xd.c,v 1.66 2009/01/12 08:27:26 cegger Exp $");
57 #undef XDC_DEBUG /* full debug */
58 #define XDC_DIAG /* extra sanity checks */
59 #if defined(DIAGNOSTIC) && !defined(XDC_DIAG)
60 #define XDC_DIAG /* link in with master DIAG option */
63 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/kernel.h>
69 #include <sys/ioctl.h>
73 #include <sys/malloc.h>
74 #include <sys/device.h>
75 #include <sys/disklabel.h>
77 #include <sys/syslog.h>
78 #include <sys/dkbad.h>
80 #include <sys/kauth.h>
82 #include <uvm/uvm_extern.h>
84 #include <machine/autoconf.h>
85 #include <machine/dvma.h>
87 #include <dev/sun/disklabel.h>
89 #include <sun3/dev/xdreg.h>
90 #include <sun3/dev/xdvar.h>
91 #include <sun3/dev/xio.h>
97 * Print a complaint when no xd children were specified
98 * in the config file. Better than a link error...
100 * XXX: Some folks say this driver should be split in two,
101 * but that seems pointless with ONLY one type of child.
105 #error "xdc but no xd?"
113 * XDC_TWAIT: add iorq "N" to tail of SC's wait queue
115 #define XDC_TWAIT(SC, N) \
117 (SC)->waitq[(SC)->waitend] = (N); \
118 (SC)->waitend = ((SC)->waitend + 1) % XDC_MAXIOPB; \
120 } while (/* CONSTCOND */ 0)
123 * XDC_HWAIT: add iorq "N" to head of SC's wait queue
125 #define XDC_HWAIT(SC, N) \
127 (SC)->waithead = ((SC)->waithead == 0) ? \
128 (XDC_MAXIOPB - 1) : ((SC)->waithead - 1); \
129 (SC)->waitq[(SC)->waithead] = (N); \
131 } while (/* CONSTCOND */ 0)
134 * XDC_GET_WAITER: gets the first request waiting on the waitq
135 * and removes it (so it can be submitted)
137 #define XDC_GET_WAITER(XDCSC, RQ) \
139 (RQ) = (XDCSC)->waitq[(XDCSC)->waithead]; \
140 (XDCSC)->waithead = ((XDCSC)->waithead + 1) % XDC_MAXIOPB; \
142 } while (/* CONSTCOND */ 0)
145 * XDC_FREE: add iorq "N" to SC's free list
147 #define XDC_FREE(SC, N) \
149 (SC)->freereq[(SC)->nfree++] = (N); \
150 (SC)->reqs[N].mode = 0; \
151 if ((SC)->nfree == 1) \
152 wakeup(&(SC)->nfree); \
153 } while (/* CONSTCOND */ 0)
157 * XDC_RQALLOC: allocate an iorq off the free list (assume nfree > 0).
159 #define XDC_RQALLOC(XDCSC) (XDCSC)->freereq[--((XDCSC)->nfree)]
162 * XDC_GO: start iopb ADDR (DVMA addr in a u_long) on XDC
164 #define XDC_GO(XDC, ADDR) \
166 (XDC)->xdc_iopbaddr0 = ((ADDR) & 0xff); \
167 (ADDR) = ((ADDR) >> 8); \
168 (XDC)->xdc_iopbaddr1 = ((ADDR) & 0xff); \
169 (ADDR) = ((ADDR) >> 8); \
170 (XDC)->xdc_iopbaddr2 = ((ADDR) & 0xff); \
171 (ADDR) = ((ADDR) >> 8); \
172 (XDC)->xdc_iopbaddr3 = (ADDR); \
173 (XDC)->xdc_iopbamod = XDC_ADDRMOD; \
174 (XDC)->xdc_csr = XDC_ADDIOPB; /* go! */ \
175 } while (/* CONSTCOND */ 0)
178 * XDC_WAIT: wait for XDC's csr "BITS" to come on in "TIME".
179 * LCV is a counter. If it goes to zero then we timed out.
181 #define XDC_WAIT(XDC, LCV, TIME, BITS) \
184 while ((LCV) > 0) { \
185 if ((XDC)->xdc_csr & (BITS)) \
190 } while (/* CONSTCOND */ 0)
193 * XDC_DONE: don't need IORQ, get error code and free (done after xdc_cmd)
195 #define XDC_DONE(SC,RQ,ER) \
197 if ((RQ) == XD_ERR_FAIL) { \
200 if ((SC)->ndone-- == XDC_SUBWAITLIM) \
201 wakeup(&(SC)->ndone); \
202 (ER) = (SC)->reqs[RQ].errno; \
203 XDC_FREE((SC), (RQ)); \
205 } while (/* CONSTCOND */ 0)
208 * XDC_ADVANCE: advance iorq's pointers by a number of sectors
210 #define XDC_ADVANCE(IORQ, N) \
213 (IORQ)->sectcnt -= (N); \
214 (IORQ)->blockno += (N); \
215 (IORQ)->dbuf += ((N) * XDFM_BPS); \
217 } while (/* CONSTCOND */ 0)
220 * note - addresses you can sleep on:
221 * [1] & of xd_softc's "state" (waiting for a chance to attach a drive)
222 * [2] & of xdc_softc's "nfree" (waiting for a free iorq/iopb)
223 * [3] & of xdc_softc's "ndone" (waiting for number of done iorq/iopb's
224 * to drop below XDC_SUBWAITLIM)
225 * [4] & an iorq (waiting for an XD_SUB_WAIT iorq to finish)
230 * function prototypes
231 * "xdc_*" functions are internal, all others are external interfaces
235 int xdc_cmd(struct xdc_softc
*, int, int, int, int, int, char *, int);
236 const char *xdc_e2str(int);
237 int xdc_error(struct xdc_softc
*, struct xd_iorq
*, struct xd_iopb
*, int,
239 int xdc_ioctlcmd(struct xd_softc
*, dev_t dev
, struct xd_iocmd
*);
240 void xdc_perror(struct xd_iorq
*, struct xd_iopb
*, int);
241 int xdc_piodriver(struct xdc_softc
*, int, int);
242 int xdc_remove_iorq(struct xdc_softc
*);
243 int xdc_reset(struct xdc_softc
*, int, int, int, struct xd_softc
*);
244 inline void xdc_rqinit(struct xd_iorq
*, struct xdc_softc
*, struct xd_softc
*,
245 int, u_long
, int, void *, struct buf
*);
246 void xdc_rqtopb(struct xd_iorq
*, struct xd_iopb
*, int, int);
247 void xdc_start(struct xdc_softc
*, int);
248 int xdc_startbuf(struct xdc_softc
*, struct xd_softc
*, struct buf
*);
249 int xdc_submit_iorq(struct xdc_softc
*, int, int);
250 void xdc_tick(void *);
251 void xdc_xdreset(struct xdc_softc
*, struct xd_softc
*);
253 /* machine interrupt hook */
257 static int xdcmatch(device_t
, cfdata_t
, void *);
258 static void xdcattach(device_t
, device_t
, void *);
259 static int xdc_print(void *, const char *);
261 static int xdmatch(device_t
, cfdata_t
, void *);
262 static void xdattach(device_t
, device_t
, void *);
263 static void xd_init(struct xd_softc
*);
265 static void xddummystrat(struct buf
*);
266 int xdgetdisklabel(struct xd_softc
*, void *);
269 * cfattach's: device driver interface to autoconfig
272 CFATTACH_DECL_NEW(xdc
, sizeof(struct xdc_softc
),
273 xdcmatch
, xdcattach
, NULL
, NULL
);
275 CFATTACH_DECL_NEW(xd
, sizeof(struct xd_softc
),
276 xdmatch
, xdattach
, NULL
, NULL
);
278 struct xdc_attach_args
{ /* this is the "aux" args to xdattach */
279 int driveno
; /* unit number */
280 char *dvmabuf
; /* scratch buffer for reading disk label */
281 int fullmode
; /* submit mode */
282 int booting
; /* are we booting or not? */
285 dev_type_open(xdopen
);
286 dev_type_close(xdclose
);
287 dev_type_read(xdread
);
288 dev_type_write(xdwrite
);
289 dev_type_ioctl(xdioctl
);
290 dev_type_strategy(xdstrategy
);
291 dev_type_dump(xddump
);
292 dev_type_size(xdsize
);
294 const struct bdevsw xd_bdevsw
= {
295 xdopen
, xdclose
, xdstrategy
, xdioctl
, xddump
, xdsize
, D_DISK
298 const struct cdevsw xd_cdevsw
= {
299 xdopen
, xdclose
, xdread
, xdwrite
, xdioctl
,
300 nostop
, notty
, nopoll
, nommap
, nokqfilter
, D_DISK
307 struct dkdriver xddkdriver
= { xdstrategy
};
310 * start: disk label fix code (XXX)
313 static void *xd_labeldata
;
316 xddummystrat(struct buf
*bp
)
318 if (bp
->b_bcount
!= XDFM_BPS
)
319 panic("%s: b_bcount", __func__
);
320 memcpy(bp
->b_data
, xd_labeldata
, XDFM_BPS
);
321 bp
->b_oflags
|= BO_DONE
;
322 bp
->b_cflags
&= ~BC_BUSY
;
326 xdgetdisklabel(struct xd_softc
*xd
, void *b
)
329 struct sun_disklabel
*sdl
;
331 /* We already have the label data in `b'; setup for dummy strategy */
334 /* Required parameter for readdisklabel() */
335 xd
->sc_dk
.dk_label
->d_secsize
= XDFM_BPS
;
337 err
= readdisklabel(MAKEDISKDEV(0, device_unit(xd
->sc_dev
), RAW_PART
),
338 xddummystrat
, xd
->sc_dk
.dk_label
, xd
->sc_dk
.dk_cpulabel
);
340 printf("%s: %s\n", device_xname(xd
->sc_dev
), err
);
344 /* Ok, we have the label; fill in `pcyl' if there's SunOS magic */
345 sdl
= (struct sun_disklabel
*)xd
->sc_dk
.dk_cpulabel
->cd_block
;
346 if (sdl
->sl_magic
== SUN_DKMAGIC
)
347 xd
->pcyl
= sdl
->sl_pcyl
;
349 printf("%s: WARNING: no `pcyl' in disk label.\n",
350 device_xname(xd
->sc_dev
));
351 xd
->pcyl
= xd
->sc_dk
.dk_label
->d_ncylinders
+
352 xd
->sc_dk
.dk_label
->d_acylinders
;
353 printf("%s: WARNING: guessing pcyl=%d (ncyl+acyl)\n",
354 device_xname(xd
->sc_dev
), xd
->pcyl
);
357 xd
->ncyl
= xd
->sc_dk
.dk_label
->d_ncylinders
;
358 xd
->acyl
= xd
->sc_dk
.dk_label
->d_acylinders
;
359 xd
->nhead
= xd
->sc_dk
.dk_label
->d_ntracks
;
360 xd
->nsect
= xd
->sc_dk
.dk_label
->d_nsectors
;
361 xd
->sectpercyl
= xd
->nhead
* xd
->nsect
;
362 xd
->sc_dk
.dk_label
->d_secsize
= XDFM_BPS
; /* not handled by
368 * end: disk label fix code (XXX)
372 * a u t o c o n f i g f u n c t i o n s
376 * xdcmatch: determine if xdc is present or not. we do a
377 * soft reset to detect the xdc.
381 xdcmatch(device_t parent
, cfdata_t cf
, void *aux
)
383 struct confargs
*ca
= aux
;
385 /* No default VME address. */
386 if (ca
->ca_paddr
== -1)
389 /* Make sure something is there... */
390 if (bus_peek(ca
->ca_bustype
, ca
->ca_paddr
+ 11, 1) == -1)
393 /* Default interrupt priority. */
394 if (ca
->ca_intpri
== -1)
401 * xdcattach: attach controller
404 xdcattach(device_t parent
, device_t self
, void *aux
)
406 struct xdc_softc
*xdc
= device_private(self
);
407 struct confargs
*ca
= aux
;
408 struct xdc_attach_args xa
;
410 struct xd_iopb_ctrl
*ctl
;
412 /* get addressing and intr level stuff from autoconfig and load it
413 * into our xdc_softc. */
416 xdc
->xdc
= (struct xdc
*)bus_mapin(ca
->ca_bustype
, ca
->ca_paddr
,
418 xdc
->bustype
= ca
->ca_bustype
;
419 xdc
->ipl
= ca
->ca_intpri
;
420 xdc
->vector
= ca
->ca_intvec
;
422 for (lcv
= 0; lcv
< XDC_MAXDEV
; lcv
++)
423 xdc
->sc_drives
[lcv
] = NULL
;
425 /* allocate and zero buffers
427 * note: we simplify the code by allocating the max number of iopbs and
428 * iorq's up front. thus, we avoid linked lists and the costs
429 * associated with them in exchange for wasting a little memory. */
431 xdc
->iopbase
= (struct xd_iopb
*)dvma_malloc(XDC_MAXIOPB
*
432 sizeof(struct xd_iopb
)); /* KVA */
433 memset(xdc
->iopbase
, 0, XDC_MAXIOPB
* sizeof(struct xd_iopb
));
434 xdc
->dvmaiopb
= (struct xd_iopb
*)dvma_kvtopa(xdc
->iopbase
,
436 xdc
->reqs
= malloc(XDC_MAXIOPB
* sizeof(struct xd_iorq
),
437 M_DEVBUF
, M_NOWAIT
| M_ZERO
);
438 if (xdc
->reqs
== NULL
)
441 /* init free list, iorq to iopb pointers, and non-zero fields in the
442 * iopb which never change. */
444 for (lcv
= 0; lcv
< XDC_MAXIOPB
; lcv
++) {
445 xdc
->reqs
[lcv
].iopb
= &xdc
->iopbase
[lcv
];
446 xdc
->freereq
[lcv
] = lcv
;
447 xdc
->iopbase
[lcv
].fixd
= 1; /* always the same */
448 xdc
->iopbase
[lcv
].naddrmod
= XDC_ADDRMOD
; /* always the same */
449 xdc
->iopbase
[lcv
].intr_vec
= xdc
->vector
; /* always the same */
451 xdc
->nfree
= XDC_MAXIOPB
;
453 xdc
->waithead
= xdc
->waitend
= xdc
->nwait
= 0;
456 /* init queue of waiting bufs */
458 bufq_alloc(&xdc
->sc_wq
, "fcfs", 0);
459 callout_init(&xdc
->sc_tick_ch
, 0);
462 * section 7 of the manual tells us how to init the controller:
463 * - read controller parameters (6/0)
464 * - write controller parameters (5/0)
467 /* read controller parameters and insure we have a 753/7053 */
469 rqno
= xdc_cmd(xdc
, XDCMD_RDP
, XDFUN_CTL
, 0, 0, 0, 0, XD_SUB_POLL
);
470 if (rqno
== XD_ERR_FAIL
) {
471 aprint_error(": couldn't read controller params\n");
472 return; /* shouldn't ever happen */
474 ctl
= (struct xd_iopb_ctrl
*)&xdc
->iopbase
[rqno
];
475 if (ctl
->ctype
!= XDCT_753
) {
476 if (xdc
->reqs
[rqno
].errno
)
477 aprint_error(": %s: ",
478 xdc_e2str(xdc
->reqs
[rqno
].errno
));
479 aprint_error(": doesn't identify as a 753/7053\n");
480 XDC_DONE(xdc
, rqno
, err
);
483 aprint_normal(": Xylogics 753/7053, PROM=0x%x.%02x.%02x\n",
484 ctl
->eprom_partno
, ctl
->eprom_lvl
, ctl
->eprom_rev
);
485 XDC_DONE(xdc
, rqno
, err
);
487 /* now write controller parameters (xdc_cmd sets all params for us) */
489 rqno
= xdc_cmd(xdc
, XDCMD_WRP
, XDFUN_CTL
, 0, 0, 0, 0, XD_SUB_POLL
);
490 XDC_DONE(xdc
, rqno
, err
);
492 aprint_error_dev(self
, "controller config error: %s\n",
497 /* link in interrupt with higher level software */
498 isr_add_vectored(xdcintr
, xdc
, ca
->ca_intpri
, ca
->ca_intvec
);
499 evcnt_attach_dynamic(&xdc
->sc_intrcnt
, EVCNT_TYPE_INTR
, NULL
,
500 device_xname(self
), "intr");
502 /* now we must look for disks using autoconfig */
504 for (xa
.driveno
= 0; xa
.driveno
< XDC_MAXDEV
; xa
.driveno
++)
505 (void)config_found(self
, (void *)&xa
, xdc_print
);
507 /* start the watchdog clock */
508 callout_reset(&xdc
->sc_tick_ch
, XDC_TICKCNT
, xdc_tick
, xdc
);
512 xdc_print(void *aux
, const char *name
)
514 struct xdc_attach_args
*xa
= aux
;
517 aprint_normal("%s: ", name
);
519 if (xa
->driveno
!= -1)
520 aprint_normal(" drive %d", xa
->driveno
);
526 * xdmatch: probe for disk.
528 * note: we almost always say disk is present. this allows us to
529 * spin up and configure a disk after the system is booted (we can
530 * call xdattach!). Also, wire down the relationship between the
531 * xd* and xdc* devices, to simplify boot device identification.
534 xdmatch(device_t parent
, cfdata_t cf
, void *aux
)
536 struct xdc_attach_args
*xa
= aux
;
539 /* Match only on the "wired-down" controller+disk. */
540 xd_unit
= device_unit(parent
) * 2 + xa
->driveno
;
541 if (cf
->cf_unit
!= xd_unit
)
548 * xdattach: attach a disk.
551 xdattach(device_t parent
, device_t self
, void *aux
)
553 struct xd_softc
*xd
= device_private(self
);
554 struct xdc_softc
*xdc
= device_private(parent
);
555 struct xdc_attach_args
*xa
= aux
;
561 * Always re-initialize the disk structure. We want statistics
562 * to start with a clean slate.
564 memset(&xd
->sc_dk
, 0, sizeof(xd
->sc_dk
));
565 disk_init(&xd
->sc_dk
, device_xname(self
), &xddkdriver
);
567 xd
->state
= XD_DRIVE_UNKNOWN
; /* to start */
571 xd
->xd_drive
= xa
->driveno
;
572 xdc
->sc_drives
[xa
->driveno
] = xd
;
574 /* Do init work common to attach and open. */
579 * end of autoconfig functions
583 * Initialize a disk. This can be called from both autoconf and
584 * also from xdopen/xdstrategy.
587 xd_init(struct xd_softc
*xd
)
589 struct xdc_softc
*xdc
;
591 struct xd_iopb_drive
*driopb
;
593 int rqno
, err
, spt
, mb
, blk
, lcv
, fullmode
, newstate
;
596 xd
->state
= XD_DRIVE_ATTACHING
;
597 newstate
= XD_DRIVE_UNKNOWN
;
598 fullmode
= (cold
) ? XD_SUB_POLL
: XD_SUB_WAIT
;
599 dvmabuf
= dvma_malloc(XDFM_BPS
);
601 /* first try and reset the drive */
602 rqno
= xdc_cmd(xdc
, XDCMD_RST
, 0, xd
->xd_drive
, 0, 0, 0, fullmode
);
603 XDC_DONE(xdc
, rqno
, err
);
604 if (err
== XD_ERR_NRDY
) {
605 printf("%s: drive %d: off-line\n",
606 device_xname(xd
->sc_dev
), xd
->xd_drive
);
610 printf("%s: ERROR 0x%02x (%s)\n",
611 device_xname(xd
->sc_dev
), err
, xdc_e2str(err
));
614 printf("%s: drive %d ready\n",
615 device_xname(xd
->sc_dev
), xd
->xd_drive
);
617 /* now set format parameters */
619 rqno
= xdc_cmd(xdc
, XDCMD_WRP
, XDFUN_FMT
, xd
->xd_drive
,
621 XDC_DONE(xdc
, rqno
, err
);
623 printf("%s: write format parameters failed: %s\n",
624 device_xname(xd
->sc_dev
), xdc_e2str(err
));
628 /* get drive parameters */
630 rqno
= xdc_cmd(xdc
, XDCMD_RDP
, XDFUN_DRV
, xd
->xd_drive
,
632 if (rqno
!= XD_ERR_FAIL
) {
633 driopb
= (struct xd_iopb_drive
*)&xdc
->iopbase
[rqno
];
634 spt
= driopb
->sectpertrk
;
636 XDC_DONE(xdc
, rqno
, err
);
638 printf("%s: read drive parameters failed: %s\n",
639 device_xname(xd
->sc_dev
), xdc_e2str(err
));
644 * now set drive parameters (to semi-bogus values) so we can read the
647 xd
->pcyl
= xd
->ncyl
= 1;
652 for (lcv
= 0; lcv
< 126; lcv
++) /* init empty bad144 table */
653 xd
->dkb
.bt_bad
[lcv
].bt_cyl
=
654 xd
->dkb
.bt_bad
[lcv
].bt_trksec
= 0xffff;
655 rqno
= xdc_cmd(xdc
, XDCMD_WRP
, XDFUN_DRV
, xd
->xd_drive
,
657 XDC_DONE(xdc
, rqno
, err
);
659 printf("%s: write drive parameters failed: %s\n",
660 device_xname(xd
->sc_dev
), xdc_e2str(err
));
664 /* read disk label */
665 rqno
= xdc_cmd(xdc
, XDCMD_RD
, 0, xd
->xd_drive
,
666 0, 1, dvmabuf
, fullmode
);
667 XDC_DONE(xdc
, rqno
, err
);
669 printf("%s: reading disk label failed: %s\n",
670 device_xname(xd
->sc_dev
), xdc_e2str(err
));
673 newstate
= XD_DRIVE_NOLABEL
;
676 /* Attach the disk: must be before getdisklabel to malloc label */
677 disk_attach(&xd
->sc_dk
);
679 if (xdgetdisklabel(xd
, dvmabuf
) != XD_ERR_AOK
)
682 /* inform the user of what is up */
683 printf("%s: <%s>, pcyl %d, hw_spt %d\n",
684 device_xname(xd
->sc_dev
), (char *)dvmabuf
, xd
->pcyl
, spt
);
685 mb
= xd
->ncyl
* (xd
->nhead
* xd
->nsect
) / (1048576 / XDFM_BPS
);
686 printf("%s: %dMB, %d cyl, %d head, %d sec\n",
687 device_xname(xd
->sc_dev
), mb
,
688 xd
->ncyl
, xd
->nhead
, xd
->nsect
);
690 /* now set the real drive parameters! */
691 rqno
= xdc_cmd(xdc
, XDCMD_WRP
, XDFUN_DRV
, xd
->xd_drive
,
693 XDC_DONE(xdc
, rqno
, err
);
695 printf("%s: write real drive parameters failed: %s\n",
696 device_xname(xd
->sc_dev
), xdc_e2str(err
));
699 newstate
= XD_DRIVE_ONLINE
;
702 * read bad144 table. this table resides on the first sector of the
703 * last track of the disk (i.e. second cyl of "acyl" area).
705 blk
= (xd
->ncyl
+ xd
->acyl
- 1) * (xd
->nhead
* xd
->nsect
) + /* last cyl */
706 (xd
->nhead
- 1) * xd
->nsect
; /* last head */
707 rqno
= xdc_cmd(xdc
, XDCMD_RD
, 0, xd
->xd_drive
,
708 blk
, 1, dvmabuf
, fullmode
);
709 XDC_DONE(xdc
, rqno
, err
);
711 printf("%s: reading bad144 failed: %s\n",
712 device_xname(xd
->sc_dev
), xdc_e2str(err
));
716 /* check dkbad for sanity */
717 dkb
= (struct dkbad
*)dvmabuf
;
718 for (lcv
= 0; lcv
< 126; lcv
++) {
719 if ((dkb
->bt_bad
[lcv
].bt_cyl
== 0xffff ||
720 dkb
->bt_bad
[lcv
].bt_cyl
== 0) &&
721 dkb
->bt_bad
[lcv
].bt_trksec
== 0xffff)
722 continue; /* blank */
723 if (dkb
->bt_bad
[lcv
].bt_cyl
>= xd
->ncyl
)
725 if ((dkb
->bt_bad
[lcv
].bt_trksec
>> 8) >= xd
->nhead
)
727 if ((dkb
->bt_bad
[lcv
].bt_trksec
& 0xff) >= xd
->nsect
)
731 printf("%s: warning: invalid bad144 sector!\n",
732 device_xname(xd
->sc_dev
));
734 memcpy(&xd
->dkb
, dvmabuf
, XDFM_BPS
);
738 xd
->state
= newstate
;
739 dvma_free(dvmabuf
, XDFM_BPS
);
743 * { b , c } d e v s w f u n c t i o n s
747 * xdclose: close device
750 xdclose(dev_t dev
, int flag
, int fmt
, struct lwp
*l
)
752 struct xd_softc
*xd
= device_lookup_private(&xd_cd
, DISKUNIT(dev
));
753 int part
= DISKPART(dev
);
755 /* clear mask bits */
759 xd
->sc_dk
.dk_copenmask
&= ~(1 << part
);
762 xd
->sc_dk
.dk_bopenmask
&= ~(1 << part
);
765 xd
->sc_dk
.dk_openmask
= xd
->sc_dk
.dk_copenmask
| xd
->sc_dk
.dk_bopenmask
;
771 * xddump: crash dump system
774 xddump(dev_t dev
, daddr_t blkno
, void *va
, size_t sz
)
779 unit
= DISKUNIT(dev
);
780 part
= DISKPART(dev
);
782 xd
= device_lookup_private(&xd_cd
, unit
);
786 printf("%s%c: crash dump not supported (yet)\n",
787 device_xname(xd
->sc_dev
), 'a' + part
);
791 /* outline: globals: "dumplo" == sector number of partition to start
792 * dump at (convert to physical sector with partition table)
793 * "dumpsize" == size of dump in clicks "physmem" == size of physical
794 * memory (clicks, ctob() to get bytes) (normal case: dumpsize ==
797 * dump a copy of physical memory to the dump device starting at sector
798 * "dumplo" in the swap partition (make sure > 0). map in pages as
799 * we go. use polled I/O.
801 * XXX how to handle NON_CONTIG?
805 static enum kauth_device_req
806 xd_getkauthreq(u_char cmd
)
808 enum kauth_device_req req
;
813 req
= KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_WRITE
;
818 req
= KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READ
;
822 req
= KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF
;
827 req
= KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_WRITECONF
;
842 * xdioctl: ioctls on XD drives. based on ioctl's of other netbsd disks.
845 xdioctl(dev_t dev
, u_long command
, void *addr
, int flag
, struct lwp
*l
)
848 struct xd_iocmd
*xio
;
851 unit
= DISKUNIT(dev
);
853 xd
= device_lookup_private(&xd_cd
, unit
);
857 /* switch on ioctl type */
860 case DIOCSBAD
: /* set bad144 info */
861 if ((flag
& FWRITE
) == 0)
864 memcpy(&xd
->dkb
, addr
, sizeof(xd
->dkb
));
868 case DIOCGDINFO
: /* get disk label */
869 memcpy(addr
, xd
->sc_dk
.dk_label
, sizeof(struct disklabel
));
872 case DIOCGPART
: /* get partition info */
873 ((struct partinfo
*)addr
)->disklab
= xd
->sc_dk
.dk_label
;
874 ((struct partinfo
*)addr
)->part
=
875 &xd
->sc_dk
.dk_label
->d_partitions
[DISKPART(dev
)];
878 case DIOCSDINFO
: /* set disk label */
879 if ((flag
& FWRITE
) == 0)
881 error
= setdisklabel(xd
->sc_dk
.dk_label
,
882 (struct disklabel
*)addr
, /* xd->sc_dk.dk_openmask : */ 0,
883 xd
->sc_dk
.dk_cpulabel
);
885 if (xd
->state
== XD_DRIVE_NOLABEL
)
886 xd
->state
= XD_DRIVE_ONLINE
;
890 case DIOCWLABEL
: /* change write status of disk label */
891 if ((flag
& FWRITE
) == 0)
894 xd
->flags
|= XD_WLABEL
;
896 xd
->flags
&= ~XD_WLABEL
;
899 case DIOCWDINFO
: /* write disk label */
900 if ((flag
& FWRITE
) == 0)
902 error
= setdisklabel(xd
->sc_dk
.dk_label
,
903 (struct disklabel
*)addr
, /* xd->sc_dk.dk_openmask : */ 0,
904 xd
->sc_dk
.dk_cpulabel
);
906 if (xd
->state
== XD_DRIVE_NOLABEL
)
907 xd
->state
= XD_DRIVE_ONLINE
;
909 /* Simulate opening partition 0 so write succeeds. */
910 xd
->sc_dk
.dk_openmask
|= (1 << 0);
911 error
= writedisklabel(MAKEDISKDEV(major(dev
),
912 DISKUNIT(dev
), RAW_PART
),
913 xdstrategy
, xd
->sc_dk
.dk_label
,
914 xd
->sc_dk
.dk_cpulabel
);
915 xd
->sc_dk
.dk_openmask
=
916 xd
->sc_dk
.dk_copenmask
| xd
->sc_dk
.dk_bopenmask
;
921 enum kauth_device_req req
;
923 xio
= (struct xd_iocmd
*)addr
;
924 req
= xd_getkauthreq(xio
->cmd
);
925 if ((error
= kauth_authorize_device_passthru(l
->l_cred
,
926 dev
, req
, xio
)) != 0)
928 return xdc_ioctlcmd(xd
, dev
, xio
);
940 xdopen(dev_t dev
, int flag
, int fmt
, struct lwp
*l
)
942 int err
, unit
, part
, s
;
945 /* first, could it be a valid target? */
946 unit
= DISKUNIT(dev
);
947 xd
= device_lookup_private(&xd_cd
, unit
);
950 part
= DISKPART(dev
);
954 * If some other processing is doing init, sleep.
957 while (xd
->state
== XD_DRIVE_ATTACHING
) {
958 if (tsleep(&xd
->state
, PRIBIO
, "xdopen", 0)) {
963 /* Do we need to init the drive? */
964 if (xd
->state
== XD_DRIVE_UNKNOWN
) {
968 /* Was the init successful? */
969 if (xd
->state
== XD_DRIVE_UNKNOWN
) {
974 /* check for partition */
975 if (part
!= RAW_PART
&&
976 (part
>= xd
->sc_dk
.dk_label
->d_npartitions
||
977 xd
->sc_dk
.dk_label
->d_partitions
[part
].p_fstype
== FS_UNUSED
)) {
985 xd
->sc_dk
.dk_copenmask
|= (1 << part
);
988 xd
->sc_dk
.dk_bopenmask
|= (1 << part
);
991 xd
->sc_dk
.dk_openmask
= xd
->sc_dk
.dk_copenmask
| xd
->sc_dk
.dk_bopenmask
;
999 xdread(dev_t dev
, struct uio
*uio
, int flags
)
1002 return physio(xdstrategy
, NULL
, dev
, B_READ
, minphys
, uio
);
1006 xdwrite(dev_t dev
, struct uio
*uio
, int flags
)
1009 return physio(xdstrategy
, NULL
, dev
, B_WRITE
, minphys
, uio
);
1014 * xdsize: return size of a partition for a dump
1019 struct xd_softc
*xdsc
;
1020 int unit
, part
, size
, omask
;
1023 unit
= DISKUNIT(dev
);
1024 xdsc
= device_lookup_private(&xd_cd
, unit
);
1028 part
= DISKPART(dev
);
1029 omask
= xdsc
->sc_dk
.dk_openmask
& (1 << part
);
1031 if (omask
== 0 && xdopen(dev
, 0, S_IFBLK
, NULL
) != 0)
1035 if (xdsc
->sc_dk
.dk_label
->d_partitions
[part
].p_fstype
!= FS_SWAP
)
1036 size
= -1; /* only give valid size for swap partitions */
1038 size
= xdsc
->sc_dk
.dk_label
->d_partitions
[part
].p_size
*
1039 (xdsc
->sc_dk
.dk_label
->d_secsize
/ DEV_BSIZE
);
1040 if (omask
== 0 && xdclose(dev
, 0, S_IFBLK
, NULL
) != 0)
1046 * xdstrategy: buffering system interface to xd.
1049 xdstrategy(struct buf
*bp
)
1051 struct xd_softc
*xd
;
1052 struct xdc_softc
*parent
;
1055 unit
= DISKUNIT(bp
->b_dev
);
1057 /* check for live device */
1059 xd
= device_lookup_private(&xd_cd
, unit
);
1062 (bp
->b_bcount
% xd
->sc_dk
.dk_label
->d_secsize
) != 0) {
1063 bp
->b_error
= EINVAL
;
1067 /* There should always be an open first. */
1068 if (xd
->state
== XD_DRIVE_UNKNOWN
) {
1073 if (xd
->state
!= XD_DRIVE_ONLINE
&& DISKPART(bp
->b_dev
) != RAW_PART
) {
1074 /* no I/O to unlabeled disks, unless raw partition */
1078 /* short circuit zero length request */
1080 if (bp
->b_bcount
== 0)
1083 /* check bounds with label (disksubr.c). Determine the size of the
1084 * transfer, and make sure it is within the boundaries of the
1085 * partition. Adjust transfer if needed, and signal errors or early
1088 if (bounds_check_with_label(&xd
->sc_dk
, bp
,
1089 (xd
->flags
& XD_WLABEL
) != 0) <= 0)
1093 * now we know we have a valid buf structure that we need to do I/O
1096 * note that we don't disksort because the controller has a sorting
1097 * algorithm built into the hardware.
1100 s
= splbio(); /* protect the queues */
1102 /* first, give jobs in front of us a chance */
1103 parent
= xd
->parent
;
1104 while (parent
->nfree
> 0 && bufq_peek(parent
->sc_wq
) != NULL
)
1105 if (xdc_startbuf(parent
, NULL
, NULL
) != XD_ERR_AOK
)
1109 * if there are no free iorq's, then we just queue and return. the
1110 * buffs will get picked up later by xdcintr().
1112 if (parent
->nfree
== 0) {
1113 bufq_put(parent
->sc_wq
, bp
);
1118 /* now we have free iopb's and we are at splbio... start 'em up */
1119 if (xdc_startbuf(parent
, xd
, bp
) != XD_ERR_AOK
) {
1129 /* tells upper layers we are done with this buf */
1130 bp
->b_resid
= bp
->b_bcount
;
1134 * end of {b,c}devsw functions
1138 * i n t e r r u p t f u n c t i o n
1140 * xdcintr: hardware interrupt.
1145 struct xdc_softc
*xdcsc
= v
;
1147 /* kick the event counter */
1148 xdcsc
->sc_intrcnt
.ev_count
++;
1150 /* remove as many done IOPBs as possible */
1151 xdc_remove_iorq(xdcsc
);
1153 /* start any iorq's already waiting */
1154 xdc_start(xdcsc
, XDC_MAXIOPB
);
1156 /* fill up any remaining iorq's with queue'd buffers */
1157 while (xdcsc
->nfree
> 0 && bufq_peek(xdcsc
->sc_wq
) != NULL
)
1158 if (xdc_startbuf(xdcsc
, NULL
, NULL
) != XD_ERR_AOK
)
1164 * end of interrupt function
1168 * i n t e r n a l f u n c t i o n s
1172 * xdc_rqinit: fill out the fields of an I/O request
1176 xdc_rqinit(struct xd_iorq
*rq
, struct xdc_softc
*xdc
, struct xd_softc
*xd
,
1177 int md
, u_long blk
, int cnt
, void *db
, struct buf
*bp
)
1182 rq
->ttl
= XDC_MAXTTL
+ 10;
1184 rq
->tries
= rq
->errno
= rq
->lasterror
= 0;
1187 rq
->dbuf
= rq
->dbufbase
= db
;
1192 * xdc_rqtopb: load up an IOPB based on an iorq
1195 xdc_rqtopb(struct xd_iorq
*iorq
, struct xd_iopb
*iopb
, int cmd
, int subfun
)
1199 /* standard stuff */
1201 iopb
->errs
= iopb
->done
= 0;
1203 iopb
->errno
= iopb
->status
= 0;
1204 iopb
->subfun
= subfun
;
1206 iopb
->unit
= iorq
->xd
->xd_drive
;
1210 /* check for alternate IOPB format */
1212 if (cmd
== XDCMD_WRP
) {
1215 struct xd_iopb_ctrl
*ctrl
=
1216 (struct xd_iopb_ctrl
*)iopb
;
1218 iopb
->intl
= (XD_STATE(iorq
->mode
) == XD_SUB_POLL
)
1219 ? 0 : iorq
->xdc
->ipl
;
1220 ctrl
->param_a
= XDPA_TMOD
| XDPA_DACF
;
1221 ctrl
->param_b
= XDPB_ROR
| XDPB_TDT_3_2USEC
;
1222 ctrl
->param_c
= XDPC_OVS
| XDPC_COP
| XDPC_ASR
|
1223 XDPC_RBC
| XDPC_ECC2
;
1224 ctrl
->throttle
= XDC_THROTTLE
;
1226 if (CPU_ISSUN4
&& cpuinfo
.cpu_type
== CPUTYP_4_300
)
1227 ctrl
->delay
= XDC_DELAY_4_300
;
1229 ctrl
->delay
= XDC_DELAY_SPARC
;
1232 ctrl
->delay
= XDC_DELAY_SUN3
;
1237 struct xd_iopb_drive
*drv
=
1238 (struct xd_iopb_drive
*)iopb
;
1239 /* we assume that the disk label has the right
1241 if (XD_STATE(iorq
->mode
) == XD_SUB_POLL
)
1242 drv
->dparam_ipl
= (XDC_DPARAM
<< 3);
1244 drv
->dparam_ipl
= (XDC_DPARAM
<< 3) |
1246 drv
->maxsect
= iorq
->xd
->nsect
- 1;
1247 drv
->maxsector
= drv
->maxsect
;
1248 /* note: maxsector != maxsect only if you are
1249 * doing cyl sparing */
1251 drv
->maxcyl
= iorq
->xd
->pcyl
- 1;
1252 drv
->maxhead
= iorq
->xd
->nhead
- 1;
1257 struct xd_iopb_format
*form
=
1258 (struct xd_iopb_format
*)iopb
;
1260 if (XD_STATE(iorq
->mode
) == XD_SUB_POLL
)
1261 form
->interleave_ipl
= (XDC_INTERLEAVE
<< 3);
1263 form
->interleave_ipl
= (XDC_INTERLEAVE
<< 3) |
1265 form
->field1
= XDFM_FIELD1
;
1266 form
->field2
= XDFM_FIELD2
;
1267 form
->field3
= XDFM_FIELD3
;
1268 form
->field4
= XDFM_FIELD4
;
1269 form
->bytespersec
= XDFM_BPS
;
1270 form
->field6
= XDFM_FIELD6
;
1271 form
->field7
= XDFM_FIELD7
;
1277 /* normal IOPB case (harmless to RDP command) */
1280 iopb
->intl
= (XD_STATE(iorq
->mode
) == XD_SUB_POLL
)
1281 ? 0 : iorq
->xdc
->ipl
;
1282 iopb
->sectcnt
= iorq
->sectcnt
;
1283 block
= iorq
->blockno
;
1284 if (iorq
->xd
== NULL
|| block
== 0) {
1285 iopb
->sectno
= iopb
->headno
= iopb
->cylno
= 0;
1287 iopb
->sectno
= block
% iorq
->xd
->nsect
;
1288 block
= block
/ iorq
->xd
->nsect
;
1289 iopb
->headno
= block
% iorq
->xd
->nhead
;
1290 block
= block
/ iorq
->xd
->nhead
;
1291 iopb
->cylno
= block
;
1293 iopb
->daddr
= dp
= (iorq
->dbuf
== NULL
) ? 0 :
1294 dvma_kvtopa(iorq
->dbuf
, iorq
->xdc
->bustype
);
1295 iopb
->addrmod
= XDC_ADDRMOD
;
1300 * xdc_cmd: front end for POLL'd and WAIT'd commands. Returns rqno.
1301 * If you've already got an IORQ, you can call submit directly (currently
1302 * there is no need to do this). NORM requests are handled separately.
1305 xdc_cmd(struct xdc_softc
*xdcsc
, int cmd
, int subfn
, int unit
, int block
,
1306 int scnt
, char *dptr
, int fullmode
)
1308 struct xd_iorq
*iorq
;
1309 struct xd_iopb
*iopb
;
1311 int submode
= XD_STATE(fullmode
);
1316 while (xdcsc
->nfree
== 0) {
1317 if (xdc_piodriver(xdcsc
, 0, 1) != XD_ERR_AOK
)
1324 while (xdcsc
->nfree
== 0) {
1325 if (tsleep(&xdcsc
->nfree
, PRIBIO
, "xdnfree", 0))
1328 while (xdcsc
->ndone
> XDC_SUBWAITLIM
) {
1329 if (tsleep(&xdcsc
->ndone
, PRIBIO
, "xdsubwait", 0))
1333 retry
= 0; /* got it */
1337 return XD_ERR_FAIL
; /* illegal */
1339 if (xdcsc
->nfree
== 0)
1340 panic("xdcmd nfree");
1341 rqno
= XDC_RQALLOC(xdcsc
);
1342 iorq
= &xdcsc
->reqs
[rqno
];
1346 /* init iorq/iopb */
1347 xdc_rqinit(iorq
, xdcsc
,
1348 (unit
== XDC_NOUNIT
) ? NULL
: xdcsc
->sc_drives
[unit
],
1349 fullmode
, block
, scnt
, dptr
, NULL
);
1351 /* load IOPB from iorq */
1352 xdc_rqtopb(iorq
, iopb
, cmd
, subfn
);
1354 /* submit it for processing */
1355 xdc_submit_iorq(xdcsc
, rqno
, fullmode
); /* error code will be in iorq */
1362 * start a buffer running, assumes nfree > 0
1365 xdc_startbuf(struct xdc_softc
*xdcsc
, struct xd_softc
*xdsc
, struct buf
*bp
)
1368 struct xd_iorq
*iorq
;
1369 struct xd_iopb
*iopb
;
1373 if (xdcsc
->nfree
== 0)
1374 panic("xdc_startbuf free");
1375 rqno
= XDC_RQALLOC(xdcsc
);
1376 iorq
= &xdcsc
->reqs
[rqno
];
1382 bp
= bufq_get(xdcsc
->sc_wq
);
1384 panic("%s bp", __func__
);
1385 xdsc
= xdcsc
->sc_drives
[DISKUNIT(bp
->b_dev
)];
1387 partno
= DISKPART(bp
->b_dev
);
1389 printf("xdc_startbuf: %s%c: %s block %d\n", device_xname(xdsc
->sc_dev
),
1390 'a' + partno
, (bp
->b_flags
& B_READ
) ? "read" : "write", bp
->b_blkno
);
1391 printf("%s: b_bcount %d, b_data 0x%x\n", __func__
,
1392 bp
->b_bcount
, bp
->b_data
);
1396 * load request. we have to calculate the correct block number based
1397 * on partition info.
1399 * also, note that there are two kinds of buf structures, those with
1400 * B_PHYS set and those without B_PHYS. if B_PHYS is set, then it is
1401 * a raw I/O (to a cdevsw) and we are doing I/O directly to the users'
1402 * buffer which has already been mapped into DVMA space. (Not on sun3)
1403 * However, if B_PHYS is not set, then the buffer is a normal system
1404 * buffer which does *not* live in DVMA space. In that case we call
1405 * dvma_mapin to map it into DVMA space so we can do the DMA to it.
1407 * in cases where we do a dvma_mapin, note that iorq points to the
1408 * buffer as mapped into DVMA space, where as the bp->b_data points
1409 * to its non-DVMA mapping.
1411 * XXX - On the sun3, B_PHYS does NOT mean the buffer is mapped
1412 * into dvma space, only that it was remapped into the kernel.
1413 * We ALWAYS have to remap the kernel buf into DVMA space.
1414 * (It is done inexpensively, using whole segments!)
1417 block
= bp
->b_blkno
+ ((partno
== RAW_PART
) ? 0 :
1418 xdsc
->sc_dk
.dk_label
->d_partitions
[partno
].p_offset
);
1420 dbuf
= dvma_mapin(bp
->b_data
, bp
->b_bcount
, 0);
1421 if (dbuf
== NULL
) { /* out of DVMA space */
1422 printf("%s: warning: out of DVMA space\n",
1423 device_xname(xdcsc
->sc_dev
));
1424 XDC_FREE(xdcsc
, rqno
);
1425 bufq_put(xdcsc
->sc_wq
, bp
);
1426 return XD_ERR_FAIL
; /* XXX: need some sort of
1427 * call-back scheme here? */
1430 /* init iorq and load iopb from it */
1432 xdc_rqinit(iorq
, xdcsc
, xdsc
, XD_SUB_NORM
| XD_MODE_VERBO
, block
,
1433 bp
->b_bcount
/ XDFM_BPS
, dbuf
, bp
);
1435 xdc_rqtopb(iorq
, iopb
, (bp
->b_flags
& B_READ
) ? XDCMD_RD
: XDCMD_WR
, 0);
1437 /* Instrumentation. */
1438 disk_busy(&xdsc
->sc_dk
);
1440 /* now submit [note that xdc_submit_iorq can never fail on NORM reqs] */
1442 xdc_submit_iorq(xdcsc
, rqno
, XD_SUB_NORM
);
1448 * xdc_submit_iorq: submit an iorq for processing. returns XD_ERR_AOK
1449 * if ok. if it fail returns an error code. type is XD_SUB_*.
1451 * note: caller frees iorq in all cases except NORM
1454 * NORM: XD_AOK (req pending), XD_FAIL (couldn't submit request)
1455 * WAIT: XD_AOK (success), <error-code> (failed)
1456 * POLL: <same as WAIT>
1457 * NOQ : <same as NORM>
1459 * there are three sources for i/o requests:
1460 * [1] xdstrategy: normal block I/O, using "struct buf" system.
1461 * [2] autoconfig/crash dump: these are polled I/O requests, no interrupts.
1462 * [3] open/ioctl: these are I/O requests done in the context of a process,
1463 * and the process should block until they are done.
1465 * software state is stored in the iorq structure. each iorq has an
1466 * iopb structure. the hardware understands the iopb structure.
1467 * every command must go through an iopb. a 7053 can only handle
1468 * XDC_MAXIOPB (31) active iopbs at one time. iopbs are allocated in
1469 * DVMA space at boot up time. what happens if we run out of iopb's?
1470 * for i/o type [1], the buffers are queued at the "buff" layer and
1471 * picked up later by the interrupt routine. for case [2] the
1472 * programmed i/o driver is called with a special flag that says
1473 * return when one iopb is free. for case [3] the process can sleep
1474 * on the iorq free list until some iopbs are available.
1478 xdc_submit_iorq(struct xdc_softc
*xdcsc
, int iorqno
, int type
)
1481 struct xd_iorq
*iorq
= &xdcsc
->reqs
[iorqno
];
1484 printf("xdc_submit_iorq(%s, no=%d, type=%d)\n",
1485 device_xname(xdcsc
->sc_dev
), iorqno
, type
);
1488 /* first check and see if controller is busy */
1489 if (xdcsc
->xdc
->xdc_csr
& XDC_ADDING
) {
1491 printf("%s: XDC not ready (ADDING)\n", __func__
);
1493 if (type
== XD_SUB_NOQ
)
1494 return XD_ERR_FAIL
; /* failed */
1495 XDC_TWAIT(xdcsc
, iorqno
); /* put at end of waitq */
1498 return XD_ERR_AOK
; /* success */
1500 while (iorq
->iopb
->done
== 0) {
1501 (void)tsleep(iorq
, PRIBIO
, "xdciorq", 0);
1505 return xdc_piodriver(xdcsc
, iorqno
, 0);
1507 panic("%s adding", __func__
);
1512 u_char
*rio
= (u_char
*)iorq
->iopb
;
1513 int sz
= sizeof(struct xd_iopb
), lcv
;
1514 printf("%s: aio #%d [",
1515 device_xname(xdcsc
->sc_dev
), iorq
- xdcsc
->reqs
);
1516 for (lcv
= 0; lcv
< sz
; lcv
++)
1517 printf(" %02x", rio
[lcv
]);
1520 #endif /* XDC_DEBUG */
1522 /* controller not busy, start command */
1523 iopbaddr
= dvma_kvtopa(iorq
->iopb
, xdcsc
->bustype
);
1524 XDC_GO(xdcsc
->xdc
, iopbaddr
); /* go! */
1526 /* command now running, wrap it up */
1530 return XD_ERR_AOK
; /* success */
1532 while (iorq
->iopb
->done
== 0) {
1533 (void)tsleep(iorq
, PRIBIO
, "xdciorq", 0);
1537 return xdc_piodriver(xdcsc
, iorqno
, 0);
1539 panic("%s wrap up", __func__
);
1541 panic("%s: impossible", __func__
);
1542 return 0; /* not reached */
1549 * programmed i/o driver. this function takes over the computer
1550 * and drains off all i/o requests. it returns the status of the iorq
1551 * the caller is interesting in. if freeone is true, then it returns
1552 * when there is a free iorq.
1555 xdc_piodriver(struct xdc_softc
*xdcsc
, int iorqno
, int freeone
)
1560 struct xdc
*xdc
= xdcsc
->xdc
;
1562 printf("%s(%s, %d, freeone=%d)\n", __func__
,
1563 device_xname(xdcsc
->sc_dev
), iorqno
, freeone
);
1566 while (xdcsc
->nwait
|| xdcsc
->nrun
) {
1568 printf("%s: wait=%d, run=%d\n", __func__
,
1569 xdcsc
->nwait
, xdcsc
->nrun
);
1571 XDC_WAIT(xdc
, count
, XDC_MAXTIME
, (XDC_REMIOPB
| XDC_F_ERROR
));
1573 printf("%s: done wait with count = %d\n", __func__
, count
);
1575 /* we expect some progress soon */
1576 if (count
== 0 && nreset
>= 2) {
1577 xdc_reset(xdcsc
, 0, XD_RSET_ALL
, XD_ERR_FAIL
, 0);
1579 printf("%s: timeout\n", __func__
);
1584 if (xdc_reset(xdcsc
, 0,
1585 (nreset
++ == 0) ? XD_RSET_NONE
: iorqno
,
1586 XD_ERR_FAIL
, 0) == XD_ERR_FAIL
)
1587 return XD_ERR_FAIL
; /* flushes all but POLL
1588 * requests, resets */
1591 xdc_remove_iorq(xdcsc
); /* could resubmit request */
1593 if (xdcsc
->nrun
< XDC_MAXIOPB
) {
1595 printf("%s: done: one free\n", __func__
);
1599 continue; /* don't xdc_start */
1601 xdc_start(xdcsc
, XDC_MAXIOPB
);
1604 /* get return value */
1606 retval
= xdcsc
->reqs
[iorqno
].errno
;
1609 printf("%s: done, retval = 0x%x (%s)\n", __func__
,
1610 xdcsc
->reqs
[iorqno
].errno
, xdc_e2str(xdcsc
->reqs
[iorqno
].errno
));
1614 * now that we've drained everything, start up any bufs that have
1618 while (xdcsc
->nfree
> 0 && bufq_peek(xdcsc
->sc_wq
) != NULL
)
1619 if (xdc_startbuf(xdcsc
, NULL
, NULL
) != XD_ERR_AOK
)
1626 * xdc_reset: reset one drive. NOTE: assumes xdc was just reset.
1627 * we steal iopb[0] for this, but we put it back when we are done.
1630 xdc_xdreset(struct xdc_softc
*xdcsc
, struct xd_softc
*xdsc
)
1632 struct xd_iopb tmpiopb
;
1636 memcpy(&tmpiopb
, xdcsc
->iopbase
, sizeof(tmpiopb
));
1637 memset(xdcsc
->iopbase
, 0, sizeof(tmpiopb
));
1638 xdcsc
->iopbase
->comm
= XDCMD_RST
;
1639 xdcsc
->iopbase
->unit
= xdsc
->xd_drive
;
1640 addr
= (u_long
)xdcsc
->dvmaiopb
;
1641 XDC_GO(xdcsc
->xdc
, addr
); /* go! */
1642 XDC_WAIT(xdcsc
->xdc
, del
, XDC_RESETUSEC
, XDC_REMIOPB
);
1643 if (del
<= 0 || xdcsc
->iopbase
->errs
) {
1644 printf("%s: off-line: %s\n", device_xname(xdcsc
->sc_dev
),
1645 xdc_e2str(xdcsc
->iopbase
->errno
));
1646 xdcsc
->xdc
->xdc_csr
= XDC_RESET
;
1647 XDC_WAIT(xdcsc
->xdc
, del
, XDC_RESETUSEC
, XDC_RESET
);
1649 panic("%s", __func__
);
1651 xdcsc
->xdc
->xdc_csr
= XDC_CLRRIO
; /* clear RIO */
1653 memcpy(xdcsc
->iopbase
, &tmpiopb
, sizeof(tmpiopb
));
1658 * xdc_reset: reset everything: requests are marked as errors except
1659 * a polled request (which is resubmitted)
1662 xdc_reset(struct xdc_softc
*xdcsc
, int quiet
, int blastmode
, int error
,
1663 struct xd_softc
*xdsc
)
1665 int del
= 0, lcv
, retval
= XD_ERR_AOK
;
1666 int oldfree
= xdcsc
->nfree
;
1667 struct xd_iorq
*iorq
;
1669 /* soft reset hardware */
1672 printf("%s: soft reset\n", device_xname(xdcsc
->sc_dev
));
1673 xdcsc
->xdc
->xdc_csr
= XDC_RESET
;
1674 XDC_WAIT(xdcsc
->xdc
, del
, XDC_RESETUSEC
, XDC_RESET
);
1676 blastmode
= XD_RSET_ALL
; /* dead, flush all requests */
1677 retval
= XD_ERR_FAIL
;
1680 xdc_xdreset(xdcsc
, xdsc
);
1682 /* fix queues based on "blast-mode" */
1684 for (lcv
= 0; lcv
< XDC_MAXIOPB
; lcv
++) {
1685 iorq
= &xdcsc
->reqs
[lcv
];
1687 if (XD_STATE(iorq
->mode
) != XD_SUB_POLL
&&
1688 XD_STATE(iorq
->mode
) != XD_SUB_WAIT
&&
1689 XD_STATE(iorq
->mode
) != XD_SUB_NORM
)
1693 xdcsc
->nrun
--; /* it isn't running any more */
1694 if (blastmode
== XD_RSET_ALL
|| blastmode
!= lcv
) {
1696 iorq
->errno
= error
;
1697 xdcsc
->iopbase
[lcv
].done
= xdcsc
->iopbase
[lcv
].errs
= 1;
1698 switch (XD_STATE(iorq
->mode
)) {
1700 iorq
->buf
->b_error
= EIO
;
1701 iorq
->buf
->b_resid
= iorq
->sectcnt
* XDFM_BPS
;
1702 /* Sun3: map/unmap regardless of B_PHYS */
1703 dvma_mapout(iorq
->dbufbase
,
1704 iorq
->buf
->b_bcount
);
1705 disk_unbusy(&iorq
->xd
->sc_dk
,
1706 (iorq
->buf
->b_bcount
- iorq
->buf
->b_resid
),
1707 (iorq
->buf
->b_flags
& B_READ
));
1709 XDC_FREE(xdcsc
, lcv
); /* add to free list */
1716 XD_NEWSTATE(iorq
->mode
, XD_SUB_DONE
);
1722 /* resubmit, put at front of wait queue */
1723 XDC_HWAIT(xdcsc
, lcv
);
1728 * now, if stuff is waiting, start it.
1729 * since we just reset it should go
1731 xdc_start(xdcsc
, XDC_MAXIOPB
);
1734 if (oldfree
== 0 && xdcsc
->nfree
)
1735 wakeup(&xdcsc
->nfree
);
1738 del
= xdcsc
->nwait
+ xdcsc
->nrun
+ xdcsc
->nfree
+ xdcsc
->ndone
;
1739 if (del
!= XDC_MAXIOPB
)
1740 printf("%s: diag: xdc_reset miscount (%d should be %d)!\n",
1741 device_xname(xdcsc
->sc_dev
), del
, XDC_MAXIOPB
);
1743 if (xdcsc
->ndone
> XDC_MAXIOPB
- XDC_SUBWAITLIM
)
1744 printf("%s: diag: lots of done jobs (%d)\n",
1745 device_xname(xdcsc
->sc_dev
), xdcsc
->ndone
);
1747 printf("RESET DONE\n");
1752 * xdc_start: start all waiting buffers
1755 xdc_start(struct xdc_softc
*xdcsc
, int maxio
)
1758 while (maxio
&& xdcsc
->nwait
&&
1759 (xdcsc
->xdc
->xdc_csr
& XDC_ADDING
) == 0) {
1760 XDC_GET_WAITER(xdcsc
, rqno
); /* note: rqno is an "out"
1762 if (xdc_submit_iorq(xdcsc
, rqno
, XD_SUB_NOQ
) != XD_ERR_AOK
)
1763 panic("%s", __func__
); /* should never happen */
1769 * xdc_remove_iorq: remove "done" IOPB's.
1772 xdc_remove_iorq(struct xdc_softc
*xdcsc
)
1774 int errno
, rqno
, comm
, errs
;
1775 struct xdc
*xdc
= xdcsc
->xdc
;
1776 struct xd_iopb
*iopb
;
1777 struct xd_iorq
*iorq
;
1780 if (xdc
->xdc_csr
& XDC_F_ERROR
) {
1782 * FATAL ERROR: should never happen under normal use. This
1783 * error is so bad, you can't even tell which IOPB is bad, so
1786 errno
= xdc
->xdc_f_err
;
1787 printf("%s: fatal error 0x%02x: %s\n",
1788 device_xname(xdcsc
->sc_dev
), errno
, xdc_e2str(errno
));
1789 if (xdc_reset(xdcsc
, 0, XD_RSET_ALL
, errno
, 0) != XD_ERR_AOK
) {
1790 printf("%s: soft reset failed!\n",
1791 device_xname(xdcsc
->sc_dev
));
1792 panic("%s: controller DEAD", __func__
);
1798 * get iopb that is done
1800 * hmm... I used to read the address of the done IOPB off the VME
1801 * registers and calculate the rqno directly from that. that worked
1802 * until I started putting a load on the controller. when loaded, i
1803 * would get interrupts but neither the REMIOPB or F_ERROR bits would
1804 * be set, even after DELAY'ing a while! later on the timeout
1805 * routine would detect IOPBs that were marked "running" but their
1806 * "done" bit was set. rather than dealing directly with this
1807 * problem, it is just easier to look at all running IOPB's for the
1810 if (xdc
->xdc_csr
& XDC_REMIOPB
) {
1811 xdc
->xdc_csr
= XDC_CLRRIO
;
1814 for (rqno
= 0; rqno
< XDC_MAXIOPB
; rqno
++) {
1815 iorq
= &xdcsc
->reqs
[rqno
];
1816 if (iorq
->mode
== 0 || XD_STATE(iorq
->mode
) == XD_SUB_DONE
)
1817 continue; /* free, or done */
1818 iopb
= &xdcsc
->iopbase
[rqno
];
1819 if (iopb
->done
== 0)
1820 continue; /* not done yet */
1824 u_char
*rio
= (u_char
*)iopb
;
1825 int sz
= sizeof(struct xd_iopb
), lcv
;
1827 printf("%s: rio #%d [",
1828 device_xname(xdcsc
->sc_dev
), rqno
);
1829 for (lcv
= 0; lcv
< sz
; lcv
++)
1830 printf(" %02x", rio
[lcv
]);
1833 #endif /* XDC_DEBUG */
1841 iorq
->errno
= iopb
->errno
;
1845 /* handle non-fatal errors */
1848 xdc_error(xdcsc
, iorq
, iopb
, rqno
, comm
) == XD_ERR_AOK
)
1849 continue; /* AOK: we resubmitted it */
1852 /* this iorq is now done (hasn't been restarted or anything) */
1854 if ((iorq
->mode
& XD_MODE_VERBO
) && iorq
->lasterror
)
1855 xdc_perror(iorq
, iopb
, 0);
1857 /* now, if read/write check to make sure we got all the data
1858 * we needed. (this may not be the case if we got an error in
1859 * the middle of a multisector request). */
1861 if ((iorq
->mode
& XD_MODE_B144
) != 0 && errs
== 0 &&
1862 (comm
== XDCMD_RD
|| comm
== XDCMD_WR
)) {
1863 /* we just successfully processed a bad144 sector
1864 * note: if we are in bad 144 mode, the pointers have
1865 * been advanced already (see above) and are pointing
1866 * at the bad144 sector. to exit bad144 mode, we
1867 * must advance the pointers 1 sector and issue a new
1868 * request if there are still sectors left to process
1871 XDC_ADVANCE(iorq
, 1); /* advance 1 sector */
1873 /* exit b144 mode */
1874 iorq
->mode
= iorq
->mode
& (~XD_MODE_B144
);
1876 if (iorq
->sectcnt
) { /* more to go! */
1877 iorq
->lasterror
= iorq
->errno
= iopb
->errno
= 0;
1878 iopb
->errs
= iopb
->done
= 0;
1880 iopb
->sectcnt
= iorq
->sectcnt
;
1882 iorq
->blockno
/ iorq
->xd
->sectpercyl
;
1884 (iorq
->blockno
/ iorq
->xd
->nhead
) %
1886 iopb
->sectno
= iorq
->blockno
% XDFM_BPS
;
1888 dvma_kvtopa(iorq
->dbuf
, xdcsc
->bustype
);
1889 XDC_HWAIT(xdcsc
, rqno
);
1890 xdc_start(xdcsc
, 1); /* resubmit */
1894 /* final cleanup, totally done with this request */
1896 switch (XD_STATE(iorq
->mode
)) {
1901 bp
->b_resid
= iorq
->sectcnt
* XDFM_BPS
;
1903 bp
->b_resid
= 0; /* done */
1905 /* Sun3: map/unmap regardless of B_PHYS */
1906 dvma_mapout(iorq
->dbufbase
, iorq
->buf
->b_bcount
);
1907 disk_unbusy(&iorq
->xd
->sc_dk
,
1908 (bp
->b_bcount
- bp
->b_resid
),
1909 (bp
->b_flags
& B_READ
));
1910 XDC_FREE(xdcsc
, rqno
);
1914 iorq
->mode
= XD_NEWSTATE(iorq
->mode
, XD_SUB_DONE
);
1919 iorq
->mode
= XD_NEWSTATE(iorq
->mode
, XD_SUB_DONE
);
1929 * xdc_perror: print error.
1930 * - if still_trying is true: we got an error, retried and got a
1931 * different error. in that case lasterror is the old error,
1932 * and errno is the new one.
1933 * - if still_trying is not true, then if we ever had an error it
1934 * is in lasterror. also, if iorq->errno == 0, then we recovered
1935 * from that error (otherwise iorq->errno == iorq->lasterror).
1938 xdc_perror(struct xd_iorq
*iorq
, struct xd_iopb
*iopb
, int still_trying
)
1940 int error
= iorq
->lasterror
;
1942 printf("%s", (iorq
->xd
) ?
1943 device_xname(iorq
->xd
->sc_dev
) :
1944 device_xname(iorq
->xdc
->sc_dev
));
1946 printf("%c: ", 'a' + (char)DISKPART(iorq
->buf
->b_dev
));
1947 if (iopb
->comm
== XDCMD_RD
|| iopb
->comm
== XDCMD_WR
)
1948 printf("%s %d/%d/%d: ",
1949 (iopb
->comm
== XDCMD_RD
) ? "read" : "write",
1950 iopb
->cylno
, iopb
->headno
, iopb
->sectno
);
1951 printf("%s", xdc_e2str(error
));
1954 printf(" [still trying, new error=%s]", xdc_e2str(iorq
->errno
));
1956 if (iorq
->errno
== 0)
1957 printf(" [recovered in %d tries]", iorq
->tries
);
1963 * xdc_error: non-fatal error encountered... recover.
1964 * return AOK if resubmitted, return FAIL if this iopb is done
1967 xdc_error(struct xdc_softc
*xdcsc
, struct xd_iorq
*iorq
, struct xd_iopb
*iopb
,
1971 int errno
= iorq
->errno
;
1972 int erract
= errno
& XD_ERA_MASK
;
1973 int oldmode
, advance
, i
;
1975 if (erract
== XD_ERA_RSET
) { /* some errors require a reset */
1976 oldmode
= iorq
->mode
;
1977 iorq
->mode
= XD_SUB_DONE
| (~XD_SUB_MASK
& oldmode
);
1979 /* make xdc_start ignore us */
1980 xdc_reset(xdcsc
, 1, XD_RSET_NONE
, errno
, iorq
->xd
);
1981 iorq
->mode
= oldmode
;
1984 /* check for read/write to a sector in bad144 table if bad: redirect
1985 * request to bad144 area */
1987 if ((comm
== XDCMD_RD
|| comm
== XDCMD_WR
) &&
1988 (iorq
->mode
& XD_MODE_B144
) == 0) {
1989 advance
= iorq
->sectcnt
- iopb
->sectcnt
;
1990 XDC_ADVANCE(iorq
, advance
);
1991 if ((i
= isbad(&iorq
->xd
->dkb
,
1992 iorq
->blockno
/ iorq
->xd
->sectpercyl
,
1993 (iorq
->blockno
/ iorq
->xd
->nsect
) % iorq
->xd
->nhead
,
1994 iorq
->blockno
% iorq
->xd
->nsect
)) != -1) {
1995 iorq
->mode
|= XD_MODE_B144
; /* enter bad144 mode &
1997 iopb
->errno
= iopb
->done
= iopb
->errs
= 0;
1999 iopb
->cylno
= (iorq
->xd
->ncyl
+ iorq
->xd
->acyl
) - 2;
2000 /* second to last acyl */
2001 i
= iorq
->xd
->sectpercyl
- 1 - i
; /* follow bad144
2003 iopb
->headno
= i
/ iorq
->xd
->nhead
;
2004 iopb
->sectno
= i
% iorq
->xd
->nhead
;
2005 XDC_HWAIT(xdcsc
, rqno
);
2006 xdc_start(xdcsc
, 1); /* resubmit */
2007 return XD_ERR_AOK
; /* recovered! */
2012 * it isn't a bad144 sector, must be real error! see if we can retry
2015 if ((iorq
->mode
& XD_MODE_VERBO
) && iorq
->lasterror
)
2016 xdc_perror(iorq
, iopb
, 1); /* inform of error state
2018 iorq
->lasterror
= errno
;
2020 if ((erract
== XD_ERA_RSET
|| erract
== XD_ERA_HARD
)
2021 && iorq
->tries
< XDC_MAXTRIES
) { /* retry? */
2023 iorq
->errno
= iopb
->errno
= iopb
->done
= iopb
->errs
= 0;
2024 XDC_HWAIT(xdcsc
, rqno
);
2025 xdc_start(xdcsc
, 1); /* restart */
2026 return XD_ERR_AOK
; /* recovered! */
2029 /* failed to recover from this error */
2034 * xdc_tick: make sure xd is still alive and ticking (err, kicking).
2039 struct xdc_softc
*xdcsc
= arg
;
2040 int lcv
, s
, reset
= 0;
2042 int nwait
, nrun
, nfree
, ndone
, whd
= 0;
2043 uint8_t fqc
[XDC_MAXIOPB
], wqc
[XDC_MAXIOPB
], mark
[XDC_MAXIOPB
];
2045 nwait
= xdcsc
->nwait
;
2047 nfree
= xdcsc
->nfree
;
2048 ndone
= xdcsc
->ndone
;
2049 memcpy(wqc
, xdcsc
->waitq
, sizeof(wqc
));
2050 memcpy(fqc
, xdcsc
->freereq
, sizeof(fqc
));
2052 if (nwait
+ nrun
+ nfree
+ ndone
!= XDC_MAXIOPB
) {
2053 printf("%s: diag: IOPB miscount "
2054 "(got w/f/r/d %d/%d/%d/%d, wanted %d)\n",
2055 device_xname(xdcsc
->sc_dev
), nwait
, nfree
, nrun
, ndone
,
2057 memset(mark
, 0, sizeof(mark
));
2059 for (lcv
= nfree
; lcv
> 0; lcv
--) {
2060 printf("%d ", fqc
[lcv
- 1]);
2061 mark
[fqc
[lcv
- 1]] = 1;
2066 printf("%d ", wqc
[whd
]);
2068 whd
= (whd
+ 1) % XDC_MAXIOPB
;
2072 for (lcv
= 0; lcv
< XDC_MAXIOPB
; lcv
++) {
2073 if (mark
[lcv
] == 0) {
2074 printf("MARK: running %d: mode %d done %d "
2075 "errs %d errno 0x%x ttl %d buf %p\n",
2076 lcv
, xdcsc
->reqs
[lcv
].mode
,
2077 xdcsc
->iopbase
[lcv
].done
,
2078 xdcsc
->iopbase
[lcv
].errs
,
2079 xdcsc
->iopbase
[lcv
].errno
,
2080 xdcsc
->reqs
[lcv
].ttl
,
2081 xdcsc
->reqs
[lcv
].buf
);
2085 if (ndone
> XDC_MAXIOPB
- XDC_SUBWAITLIM
)
2086 printf("%s: diag: lots of done jobs (%d)\n",
2087 device_xname(xdcsc
->sc_dev
), ndone
);
2091 printf("%s: tick: csr 0x%x, w/f/r/d %d/%d/%d/%d\n",
2092 device_xname(xdcsc
->sc_dev
),
2093 xdcsc
->xdc
->xdc_csr
, xdcsc
->nwait
, xdcsc
->nfree
, xdcsc
->nrun
,
2095 for (lcv
= 0; lcv
< XDC_MAXIOPB
; lcv
++) {
2096 if (xdcsc
->reqs
[lcv
].mode
) {
2097 printf("running %d: "
2098 "mode %d done %d errs %d errno 0x%x\n", lcv
,
2099 xdcsc
->reqs
[lcv
].mode
, xdcsc
->iopbase
[lcv
].done
,
2100 xdcsc
->iopbase
[lcv
].errs
,
2101 xdcsc
->iopbase
[lcv
].errno
);
2106 /* reduce ttl for each request if one goes to zero, reset xdc */
2108 for (lcv
= 0; lcv
< XDC_MAXIOPB
; lcv
++) {
2109 if (xdcsc
->reqs
[lcv
].mode
== 0 ||
2110 XD_STATE(xdcsc
->reqs
[lcv
].mode
) == XD_SUB_DONE
)
2112 xdcsc
->reqs
[lcv
].ttl
--;
2113 if (xdcsc
->reqs
[lcv
].ttl
== 0)
2117 printf("%s: watchdog timeout\n", device_xname(xdcsc
->sc_dev
));
2118 xdc_reset(xdcsc
, 0, XD_RSET_NONE
, XD_ERR_FAIL
, NULL
);
2122 /* until next time */
2124 callout_reset(&xdcsc
->sc_tick_ch
, XDC_TICKCNT
, xdc_tick
, xdcsc
);
2128 * xdc_ioctlcmd: this function provides a user level interface to the
2129 * controller via ioctl. this allows "format" programs to be written
2130 * in user code, and is also useful for some debugging. we return
2131 * an error code. called at user priority.
2134 xdc_ioctlcmd(struct xd_softc
*xd
, dev_t dev
, struct xd_iocmd
*xio
)
2137 void *dvmabuf
= NULL
;
2138 struct xdc_softc
*xdcsc
;
2140 /* check sanity of requested command */
2144 case XDCMD_NOP
: /* no op: everything should be zero */
2145 if (xio
->subfn
|| xio
->dptr
|| xio
->dlen
||
2146 xio
->block
|| xio
->sectcnt
)
2150 case XDCMD_RD
: /* read / write sectors (up to XD_IOCMD_MAXS) */
2152 if (xio
->subfn
|| xio
->sectcnt
> XD_IOCMD_MAXS
||
2153 xio
->sectcnt
* XDFM_BPS
!= xio
->dlen
|| xio
->dptr
== NULL
)
2157 case XDCMD_SK
: /* seek: doesn't seem useful to export this */
2160 case XDCMD_WRP
: /* write parameters */
2161 return EINVAL
; /* not useful, except maybe drive
2162 * parameters... but drive parameters should
2163 * go via disklabel changes */
2165 case XDCMD_RDP
: /* read parameters */
2166 if (xio
->subfn
!= XDFUN_DRV
||
2167 xio
->dlen
|| xio
->block
|| xio
->dptr
)
2168 return EINVAL
; /* allow read drive params to
2170 xio
->sectcnt
= xd
->hw_spt
; /* we already know the answer */
2174 case XDCMD_XRD
: /* extended read/write */
2177 switch (xio
->subfn
) {
2179 case XDFUN_THD
:/* track headers */
2180 if (xio
->sectcnt
!= xd
->hw_spt
||
2181 (xio
->block
% xd
->nsect
) != 0 ||
2182 xio
->dlen
!= XD_IOCMD_HSZ
* xd
->hw_spt
||
2188 case XDFUN_FMT
:/* NOTE: also XDFUN_VFY */
2189 if (xio
->cmd
== XDCMD_XRD
)
2190 return EINVAL
; /* no XDFUN_VFY */
2191 if (xio
->sectcnt
|| xio
->dlen
||
2192 (xio
->block
% xd
->nsect
) != 0 || xio
->dptr
)
2196 case XDFUN_HDR
:/* header, header verify, data, data ECC */
2197 return EINVAL
; /* not yet */
2199 case XDFUN_DM
: /* defect map */
2200 case XDFUN_DMX
:/* defect map (alternate location) */
2201 if (xio
->sectcnt
|| xio
->dlen
!= XD_IOCMD_DMSZ
||
2202 (xio
->block
% xd
->nsect
) != 0 || xio
->dptr
== NULL
)
2211 case XDCMD_TST
: /* diagnostics */
2215 return EINVAL
;/* ??? */
2218 /* create DVMA buffer for request if needed */
2221 dvmabuf
= dvma_malloc(xio
->dlen
);
2222 if (xio
->cmd
== XDCMD_WR
|| xio
->cmd
== XDCMD_XWR
) {
2223 err
= copyin(xio
->dptr
, dvmabuf
, xio
->dlen
);
2225 dvma_free(dvmabuf
, xio
->dlen
);
2235 rqno
= xdc_cmd(xdcsc
, xio
->cmd
, xio
->subfn
, xd
->xd_drive
, xio
->block
,
2236 xio
->sectcnt
, dvmabuf
, XD_SUB_WAIT
);
2237 if (rqno
== XD_ERR_FAIL
) {
2241 xio
->errno
= xdcsc
->reqs
[rqno
].errno
;
2242 xio
->tries
= xdcsc
->reqs
[rqno
].tries
;
2243 XDC_DONE(xdcsc
, rqno
, err
);
2245 if (xio
->cmd
== XDCMD_RD
|| xio
->cmd
== XDCMD_XRD
)
2246 err
= copyout(dvmabuf
, xio
->dptr
, xio
->dlen
);
2251 dvma_free(dvmabuf
, xio
->dlen
);
2256 * xdc_e2str: convert error code number into an error string
2264 return "Software fatal error";
2266 return "Successful completion";
2268 return "Illegal cylinder address";
2270 return "Illegal head address";
2272 return "Illgal sector address";
2274 return "Count zero";
2276 return "Unimplemented command";
2278 return "Illegal field length 1";
2280 return "Illegal field length 2";
2282 return "Illegal field length 3";
2284 return "Illegal field length 4";
2286 return "Illegal field length 5";
2288 return "Illegal field length 6";
2290 return "Illegal field length 7";
2292 return "Illegal scatter/gather length";
2294 return "Not enough sectors per track";
2296 return "Next IOPB address alignment error";
2298 return "Scatter/gather address alignment error";
2300 return "Scatter/gather with auto-ECC";
2302 return "Soft ECC corrected";
2304 return "ECC ignored";
2306 return "Auto-seek retry recovered";
2308 return "Soft retry recovered";
2310 return "Hard data ECC";
2312 return "Header not found";
2314 return "Drive not ready";
2316 return "Operation timeout";
2318 return "VMEDMA timeout";
2320 return "Disk sequencer error";
2322 return "Header ECC error";
2324 return "Read verify";
2326 return "Fatail VMEDMA error";
2328 return "VMEbus error";
2330 return "Drive faulted";
2332 return "Header error/cyliner";
2334 return "Header error/head";
2336 return "Drive not on-cylinder";
2338 return "Seek error";
2340 return "Illegal sector size";
2344 return "Write-protect error";
2346 return "IRAM self test failure";
2348 return "Maintenance test 3 failure (DSKCEL RAM)";
2350 return "Maintenance test 4 failure (header shift reg)";
2352 return "Maintenance test 5 failure (VMEDMA regs)";
2354 return "Maintenance test 6 failure (REGCEL chip)";
2356 return "Maintenance test 7 failure (buffer parity)";
2358 return "Maintenance test 8 failure (disk FIFO)";
2360 return "IOPB checksum miscompare";
2362 return "IOPB DMA fatal";
2364 return "IOPB address alignment error";
2366 return "Firmware error";
2368 return "Illegal maintenance mode test number";
2370 return "ACFAIL asserted";
2372 return "Unknown error";