xref: /netbsd-src/sys/dev/qbus/rl.c (revision 37b34d511dea595d3ba03a661cf3b775038ea5f8)
1 /*	$NetBSD: rl.c,v 1.16 2002/10/02 16:52:30 thorpej Exp $	*/
2 
3 /*
4  * Copyright (c) 2000 Ludd, University of Lule}, Sweden. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed at Ludd, University of
17  *      Lule}, Sweden and its contributors.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * RL11/RLV11/RLV12 disk controller driver and
35  * RL01/RL02 disk device driver.
36  *
37  * TODO:
38  *	Handle disk errors more gracefully
39  *	Do overlapping seeks on multiple drives
40  *
41  * Implementation comments:
42  *
43  */
44 
45 #include <sys/cdefs.h>
46 __KERNEL_RCSID(0, "$NetBSD: rl.c,v 1.16 2002/10/02 16:52:30 thorpej Exp $");
47 
48 #include <sys/param.h>
49 #include <sys/device.h>
50 #include <sys/systm.h>
51 #include <sys/conf.h>
52 #include <sys/disk.h>
53 #include <sys/disklabel.h>
54 #include <sys/buf.h>
55 #include <sys/stat.h>
56 #include <sys/dkio.h>
57 #include <sys/fcntl.h>
58 
59 #include <ufs/ufs/dinode.h>
60 #include <ufs/ffs/fs.h>
61 
62 #include <machine/bus.h>
63 
64 #include <dev/qbus/ubavar.h>
65 #include <dev/qbus/rlreg.h>
66 #include <dev/qbus/rlvar.h>
67 
68 #include "ioconf.h"
69 #include "locators.h"
70 
71 static	int rlcmatch(struct device *, struct cfdata *, void *);
72 static	void rlcattach(struct device *, struct device *, void *);
73 static	int rlcprint(void *, const char *);
74 static	void rlcintr(void *);
75 static	int rlmatch(struct device *, struct cfdata *, void *);
76 static	void rlattach(struct device *, struct device *, void *);
77 static	void rlcstart(struct rlc_softc *, struct buf *);
78 static	void waitcrdy(struct rlc_softc *);
79 static	void rlcreset(struct device *);
80 
81 CFATTACH_DECL(rlc, sizeof(struct rlc_softc),
82     rlcmatch, rlcattach, NULL, NULL);
83 
84 CFATTACH_DECL(rl, sizeof(struct rl_softc),
85     rlmatch, rlattach, NULL, NULL);
86 
87 dev_type_open(rlopen);
88 dev_type_close(rlclose);
89 dev_type_read(rlread);
90 dev_type_write(rlwrite);
91 dev_type_ioctl(rlioctl);
92 dev_type_strategy(rlstrategy);
93 dev_type_dump(rldump);
94 dev_type_size(rlsize);
95 
96 const struct bdevsw rl_bdevsw = {
97 	rlopen, rlclose, rlstrategy, rlioctl, rldump, rlsize, D_DISK
98 };
99 
100 const struct cdevsw rl_cdevsw = {
101 	rlopen, rlclose, rlread, rlwrite, rlioctl,
102 	nostop, notty, nopoll, nommap, D_DISK
103 };
104 
105 #define	MAXRLXFER (RL_BPS * RL_SPT)
106 
107 #define	RL_WREG(reg, val) \
108 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, (reg), (val))
109 #define RL_RREG(reg) \
110 	bus_space_read_2(sc->sc_iot, sc->sc_ioh, (reg))
111 
112 static char *rlstates[] = {
113 	"drive not loaded",
114 	"drive spinning up",
115 	"drive brushes out",
116 	"drive loading heads",
117 	"drive seeking",
118 	"drive ready",
119 	"drive unloading heads",
120 	"drive spun down",
121 };
122 
123 static char *
124 rlstate(struct rlc_softc *sc, int unit)
125 {
126 	int i = 0;
127 
128 	do {
129 		RL_WREG(RL_DA, RLDA_GS);
130 		RL_WREG(RL_CS, RLCS_GS|(unit << RLCS_USHFT));
131 		waitcrdy(sc);
132 	} while (((RL_RREG(RL_CS) & RLCS_ERR) != 0) && i++ < 10);
133 	if (i == 10)
134 		return NULL;
135 	i = RL_RREG(RL_MP) & RLMP_STATUS;
136 	return rlstates[i];
137 }
138 
139 void
140 waitcrdy(struct rlc_softc *sc)
141 {
142 	int i;
143 
144 	for (i = 0; i < 1000; i++) {
145 		DELAY(10000);
146 		if (RL_RREG(RL_CS) & RLCS_CRDY)
147 			return;
148 	}
149 	printf("%s: never got ready\n", sc->sc_dev.dv_xname); /* ?panic? */
150 }
151 
152 int
153 rlcprint(void *aux, const char *name)
154 {
155 	struct rlc_attach_args *ra = aux;
156 
157 	if (name)
158 		printf("RL0%d at %s", ra->type & RLMP_DT ? '2' : '1', name);
159 	printf(" drive %d", ra->hwid);
160 	return UNCONF;
161 }
162 
163 /*
164  * Force the controller to interrupt.
165  */
166 int
167 rlcmatch(struct device *parent, struct cfdata *cf, void *aux)
168 {
169 	struct uba_attach_args *ua = aux;
170 	struct rlc_softc ssc, *sc = &ssc;
171 	int i;
172 
173 	sc->sc_iot = ua->ua_iot;
174 	sc->sc_ioh = ua->ua_ioh;
175 	/* Force interrupt by issuing a "Get Status" command */
176 	RL_WREG(RL_DA, RLDA_GS);
177 	RL_WREG(RL_CS, RLCS_GS|RLCS_IE);
178 
179 	for (i = 0; i < 100; i++) {
180 		DELAY(100000);
181 		if (RL_RREG(RL_CS) & RLCS_CRDY)
182 			return 1;
183 	}
184 	return 0;
185 }
186 
187 void
188 rlcattach(struct device *parent, struct device *self, void *aux)
189 {
190 	struct rlc_softc *sc = (struct rlc_softc *)self;
191 	struct uba_attach_args *ua = aux;
192 	struct rlc_attach_args ra;
193 	int i, error;
194 
195 	sc->sc_iot = ua->ua_iot;
196 	sc->sc_ioh = ua->ua_ioh;
197 	sc->sc_dmat = ua->ua_dmat;
198 	uba_intr_establish(ua->ua_icookie, ua->ua_cvec,
199 		rlcintr, sc, &sc->sc_intrcnt);
200 	evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt,
201 		sc->sc_dev.dv_xname, "intr");
202 	uba_reset_establish(rlcreset, self);
203 
204 	printf("\n");
205 
206 	/*
207 	 * The RL11 can only have one transfer going at a time,
208 	 * and max transfer size is one track, so only one dmamap
209 	 * is needed.
210 	 */
211 	error = bus_dmamap_create(sc->sc_dmat, MAXRLXFER, 1, MAXRLXFER, 0,
212 	    BUS_DMA_ALLOCNOW, &sc->sc_dmam);
213 	if (error) {
214 		printf(": Failed to allocate DMA map, error %d\n", error);
215 		return;
216 	}
217 	bufq_alloc(&sc->sc_q, BUFQ_DISKSORT|BUFQ_SORT_CYLINDER);
218 	for (i = 0; i < RL_MAXDPC; i++) {
219 		waitcrdy(sc);
220 		RL_WREG(RL_DA, RLDA_GS|RLDA_RST);
221 		RL_WREG(RL_CS, RLCS_GS|(i << RLCS_USHFT));
222 		waitcrdy(sc);
223 		ra.type = RL_RREG(RL_MP);
224 		ra.hwid = i;
225 		if ((RL_RREG(RL_CS) & RLCS_ERR) == 0)
226 			config_found(&sc->sc_dev, &ra, rlcprint);
227 	}
228 }
229 
230 int
231 rlmatch(struct device *parent, struct cfdata *cf, void *aux)
232 {
233 	struct rlc_attach_args *ra = aux;
234 
235 	if (cf->cf_loc[RLCCF_DRIVE] != RLCCF_DRIVE_DEFAULT &&
236 	    cf->cf_loc[RLCCF_DRIVE] != ra->hwid)
237 		return 0;
238 	return 1;
239 }
240 
241 void
242 rlattach(struct device *parent, struct device *self, void *aux)
243 {
244 	struct rl_softc *rc = (struct rl_softc *)self;
245 	struct rlc_attach_args *ra = aux;
246 	struct disklabel *dl;
247 
248 	rc->rc_hwid = ra->hwid;
249 	rc->rc_disk.dk_name = rc->rc_dev.dv_xname;
250 	disk_attach(&rc->rc_disk);
251 	dl = rc->rc_disk.dk_label;
252 	dl->d_npartitions = 3;
253 	strcpy(dl->d_typename, "RL01");
254 	if (ra->type & RLMP_DT)
255 		dl->d_typename[3] = '2';
256 	dl->d_secsize = DEV_BSIZE; /* XXX - wrong, but OK for now */
257 	dl->d_nsectors = RL_SPT/2;
258 	dl->d_ntracks = RL_SPD;
259 	dl->d_ncylinders = ra->type & RLMP_DT ? RL_TPS02 : RL_TPS01;
260 	dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks;
261 	dl->d_secperunit = dl->d_ncylinders * dl->d_secpercyl;
262 	dl->d_partitions[0].p_size = dl->d_partitions[2].p_size =
263 	    dl->d_secperunit;
264 	dl->d_partitions[0].p_offset = dl->d_partitions[2].p_offset = 0;
265 	dl->d_interleave = dl->d_headswitch = 1;
266 	dl->d_bbsize = BBSIZE;
267 	dl->d_sbsize = SBSIZE;
268 	dl->d_rpm = 2400;
269 	dl->d_type = DTYPE_DEC;
270 	printf(": %s, %s\n", dl->d_typename,
271 	    rlstate((struct rlc_softc *)parent, ra->hwid));
272 }
273 
274 int
275 rlopen(dev_t dev, int flag, int fmt, struct proc *p)
276 {
277 	int part, unit, mask;
278 	struct disklabel *dl;
279 	struct rlc_softc *sc;
280 	struct rl_softc *rc;
281 	char *msg;
282 
283 	/*
284 	 * Make sure this is a reasonable open request.
285 	 */
286 	unit = DISKUNIT(dev);
287 	if (unit >= rl_cd.cd_ndevs)
288 		return ENXIO;
289 	rc = rl_cd.cd_devs[unit];
290 	if (rc == 0)
291 		return ENXIO;
292 
293 	sc = (struct rlc_softc *)rc->rc_dev.dv_parent;
294 	/* Check that the disk actually is useable */
295 	msg = rlstate(sc, rc->rc_hwid);
296 	if (msg == NULL || msg == rlstates[RLMP_UNLOAD] ||
297 	    msg == rlstates[RLMP_SPUNDOWN])
298 		return ENXIO;
299 	/*
300 	 * If this is the first open; read in where on the disk we are.
301 	 */
302 	dl = rc->rc_disk.dk_label;
303 	if (rc->rc_state == DK_CLOSED) {
304 		u_int16_t mp;
305 		int maj;
306 		RL_WREG(RL_CS, RLCS_RHDR|(rc->rc_hwid << RLCS_USHFT));
307 		waitcrdy(sc);
308 		mp = RL_RREG(RL_MP);
309 		rc->rc_head = ((mp & RLMP_HS) == RLMP_HS);
310 		rc->rc_cyl = (mp >> 7) & 0777;
311 		rc->rc_state = DK_OPEN;
312 		/* Get disk label */
313 		printf("%s: ", rc->rc_dev.dv_xname);
314 		maj = cdevsw_lookup_major(&rl_cdevsw);
315 		if ((msg = readdisklabel(MAKEDISKDEV(maj,
316 		    rc->rc_dev.dv_unit, RAW_PART), rlstrategy, dl, NULL)))
317 			printf("%s: ", msg);
318 		printf("size %d sectors\n", dl->d_secperunit);
319 	}
320 	part = DISKPART(dev);
321 	if (part >= dl->d_npartitions)
322 		return ENXIO;
323 
324 	mask = 1 << part;
325 	switch (fmt) {
326 	case S_IFCHR:
327 		rc->rc_disk.dk_copenmask |= mask;
328 		break;
329 	case S_IFBLK:
330 		rc->rc_disk.dk_bopenmask |= mask;
331 		break;
332 	}
333 	rc->rc_disk.dk_openmask |= mask;
334 	return 0;
335 }
336 
337 int
338 rlclose(dev_t dev, int flag, int fmt, struct proc *p)
339 {
340 	int unit = DISKUNIT(dev);
341 	struct rl_softc *rc = rl_cd.cd_devs[unit];
342 	int mask = (1 << DISKPART(dev));
343 
344 	switch (fmt) {
345 	case S_IFCHR:
346 		rc->rc_disk.dk_copenmask &= ~mask;
347 		break;
348 	case S_IFBLK:
349 		rc->rc_disk.dk_bopenmask &= ~mask;
350 		break;
351 	}
352 	rc->rc_disk.dk_openmask =
353 	    rc->rc_disk.dk_copenmask | rc->rc_disk.dk_bopenmask;
354 
355 	if (rc->rc_disk.dk_openmask == 0)
356 		rc->rc_state = DK_CLOSED; /* May change pack */
357 	return 0;
358 }
359 
360 void
361 rlstrategy(struct buf *bp)
362 {
363 	struct disklabel *lp;
364 	struct rlc_softc *sc;
365         struct rl_softc *rc;
366         int unit, s, err;
367         /*
368          * Make sure this is a reasonable drive to use.
369          */
370         unit = DISKUNIT(bp->b_dev);
371         if (unit > rl_cd.cd_ndevs || (rc = rl_cd.cd_devs[unit]) == NULL) {
372                 bp->b_error = ENXIO;
373                 bp->b_flags |= B_ERROR;
374                 goto done;
375         }
376 	if (rc->rc_state != DK_OPEN) /* How did we end up here at all? */
377 		panic("rlstrategy: state impossible");
378 
379 	lp = rc->rc_disk.dk_label;
380 	if ((err = bounds_check_with_label(bp, lp, 1)) <= 0)
381 		goto done;
382 
383 	if (bp->b_bcount == 0)
384 		goto done;
385 
386 	bp->b_rawblkno =
387 	    bp->b_blkno + lp->d_partitions[DISKPART(bp->b_dev)].p_offset;
388 	bp->b_cylinder = bp->b_rawblkno / lp->d_secpercyl;
389 	sc = (struct rlc_softc *)rc->rc_dev.dv_parent;
390 
391 	s = splbio();
392 	BUFQ_PUT(&sc->sc_q, bp);
393 	rlcstart(sc, 0);
394 	splx(s);
395 	return;
396 
397 done:	biodone(bp);
398 }
399 
400 int
401 rlioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
402 {
403 	struct rl_softc *rc = rl_cd.cd_devs[DISKUNIT(dev)];
404 	struct disklabel *lp = rc->rc_disk.dk_label;
405 	int err = 0;
406 #ifdef __HAVE_OLD_DISKLABEL
407 	struct disklabel newlabel;
408 #endif
409 
410 	switch (cmd) {
411 	case DIOCGDINFO:
412 		bcopy(lp, addr, sizeof (struct disklabel));
413 		break;
414 
415 #ifdef __HAVE_OLD_DISKLABEL
416 	case ODIOCGDINFO:
417 		newlabel = *lp;
418 		if (newlabel.d_npartitions > OLDMAXPARTITIONS)
419 			return ENOTTY;
420 		bcopy(&newlabel, addr, sizeof (struct olddisklabel));
421 		break;
422 #endif
423 
424 	case DIOCGPART:
425 		((struct partinfo *)addr)->disklab = lp;
426 		((struct partinfo *)addr)->part =
427 		    &lp->d_partitions[DISKPART(dev)];
428 		break;
429 
430 	case DIOCSDINFO:
431 	case DIOCWDINFO:
432 #ifdef __HAVE_OLD_DISKLABEL
433 	case ODIOCWDINFO:
434 	case ODIOCSDINFO:
435 #endif
436 	{
437 		struct disklabel *tp;
438 
439 #ifdef __HAVE_OLD_DISKLABEL
440 		if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) {
441 			memset(&newlabel, 0, sizeof newlabel);
442 			memcpy(&newlabel, addr, sizeof (struct olddisklabel));
443 			tp = &newlabel;
444 		} else
445 #endif
446 		tp = (struct disklabel *)addr;
447 
448 		if ((flag & FWRITE) == 0)
449 			err = EBADF;
450 		else
451 			err = ((
452 #ifdef __HAVE_OLD_DISKLABEL
453 			       cmd == ODIOCSDINFO ||
454 #endif
455 			       cmd == DIOCSDINFO) ?
456 			    setdisklabel(lp, tp, 0, 0) :
457 			    writedisklabel(dev, rlstrategy, lp, 0));
458 		break;
459 	}
460 
461 	case DIOCWLABEL:
462 		if ((flag & FWRITE) == 0)
463 			err = EBADF;
464 		break;
465 
466 	default:
467 		err = ENOTTY;
468 	}
469 	return err;
470 }
471 
472 int
473 rlsize(dev_t dev)
474 {
475 	struct disklabel *dl;
476 	struct rl_softc *rc;
477 	int size, unit = DISKUNIT(dev);
478 
479 	if ((unit >= rl_cd.cd_ndevs) || ((rc = rl_cd.cd_devs[unit]) == 0))
480 		return -1;
481 	dl = rc->rc_disk.dk_label;
482 	size = dl->d_partitions[DISKPART(dev)].p_size *
483 	    (dl->d_secsize / DEV_BSIZE);
484 	return size;
485 }
486 
487 int
488 rldump(dev_t dev, daddr_t blkno, caddr_t va, size_t size)
489 {
490 	/* Not likely... */
491 	return 0;
492 }
493 
494 int
495 rlread(dev_t dev, struct uio *uio, int ioflag)
496 {
497 	return (physio(rlstrategy, NULL, dev, B_READ, minphys, uio));
498 }
499 
500 int
501 rlwrite(dev_t dev, struct uio *uio, int ioflag)
502 {
503 	return (physio(rlstrategy, NULL, dev, B_WRITE, minphys, uio));
504 }
505 
506 static char *rlerr[] = {
507 	"no",
508 	"operation incomplete",
509 	"read data CRC",
510 	"header CRC",
511 	"data late",
512 	"header not found",
513 	"",
514 	"",
515 	"non-existent memory",
516 	"memory parity error",
517 	"",
518 	"",
519 	"",
520 	"",
521 	"",
522 	"",
523 };
524 
525 void
526 rlcintr(void *arg)
527 {
528 	struct rlc_softc *sc = arg;
529 	struct buf *bp;
530 	u_int16_t cs;
531 
532 	bp = sc->sc_active;
533 	if (bp == 0) {
534 		printf("%s: strange interrupt\n", sc->sc_dev.dv_xname);
535 		return;
536 	}
537 	bus_dmamap_unload(sc->sc_dmat, sc->sc_dmam);
538 	sc->sc_active = 0;
539 	cs = RL_RREG(RL_CS);
540 	if (cs & RLCS_ERR) {
541 		int error = (cs & RLCS_ERRMSK) >> 10;
542 
543 		printf("%s: %s\n", sc->sc_dev.dv_xname, rlerr[error]);
544 		bp->b_flags |= B_ERROR;
545 		bp->b_error = EIO;
546 		bp->b_resid = bp->b_bcount;
547 		sc->sc_bytecnt = 0;
548 	}
549 	if (sc->sc_bytecnt == 0) /* Finished transfer */
550 		biodone(bp);
551 	rlcstart(sc, sc->sc_bytecnt ? bp : 0);
552 }
553 
554 /*
555  * Start routine. First position the disk to the given position,
556  * then start reading/writing. An optimization would be to be able
557  * to handle overlapping seeks between disks.
558  */
559 void
560 rlcstart(struct rlc_softc *sc, struct buf *ob)
561 {
562 	struct disklabel *lp;
563 	struct rl_softc *rc;
564 	struct buf *bp;
565 	int bn, cn, sn, tn, blks, err;
566 
567 	if (sc->sc_active)
568 		return;	/* Already doing something */
569 
570 	if (ob == 0) {
571 		bp = BUFQ_GET(&sc->sc_q);
572 		if (bp == NULL)
573 			return;	/* Nothing to do */
574 		sc->sc_bufaddr = bp->b_data;
575 		sc->sc_diskblk = bp->b_rawblkno;
576 		sc->sc_bytecnt = bp->b_bcount;
577 		bp->b_resid = 0;
578 	} else
579 		bp = ob;
580 	sc->sc_active = bp;
581 
582 	rc = rl_cd.cd_devs[DISKUNIT(bp->b_dev)];
583 	bn = sc->sc_diskblk;
584 	lp = rc->rc_disk.dk_label;
585 	if (bn) {
586 		cn = bn / lp->d_secpercyl;
587 		sn = bn % lp->d_secpercyl;
588 		tn = sn / lp->d_nsectors;
589 		sn = sn % lp->d_nsectors;
590 	} else
591 		cn = sn = tn = 0;
592 
593 	/*
594 	 * Check if we have to position disk first.
595 	 */
596 	if (rc->rc_cyl != cn || rc->rc_head != tn) {
597 		u_int16_t da = RLDA_SEEK;
598 		if (cn > rc->rc_cyl)
599 			da |= ((cn - rc->rc_cyl) << RLDA_CYLSHFT) | RLDA_DIR;
600 		else
601 			da |= ((rc->rc_cyl - cn) << RLDA_CYLSHFT);
602 		if (tn)
603 			da |= RLDA_HSSEEK;
604 		waitcrdy(sc);
605 		RL_WREG(RL_DA, da);
606 		RL_WREG(RL_CS, RLCS_SEEK | (rc->rc_hwid << RLCS_USHFT));
607 		waitcrdy(sc);
608 		rc->rc_cyl = cn;
609 		rc->rc_head = tn;
610 	}
611 	RL_WREG(RL_DA, (cn << RLDA_CYLSHFT) | (tn ? RLDA_HSRW : 0) | (sn << 1));
612 	blks = sc->sc_bytecnt/DEV_BSIZE;
613 
614 	if (sn + blks > RL_SPT/2)
615 		blks = RL_SPT/2 - sn;
616 	RL_WREG(RL_MP, -(blks*DEV_BSIZE)/2);
617 	err = bus_dmamap_load(sc->sc_dmat, sc->sc_dmam, sc->sc_bufaddr,
618 	    (blks*DEV_BSIZE), (bp->b_flags & B_PHYS ? bp->b_proc : 0),
619 	    BUS_DMA_NOWAIT);
620 	if (err)
621 		panic("%s: bus_dmamap_load failed: %d",
622 		    sc->sc_dev.dv_xname, err);
623 	RL_WREG(RL_BA, (sc->sc_dmam->dm_segs[0].ds_addr & 0xffff));
624 
625 	/* Count up vars */
626 	sc->sc_bufaddr += (blks*DEV_BSIZE);
627 	sc->sc_diskblk += blks;
628 	sc->sc_bytecnt -= (blks*DEV_BSIZE);
629 
630 	if (bp->b_flags & B_READ)
631 		RL_WREG(RL_CS, RLCS_IE|RLCS_RD|(rc->rc_hwid << RLCS_USHFT));
632 	else
633 		RL_WREG(RL_CS, RLCS_IE|RLCS_WD|(rc->rc_hwid << RLCS_USHFT));
634 }
635 
636 /*
637  * Called once per controller when an ubareset occurs.
638  * Retracts all disks and restarts active transfers.
639  */
640 void
641 rlcreset(struct device *dev)
642 {
643 	struct rlc_softc *sc = (struct rlc_softc *)dev;
644 	struct rl_softc *rc;
645 	int i;
646 	u_int16_t mp;
647 
648 	for (i = 0; i < rl_cd.cd_ndevs; i++) {
649 		if ((rc = rl_cd.cd_devs[i]) == NULL)
650 			continue;
651 		if (rc->rc_state != DK_OPEN)
652 			continue;
653 
654 		printf(" %s", rc->rc_dev.dv_xname);
655 		RL_WREG(RL_CS, RLCS_RHDR|(rc->rc_hwid << RLCS_USHFT));
656 		waitcrdy(sc);
657 		mp = RL_RREG(RL_MP);
658 		rc->rc_head = ((mp & RLMP_HS) == RLMP_HS);
659 		rc->rc_cyl = (mp >> 7) & 0777;
660 	}
661 	if (sc->sc_active == 0)
662 		return;
663 
664 	BUFQ_PUT(&sc->sc_q, sc->sc_active);
665 	sc->sc_active = 0;
666 	rlcstart(sc, 0);
667 }
668