1 /*	$OpenBSD: xy.c,v 1.24 2004/02/15 02:45:46 tedu Exp $	*/
2 /*	$NetBSD: xy.c,v 1.26 1997/07/19 21:43:56 pk Exp $	*/
3 
4 /*
5  *
6  * Copyright (c) 1995 Charles D. Cranor
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by Charles D. Cranor.
20  * 4. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 /*
36  *
37  * x y . c   x y l o g i c s   4 5 0 / 4 5 1   s m d   d r i v e r
38  *
39  * author: Chuck Cranor <chuck@ccrc.wustl.edu>
40  * id: $NetBSD: xy.c,v 1.26 1997/07/19 21:43:56 pk Exp $
41  * started: 14-Sep-95
42  * references: [1] Xylogics Model 753 User's Manual
43  *                 part number: 166-753-001, Revision B, May 21, 1988.
44  *                 "Your Partner For Performance"
45  *             [2] other NetBSD disk device drivers
46  *	       [3] Xylogics Model 450 User's Manual
47  *		   part number: 166-017-001, Revision B, 1983.
48  *	       [4] Addendum to Xylogics Model 450 Disk Controller User's
49  *			Manual, Jan. 1985.
50  *	       [5] The 451 Controller, Rev. B3, September 2, 1986.
51  *	       [6] David Jones <dej@achilles.net>'s unfinished 450/451 driver
52  *
53  */
54 
55 #undef XYC_DEBUG		/* full debug */
56 #undef XYC_DIAG			/* extra sanity checks */
57 #if defined(DIAGNOSTIC) && !defined(XYC_DIAG)
58 #define XYC_DIAG		/* link in with master DIAG option */
59 #endif
60 
61 #include <sys/param.h>
62 #include <sys/proc.h>
63 #include <sys/systm.h>
64 #include <sys/kernel.h>
65 #include <sys/file.h>
66 #include <sys/stat.h>
67 #include <sys/ioctl.h>
68 #include <sys/buf.h>
69 #include <sys/uio.h>
70 #include <sys/malloc.h>
71 #include <sys/device.h>
72 #include <sys/disklabel.h>
73 #include <sys/disk.h>
74 #include <sys/syslog.h>
75 #include <sys/dkbad.h>
76 #include <sys/conf.h>
77 #include <sys/timeout.h>
78 
79 #include <uvm/uvm_extern.h>
80 
81 #include <machine/autoconf.h>
82 #include <machine/sun_disklabel.h>
83 #include <machine/conf.h>
84 
85 #include <sparc/dev/xyreg.h>
86 #include <sparc/dev/xyvar.h>
87 #include <sparc/dev/xio.h>
88 #include <sparc/sparc/vaddrs.h>
89 
90 /*
91  * macros
92  */
93 
94 /*
95  * XYC_GO: start iopb ADDR (DVMA addr in a u_long) on XYC
96  */
97 #define XYC_GO(XYC, ADDR) { \
98 	(XYC)->xyc_addr_lo = ((ADDR) & 0xff); \
99 	(ADDR) = ((ADDR) >> 8); \
100 	(XYC)->xyc_addr_hi = ((ADDR) & 0xff); \
101 	(ADDR) = ((ADDR) >> 8); \
102 	(XYC)->xyc_reloc_lo = ((ADDR) & 0xff); \
103 	(ADDR) = ((ADDR) >> 8); \
104 	(XYC)->xyc_reloc_hi = (ADDR); \
105 	(XYC)->xyc_csr = XYC_GBSY; /* go! */ \
106 }
107 
108 /*
109  * XYC_DONE: don't need IORQ, get error code and free (done after xyc_cmd)
110  */
111 
112 #define XYC_DONE(SC,ER) { \
113 	if ((ER) == XY_ERR_AOK) { \
114 		(ER) = (SC)->ciorq->errno; \
115 		(SC)->ciorq->mode = XY_SUB_FREE; \
116 		wakeup((SC)->ciorq); \
117 	} \
118 	}
119 
120 /*
121  * XYC_ADVANCE: advance iorq's pointers by a number of sectors
122  */
123 
124 #define XYC_ADVANCE(IORQ, N) { \
125 	if (N) { \
126 		(IORQ)->sectcnt -= (N); \
127 		(IORQ)->blockno += (N); \
128 		(IORQ)->dbuf += ((N)*XYFM_BPS); \
129 	} \
130 }
131 
132 /*
133  * note - addresses you can sleep on:
134  *   [1] & of xy_softc's "state" (waiting for a chance to attach a drive)
135  *   [2] & an iorq (waiting for an XY_SUB_WAIT iorq to finish)
136  */
137 
138 
139 /*
140  * function prototypes
141  * "xyc_*" functions are internal, all others are external interfaces
142  */
143 
144 extern int pil_to_vme[];	/* from obio.c */
145 
146 /* internals */
147 struct xy_iopb *xyc_chain(struct xyc_softc *, struct xy_iorq *);
148 int	xyc_cmd(struct xyc_softc *, int, int, int, int, int, char *, int);
149 char   *xyc_e2str(int);
150 int	xyc_entoact(int);
151 int	xyc_error(struct xyc_softc *, struct xy_iorq *,
152 		   struct xy_iopb *, int);
153 int	xyc_ioctlcmd(struct xy_softc *, dev_t dev, struct xd_iocmd *);
154 void	xyc_perror(struct xy_iorq *, struct xy_iopb *, int);
155 int	xyc_piodriver(struct xyc_softc *, struct xy_iorq *);
156 int	xyc_remove_iorq(struct xyc_softc *);
157 int	xyc_reset(struct xyc_softc *, int, struct xy_iorq *, int,
158 			struct xy_softc *);
159 inline void xyc_rqinit(struct xy_iorq *, struct xyc_softc *,
160 			    struct xy_softc *, int, u_long, int,
161 			    caddr_t, struct buf *);
162 void	xyc_rqtopb(struct xy_iorq *, struct xy_iopb *, int, int);
163 void	xyc_start(struct xyc_softc *, struct xy_iorq *);
164 int	xyc_startbuf(struct xyc_softc *, struct xy_softc *, struct buf *);
165 int	xyc_submit_iorq(struct xyc_softc *, struct xy_iorq *, int);
166 void	xyc_tick(void *);
167 int	xyc_unbusy(struct xyc *, int);
168 void	xyc_xyreset(struct xyc_softc *, struct xy_softc *);
169 
170 /* machine interrupt hook */
171 int	xycintr(void *);
172 
173 /* autoconf */
174 int	xycmatch(struct device *, void *, void *);
175 void	xycattach(struct device *, struct device *, void *);
176 int	xymatch(struct device *, void *, void *);
177 void	xyattach(struct device *, struct device *, void *);
178 
179 static	void xydummystrat(struct buf *);
180 int	xygetdisklabel(struct xy_softc *, void *);
181 
182 /*
183  * cfdrivers: device driver interface to autoconfig
184  */
185 
186 struct cfattach xyc_ca = {
187 	sizeof(struct xyc_softc), xycmatch, xycattach
188 };
189 
190 struct cfdriver xyc_cd = {
191 	NULL, "xyc", DV_DULL
192 };
193 
194 struct cfattach xy_ca = {
195 	sizeof(struct xy_softc), xymatch, xyattach
196 };
197 
198 struct cfdriver xy_cd = {
199 	NULL, "xy", DV_DISK
200 };
201 
202 struct xyc_attach_args {	/* this is the "aux" args to xyattach */
203 	int	driveno;	/* unit number */
204 	char	*buf;		/* scratch buffer for reading disk label */
205 	char	*dvmabuf;	/* DVMA address of above */
206 	int	fullmode;	/* submit mode */
207 	int	booting;	/* are we booting or not? */
208 };
209 
210 /*
211  * dkdriver
212  */
213 
214 struct dkdriver xydkdriver = { xystrategy };
215 
216 /*
217  * start: disk label fix code (XXX)
218  */
219 
220 static void *xy_labeldata;
221 
222 static void
xydummystrat(bp)223 xydummystrat(bp)
224 	struct buf *bp;
225 {
226 	if (bp->b_bcount != XYFM_BPS)
227 		panic("xydummystrat");
228 	bcopy(xy_labeldata, bp->b_un.b_addr, XYFM_BPS);
229 	bp->b_flags |= B_DONE;
230 	bp->b_flags &= ~B_BUSY;
231 }
232 
233 int
xygetdisklabel(xy,b)234 xygetdisklabel(xy, b)
235 	struct xy_softc *xy;
236 	void *b;
237 {
238 	char *err;
239 	struct sun_disklabel *sdl;
240 
241 	/* We already have the label data in `b'; setup for dummy strategy */
242 	xy_labeldata = b;
243 
244 	/* Required parameter for readdisklabel() */
245 	xy->sc_dk.dk_label->d_secsize = XYFM_BPS;
246 
247 	err = readdisklabel(MAKEDISKDEV(0, xy->sc_dev.dv_unit, RAW_PART),
248 					xydummystrat,
249 				xy->sc_dk.dk_label, xy->sc_dk.dk_cpulabel, 0);
250 	if (err) {
251 		printf("%s: %s\n", xy->sc_dev.dv_xname, err);
252 		return(XY_ERR_FAIL);
253 	}
254 
255 	/* Ok, we have the label; fill in `pcyl' if there's SunOS magic */
256 	sdl = (struct sun_disklabel *)xy->sc_dk.dk_cpulabel->cd_block;
257 	if (sdl->sl_magic == SUN_DKMAGIC)
258 		xy->pcyl = sdl->sl_pcylinders;
259 	else {
260 		printf("%s: WARNING: no `pcyl' in disk label.\n",
261 			xy->sc_dev.dv_xname);
262 		xy->pcyl = xy->sc_dk.dk_label->d_ncylinders +
263 			xy->sc_dk.dk_label->d_acylinders;
264 		printf("%s: WARNING: guessing pcyl=%d (ncyl+acyl)\n",
265 		xy->sc_dev.dv_xname, xy->pcyl);
266 	}
267 
268 	xy->ncyl = xy->sc_dk.dk_label->d_ncylinders;
269 	xy->acyl = xy->sc_dk.dk_label->d_acylinders;
270 	xy->nhead = xy->sc_dk.dk_label->d_ntracks;
271 	xy->nsect = xy->sc_dk.dk_label->d_nsectors;
272 	xy->sectpercyl = xy->nhead * xy->nsect;
273 	xy->sc_dk.dk_label->d_secsize = XYFM_BPS; /* not handled by
274                                           	  * sun->bsd */
275 	return(XY_ERR_AOK);
276 }
277 
278 /*
279  * end: disk label fix code (XXX)
280  */
281 
282 /*
283  * a u t o c o n f i g   f u n c t i o n s
284  */
285 
286 /*
287  * xycmatch: determine if xyc is present or not.   we do a
288  * soft reset to detect the xyc.
289  */
290 
xycmatch(parent,vcf,aux)291 int xycmatch(parent, vcf, aux)
292 	struct device *parent;
293 	void *vcf, *aux;
294 {
295 	struct cfdata *cf = vcf;
296 	struct confargs *ca = aux;
297 	struct romaux *ra = &ca->ca_ra;
298 	struct xyc *xyc;
299 
300 	if (strcmp(cf->cf_driver->cd_name, ra->ra_name))
301 		return (0);
302 
303 	switch (ca->ca_bustype) {
304 	case BUS_OBIO:
305 	case BUS_SBUS:
306 	case BUS_VME32:
307 	default:
308 		return (0);
309 	case BUS_VME16:
310 		xyc = (struct xyc *) ra->ra_vaddr;
311 		if (probeget((caddr_t) &xyc->xyc_rsetup, 1) == -1)
312 			return (0);
313 		if (xyc_unbusy(xyc, XYC_RESETUSEC) == XY_ERR_FAIL)
314 			return(0);
315 		return (1);
316 	}
317 }
318 
319 /*
320  * xycattach: attach controller
321  */
322 void
xycattach(parent,self,aux)323 xycattach(parent, self, aux)
324 	struct device *parent, *self;
325 	void   *aux;
326 
327 {
328 	struct xyc_softc *xyc = (void *) self;
329 	struct confargs *ca = aux;
330 	struct xyc_attach_args xa;
331 	int     lcv, err, pri, res, pbsz;
332 	void	*tmp, *tmp2;
333 	void	*dtmp, *dtmp2;
334 	u_long	ultmp;
335 
336 	/* get addressing and intr level stuff from autoconfig and load it
337 	 * into our xyc_softc. */
338 
339 	ca->ca_ra.ra_vaddr = mapiodev(ca->ca_ra.ra_reg, 0, sizeof(struct xyc));
340 
341 	xyc->xyc = (struct xyc *) ca->ca_ra.ra_vaddr;
342 	pri = ca->ca_ra.ra_intr[0].int_pri;
343 	xyc->ipl = pil_to_vme[pri];
344 	xyc->vector = ca->ca_ra.ra_intr[0].int_vec;
345 	printf(" pri %d", pri);
346 	xyc->no_ols = 0; /* XXX should be from config */
347 
348 	for (lcv = 0; lcv < XYC_MAXDEV; lcv++)
349 		xyc->sc_drives[lcv] = (struct xy_softc *) 0;
350 
351 	/*
352 	 * allocate and zero buffers
353 	 * check boundaries of the KVA's ... all IOPBs must reside in
354  	 * the same 64K region.
355 	 */
356 
357 	pbsz = XYC_MAXIOPB * sizeof(struct xy_iopb);
358 	dtmp = dtmp2 = (struct xy_iopb *)dvma_malloc(pbsz, &tmp, M_NOWAIT);
359 	tmp2 = tmp;
360 	ultmp = (u_long) dtmp;
361 	if ((ultmp & 0xffff0000) != ((ultmp + pbsz) & 0xffff0000)) {
362 		dtmp = (struct xy_iopb *)
363 		    dvma_malloc(pbsz, &tmp, M_NOWAIT); /* retry! */
364 		dvma_free(dtmp2, pbsz, &tmp2);
365 		ultmp = (u_long) dtmp;
366 		if ((ultmp & 0xffff0000) != ((ultmp + pbsz) & 0xffff0000)) {
367 			printf("%s: can't alloc IOPB mem in 64K\n",
368 				xyc->sc_dev.dv_xname);
369 			return;
370 		}
371 	}
372 	bzero(tmp, pbsz);
373 	xyc->iopbase = tmp;
374 	xyc->iopbase = dtmp; /* XXX TMP HACK */
375 	xyc->dvmaiopb = (struct xy_iopb *) ((u_long)dtmp - DVMA_BASE);
376 	xyc->reqs = (struct xy_iorq *)
377 	    malloc(XYC_MAXIOPB * sizeof(struct xy_iorq), M_DEVBUF, M_NOWAIT);
378 	if (xyc->reqs == NULL)
379 		panic("xyc malloc");
380 	bzero(xyc->reqs, XYC_MAXIOPB * sizeof(struct xy_iorq));
381 
382 	/*
383 	 * init iorq to iopb pointers, and non-zero fields in the
384 	 * iopb which never change.
385 	 */
386 
387 	for (lcv = 0; lcv < XYC_MAXIOPB; lcv++) {
388 		xyc->xy_chain[lcv] = NULL;
389 		xyc->reqs[lcv].iopb = &xyc->iopbase[lcv];
390 		xyc->iopbase[lcv].asr = 1;	/* always the same */
391 		xyc->iopbase[lcv].eef = 1;	/* always the same */
392 		xyc->iopbase[lcv].ecm = XY_ECM;	/* always the same */
393 		xyc->iopbase[lcv].aud = 1;	/* always the same */
394 		xyc->iopbase[lcv].relo = 1;	/* always the same */
395 		xyc->iopbase[lcv].thro = XY_THRO;/* always the same */
396 	}
397 	xyc->ciorq = &xyc->reqs[XYC_CTLIOPB];    /* short hand name */
398 	xyc->ciopb = &xyc->iopbase[XYC_CTLIOPB]; /* short hand name */
399 	xyc->xy_hand = 0;
400 
401 	/* read controller parameters and insure we have a 450/451 */
402 
403 	err = xyc_cmd(xyc, XYCMD_ST, 0, 0, 0, 0, 0, XY_SUB_POLL);
404 	res = xyc->ciopb->ctyp;
405 	XYC_DONE(xyc, err);
406 	if (res != XYCT_450) {
407 		if (err)
408 			printf(": %s: ", xyc_e2str(err));
409 		printf(": doesn't identify as a 450/451\n");
410 		return;
411 	}
412 	printf(": Xylogics 450/451");
413 	if (xyc->no_ols)
414 		printf(" [OLS disabled]"); /* 450 doesn't overlap seek right */
415 	printf("\n");
416 	if (err) {
417 		printf("%s: error: %s\n", xyc->sc_dev.dv_xname,
418 				xyc_e2str(err));
419 		return;
420 	}
421 	if ((xyc->xyc->xyc_csr & XYC_ADRM) == 0) {
422 		printf("%s: 24 bit addressing turned off\n",
423 			xyc->sc_dev.dv_xname);
424 		printf("please set hardware jumpers JM1-JM2=in, JM3-JM4=out\n");
425 		printf("to enable 24 bit mode and this driver\n");
426 		return;
427 	}
428 
429 	/* link in interrupt with higher level software */
430 
431 	xyc->sc_ih.ih_fun = xycintr;
432 	xyc->sc_ih.ih_arg = xyc;
433 	vmeintr_establish(ca->ca_ra.ra_intr[0].int_vec,
434 			  ca->ca_ra.ra_intr[0].int_pri, &xyc->sc_ih, IPL_BIO);
435 	evcnt_attach(&xyc->sc_dev, "intr", &xyc->sc_intrcnt);
436 
437 
438 	/* now we must look for disks using autoconfig */
439 	xa.dvmabuf = (char *)dvma_malloc(XYFM_BPS, &xa.buf, M_NOWAIT);
440 	xa.fullmode = XY_SUB_POLL;
441 	xa.booting = 1;
442 
443 	if (ca->ca_ra.ra_bp && ca->ca_ra.ra_bp->val[0] == -1 &&
444 	    ca->ca_ra.ra_bp->val[1] == xyc->sc_dev.dv_unit) {
445 		bootpath_store(1, ca->ca_ra.ra_bp + 1); /* advance bootpath */
446 	}
447 
448 	for (xa.driveno = 0; xa.driveno < XYC_MAXDEV; xa.driveno++)
449 		(void) config_found(self, (void *) &xa, NULL);
450 
451 	dvma_free(xa.dvmabuf, XYFM_BPS, &xa.buf);
452 	bootpath_store(1, NULL);
453 
454 	/* start the watchdog clock */
455 	timeout_set(&xyc->xyc_tick_tmo, xyc_tick, xyc);
456 	timeout_add(&xyc->xyc_tick_tmo, XYC_TICKCNT);
457 
458 }
459 
460 /*
461  * xymatch: probe for disk.
462  *
463  * note: we almost always say disk is present.   this allows us to
464  * spin up and configure a disk after the system is booted (we can
465  * call xyattach!).
466  */
467 int
xymatch(parent,vcf,aux)468 xymatch(parent, vcf, aux)
469 	struct device *parent;
470 	void *vcf, *aux;
471 {
472 	struct cfdata *cf = vcf;
473 	struct xyc_attach_args *xa = aux;
474 
475 	/* looking for autoconf wildcard or exact match */
476 
477 	if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != xa->driveno)
478 		return 0;
479 
480 	return 1;
481 
482 }
483 
484 /*
485  * xyattach: attach a disk.   this can be called from autoconf and also
486  * from xyopen/xystrategy.
487  */
488 void
xyattach(parent,self,aux)489 xyattach(parent, self, aux)
490 	struct device *parent, *self;
491 	void   *aux;
492 
493 {
494 	struct xy_softc *xy = (void *) self, *oxy;
495 	struct xyc_softc *xyc = (void *) parent;
496 	struct xyc_attach_args *xa = aux;
497 	int     err, spt, mb, blk, lcv, fmode, s = 0, newstate;
498 	struct dkbad *dkb;
499 	struct bootpath *bp;
500 
501 	/*
502 	 * Always re-initialize the disk structure.  We want statistics
503 	 * to start with a clean slate.
504 	 */
505 	bzero(&xy->sc_dk, sizeof(xy->sc_dk));
506 	xy->sc_dk.dk_driver = &xydkdriver;
507 	xy->sc_dk.dk_name = xy->sc_dev.dv_xname;
508 
509 	/* if booting, init the xy_softc */
510 
511 	if (xa->booting) {
512 		xy->state = XY_DRIVE_UNKNOWN;	/* to start */
513 		xy->flags = 0;
514 		xy->parent = xyc;
515 
516 		/* init queue of waiting bufs */
517 
518 		xy->xyq.b_active = 0;
519 		xy->xyq.b_actf = 0;
520 		xy->xyq.b_actb = &xy->xyq.b_actf; /* XXX b_actb: not used? */
521 
522 		xy->xyrq = &xyc->reqs[xa->driveno];
523 
524 	}
525 	xy->xy_drive = xa->driveno;
526 	fmode = xa->fullmode;
527 	xyc->sc_drives[xa->driveno] = xy;
528 
529 	/* if not booting, make sure we are the only process in the attach for
530 	 * this drive.   if locked out, sleep on it. */
531 
532 	if (!xa->booting) {
533 		s = splbio();
534 		while (xy->state == XY_DRIVE_ATTACHING) {
535 			if (tsleep(&xy->state, PRIBIO, "xyattach", 0)) {
536 				splx(s);
537 				return;
538 			}
539 		}
540 		printf("%s at %s",
541 			xy->sc_dev.dv_xname, xy->parent->sc_dev.dv_xname);
542 	}
543 	/* we now have control */
544 
545 	xy->state = XY_DRIVE_ATTACHING;
546 	newstate = XY_DRIVE_UNKNOWN;
547 
548 	/* first try and reset the drive */
549 
550 	err = xyc_cmd(xyc, XYCMD_RST, 0, xy->xy_drive, 0, 0, 0, fmode);
551 	XYC_DONE(xyc, err);
552 	if (err == XY_ERR_DNRY) {
553 		printf(" drive %d: off-line\n", xa->driveno);
554 		goto done;
555 	}
556 	if (err) {
557 		printf(": ERROR 0x%02x (%s)\n", err, xyc_e2str(err));
558 		goto done;
559 	}
560 	printf(" drive %d: ready", xa->driveno);
561 
562 	/*
563 	 * now set drive parameters (to semi-bogus values) so we can read the
564 	 * disk label.
565 	 */
566 	xy->pcyl = xy->ncyl = 1;
567 	xy->acyl = 0;
568 	xy->nhead = 1;
569 	xy->nsect = 1;
570 	xy->sectpercyl = 1;
571 	for (lcv = 0; lcv < 126; lcv++)	/* init empty bad144 table */
572 		xy->dkb.bt_bad[lcv].bt_cyl =
573 			xy->dkb.bt_bad[lcv].bt_trksec = 0xffff;
574 
575 	/* read disk label */
576 	for (xy->drive_type = 0 ; xy->drive_type <= XYC_MAXDT ;
577 						xy->drive_type++) {
578 		err = xyc_cmd(xyc, XYCMD_RD, 0, xy->xy_drive, 0, 1,
579 						xa->dvmabuf, fmode);
580 		XYC_DONE(xyc, err);
581 		if (err == XY_ERR_AOK) break;
582 	}
583 
584 	if (err != XY_ERR_AOK) {
585 		printf("\n%s: reading disk label failed: %s\n",
586 			xy->sc_dev.dv_xname, xyc_e2str(err));
587 		goto done;
588 	}
589 	printf(" (drive type %d)\n", xy->drive_type);
590 
591 	newstate = XY_DRIVE_NOLABEL;
592 
593 	xy->hw_spt = spt = 0; /* XXX needed ? */
594 	/* Attach the disk: must be before getdisklabel to malloc label */
595 	disk_attach(&xy->sc_dk);
596 
597 	if (xygetdisklabel(xy, xa->buf) != XY_ERR_AOK)
598 		goto done;
599 
600 	/* inform the user of what is up */
601 	printf("%s: <%s>, pcyl %d\n", xy->sc_dev.dv_xname,
602 		xa->buf, xy->pcyl);
603 	mb = xy->ncyl * (xy->nhead * xy->nsect) / (1048576 / XYFM_BPS);
604 	printf("%s: %dMB, %d cyl, %d head, %d sec, %d bytes/sec\n",
605 		xy->sc_dev.dv_xname, mb, xy->ncyl, xy->nhead, xy->nsect,
606 		XYFM_BPS);
607 
608 	/*
609 	 * 450/451 stupidity: the drive type is encoded into the format
610 	 * of the disk.   the drive type in the IOPB must match the drive
611 	 * type in the format, or you will not be able to do I/O to the
612 	 * disk (you get header not found errors).  if you have two drives
613 	 * of different sizes that have the same drive type in their
614 	 * formatting then you are out of luck.
615 	 *
616 	 * this problem was corrected in the 753/7053.
617 	 */
618 
619 	for (lcv = 0 ; lcv < XYC_MAXDEV ; lcv++) {
620 		oxy = xyc->sc_drives[lcv];
621 		if (oxy == NULL || oxy == xy) continue;
622 		if (oxy->drive_type != xy->drive_type) continue;
623 		if (xy->nsect != oxy->nsect || xy->pcyl != oxy->pcyl ||
624 			xy->nhead != oxy->nhead) {
625 			printf("%s: %s and %s must be the same size!\n",
626 				xyc->sc_dev.dv_xname, xy->sc_dev.dv_xname,
627 				oxy->sc_dev.dv_xname);
628 			panic("xy drive size mismatch");
629 		}
630 	}
631 
632 
633 	/* now set the real drive parameters! */
634 
635 	blk = (xy->nsect - 1) +
636 		((xy->nhead - 1) * xy->nsect) +
637 		((xy->pcyl - 1) * xy->nsect * xy->nhead);
638 	err = xyc_cmd(xyc, XYCMD_SDS, 0, xy->xy_drive, blk, 0, 0, fmode);
639 	XYC_DONE(xyc, err);
640 	if (err) {
641 		printf("%s: write drive size failed: %s\n",
642 			xy->sc_dev.dv_xname, xyc_e2str(err));
643 		goto done;
644 	}
645 	newstate = XY_DRIVE_ONLINE;
646 
647 	/*
648 	 * read bad144 table. this table resides on the first sector of the
649 	 * last track of the disk (i.e. second cyl of "acyl" area).
650 	 */
651 
652 	blk = (xy->ncyl + xy->acyl - 1) * (xy->nhead * xy->nsect) +
653 								/* last cyl */
654 	    (xy->nhead - 1) * xy->nsect;	/* last head */
655 	err = xyc_cmd(xyc, XYCMD_RD, 0, xy->xy_drive, blk, 1,
656 						xa->dvmabuf, fmode);
657 	XYC_DONE(xyc, err);
658 	if (err) {
659 		printf("%s: reading bad144 failed: %s\n",
660 			xy->sc_dev.dv_xname, xyc_e2str(err));
661 		goto done;
662 	}
663 
664 	/* check dkbad for sanity */
665 	dkb = (struct dkbad *) xa->buf;
666 	for (lcv = 0; lcv < 126; lcv++) {
667 		if ((dkb->bt_bad[lcv].bt_cyl == 0xffff ||
668 				dkb->bt_bad[lcv].bt_cyl == 0) &&
669 		     dkb->bt_bad[lcv].bt_trksec == 0xffff)
670 			continue;	/* blank */
671 		if (dkb->bt_bad[lcv].bt_cyl >= xy->ncyl)
672 			break;
673 		if ((dkb->bt_bad[lcv].bt_trksec >> 8) >= xy->nhead)
674 			break;
675 		if ((dkb->bt_bad[lcv].bt_trksec & 0xff) >= xy->nsect)
676 			break;
677 	}
678 	if (lcv != 126) {
679 		printf("%s: warning: invalid bad144 sector!\n",
680 			xy->sc_dev.dv_xname);
681 	} else {
682 		bcopy(xa->buf, &xy->dkb, XYFM_BPS);
683 	}
684 
685 	if (xa->booting) {
686 		/* restore bootpath! (do this via attach_args again?)*/
687 		bp = bootpath_store(0, NULL);
688 		if (bp && strcmp("xy", bp->name) == 0 &&
689 					xy->xy_drive == bp->val[0])
690 			bp->dev = &xy->sc_dev;
691 	}
692 
693 	dk_establish(&xy->sc_dk, &xy->sc_dev);		/* XXX */
694 
695 done:
696 	xy->state = newstate;
697 	if (!xa->booting) {
698 		wakeup(&xy->state);
699 		splx(s);
700 	}
701 }
702 
703 /*
704  * end of autoconfig functions
705  */
706 
707 /*
708  * { b , c } d e v s w   f u n c t i o n s
709  */
710 
711 /*
712  * xyclose: close device
713  */
714 int
xyclose(dev,flag,fmt,p)715 xyclose(dev, flag, fmt, p)
716 	dev_t   dev;
717 	int     flag, fmt;
718 	struct proc *p;
719 
720 {
721 	struct xy_softc *xy = xy_cd.cd_devs[DISKUNIT(dev)];
722 	int     part = DISKPART(dev);
723 
724 	/* clear mask bits */
725 
726 	switch (fmt) {
727 	case S_IFCHR:
728 		xy->sc_dk.dk_copenmask &= ~(1 << part);
729 		break;
730 	case S_IFBLK:
731 		xy->sc_dk.dk_bopenmask &= ~(1 << part);
732 		break;
733 	}
734 	xy->sc_dk.dk_openmask = xy->sc_dk.dk_copenmask | xy->sc_dk.dk_bopenmask;
735 
736 	return 0;
737 }
738 
739 /*
740  * xydump: crash dump system
741  */
742 int
xydump(dev,blkno,va,size)743 xydump(dev, blkno, va, size)
744 	dev_t dev;
745 	daddr_t blkno;
746 	caddr_t va;
747 	size_t size;
748 {
749 	int     unit, part;
750 	struct xy_softc *xy;
751 
752 	unit = DISKUNIT(dev);
753 	if (unit >= xy_cd.cd_ndevs)
754 		return ENXIO;
755 	part = DISKPART(dev);
756 
757 	xy = xy_cd.cd_devs[unit];
758 
759 	printf("%s%c: crash dump not supported (yet)\n", xy->sc_dev.dv_xname,
760 	    'a' + part);
761 
762 	return ENXIO;
763 
764 	/* outline: globals: "dumplo" == sector number of partition to start
765 	 * dump at (convert to physical sector with partition table)
766 	 * "dumpsize" == size of dump in clicks "physmem" == size of physical
767 	 * memory (clicks, ctob() to get bytes) (normal case: dumpsize ==
768 	 * physmem)
769 	 *
770 	 * dump a copy of physical memory to the dump device starting at sector
771 	 * "dumplo" in the swap partition (make sure > 0).   map in pages as
772 	 * we go.   use polled I/O.
773 	 *
774 	 * XXX how to handle NON_CONTIG? */
775 
776 }
777 
778 /*
779  * xyioctl: ioctls on XY drives.   based on ioctl's of other netbsd disks.
780  */
781 int
xyioctl(dev,command,addr,flag,p)782 xyioctl(dev, command, addr, flag, p)
783 	dev_t   dev;
784 	u_long  command;
785 	caddr_t addr;
786 	int     flag;
787 	struct proc *p;
788 
789 {
790 	struct xy_softc *xy;
791 	struct xd_iocmd *xio;
792 	int     error, s, unit;
793 
794 	unit = DISKUNIT(dev);
795 
796 	if (unit >= xy_cd.cd_ndevs || (xy = xy_cd.cd_devs[unit]) == NULL)
797 		return (ENXIO);
798 
799 	/* switch on ioctl type */
800 
801 	switch (command) {
802 	case DIOCSBAD:		/* set bad144 info */
803 		if ((flag & FWRITE) == 0)
804 			return EBADF;
805 		s = splbio();
806 		bcopy(addr, &xy->dkb, sizeof(xy->dkb));
807 		splx(s);
808 		return 0;
809 
810 	case DIOCGDINFO:	/* get disk label */
811 		bcopy(xy->sc_dk.dk_label, addr, sizeof(struct disklabel));
812 		return 0;
813 
814 	case DIOCGPART:	/* get partition info */
815 		((struct partinfo *) addr)->disklab = xy->sc_dk.dk_label;
816 		((struct partinfo *) addr)->part =
817 		    &xy->sc_dk.dk_label->d_partitions[DISKPART(dev)];
818 		return 0;
819 
820 	case DIOCSDINFO:	/* set disk label */
821 		if ((flag & FWRITE) == 0)
822 			return EBADF;
823 		error = setdisklabel(xy->sc_dk.dk_label,
824 		    (struct disklabel *) addr, /* xy->sc_dk.dk_openmask : */ 0,
825 		    xy->sc_dk.dk_cpulabel);
826 		if (error == 0) {
827 			if (xy->state == XY_DRIVE_NOLABEL)
828 				xy->state = XY_DRIVE_ONLINE;
829 		}
830 		return error;
831 
832 	case DIOCWLABEL:	/* change write status of disk label */
833 		if ((flag & FWRITE) == 0)
834 			return EBADF;
835 		if (*(int *) addr)
836 			xy->flags |= XY_WLABEL;
837 		else
838 			xy->flags &= ~XY_WLABEL;
839 		return 0;
840 
841 	case DIOCWDINFO:	/* write disk label */
842 		if ((flag & FWRITE) == 0)
843 			return EBADF;
844 		error = setdisklabel(xy->sc_dk.dk_label,
845 		    (struct disklabel *) addr, /* xy->sc_dk.dk_openmask : */ 0,
846 		    xy->sc_dk.dk_cpulabel);
847 		if (error == 0) {
848 			if (xy->state == XY_DRIVE_NOLABEL)
849 				xy->state = XY_DRIVE_ONLINE;
850 
851 			/* Simulate opening partition 0 so write succeeds. */
852 			xy->sc_dk.dk_openmask |= (1 << 0);
853 			error = writedisklabel(MAKEDISKDEV(major(dev), DISKUNIT(dev), RAW_PART),
854 			    xystrategy, xy->sc_dk.dk_label,
855 			    xy->sc_dk.dk_cpulabel);
856 			xy->sc_dk.dk_openmask =
857 			    xy->sc_dk.dk_copenmask | xy->sc_dk.dk_bopenmask;
858 		}
859 		return error;
860 
861 	case DIOSXDCMD:
862 		xio = (struct xd_iocmd *) addr;
863 		if ((error = suser(p, 0)) != 0)
864 			return (error);
865 		return (xyc_ioctlcmd(xy, dev, xio));
866 
867 	default:
868 		return ENOTTY;
869 	}
870 }
871 
872 /*
873  * xyopen: open drive
874  */
875 
876 int
xyopen(dev,flag,fmt,p)877 xyopen(dev, flag, fmt, p)
878 	dev_t   dev;
879 	int     flag, fmt;
880 	struct proc *p;
881 {
882 	int     unit, part;
883 	struct xy_softc *xy;
884 	struct xyc_attach_args xa;
885 
886 	/* first, could it be a valid target? */
887 
888 	unit = DISKUNIT(dev);
889 	if (unit >= xy_cd.cd_ndevs || (xy = xy_cd.cd_devs[unit]) == NULL)
890 		return (ENXIO);
891 	part = DISKPART(dev);
892 
893 	/* do we need to attach the drive? */
894 
895 	if (xy->state == XY_DRIVE_UNKNOWN) {
896 		xa.driveno = xy->xy_drive;
897 		xa.dvmabuf = (char *)dvma_malloc(XYFM_BPS, &xa.buf, M_NOWAIT);
898 		xa.fullmode = XY_SUB_WAIT;
899 		xa.booting = 0;
900 		xyattach((struct device *) xy->parent,
901 						(struct device *) xy, &xa);
902 		dvma_free(xa.dvmabuf, XYFM_BPS, &xa.buf);
903 		if (xy->state == XY_DRIVE_UNKNOWN) {
904 			return (EIO);
905 		}
906 	}
907 	/* check for partition */
908 
909 	if (part != RAW_PART &&
910 	    (part >= xy->sc_dk.dk_label->d_npartitions ||
911 		xy->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
912 		return (ENXIO);
913 	}
914 	/* set open masks */
915 
916 	switch (fmt) {
917 	case S_IFCHR:
918 		xy->sc_dk.dk_copenmask |= (1 << part);
919 		break;
920 	case S_IFBLK:
921 		xy->sc_dk.dk_bopenmask |= (1 << part);
922 		break;
923 	}
924 	xy->sc_dk.dk_openmask = xy->sc_dk.dk_copenmask | xy->sc_dk.dk_bopenmask;
925 
926 	return 0;
927 }
928 
929 int
xyread(dev,uio,flags)930 xyread(dev, uio, flags)
931 	dev_t   dev;
932 	struct uio *uio;
933 	int flags;
934 {
935 
936 	return (physio(xystrategy, NULL, dev, B_READ, minphys, uio));
937 }
938 
939 int
xywrite(dev,uio,flags)940 xywrite(dev, uio, flags)
941 	dev_t   dev;
942 	struct uio *uio;
943 	int flags;
944 {
945 
946 	return (physio(xystrategy, NULL, dev, B_WRITE, minphys, uio));
947 }
948 
949 
950 /*
951  * xysize: return size of a partition for a dump
952  */
953 
954 int
xysize(dev)955 xysize(dev)
956 	dev_t   dev;
957 
958 {
959 	struct xy_softc *xysc;
960 	int     unit, part, size, omask;
961 
962 	/* valid unit? */
963 	unit = DISKUNIT(dev);
964 	if (unit >= xy_cd.cd_ndevs || (xysc = xy_cd.cd_devs[unit]) == NULL)
965 		return (-1);
966 
967 	part = DISKPART(dev);
968 	omask = xysc->sc_dk.dk_openmask & (1 << part);
969 
970 	if (omask == 0 && xyopen(dev, 0, S_IFBLK, NULL) != 0)
971 		return (-1);
972 
973 	/* do it */
974 	if (xysc->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
975 		size = -1;	/* only give valid size for swap partitions */
976 	else
977 		size = xysc->sc_dk.dk_label->d_partitions[part].p_size *
978 		    (xysc->sc_dk.dk_label->d_secsize / DEV_BSIZE);
979 	if (omask == 0 && xyclose(dev, 0, S_IFBLK, NULL) != 0)
980 		return (-1);
981 	return (size);
982 }
983 
984 /*
985  * xystrategy: buffering system interface to xy.
986  */
987 
988 void
xystrategy(bp)989 xystrategy(bp)
990 	struct buf *bp;
991 
992 {
993 	struct xy_softc *xy;
994 	int     s, unit;
995 	struct xyc_attach_args xa;
996 
997 	unit = DISKUNIT(bp->b_dev);
998 
999 	/* check for live device */
1000 
1001 	if (unit >= xy_cd.cd_ndevs || (xy = xy_cd.cd_devs[unit]) == 0 ||
1002 	    bp->b_blkno < 0 ||
1003 	    (bp->b_bcount % xy->sc_dk.dk_label->d_secsize) != 0) {
1004 		bp->b_error = EINVAL;
1005 		goto bad;
1006 	}
1007 	/* do we need to attach the drive? */
1008 
1009 	if (xy->state == XY_DRIVE_UNKNOWN) {
1010 		xa.driveno = xy->xy_drive;
1011 		xa.dvmabuf = (char *)dvma_malloc(XYFM_BPS, &xa.buf, M_NOWAIT);
1012 		xa.fullmode = XY_SUB_WAIT;
1013 		xa.booting = 0;
1014 		xyattach((struct device *)xy->parent, (struct device *)xy, &xa);
1015 		dvma_free(xa.dvmabuf, XYFM_BPS, &xa.buf);
1016 		if (xy->state == XY_DRIVE_UNKNOWN) {
1017 			bp->b_error = EIO;
1018 			goto bad;
1019 		}
1020 	}
1021 	if (xy->state != XY_DRIVE_ONLINE && DISKPART(bp->b_dev) != RAW_PART) {
1022 		/* no I/O to unlabeled disks, unless raw partition */
1023 		bp->b_error = EIO;
1024 		goto bad;
1025 	}
1026 	/* short circuit zero length request */
1027 
1028 	if (bp->b_bcount == 0)
1029 		goto done;
1030 
1031 	/* check bounds with label (disksubr.c).  Determine the size of the
1032 	 * transfer, and make sure it is within the boundaries of the
1033 	 * partition. Adjust transfer if needed, and signal errors or early
1034 	 * completion. */
1035 
1036 	if (bounds_check_with_label(bp, xy->sc_dk.dk_label,
1037 	    xy->sc_dk.dk_cpulabel, (xy->flags & XY_WLABEL) != 0) <= 0)
1038 		goto done;
1039 
1040 	/*
1041 	 * now we know we have a valid buf structure that we need to do I/O
1042 	 * on.
1043 	 */
1044 	s = splbio();		/* protect the queues */
1045 
1046 	disksort(&xy->xyq, bp);
1047 
1048 	/* start 'em up */
1049 
1050 	xyc_start(xy->parent, NULL);
1051 
1052 	/* done! */
1053 
1054 	splx(s);
1055 	return;
1056 
1057 bad:				/* tells upper layers we have an error */
1058 	bp->b_flags |= B_ERROR;
1059 done:				/* tells upper layers we are done with this
1060 				 * buf */
1061 	bp->b_resid = bp->b_bcount;
1062 	s = splbio();
1063 	biodone(bp);
1064 	splx(s);
1065 }
1066 /*
1067  * end of {b,c}devsw functions
1068  */
1069 
1070 /*
1071  * i n t e r r u p t   f u n c t i o n
1072  *
1073  * xycintr: hardware interrupt.
1074  */
1075 int
xycintr(v)1076 xycintr(v)
1077 	void   *v;
1078 
1079 {
1080 	struct xyc_softc *xycsc = v;
1081 
1082 	/* kick the event counter */
1083 
1084 	xycsc->sc_intrcnt.ev_count++;
1085 
1086 	/* remove as many done IOPBs as possible */
1087 
1088 	xyc_remove_iorq(xycsc);
1089 
1090 	/* start any iorq's already waiting */
1091 
1092 	xyc_start(xycsc, NULL);
1093 
1094 	return (1);
1095 }
1096 /*
1097  * end of interrupt function
1098  */
1099 
1100 /*
1101  * i n t e r n a l   f u n c t i o n s
1102  */
1103 
1104 /*
1105  * xyc_rqinit: fill out the fields of an I/O request
1106  */
1107 
1108 inline void
xyc_rqinit(rq,xyc,xy,md,blk,cnt,db,bp)1109 xyc_rqinit(rq, xyc, xy, md, blk, cnt, db, bp)
1110 	struct xy_iorq *rq;
1111 	struct xyc_softc *xyc;
1112 	struct xy_softc *xy;
1113 	int     md;
1114 	u_long  blk;
1115 	int     cnt;
1116 	caddr_t db;
1117 	struct buf *bp;
1118 {
1119 	rq->xyc = xyc;
1120 	rq->xy = xy;
1121 	rq->ttl = XYC_MAXTTL + 10;
1122 	rq->mode = md;
1123 	rq->tries = rq->errno = rq->lasterror = 0;
1124 	rq->blockno = blk;
1125 	rq->sectcnt = cnt;
1126 	rq->dbuf = rq->dbufbase = db;
1127 	rq->buf = bp;
1128 }
1129 
1130 /*
1131  * xyc_rqtopb: load up an IOPB based on an iorq
1132  */
1133 
1134 void
xyc_rqtopb(iorq,iopb,cmd,subfun)1135 xyc_rqtopb(iorq, iopb, cmd, subfun)
1136 	struct xy_iorq *iorq;
1137 	struct xy_iopb *iopb;
1138 	int     cmd, subfun;
1139 
1140 {
1141 	u_long  block, dp;
1142 
1143 	/* normal IOPB case, standard stuff */
1144 
1145 	/* chain bit handled later */
1146 	iopb->ien = (XY_STATE(iorq->mode) == XY_SUB_POLL) ? 0 : 1;
1147 	iopb->com = cmd;
1148 	iopb->errno = 0;
1149 	iopb->errs = 0;
1150 	iopb->done = 0;
1151 	if (iorq->xy) {
1152 		iopb->unit = iorq->xy->xy_drive;
1153 		iopb->dt = iorq->xy->drive_type;
1154 	} else {
1155 		iopb->unit = 0;
1156 		iopb->dt = 0;
1157 	}
1158 	block = iorq->blockno;
1159 	if (iorq->xy == NULL || block == 0) {
1160 		iopb->sect = iopb->head = iopb->cyl = 0;
1161 	} else {
1162 		iopb->sect = block % iorq->xy->nsect;
1163 		block = block / iorq->xy->nsect;
1164 		iopb->head = block % iorq->xy->nhead;
1165 		block = block / iorq->xy->nhead;
1166 		iopb->cyl = block;
1167 	}
1168 	iopb->scnt = iorq->sectcnt;
1169 	dp = (u_long) iorq->dbuf - DVMA_BASE;
1170 	if (iorq->dbuf == NULL) {
1171 		iopb->dataa = 0;
1172 		iopb->datar = 0;
1173 	} else {
1174 		iopb->dataa = (dp & 0xffff);
1175 		iopb->datar = ((dp & 0xff0000) >> 16);
1176 	}
1177 	iopb->subfn = subfun;
1178 }
1179 
1180 
1181 /*
1182  * xyc_unbusy: wait for the xyc to go unbusy, or timeout.
1183  */
1184 
1185 int
xyc_unbusy(xyc,del)1186 xyc_unbusy(xyc, del)
1187 
1188 struct xyc *xyc;
1189 int del;
1190 
1191 {
1192 	while (del-- > 0) {
1193 		if ((xyc->xyc_csr & XYC_GBSY) == 0)
1194 			break;
1195 		DELAY(1);
1196 	}
1197 	return(del == 0 ? XY_ERR_FAIL : XY_ERR_AOK);
1198 }
1199 
1200 /*
1201  * xyc_cmd: front end for POLL'd and WAIT'd commands.  Returns 0 or error.
1202  * note that NORM requests are handled separately.
1203  */
1204 int
xyc_cmd(xycsc,cmd,subfn,unit,block,scnt,dptr,fullmode)1205 xyc_cmd(xycsc, cmd, subfn, unit, block, scnt, dptr, fullmode)
1206 	struct xyc_softc *xycsc;
1207 	int     cmd, subfn, unit, block, scnt;
1208 	char   *dptr;
1209 	int     fullmode;
1210 
1211 {
1212 	int     submode = XY_STATE(fullmode);
1213 	struct xy_iorq *iorq = xycsc->ciorq;
1214 	struct xy_iopb *iopb = xycsc->ciopb;
1215 
1216 	/*
1217 	 * is someone else using the control iopq wait for it if we can
1218 	 */
1219 start:
1220 	if (submode == XY_SUB_WAIT && XY_STATE(iorq->mode) != XY_SUB_FREE) {
1221 		if (tsleep(iorq, PRIBIO, "xyc_cmd", 0))
1222                                 return(XY_ERR_FAIL);
1223 		goto start;
1224 	}
1225 
1226 	if (XY_STATE(iorq->mode) != XY_SUB_FREE) {
1227 		DELAY(1000000);		/* XY_SUB_POLL: steal the iorq */
1228 		iorq->mode = XY_SUB_FREE;
1229 		printf("%s: stole control iopb\n", xycsc->sc_dev.dv_xname);
1230 	}
1231 
1232 	/* init iorq/iopb */
1233 
1234 	xyc_rqinit(iorq, xycsc,
1235 	    (unit == XYC_NOUNIT) ? NULL : xycsc->sc_drives[unit],
1236 	    fullmode, block, scnt, dptr, NULL);
1237 
1238 	/* load IOPB from iorq */
1239 
1240 	xyc_rqtopb(iorq, iopb, cmd, subfn);
1241 
1242 	/* submit it for processing */
1243 
1244 	xyc_submit_iorq(xycsc, iorq, fullmode);	/* error code will be in iorq */
1245 
1246 	return(XY_ERR_AOK);
1247 }
1248 
1249 /*
1250  * xyc_startbuf
1251  * start a buffer for running
1252  */
1253 
1254 int
xyc_startbuf(xycsc,xysc,bp)1255 xyc_startbuf(xycsc, xysc, bp)
1256 	struct xyc_softc *xycsc;
1257 	struct xy_softc *xysc;
1258 	struct buf *bp;
1259 
1260 {
1261 	int     partno;
1262 	struct xy_iorq *iorq;
1263 	struct xy_iopb *iopb;
1264 	u_long  block;
1265 	caddr_t dbuf;
1266 
1267 	iorq = xysc->xyrq;
1268 	iopb = iorq->iopb;
1269 
1270 	/* get buf */
1271 
1272 	if (bp == NULL)
1273 		panic("xyc_startbuf null buf");
1274 
1275 	partno = DISKPART(bp->b_dev);
1276 #ifdef XYC_DEBUG
1277 	printf("xyc_startbuf: %s%c: %s block %d\n", xysc->sc_dev.dv_xname,
1278 	    'a' + partno, (bp->b_flags & B_READ) ? "read" : "write", bp->b_blkno);
1279 	printf("xyc_startbuf: b_bcount %d, b_data 0x%x\n",
1280 	    bp->b_bcount, bp->b_data);
1281 #endif
1282 
1283 	/*
1284 	 * load request.  we have to calculate the correct block number based
1285 	 * on partition info.
1286 	 *
1287 	 * note that iorq points to the buffer as mapped into DVMA space,
1288 	 * where as the bp->b_data points to its non-DVMA mapping.
1289 	 */
1290 
1291 	block = bp->b_blkno + ((partno == RAW_PART) ? 0 :
1292 	    xysc->sc_dk.dk_label->d_partitions[partno].p_offset);
1293 
1294 	dbuf = kdvma_mapin(bp->b_data, bp->b_bcount, 0);
1295 	if (dbuf == NULL) {	/* out of DVMA space */
1296 		printf("%s: warning: out of DVMA space\n",
1297 			xycsc->sc_dev.dv_xname);
1298 		return (XY_ERR_FAIL);	/* XXX: need some sort of
1299 					 * call-back scheme here? */
1300 	}
1301 
1302 	/* init iorq and load iopb from it */
1303 
1304 	xyc_rqinit(iorq, xycsc, xysc, XY_SUB_NORM | XY_MODE_VERBO, block,
1305 	    bp->b_bcount / XYFM_BPS, dbuf, bp);
1306 
1307 	xyc_rqtopb(iorq, iopb, (bp->b_flags & B_READ) ? XYCMD_RD : XYCMD_WR, 0);
1308 
1309 	/* Instrumentation. */
1310 	disk_busy(&xysc->sc_dk);
1311 
1312 	return (XY_ERR_AOK);
1313 }
1314 
1315 
1316 /*
1317  * xyc_submit_iorq: submit an iorq for processing.  returns XY_ERR_AOK
1318  * if ok.  if it fail returns an error code.  type is XY_SUB_*.
1319  *
1320  * note: caller frees iorq in all cases except NORM
1321  *
1322  * return value:
1323  *   NORM: XY_AOK (req pending), XY_FAIL (couldn't submit request)
1324  *   WAIT: XY_AOK (success), <error-code> (failed)
1325  *   POLL: <same as WAIT>
1326  *   NOQ : <same as NORM>
1327  *
1328  * there are three sources for i/o requests:
1329  * [1] xystrategy: normal block I/O, using "struct buf" system.
1330  * [2] autoconfig/crash dump: these are polled I/O requests, no interrupts.
1331  * [3] open/ioctl: these are I/O requests done in the context of a process,
1332  *                 and the process should block until they are done.
1333  *
1334  * software state is stored in the iorq structure.  each iorq has an
1335  * iopb structure.  the hardware understands the iopb structure.
1336  * every command must go through an iopb.  a 450 handles one iopb at a
1337  * time, where as a 451 can take them in chains.  [the 450 claims it
1338  * can handle chains, but is appears to be buggy...]   iopb are allocated
1339  * in DVMA space at boot up time.  each disk gets one iopb, and the
1340  * controller gets one (for POLL and WAIT commands).  what happens if
1341  * the iopb is busy?  for i/o type [1], the buffers are queued at the
1342  * "buff" layer and * picked up later by the interrupt routine.  for case
1343  * [2] we can only be blocked if there is a WAIT type I/O request being
1344  * run.   since this can only happen when we are crashing, we wait a sec
1345  * and then steal the IOPB.  for case [3] the process can sleep
1346  * on the iorq free list until some iopbs are available.
1347  */
1348 
1349 
1350 int
xyc_submit_iorq(xycsc,iorq,type)1351 xyc_submit_iorq(xycsc, iorq, type)
1352 	struct xyc_softc *xycsc;
1353 	struct xy_iorq *iorq;
1354 	int     type;
1355 
1356 {
1357 	struct xy_iopb *iopb;
1358 	u_long  iopbaddr;
1359 
1360 #ifdef XYC_DEBUG
1361 	printf("xyc_submit_iorq(%s, addr=0x%x, type=%d)\n",
1362 		xycsc->sc_dev.dv_xname, iorq, type);
1363 #endif
1364 
1365 	/* first check and see if controller is busy */
1366 	if ((xycsc->xyc->xyc_csr & XYC_GBSY) != 0) {
1367 #ifdef XYC_DEBUG
1368 		printf("xyc_submit_iorq: XYC not ready (BUSY)\n");
1369 #endif
1370 		if (type == XY_SUB_NOQ)
1371 			return (XY_ERR_FAIL);	/* failed */
1372 		switch (type) {
1373 		case XY_SUB_NORM:
1374 			return XY_ERR_AOK;	/* success */
1375 		case XY_SUB_WAIT:
1376 			while (iorq->iopb->done == 0) {
1377 				tsleep(iorq, PRIBIO, "xyiorq", 0);
1378 			}
1379 			return (iorq->errno);
1380 		case XY_SUB_POLL:		/* steal controller */
1381 			iopbaddr = xycsc->xyc->xyc_rsetup; /* RESET */
1382 			if (xyc_unbusy(xycsc->xyc,XYC_RESETUSEC) == XY_ERR_FAIL)
1383 				panic("xyc_submit_iorq: stuck xyc");
1384 			printf("%s: stole controller\n",
1385 				xycsc->sc_dev.dv_xname);
1386 			break;
1387 		default:
1388 			panic("xyc_submit_iorq adding");
1389 		}
1390 	}
1391 
1392 	iopb = xyc_chain(xycsc, iorq);	 /* build chain */
1393 	if (iopb == NULL) { /* nothing doing? */
1394 		if (type == XY_SUB_NORM || type == XY_SUB_NOQ)
1395 			return(XY_ERR_AOK);
1396 		panic("xyc_submit_iorq: xyc_chain failed!");
1397 	}
1398 	iopbaddr = (u_long) iopb - DVMA_BASE;
1399 
1400 	XYC_GO(xycsc->xyc, iopbaddr);
1401 
1402 	/* command now running, wrap it up */
1403 	switch (type) {
1404 	case XY_SUB_NORM:
1405 	case XY_SUB_NOQ:
1406 		return (XY_ERR_AOK);	/* success */
1407 	case XY_SUB_WAIT:
1408 		while (iorq->iopb->done == 0) {
1409 			tsleep(iorq, PRIBIO, "xyiorq", 0);
1410 		}
1411 		return (iorq->errno);
1412 	case XY_SUB_POLL:
1413 		return (xyc_piodriver(xycsc, iorq));
1414 	default:
1415 		panic("xyc_submit_iorq wrap up");
1416 	}
1417 	panic("xyc_submit_iorq");
1418 	return 0;	/* not reached */
1419 }
1420 
1421 
1422 /*
1423  * xyc_chain: build a chain.  return dvma address of first element in
1424  * the chain.   iorq != NULL: means we only want that item on the chain.
1425  */
1426 
1427 struct xy_iopb *
xyc_chain(xycsc,iorq)1428 xyc_chain(xycsc, iorq)
1429 
1430 struct xyc_softc *xycsc;
1431 struct xy_iorq *iorq;
1432 
1433 {
1434   int togo, chain, hand;
1435   struct xy_iopb *iopb, *prev_iopb;
1436   bzero(xycsc->xy_chain, sizeof(xycsc->xy_chain));
1437 
1438   /*
1439    * promote control IOPB to the top
1440    */
1441   if (iorq == NULL) {
1442     if ((XY_STATE(xycsc->reqs[XYC_CTLIOPB].mode) == XY_SUB_POLL ||
1443         XY_STATE(xycsc->reqs[XYC_CTLIOPB].mode) == XY_SUB_WAIT) &&
1444 		xycsc->iopbase[XYC_CTLIOPB].done == 0)
1445     iorq = &xycsc->reqs[XYC_CTLIOPB];
1446   }
1447   /*
1448    * special case: if iorq != NULL then we have a POLL or WAIT request.
1449    * we let these take priority and do them first.
1450    */
1451   if (iorq) {
1452     xycsc->xy_chain[0] = iorq;
1453     iorq->iopb->chen = 0;
1454     return(iorq->iopb);
1455   }
1456 
1457   /*
1458    * NORM case: do round robin and maybe chain (if allowed and possible)
1459    */
1460 
1461   chain = 0;
1462   hand = xycsc->xy_hand;
1463   xycsc->xy_hand = (xycsc->xy_hand + 1) % XYC_MAXIOPB;
1464 
1465   for (togo = XYC_MAXIOPB ; togo > 0 ; togo--, hand = (hand + 1) % XYC_MAXIOPB){
1466 
1467     if (XY_STATE(xycsc->reqs[hand].mode) != XY_SUB_NORM ||
1468 		xycsc->iopbase[hand].done)
1469       continue;   /* not ready-for-i/o */
1470 
1471     xycsc->xy_chain[chain] = &xycsc->reqs[hand];
1472     iopb = xycsc->xy_chain[chain]->iopb;
1473     iopb->chen = 0;
1474     if (chain != 0) {   /* adding a link to a chain? */
1475       prev_iopb = xycsc->xy_chain[chain-1]->iopb;
1476       prev_iopb->chen = 1;
1477       prev_iopb->nxtiopb = ((u_long) iopb - DVMA_BASE) & 0xffff;
1478     } else {            /* head of chain */
1479       iorq = xycsc->xy_chain[chain];
1480     }
1481     chain++;
1482     if (xycsc->no_ols) break;   /* quit if chaining dis-allowed */
1483   }
1484   return(iorq ? iorq->iopb : NULL);
1485 }
1486 
1487 /*
1488  * xyc_piodriver
1489  *
1490  * programmed i/o driver.   this function takes over the computer
1491  * and drains off the polled i/o request.   it returns the status of the iorq
1492  * the caller is interesting in.
1493  */
1494 int
xyc_piodriver(xycsc,iorq)1495 xyc_piodriver(xycsc, iorq)
1496 	struct xyc_softc *xycsc;
1497 	struct xy_iorq  *iorq;
1498 
1499 {
1500 	int     nreset = 0;
1501 	int     retval = 0;
1502 	u_long  res;
1503 #ifdef XYC_DEBUG
1504 	printf("xyc_piodriver(%s, 0x%x)\n", xycsc->sc_dev.dv_xname, iorq);
1505 #endif
1506 
1507 	while (iorq->iopb->done == 0) {
1508 
1509 		res = xyc_unbusy(xycsc->xyc, XYC_MAXTIME);
1510 
1511 		/* we expect some progress soon */
1512 		if (res == XY_ERR_FAIL && nreset >= 2) {
1513 			xyc_reset(xycsc, 0, XY_RSET_ALL, XY_ERR_FAIL, 0);
1514 #ifdef XYC_DEBUG
1515 			printf("xyc_piodriver: timeout\n");
1516 #endif
1517 			return (XY_ERR_FAIL);
1518 		}
1519 		if (res == XY_ERR_FAIL) {
1520 			if (xyc_reset(xycsc, 0,
1521 				      (nreset++ == 0) ? XY_RSET_NONE : iorq,
1522 				      XY_ERR_FAIL,
1523 				      0) == XY_ERR_FAIL)
1524 				return (XY_ERR_FAIL);	/* flushes all but POLL
1525 							 * requests, resets */
1526 			continue;
1527 		}
1528 
1529 		xyc_remove_iorq(xycsc);	 /* may resubmit request */
1530 
1531 		if (iorq->iopb->done == 0)
1532 			xyc_start(xycsc, iorq);
1533 	}
1534 
1535 	/* get return value */
1536 
1537 	retval = iorq->errno;
1538 
1539 #ifdef XYC_DEBUG
1540 	printf("xyc_piodriver: done, retval = 0x%x (%s)\n",
1541 	    iorq->errno, xyc_e2str(iorq->errno));
1542 #endif
1543 
1544 	/* start up any bufs that have queued */
1545 
1546 	xyc_start(xycsc, NULL);
1547 
1548 	return (retval);
1549 }
1550 
1551 /*
1552  * xyc_xyreset: reset one drive.   NOTE: assumes xyc was just reset.
1553  * we steal iopb[XYC_CTLIOPB] for this, but we put it back when we are done.
1554  */
1555 void
xyc_xyreset(xycsc,xysc)1556 xyc_xyreset(xycsc, xysc)
1557 	struct xyc_softc *xycsc;
1558 	struct xy_softc *xysc;
1559 
1560 {
1561 	struct xy_iopb tmpiopb;
1562 	u_long  addr;
1563 	int     del;
1564 	bcopy(xycsc->ciopb, &tmpiopb, sizeof(tmpiopb));
1565 	xycsc->ciopb->chen = xycsc->ciopb->done = xycsc->ciopb->errs = 0;
1566 	xycsc->ciopb->ien = 0;
1567 	xycsc->ciopb->com = XYCMD_RST;
1568 	xycsc->ciopb->unit = xysc->xy_drive;
1569 	addr = (u_long) xycsc->ciopb - DVMA_BASE;
1570 
1571 	XYC_GO(xycsc->xyc, addr);
1572 
1573 	del = XYC_RESETUSEC;
1574 	while (del > 0) {
1575 		if ((xycsc->xyc->xyc_csr & XYC_GBSY) == 0) break;
1576 		DELAY(1);
1577 		del--;
1578 	}
1579 
1580 	if (del <= 0 || xycsc->ciopb->errs) {
1581 		printf("%s: off-line: %s\n", xycsc->sc_dev.dv_xname,
1582 		    xyc_e2str(xycsc->ciopb->errno));
1583 		del = xycsc->xyc->xyc_rsetup;
1584 		if (xyc_unbusy(xycsc->xyc, XYC_RESETUSEC) == XY_ERR_FAIL)
1585 			panic("xyc_reset");
1586 	} else {
1587 		xycsc->xyc->xyc_csr = XYC_IPND;	/* clear IPND */
1588 	}
1589 	bcopy(&tmpiopb, xycsc->ciopb, sizeof(tmpiopb));
1590 }
1591 
1592 
1593 /*
1594  * xyc_reset: reset everything: requests are marked as errors except
1595  * a polled request (which is resubmitted)
1596  */
1597 int
xyc_reset(xycsc,quiet,blastmode,error,xysc)1598 xyc_reset(xycsc, quiet, blastmode, error, xysc)
1599 	struct xyc_softc *xycsc;
1600 	int     quiet, error;
1601 	struct xy_iorq *blastmode;
1602 	struct xy_softc *xysc;
1603 
1604 {
1605 	int     del = 0, lcv, retval = XY_ERR_AOK;
1606 
1607 	/* soft reset hardware */
1608 
1609 	if (!quiet)
1610 		printf("%s: soft reset\n", xycsc->sc_dev.dv_xname);
1611 	del = xycsc->xyc->xyc_rsetup;
1612 	del = xyc_unbusy(xycsc->xyc, XYC_RESETUSEC);
1613 	if (del == XY_ERR_FAIL) {
1614 		blastmode = XY_RSET_ALL;	/* dead, flush all requests */
1615 		retval = XY_ERR_FAIL;
1616 	}
1617 	if (xysc)
1618 		xyc_xyreset(xycsc, xysc);
1619 
1620 	/* fix queues based on "blast-mode" */
1621 
1622 	for (lcv = 0; lcv < XYC_MAXIOPB; lcv++) {
1623 		struct xy_iorq *iorq = &xycsc->reqs[lcv];
1624 
1625 		if (XY_STATE(iorq->mode) != XY_SUB_POLL &&
1626 		    XY_STATE(iorq->mode) != XY_SUB_WAIT &&
1627 		    XY_STATE(iorq->mode) != XY_SUB_NORM)
1628 			/* is it active? */
1629 			continue;
1630 
1631 		if (blastmode == XY_RSET_ALL ||
1632 				blastmode != iorq) {
1633 			/* failed */
1634 			iorq->errno = error;
1635 			xycsc->iopbase[lcv].done = xycsc->iopbase[lcv].errs = 1;
1636 			switch (XY_STATE(iorq->mode)) {
1637 			case XY_SUB_NORM:
1638 			    iorq->buf->b_error = EIO;
1639 			    iorq->buf->b_flags |= B_ERROR;
1640 			    iorq->buf->b_resid = iorq->sectcnt * XYFM_BPS;
1641 			    dvma_mapout((vaddr_t)iorq->dbufbase,
1642 					(vaddr_t)iorq->buf->b_un.b_addr,
1643 					iorq->buf->b_bcount);
1644 			    iorq->xy->xyq.b_actf = iorq->buf->b_actf;
1645 			    disk_unbusy(&xycsc->reqs[lcv].xy->sc_dk,
1646 				(xycsc->reqs[lcv].buf->b_bcount -
1647 				xycsc->reqs[lcv].buf->b_resid),
1648 				(xycsc->reqs[lcv].buf->b_flags & B_READ));
1649 			    biodone(iorq->buf);
1650 			    iorq->mode = XY_SUB_FREE;
1651 			    break;
1652 			case XY_SUB_WAIT:
1653 			    wakeup(iorq);
1654 			case XY_SUB_POLL:
1655 			    iorq->mode =
1656 				XY_NEWSTATE(iorq->mode, XY_SUB_DONE);
1657 			    break;
1658 			}
1659 
1660 		} else {
1661 
1662 			/* resubmit, no need to do anything here */
1663 		}
1664 	}
1665 
1666 	/*
1667 	 * now, if stuff is waiting, start it.
1668 	 * since we just reset it should go
1669 	 */
1670 	xyc_start(xycsc, NULL);
1671 
1672 	return (retval);
1673 }
1674 
1675 /*
1676  * xyc_start: start waiting buffers
1677  */
1678 
1679 void
xyc_start(xycsc,iorq)1680 xyc_start(xycsc, iorq)
1681 	struct xyc_softc *xycsc;
1682 	struct xy_iorq *iorq;
1683 
1684 {
1685 	int lcv;
1686 	struct xy_softc *xy;
1687 
1688 	if (iorq == NULL) {
1689 		for (lcv = 0; lcv < XYC_MAXDEV ; lcv++) {
1690 			if ((xy = xycsc->sc_drives[lcv]) == NULL) continue;
1691 			if (xy->xyq.b_actf == NULL) continue;
1692 			if (xy->xyrq->mode != XY_SUB_FREE) continue;
1693 			xyc_startbuf(xycsc, xy, xy->xyq.b_actf);
1694 		}
1695 	}
1696 	xyc_submit_iorq(xycsc, iorq, XY_SUB_NOQ);
1697 }
1698 
1699 /*
1700  * xyc_remove_iorq: remove "done" IOPB's.
1701  */
1702 
1703 int
xyc_remove_iorq(xycsc)1704 xyc_remove_iorq(xycsc)
1705 	struct xyc_softc *xycsc;
1706 
1707 {
1708 	int     errno, rq, comm, errs;
1709 	struct xyc *xyc = xycsc->xyc;
1710 	u_long  addr;
1711 	struct xy_iopb *iopb;
1712 	struct xy_iorq *iorq;
1713 	struct buf *bp;
1714 
1715 	if (xyc->xyc_csr & XYC_DERR) {
1716 		/*
1717 		 * DOUBLE ERROR: should never happen under normal use. This
1718 		 * error is so bad, you can't even tell which IOPB is bad, so
1719 		 * we dump them all.
1720 		 */
1721 		errno = XY_ERR_DERR;
1722 		printf("%s: DOUBLE ERROR!\n", xycsc->sc_dev.dv_xname);
1723 		if (xyc_reset(xycsc, 0, XY_RSET_ALL, errno, 0) != XY_ERR_AOK) {
1724 			printf("%s: soft reset failed!\n",
1725 				xycsc->sc_dev.dv_xname);
1726 			panic("xyc_remove_iorq: controller DEAD");
1727 		}
1728 		return (XY_ERR_AOK);
1729 	}
1730 
1731 	/*
1732 	 * get iopb that is done, loop down the chain
1733 	 */
1734 
1735 	if (xyc->xyc_csr & XYC_ERR) {
1736 		xyc->xyc_csr = XYC_ERR; /* clear error condition */
1737 	}
1738 	if (xyc->xyc_csr & XYC_IPND) {
1739 		xyc->xyc_csr = XYC_IPND; /* clear interrupt */
1740 	}
1741 
1742 	for (rq = 0; rq < XYC_MAXIOPB; rq++) {
1743 		iorq = xycsc->xy_chain[rq];
1744 		if (iorq == NULL) break; /* done ! */
1745 		if (iorq->mode == 0 || XY_STATE(iorq->mode) == XY_SUB_DONE)
1746 			continue;	/* free, or done */
1747 		iopb = iorq->iopb;
1748 		if (iopb->done == 0)
1749 			continue;	/* not done yet */
1750 
1751 		comm = iopb->com;
1752 		errs = iopb->errs;
1753 
1754 		if (errs)
1755 			iorq->errno = iopb->errno;
1756 		else
1757 			iorq->errno = 0;
1758 
1759 		/* handle non-fatal errors */
1760 
1761 		if (errs &&
1762 		    xyc_error(xycsc, iorq, iopb, comm) == XY_ERR_AOK)
1763 			continue;	/* AOK: we resubmitted it */
1764 
1765 
1766 		/* this iorq is now done (hasn't been restarted or anything) */
1767 
1768 		if ((iorq->mode & XY_MODE_VERBO) && iorq->lasterror)
1769 			xyc_perror(iorq, iopb, 0);
1770 
1771 		/* now, if read/write check to make sure we got all the data
1772 		 * we needed. (this may not be the case if we got an error in
1773 		 * the middle of a multisector request).   */
1774 
1775 		if ((iorq->mode & XY_MODE_B144) != 0 && errs == 0 &&
1776 		    (comm == XYCMD_RD || comm == XYCMD_WR)) {
1777 			/* we just successfully processed a bad144 sector
1778 			 * note: if we are in bad 144 mode, the pointers have
1779 			 * been advanced already (see above) and are pointing
1780 			 * at the bad144 sector.   to exit bad144 mode, we
1781 			 * must advance the pointers 1 sector and issue a new
1782 			 * request if there are still sectors left to process
1783 			 *
1784 			 */
1785 			XYC_ADVANCE(iorq, 1);	/* advance 1 sector */
1786 
1787 			/* exit b144 mode */
1788 			iorq->mode = iorq->mode & (~XY_MODE_B144);
1789 
1790 			if (iorq->sectcnt) {	/* more to go! */
1791 				iorq->lasterror = iorq->errno = iopb->errno = 0;
1792 				iopb->errs = iopb->done = 0;
1793 				iorq->tries = 0;
1794 				iopb->scnt = iorq->sectcnt;
1795 				iopb->cyl = iorq->blockno /
1796 						iorq->xy->sectpercyl;
1797 				iopb->head =
1798 					(iorq->blockno / iorq->xy->nhead) %
1799 						iorq->xy->nhead;
1800 				iopb->sect = iorq->blockno % XYFM_BPS;
1801 				addr = (u_long) iorq->dbuf - DVMA_BASE;
1802 				iopb->dataa = (addr & 0xffff);
1803 				iopb->datar = ((addr & 0xff0000) >> 16);
1804 				/* will resubit at end */
1805 				continue;
1806 			}
1807 		}
1808 		/* final cleanup, totally done with this request */
1809 
1810 		switch (XY_STATE(iorq->mode)) {
1811 		case XY_SUB_NORM:
1812 			bp = iorq->buf;
1813 			if (errs) {
1814 				bp->b_error = EIO;
1815 				bp->b_flags |= B_ERROR;
1816 				bp->b_resid = iorq->sectcnt * XYFM_BPS;
1817 			} else {
1818 				bp->b_resid = 0;	/* done */
1819 			}
1820 			dvma_mapout((vaddr_t) iorq->dbufbase,
1821 				    (vaddr_t) bp->b_un.b_addr,
1822 				    bp->b_bcount);
1823 			iorq->xy->xyq.b_actf = bp->b_actf;
1824 			disk_unbusy(&iorq->xy->sc_dk,
1825 			    (bp->b_bcount - bp->b_resid),
1826 			    (bp->b_flags & B_READ));
1827 			iorq->mode = XY_SUB_FREE;
1828 			biodone(bp);
1829 			break;
1830 		case XY_SUB_WAIT:
1831 			iorq->mode = XY_NEWSTATE(iorq->mode, XY_SUB_DONE);
1832 			wakeup(iorq);
1833 			break;
1834 		case XY_SUB_POLL:
1835 			iorq->mode = XY_NEWSTATE(iorq->mode, XY_SUB_DONE);
1836 			break;
1837 		}
1838 	}
1839 
1840 	return (XY_ERR_AOK);
1841 }
1842 
1843 /*
1844  * xyc_perror: print error.
1845  * - if still_trying is true: we got an error, retried and got a
1846  *   different error.  in that case lasterror is the old error,
1847  *   and errno is the new one.
1848  * - if still_trying is not true, then if we ever had an error it
1849  *   is in lasterror. also, if iorq->errno == 0, then we recovered
1850  *   from that error (otherwise iorq->errno == iorq->lasterror).
1851  */
1852 void
xyc_perror(iorq,iopb,still_trying)1853 xyc_perror(iorq, iopb, still_trying)
1854 	struct xy_iorq *iorq;
1855 	struct xy_iopb *iopb;
1856 	int     still_trying;
1857 
1858 {
1859 
1860 	int     error = iorq->lasterror;
1861 
1862 	printf("%s", (iorq->xy) ? iorq->xy->sc_dev.dv_xname
1863 	    : iorq->xyc->sc_dev.dv_xname);
1864 	if (iorq->buf)
1865 		printf("%c: ", 'a' + DISKPART(iorq->buf->b_dev));
1866 	if (iopb->com == XYCMD_RD || iopb->com == XYCMD_WR)
1867 		printf("%s %d/%d/%d: ",
1868 			(iopb->com == XYCMD_RD) ? "read" : "write",
1869 			iopb->cyl, iopb->head, iopb->sect);
1870 	printf("%s", xyc_e2str(error));
1871 
1872 	if (still_trying)
1873 		printf(" [still trying, new error=%s]", xyc_e2str(iorq->errno));
1874 	else
1875 		if (iorq->errno == 0)
1876 			printf(" [recovered in %d tries]", iorq->tries);
1877 
1878 	printf("\n");
1879 }
1880 
1881 /*
1882  * xyc_error: non-fatal error encountered... recover.
1883  * return AOK if resubmitted, return FAIL if this iopb is done
1884  */
1885 int
xyc_error(xycsc,iorq,iopb,comm)1886 xyc_error(xycsc, iorq, iopb, comm)
1887 	struct xyc_softc *xycsc;
1888 	struct xy_iorq *iorq;
1889 	struct xy_iopb *iopb;
1890 	int     comm;
1891 
1892 {
1893 	int     errno = iorq->errno;
1894 	int     erract = xyc_entoact(errno);
1895 	int     oldmode, advance, i;
1896 
1897 	if (erract == XY_ERA_RSET) {	/* some errors require a reset */
1898 		oldmode = iorq->mode;
1899 		iorq->mode = XY_SUB_DONE | (~XY_SUB_MASK & oldmode);
1900 		/* make xyc_start ignore us */
1901 		xyc_reset(xycsc, 1, XY_RSET_NONE, errno, iorq->xy);
1902 		iorq->mode = oldmode;
1903 	}
1904 	/* check for read/write to a sector in bad144 table if bad: redirect
1905 	 * request to bad144 area */
1906 
1907 	if ((comm == XYCMD_RD || comm == XYCMD_WR) &&
1908 	    (iorq->mode & XY_MODE_B144) == 0) {
1909 		advance = iorq->sectcnt - iopb->scnt;
1910 		XYC_ADVANCE(iorq, advance);
1911 		if ((i = isbad(&iorq->xy->dkb, iorq->blockno / iorq->xy->sectpercyl,
1912 			    (iorq->blockno / iorq->xy->nsect) % iorq->xy->nhead,
1913 			    iorq->blockno % iorq->xy->nsect)) != -1) {
1914 			iorq->mode |= XY_MODE_B144;	/* enter bad144 mode &
1915 							 * redirect */
1916 			iopb->errno = iopb->done = iopb->errs = 0;
1917 			iopb->scnt = 1;
1918 			iopb->cyl = (iorq->xy->ncyl + iorq->xy->acyl) - 2;
1919 			/* second to last acyl */
1920 			i = iorq->xy->sectpercyl - 1 - i;	/* follow bad144
1921 								 * standard */
1922 			iopb->head = i / iorq->xy->nhead;
1923 			iopb->sect = i % iorq->xy->nhead;
1924 			/* will resubmit when we come out of remove_iorq */
1925 			return (XY_ERR_AOK);	/* recovered! */
1926 		}
1927 	}
1928 
1929 	/*
1930 	 * it isn't a bad144 sector, must be real error! see if we can retry
1931 	 * it?
1932 	 */
1933 	if ((iorq->mode & XY_MODE_VERBO) && iorq->lasterror)
1934 		xyc_perror(iorq, iopb, 1);	/* inform of error state
1935 						 * change */
1936 	iorq->lasterror = errno;
1937 
1938 	if ((erract == XY_ERA_RSET || erract == XY_ERA_HARD)
1939 	    && iorq->tries < XYC_MAXTRIES) {	/* retry? */
1940 		iorq->tries++;
1941 		iorq->errno = iopb->errno = iopb->done = iopb->errs = 0;
1942 		/* will resubmit at end of remove_iorq */
1943 		return (XY_ERR_AOK);	/* recovered! */
1944 	}
1945 
1946 	/* failed to recover from this error */
1947 	return (XY_ERR_FAIL);
1948 }
1949 
1950 /*
1951  * xyc_tick: make sure xy is still alive and ticking (err, kicking).
1952  */
1953 void
xyc_tick(arg)1954 xyc_tick(arg)
1955 	void   *arg;
1956 
1957 {
1958 	struct xyc_softc *xycsc = arg;
1959 	int     lcv, s, reset = 0;
1960 
1961 	/* reduce ttl for each request if one goes to zero, reset xyc */
1962 	s = splbio();
1963 	for (lcv = 0; lcv < XYC_MAXIOPB; lcv++) {
1964 		if (xycsc->reqs[lcv].mode == 0 ||
1965 		    XY_STATE(xycsc->reqs[lcv].mode) == XY_SUB_DONE)
1966 			continue;
1967 		xycsc->reqs[lcv].ttl--;
1968 		if (xycsc->reqs[lcv].ttl == 0)
1969 			reset = 1;
1970 	}
1971 	if (reset) {
1972 		printf("%s: watchdog timeout\n", xycsc->sc_dev.dv_xname);
1973 		xyc_reset(xycsc, 0, XY_RSET_NONE, XY_ERR_FAIL, NULL);
1974 	}
1975 	splx(s);
1976 
1977 	/* until next time */
1978 
1979 	timeout_add(&xycsc->xyc_tick_tmo, XYC_TICKCNT);
1980 }
1981 
1982 /*
1983  * xyc_ioctlcmd: this function provides a user level interface to the
1984  * controller via ioctl.   this allows "format" programs to be written
1985  * in user code, and is also useful for some debugging.   we return
1986  * an error code.   called at user priority.
1987  *
1988  * XXX missing a few commands (see the 7053 driver for ideas)
1989  */
1990 int
xyc_ioctlcmd(xy,dev,xio)1991 xyc_ioctlcmd(xy, dev, xio)
1992 	struct xy_softc *xy;
1993 	dev_t   dev;
1994 	struct xd_iocmd *xio;
1995 
1996 {
1997 	int     s, err, rqno, dummy = 0;
1998 	caddr_t dvmabuf = NULL, buf = NULL;
1999 	struct xyc_softc *xycsc;
2000 
2001 	/* check sanity of requested command */
2002 
2003 	switch (xio->cmd) {
2004 
2005 	case XYCMD_NOP:	/* no op: everything should be zero */
2006 		if (xio->subfn || xio->dptr || xio->dlen ||
2007 		    xio->block || xio->sectcnt)
2008 			return (EINVAL);
2009 		break;
2010 
2011 	case XYCMD_RD:		/* read / write sectors (up to XD_IOCMD_MAXS) */
2012 	case XYCMD_WR:
2013 		if (xio->subfn || xio->sectcnt > XD_IOCMD_MAXS ||
2014 		    xio->sectcnt * XYFM_BPS != xio->dlen || xio->dptr == NULL)
2015 			return (EINVAL);
2016 		break;
2017 
2018 	case XYCMD_SK:		/* seek: doesn't seem useful to export this */
2019 		return (EINVAL);
2020 
2021 		break;
2022 
2023 	default:
2024 		return (EINVAL);/* ??? */
2025 	}
2026 
2027 	/* create DVMA buffer for request if needed */
2028 
2029 	if (xio->dlen) {
2030 		dvmabuf = dvma_malloc(xio->dlen, &buf, M_WAITOK);
2031 		if (xio->cmd == XYCMD_WR) {
2032 			if ((err = copyin(xio->dptr, buf, xio->dlen)) != 0) {
2033 				dvma_free(dvmabuf, xio->dlen, &buf);
2034 				return (err);
2035 			}
2036 		}
2037 	}
2038 	/* do it! */
2039 
2040 	err = 0;
2041 	xycsc = xy->parent;
2042 	s = splbio();
2043 	rqno = xyc_cmd(xycsc, xio->cmd, xio->subfn, xy->xy_drive, xio->block,
2044 	    xio->sectcnt, dvmabuf, XY_SUB_WAIT);
2045 	if (rqno == XY_ERR_FAIL) {
2046 		err = EIO;
2047 		goto done;
2048 	}
2049 	xio->errno = xycsc->ciorq->errno;
2050 	xio->tries = xycsc->ciorq->tries;
2051 	XYC_DONE(xycsc, dummy);
2052 
2053 	if (xio->cmd == XYCMD_RD)
2054 		err = copyout(buf, xio->dptr, xio->dlen);
2055 
2056 done:
2057 	splx(s);
2058 	if (dvmabuf)
2059 		dvma_free(dvmabuf, xio->dlen, &buf);
2060 	return (err);
2061 }
2062 
2063 /*
2064  * xyc_e2str: convert error code number into an error string
2065  */
2066 char *
xyc_e2str(no)2067 xyc_e2str(no)
2068 	int     no;
2069 {
2070 	switch (no) {
2071 	case XY_ERR_FAIL:
2072 		return ("Software fatal error");
2073 	case XY_ERR_DERR:
2074 		return ("DOUBLE ERROR");
2075 	case XY_ERR_AOK:
2076 		return ("Successful completion");
2077 	case XY_ERR_IPEN:
2078 		return("Interrupt pending");
2079 	case XY_ERR_BCFL:
2080 		return("Busy conflict");
2081 	case XY_ERR_TIMO:
2082 		return("Operation timeout");
2083 	case XY_ERR_NHDR:
2084 		return("Header not found");
2085 	case XY_ERR_HARD:
2086 		return("Hard ECC error");
2087 	case XY_ERR_ICYL:
2088 		return("Illegal cylinder address");
2089 	case XY_ERR_ISEC:
2090 		return("Illegal sector address");
2091 	case XY_ERR_SMAL:
2092 		return("Last sector too small");
2093 	case XY_ERR_SACK:
2094 		return("Slave ACK error (non-existent memory)");
2095 	case XY_ERR_CHER:
2096 		return("Cylinder and head/header error");
2097 	case XY_ERR_SRTR:
2098 		return("Auto-seek retry successful");
2099 	case XY_ERR_WPRO:
2100 		return("Write-protect error");
2101 	case XY_ERR_UIMP:
2102 		return("Unimplemented command");
2103 	case XY_ERR_DNRY:
2104 		return("Drive not ready");
2105 	case XY_ERR_SZER:
2106 		return("Sector count zero");
2107 	case XY_ERR_DFLT:
2108 		return("Drive faulted");
2109 	case XY_ERR_ISSZ:
2110 		return("Illegal sector size");
2111 	case XY_ERR_SLTA:
2112 		return("Self test A");
2113 	case XY_ERR_SLTB:
2114 		return("Self test B");
2115 	case XY_ERR_SLTC:
2116 		return("Self test C");
2117 	case XY_ERR_SOFT:
2118 		return("Soft ECC error");
2119 	case XY_ERR_SFOK:
2120 		return("Soft ECC error recovered");
2121 	case XY_ERR_IHED:
2122 		return("Illegal head");
2123 	case XY_ERR_DSEQ:
2124 		return("Disk sequencer error");
2125 	case XY_ERR_SEEK:
2126 		return("Seek error");
2127 	default:
2128 		return ("Unknown error");
2129 	}
2130 }
2131 
2132 int
xyc_entoact(errno)2133 xyc_entoact(errno)
2134 
2135 int errno;
2136 
2137 {
2138   switch (errno) {
2139     case XY_ERR_FAIL:	case XY_ERR_DERR:	case XY_ERR_IPEN:
2140     case XY_ERR_BCFL:	case XY_ERR_ICYL:	case XY_ERR_ISEC:
2141     case XY_ERR_UIMP:	case XY_ERR_SZER:	case XY_ERR_ISSZ:
2142     case XY_ERR_SLTA:	case XY_ERR_SLTB:	case XY_ERR_SLTC:
2143     case XY_ERR_IHED:	case XY_ERR_SACK:	case XY_ERR_SMAL:
2144 
2145 	return(XY_ERA_PROG); /* program error ! */
2146 
2147     case XY_ERR_TIMO:	case XY_ERR_NHDR:	case XY_ERR_HARD:
2148     case XY_ERR_DNRY:	case XY_ERR_CHER:	case XY_ERR_SEEK:
2149     case XY_ERR_SOFT:
2150 
2151 	return(XY_ERA_HARD); /* hard error, retry */
2152 
2153     case XY_ERR_DFLT:	case XY_ERR_DSEQ:
2154 
2155 	return(XY_ERA_RSET); /* hard error reset */
2156 
2157     case XY_ERR_SRTR:	case XY_ERR_SFOK:	case XY_ERR_AOK:
2158 
2159 	return(XY_ERA_SOFT); /* an FYI error */
2160 
2161     case XY_ERR_WPRO:
2162 
2163 	return(XY_ERA_WPRO); /* write protect */
2164   }
2165 
2166   return(XY_ERA_PROG); /* ??? */
2167 }
2168