xref: /netbsd-src/sys/dev/mscp/mscp_disk.c (revision e4d7c2e329d54c97e0c0bd3016bbe74f550c3d5e)
1 /*	$NetBSD: mscp_disk.c,v 1.22 2000/01/21 23:39:59 thorpej Exp $	*/
2 /*
3  * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
4  * Copyright (c) 1988 Regents of the University of California.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Chris Torek.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *	@(#)uda.c	7.32 (Berkeley) 2/13/91
39  */
40 
41 /*
42  * RA disk device driver
43  * RX MSCP floppy disk device driver
44  */
45 
46 /*
47  * TODO
48  *	write bad block forwarding code
49  */
50 
51 #include <sys/param.h>
52 #include <sys/buf.h>
53 #include <sys/device.h>
54 #include <sys/disk.h>
55 #include <sys/disklabel.h>
56 #include <sys/ioctl.h>
57 #include <sys/stat.h>
58 #include <sys/fcntl.h>
59 #include <sys/reboot.h>
60 #include <sys/proc.h>
61 #include <sys/systm.h>
62 
63 #include <ufs/ufs/dinode.h>
64 #include <ufs/ffs/fs.h>
65 
66 #include <machine/bus.h>
67 #include <machine/cpu.h>
68 #include <machine/rpb.h>
69 
70 #include <dev/mscp/mscp.h>
71 #include <dev/mscp/mscpreg.h>
72 #include <dev/mscp/mscpvar.h>
73 
74 #include "locators.h"
75 #include "ioconf.h"
76 #include "ra.h"
77 
78 #define RAMAJOR 9	/* RA major device number XXX */
79 
80 /*
81  * Drive status, per drive
82  */
83 struct ra_softc {
84 	struct	device ra_dev;	/* Autoconf struct */
85 	struct	disk ra_disk;
86 	int	ra_state;	/* open/closed state */
87 	u_long	ra_mediaid;	/* media id */
88 	int	ra_hwunit;	/* Hardware unit number */
89 	int	ra_havelabel;	/* true if we have a label */
90 	int	ra_wlabel;	/* label sector is currently writable */
91 };
92 
93 #define rx_softc ra_softc
94 
95 void	rxattach __P((struct device *, struct device *, void *));
96 int	rx_putonline __P((struct rx_softc *));
97 void	rrmakelabel __P((struct disklabel *, long));
98 
99 #if NRA
100 
101 int	ramatch __P((struct device *, struct cfdata *, void *));
102 void	raattach __P((struct device *, struct device *, void *));
103 int	raopen __P((dev_t, int, int, struct proc *));
104 int	raclose __P((dev_t, int, int, struct proc *));
105 void	rastrategy __P((struct buf *));
106 int	raread __P((dev_t, struct uio *));
107 int	rawrite __P((dev_t, struct uio *));
108 int	raioctl __P((dev_t, int, caddr_t, int, struct proc *));
109 int	radump __P((dev_t, daddr_t, caddr_t, size_t));
110 int	rasize __P((dev_t));
111 int	ra_putonline __P((struct ra_softc *));
112 
113 struct	cfattach ra_ca = {
114 	sizeof(struct ra_softc), ramatch, raattach
115 };
116 
117 /*
118  * More driver definitions, for generic MSCP code.
119  */
120 
121 int
122 ramatch(parent, cf, aux)
123 	struct	device *parent;
124 	struct	cfdata *cf;
125 	void	*aux;
126 {
127 	struct	drive_attach_args *da = aux;
128 	struct	mscp *mp = da->da_mp;
129 
130 	if ((da->da_typ & MSCPBUS_DISK) == 0)
131 		return 0;
132 	if (cf->cf_loc[MSCPBUSCF_DRIVE] != MSCPBUSCF_DRIVE_DEFAULT &&
133 	    cf->cf_loc[MSCPBUSCF_DRIVE] != mp->mscp_unit)
134 		return 0;
135 	/*
136 	 * Check if this disk is a floppy; then don't configure it.
137 	 * Seems to be a safe way to test it per Chris Torek.
138 	 */
139 	if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@')
140 		return 0;
141 	return 1;
142 }
143 
144 /*
145  * The attach routine only checks and prints drive type.
146  * Bringing the disk online is done when the disk is accessed
147  * the first time.
148  */
149 void
150 raattach(parent, self, aux)
151 	struct	device *parent, *self;
152 	void	*aux;
153 {
154 	struct	ra_softc *ra = (void *)self;
155 	struct	mscp_softc *mi = (void *)parent;
156 
157 	rxattach(parent, self, aux);
158 	/*
159 	 * Find out if we booted from this disk.
160 	 */
161 	if ((B_TYPE(bootdev) == BDEV_UDA) && (ra->ra_hwunit == B_UNIT(bootdev))
162 	    && (mi->mi_ctlrnr == B_CONTROLLER(bootdev))
163 	    && (mi->mi_adapnr == B_ADAPTOR(bootdev)))
164 		booted_from = self;
165 }
166 
167 /*
168  * (Try to) put the drive online. This is done the first time the
169  * drive is opened, or if it har fallen offline.
170  */
171 int
172 ra_putonline(ra)
173 	struct ra_softc *ra;
174 {
175 	struct	disklabel *dl;
176 	char *msg;
177 
178 	if (rx_putonline(ra) != MSCP_DONE)
179 		return MSCP_FAILED;
180 
181 	dl = ra->ra_disk.dk_label;
182 
183 	ra->ra_state = DK_RDLABEL;
184 	printf("%s", ra->ra_dev.dv_xname);
185 	if ((msg = readdisklabel(MAKEDISKDEV(RAMAJOR, ra->ra_dev.dv_unit,
186 	    RAW_PART), rastrategy, dl, NULL)) != NULL)
187 		printf(": %s", msg);
188 	else {
189 		ra->ra_havelabel = 1;
190 		ra->ra_state = DK_OPEN;
191 	}
192 
193 	printf(": size %d sectors\n", dl->d_secperunit);
194 
195 	return MSCP_DONE;
196 }
197 
198 /*
199  * Open a drive.
200  */
201 /*ARGSUSED*/
202 int
203 raopen(dev, flag, fmt, p)
204 	dev_t dev;
205 	int flag, fmt;
206 	struct	proc *p;
207 {
208 	register struct ra_softc *ra;
209 	int part, unit, mask;
210 	/*
211 	 * Make sure this is a reasonable open request.
212 	 */
213 	unit = DISKUNIT(dev);
214 	if (unit >= ra_cd.cd_ndevs)
215 		return ENXIO;
216 	ra = ra_cd.cd_devs[unit];
217 	if (ra == 0)
218 		return ENXIO;
219 
220 	/*
221 	 * If this is the first open; we must first try to put
222 	 * the disk online (and read the label).
223 	 */
224 	if (ra->ra_state == DK_CLOSED)
225 		if (ra_putonline(ra) == MSCP_FAILED)
226 			return ENXIO;
227 
228 	/* If the disk has no label; allow writing everywhere */
229 	if (ra->ra_havelabel == 0)
230 		ra->ra_wlabel = 1;
231 
232 	part = DISKPART(dev);
233 	if (part >= ra->ra_disk.dk_label->d_npartitions)
234 		return ENXIO;
235 
236 	/*
237 	 * Wait for the state to settle
238 	 */
239 #if notyet
240 	while (ra->ra_state != DK_OPEN)
241 		if ((error = tsleep((caddr_t)ra, (PZERO + 1) | PCATCH,
242 		    devopn, 0))) {
243 			splx(s);
244 			return (error);
245 		}
246 #endif
247 
248 	mask = 1 << part;
249 
250 	switch (fmt) {
251 	case S_IFCHR:
252 		ra->ra_disk.dk_copenmask |= mask;
253 		break;
254 	case S_IFBLK:
255 		ra->ra_disk.dk_bopenmask |= mask;
256 		break;
257 	}
258 	ra->ra_disk.dk_openmask |= mask;
259 	return 0;
260 }
261 
262 /* ARGSUSED */
263 int
264 raclose(dev, flags, fmt, p)
265 	dev_t dev;
266 	int flags, fmt;
267 	struct	proc *p;
268 {
269 	register int unit = DISKUNIT(dev);
270 	register struct ra_softc *ra = ra_cd.cd_devs[unit];
271 	int mask = (1 << DISKPART(dev));
272 
273 	switch (fmt) {
274 	case S_IFCHR:
275 		ra->ra_disk.dk_copenmask &= ~mask;
276 		break;
277 	case S_IFBLK:
278 		ra->ra_disk.dk_bopenmask &= ~mask;
279 		break;
280 	}
281 	ra->ra_disk.dk_openmask =
282 	    ra->ra_disk.dk_copenmask | ra->ra_disk.dk_bopenmask;
283 
284 	/*
285 	 * Should wait for I/O to complete on this partition even if
286 	 * others are open, but wait for work on blkflush().
287 	 */
288 #if notyet
289 	if (ra->ra_openpart == 0) {
290 		s = splimp();
291 		while (BUFQ_FIRST(&udautab[unit]) != NULL)
292 			sleep((caddr_t)&udautab[unit], PZERO - 1);
293 		splx(s);
294 		ra->ra_state = CLOSED;
295 		ra->ra_wlabel = 0;
296 	}
297 #endif
298 	return (0);
299 }
300 
301 /*
302  * Queue a transfer request, and if possible, hand it to the controller.
303  */
304 void
305 rastrategy(bp)
306 	register struct buf *bp;
307 {
308 	register int unit;
309 	register struct ra_softc *ra;
310 	/*
311 	 * Make sure this is a reasonable drive to use.
312 	 */
313 	unit = DISKUNIT(bp->b_dev);
314 	if (unit > ra_cd.cd_ndevs || (ra = ra_cd.cd_devs[unit]) == NULL) {
315 		bp->b_error = ENXIO;
316 		bp->b_flags |= B_ERROR;
317 		goto done;
318 	}
319 	/*
320 	 * If drive is open `raw' or reading label, let it at it.
321 	 */
322 	if (ra->ra_state == DK_RDLABEL) {
323 		mscp_strategy(bp, ra->ra_dev.dv_parent);
324 		return;
325 	}
326 
327 	/* If disk is not online, try to put it online */
328 	if (ra->ra_state == DK_CLOSED)
329 		if (ra_putonline(ra) == MSCP_FAILED) {
330 			bp->b_flags |= B_ERROR;
331 			bp->b_error = EIO;
332 			goto done;
333 		}
334 
335 	/*
336 	 * Determine the size of the transfer, and make sure it is
337 	 * within the boundaries of the partition.
338 	 */
339 	if (bounds_check_with_label(bp, ra->ra_disk.dk_label,
340 	    ra->ra_wlabel) <= 0)
341 		goto done;
342 
343 	/* Make some statistics... /bqt */
344 	ra->ra_disk.dk_xfer++;
345 	ra->ra_disk.dk_bytes += bp->b_bcount;
346 	mscp_strategy(bp, ra->ra_dev.dv_parent);
347 	return;
348 
349 done:
350 	biodone(bp);
351 }
352 
353 int
354 raread(dev, uio)
355 	dev_t dev;
356 	struct uio *uio;
357 {
358 
359 	return (physio(rastrategy, NULL, dev, B_READ, minphys, uio));
360 }
361 
362 int
363 rawrite(dev, uio)
364 	dev_t dev;
365 	struct uio *uio;
366 {
367 
368 	return (physio(rastrategy, NULL, dev, B_WRITE, minphys, uio));
369 }
370 
371 /*
372  * I/O controls.
373  */
374 int
375 raioctl(dev, cmd, data, flag, p)
376 	dev_t dev;
377 	int cmd;
378 	caddr_t data;
379 	int flag;
380 	struct proc *p;
381 {
382 	register int unit = DISKUNIT(dev);
383 	register struct disklabel *lp, *tp;
384 	register struct ra_softc *ra = ra_cd.cd_devs[unit];
385 	int error = 0;
386 
387 	lp = ra->ra_disk.dk_label;
388 
389 	switch (cmd) {
390 
391 	case DIOCGDINFO:
392 		bcopy(lp, data, sizeof (struct disklabel));
393 		break;
394 
395 	case DIOCGPART:
396 		((struct partinfo *)data)->disklab = lp;
397 		((struct partinfo *)data)->part =
398 		    &lp->d_partitions[DISKPART(dev)];
399 		break;
400 
401 	case DIOCWDINFO:
402 	case DIOCSDINFO:
403 		if ((flag & FWRITE) == 0)
404 			error = EBADF;
405 		else {
406 			error = setdisklabel(lp, (struct disklabel *)data,0,0);
407 			if ((error == 0) && (cmd == DIOCWDINFO)) {
408 				ra->ra_wlabel = 1;
409 				error = writedisklabel(dev, rastrategy, lp,0);
410 				ra->ra_wlabel = 0;
411 			}
412 		}
413 		break;
414 
415 	case DIOCWLABEL:
416 		if ((flag & FWRITE) == 0)
417 			error = EBADF;
418 		else
419 			ra->ra_wlabel = 1;
420 		break;
421 
422 	case DIOCGDEFLABEL:
423 		tp = (struct disklabel *)data;
424 		bzero(data, sizeof(struct disklabel));
425 		tp->d_secsize = lp->d_secsize;
426 		tp->d_nsectors = lp->d_nsectors;
427 		tp->d_ntracks = lp->d_ntracks;
428 		tp->d_ncylinders = lp->d_ncylinders;
429 		tp->d_secpercyl = lp->d_secpercyl;
430 		tp->d_secperunit = lp->d_secperunit;
431 		tp->d_type = DTYPE_MSCP;
432 		tp->d_rpm = 3600;
433 		rrmakelabel(tp, ra->ra_mediaid);
434 		break;
435 
436 	default:
437 		error = ENOTTY;
438 		break;
439 	}
440 	return (error);
441 }
442 
443 
444 int
445 radump(dev, blkno, va, size)
446 	dev_t	dev;
447 	daddr_t blkno;
448 	caddr_t va;
449 	size_t	size;
450 {
451 	return ENXIO;
452 }
453 
454 /*
455  * Return the size of a partition, if known, or -1 if not.
456  */
457 int
458 rasize(dev)
459 	dev_t dev;
460 {
461 	register int unit = DISKUNIT(dev);
462 	struct ra_softc *ra;
463 
464 	if (unit >= ra_cd.cd_ndevs || ra_cd.cd_devs[unit] == 0)
465 		return -1;
466 
467 	ra = ra_cd.cd_devs[unit];
468 
469 	if (ra->ra_state == DK_CLOSED)
470 		if (ra_putonline(ra) == MSCP_FAILED)
471 			return -1;
472 
473 	return ra->ra_disk.dk_label->d_partitions[DISKPART(dev)].p_size *
474 	    (ra->ra_disk.dk_label->d_secsize / DEV_BSIZE);
475 }
476 
477 #endif /* NRA */
478 
479 #if NRX
480 
481 int	rxmatch __P((struct device *, struct cfdata *, void *));
482 int	rxopen __P((dev_t, int, int, struct proc *));
483 int	rxclose __P((dev_t, int, int, struct proc *));
484 void	rxstrategy __P((struct buf *));
485 int	rxread __P((dev_t, struct uio *));
486 int	rxwrite __P((dev_t, struct uio *));
487 int	rxioctl __P((dev_t, int, caddr_t, int, struct proc *));
488 int	rxdump __P((dev_t, daddr_t, caddr_t, size_t));
489 int	rxsize __P((dev_t));
490 
491 struct	cfattach rx_ca = {
492 	sizeof(struct rx_softc), rxmatch, rxattach
493 };
494 
495 /*
496  * More driver definitions, for generic MSCP code.
497  */
498 
499 int
500 rxmatch(parent, cf, aux)
501 	struct	device *parent;
502 	struct	cfdata *cf;
503 	void	*aux;
504 {
505 	struct	drive_attach_args *da = aux;
506 	struct	mscp *mp = da->da_mp;
507 
508 	if ((da->da_typ & MSCPBUS_DISK) == 0)
509 		return 0;
510 	if (cf->cf_loc[MSCPBUSCF_DRIVE] != MSCPBUSCF_DRIVE_DEFAULT &&
511 	    cf->cf_loc[MSCPBUSCF_DRIVE] != mp->mscp_unit)
512 		return 0;
513 	/*
514 	 * Check if this disk is a floppy; then configure it.
515 	 * Seems to be a safe way to test it per Chris Torek.
516 	 */
517 	if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@')
518 		return 1;
519 	return 0;
520 }
521 
522 #endif /* NRX */
523 
524 /*
525  * The attach routine only checks and prints drive type.
526  * Bringing the disk online is done when the disk is accessed
527  * the first time.
528  */
529 void
530 rxattach(parent, self, aux)
531 	struct	device *parent, *self;
532 	void	*aux;
533 {
534 	struct	rx_softc *rx = (void *)self;
535 	struct	drive_attach_args *da = aux;
536 	struct	mscp *mp = da->da_mp;
537 	struct	mscp_softc *mi = (void *)parent;
538 	struct	disklabel *dl;
539 
540 	rx->ra_mediaid = mp->mscp_guse.guse_mediaid;
541 	rx->ra_state = DK_CLOSED;
542 	rx->ra_hwunit = mp->mscp_unit;
543 	mi->mi_dp[mp->mscp_unit] = self;
544 
545 	rx->ra_disk.dk_name = rx->ra_dev.dv_xname;
546 	disk_attach((struct disk *)&rx->ra_disk);
547 
548 	/* Fill in what we know. The actual size is gotten later */
549 	dl = rx->ra_disk.dk_label;
550 
551 	dl->d_secsize = DEV_BSIZE;
552 	dl->d_nsectors = mp->mscp_guse.guse_nspt;
553 	dl->d_ntracks = mp->mscp_guse.guse_ngpc * mp->mscp_guse.guse_group;
554 	dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks;
555 	disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid);
556 #ifdef DEBUG
557 	printf("%s: nspt %d group %d ngpc %d rct %d nrpt %d nrct %d\n",
558 	    self->dv_xname, mp->mscp_guse.guse_nspt, mp->mscp_guse.guse_group,
559 	    mp->mscp_guse.guse_ngpc, mp->mscp_guse.guse_rctsize,
560 	    mp->mscp_guse.guse_nrpt, mp->mscp_guse.guse_nrct);
561 #endif
562 }
563 
564 /*
565  * (Try to) put the drive online. This is done the first time the
566  * drive is opened, or if it har fallen offline.
567  */
568 int
569 rx_putonline(rx)
570 	struct rx_softc *rx;
571 {
572 	struct	mscp *mp;
573 	struct	mscp_softc *mi = (struct mscp_softc *)rx->ra_dev.dv_parent;
574 	volatile int i;
575 
576 	rx->ra_state = DK_CLOSED;
577 	mp = mscp_getcp(mi, MSCP_WAIT);
578 	mp->mscp_opcode = M_OP_ONLINE;
579 	mp->mscp_unit = rx->ra_hwunit;
580 	mp->mscp_cmdref = 1;
581 	*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
582 
583 	/* Poll away */
584 	i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
585 	if (tsleep(&rx->ra_dev.dv_unit, PRIBIO, "rxonline", 100*100))
586 		rx->ra_state = DK_CLOSED;
587 
588 	if (rx->ra_state == DK_CLOSED)
589 		return MSCP_FAILED;
590 
591 	return MSCP_DONE;
592 }
593 
594 #if NRX
595 
596 /*
597  * Open a drive.
598  */
599 /*ARGSUSED*/
600 int
601 rxopen(dev, flag, fmt, p)
602 	dev_t dev;
603 	int flag, fmt;
604 	struct	proc *p;
605 {
606 	register struct rx_softc *rx;
607 	int unit;
608 
609 	/*
610 	 * Make sure this is a reasonable open request.
611 	 */
612 	unit = DISKUNIT(dev);
613 	if (unit >= rx_cd.cd_ndevs)
614 		return ENXIO;
615 	rx = rx_cd.cd_devs[unit];
616 	if (rx == 0)
617 		return ENXIO;
618 
619 	/*
620 	 * If this is the first open; we must first try to put
621 	 * the disk online (and read the label).
622 	 */
623 	if (rx->ra_state == DK_CLOSED)
624 		if (rx_putonline(rx) == MSCP_FAILED)
625 			return ENXIO;
626 
627 	return 0;
628 }
629 
630 /* ARGSUSED */
631 int
632 rxclose(dev, flags, fmt, p)
633 	dev_t dev;
634 	int flags, fmt;
635 	struct	proc *p;
636 {
637 	return (0);
638 }
639 
640 /*
641  * Queue a transfer request, and if possible, hand it to the controller.
642  *
643  * This routine is broken into two so that the internal version
644  * udastrat1() can be called by the (nonexistent, as yet) bad block
645  * revectoring routine.
646  */
647 void
648 rxstrategy(bp)
649 	register struct buf *bp;
650 {
651 	register int unit;
652 	register struct rx_softc *rx;
653 
654 	/*
655 	 * Make sure this is a reasonable drive to use.
656 	 */
657 	unit = DISKUNIT(bp->b_dev);
658 	if (unit > rx_cd.cd_ndevs || (rx = rx_cd.cd_devs[unit]) == NULL) {
659 		bp->b_error = ENXIO;
660 		bp->b_flags |= B_ERROR;
661 		goto done;
662 	}
663 
664 	/* If disk is not online, try to put it online */
665 	if (rx->ra_state == DK_CLOSED)
666 		if (rx_putonline(rx) == MSCP_FAILED) {
667 			bp->b_flags |= B_ERROR;
668 			bp->b_error = EIO;
669 			goto done;
670 		}
671 
672 	/*
673 	 * Determine the size of the transfer, and make sure it is
674 	 * within the boundaries of the partition.
675 	 */
676 	if (bp->b_blkno >= rx->ra_disk.dk_label->d_secperunit) {
677 		bp->b_resid = bp->b_bcount;
678 		goto done;
679 	}
680 
681 	/* Make some statistics... /bqt */
682 	rx->ra_disk.dk_xfer++;
683 	rx->ra_disk.dk_bytes += bp->b_bcount;
684 	mscp_strategy(bp, rx->ra_dev.dv_parent);
685 	return;
686 
687 done:
688 	biodone(bp);
689 }
690 
691 int
692 rxread(dev, uio)
693 	dev_t dev;
694 	struct uio *uio;
695 {
696 
697 	return (physio(rxstrategy, NULL, dev, B_READ, minphys, uio));
698 }
699 
700 int
701 rxwrite(dev, uio)
702 	dev_t dev;
703 	struct uio *uio;
704 {
705 
706 	return (physio(rxstrategy, NULL, dev, B_WRITE, minphys, uio));
707 }
708 
709 /*
710  * I/O controls.
711  */
712 int
713 rxioctl(dev, cmd, data, flag, p)
714 	dev_t dev;
715 	int cmd;
716 	caddr_t data;
717 	int flag;
718 	struct proc *p;
719 {
720 	register int unit = DISKUNIT(dev);
721 	register struct disklabel *lp;
722 	register struct rx_softc *rx = rx_cd.cd_devs[unit];
723 	int error = 0;
724 
725 	lp = rx->ra_disk.dk_label;
726 
727 	switch (cmd) {
728 
729 	case DIOCGDINFO:
730 		bcopy(lp, data, sizeof (struct disklabel));
731 		break;
732 
733 	case DIOCGPART:
734 		((struct partinfo *)data)->disklab = lp;
735 		((struct partinfo *)data)->part =
736 		    &lp->d_partitions[DISKPART(dev)];
737 		break;
738 
739 
740 	case DIOCWDINFO:
741 	case DIOCSDINFO:
742 	case DIOCWLABEL:
743 		break;
744 
745 	default:
746 		error = ENOTTY;
747 		break;
748 	}
749 	return (error);
750 }
751 
752 int
753 rxdump(dev, blkno, va, size)
754 	dev_t dev;
755 	daddr_t blkno;
756 	caddr_t va;
757 	size_t size;
758 {
759 
760 	/* Not likely. */
761 	return ENXIO;
762 }
763 
764 int
765 rxsize(dev)
766 	dev_t dev;
767 {
768 
769 	return -1;
770 }
771 
772 #endif /* NRX */
773 
774 void	rrdgram __P((struct device *, struct mscp *, struct mscp_softc *));
775 void	rriodone __P((struct device *, struct buf *));
776 int	rronline __P((struct device *, struct mscp *));
777 int	rrgotstatus __P((struct device *, struct mscp *));
778 void	rrreplace __P((struct device *, struct mscp *));
779 int	rrioerror __P((struct device *, struct mscp *, struct buf *));
780 void	rrfillin __P((struct buf *, struct mscp *));
781 void	rrbb __P((struct device *, struct mscp *, struct buf *));
782 
783 
784 struct	mscp_device ra_device = {
785 	rrdgram,
786 	rriodone,
787 	rronline,
788 	rrgotstatus,
789 	rrreplace,
790 	rrioerror,
791 	rrbb,
792 	rrfillin,
793 };
794 
795 /*
796  * Handle an error datagram.
797  * This can come from an unconfigured drive as well.
798  */
799 void
800 rrdgram(usc, mp, mi)
801 	struct device *usc;
802 	struct mscp *mp;
803 	struct mscp_softc *mi;
804 {
805 	if (mscp_decodeerror(usc == NULL?"unconf disk" : usc->dv_xname, mp, mi))
806 		return;
807 	/*
808 	 * SDI status information bytes 10 and 11 are the microprocessor
809 	 * error code and front panel code respectively.  These vary per
810 	 * drive type and are printed purely for field service information.
811 	 */
812 	if (mp->mscp_format == M_FM_SDI)
813 		printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n",
814 			mp->mscp_erd.erd_sdistat[10],
815 			mp->mscp_erd.erd_sdistat[11]);
816 }
817 
818 void
819 rriodone(usc, bp)
820 	struct device *usc;
821 	struct buf *bp;
822 {
823 
824 	biodone(bp);
825 }
826 
827 /*
828  * A drive came on line.  Check its type and size.  Return DONE if
829  * we think the drive is truly on line.	 In any case, awaken anyone
830  * sleeping on the drive on-line-ness.
831  */
832 int
833 rronline(usc, mp)
834 	struct device *usc;
835 	struct mscp *mp;
836 {
837 	struct rx_softc *rx = (struct rx_softc *)usc;
838 	struct disklabel *dl;
839 
840 	wakeup((caddr_t)&usc->dv_unit);
841 	if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
842 		printf("%s: attempt to bring on line failed: ", usc->dv_xname);
843 		mscp_printevent(mp);
844 		return (MSCP_FAILED);
845 	}
846 
847 	rx->ra_state = DK_OPEN;
848 
849 	dl = rx->ra_disk.dk_label;
850 	dl->d_secperunit = (daddr_t)mp->mscp_onle.onle_unitsize;
851 
852 	if (dl->d_secpercyl) {
853 		dl->d_ncylinders = dl->d_secperunit/dl->d_secpercyl;
854 		dl->d_type = DTYPE_MSCP;
855 		dl->d_rpm = 3600;
856 	} else {
857 		dl->d_type = DTYPE_FLOPPY;
858 		dl->d_rpm = 300;
859 	}
860 	rrmakelabel(dl, rx->ra_mediaid);
861 
862 	return (MSCP_DONE);
863 }
864 
865 void
866 rrmakelabel(dl, type)
867 	struct disklabel *dl;
868 	long type;
869 {
870 	int n, p = 0;
871 
872 	dl->d_bbsize = BBSIZE;
873 	dl->d_sbsize = SBSIZE;
874 
875 	/* Create the disk name for disklabel. Phew... */
876 	dl->d_typename[p++] = MSCP_MID_CHAR(2, type);
877 	dl->d_typename[p++] = MSCP_MID_CHAR(1, type);
878 	if (MSCP_MID_ECH(0, type))
879 		dl->d_typename[p++] = MSCP_MID_CHAR(0, type);
880 	n = MSCP_MID_NUM(type);
881 	if (n > 99) {
882 		dl->d_typename[p++] = '1';
883 		n -= 100;
884 	}
885 	if (n > 9) {
886 		dl->d_typename[p++] = (n / 10) + '0';
887 		n %= 10;
888 	}
889 	dl->d_typename[p++] = n + '0';
890 	dl->d_typename[p] = 0;
891 	dl->d_npartitions = MAXPARTITIONS;
892 	dl->d_partitions[0].p_size = dl->d_partitions[2].p_size =
893 	    dl->d_secperunit;
894 	dl->d_partitions[0].p_offset = dl->d_partitions[2].p_offset = 0;
895 	dl->d_interleave = dl->d_headswitch = 1;
896 	dl->d_magic = dl->d_magic2 = DISKMAGIC;
897 	dl->d_checksum = dkcksum(dl);
898 }
899 
900 /*
901  * We got some (configured) unit's status.  Return DONE if it succeeded.
902  */
903 int
904 rrgotstatus(usc, mp)
905 	register struct device *usc;
906 	register struct mscp *mp;
907 {
908 	if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
909 		printf("%s: attempt to get status failed: ", usc->dv_xname);
910 		mscp_printevent(mp);
911 		return (MSCP_FAILED);
912 	}
913 	/* record for (future) bad block forwarding and whatever else */
914 #ifdef notyet
915 	uda_rasave(ui->ui_unit, mp, 1);
916 #endif
917 	return (MSCP_DONE);
918 }
919 
920 /*
921  * A replace operation finished.
922  */
923 /*ARGSUSED*/
924 void
925 rrreplace(usc, mp)
926 	struct device *usc;
927 	struct mscp *mp;
928 {
929 
930 	panic("udareplace");
931 }
932 
933 /*
934  * A transfer failed.  We get a chance to fix or restart it.
935  * Need to write the bad block forwaring code first....
936  */
937 /*ARGSUSED*/
938 int
939 rrioerror(usc, mp, bp)
940 	register struct device *usc;
941 	register struct mscp *mp;
942 	struct buf *bp;
943 {
944 	struct ra_softc *ra = (void *)usc;
945 	int code = mp->mscp_event;
946 
947 	switch (code & M_ST_MASK) {
948 	/* The unit has fallen offline. Try to figure out why. */
949 	case M_ST_OFFLINE:
950 		bp->b_flags |= B_ERROR;
951 		bp->b_error = EIO;
952 		ra->ra_state = DK_CLOSED;
953 		if (code & M_OFFLINE_UNMOUNTED)
954 			printf("%s: not mounted/spun down\n", usc->dv_xname);
955 		if (code & M_OFFLINE_DUPLICATE)
956 			printf("%s: duplicate unit number!!!\n", usc->dv_xname);
957 		return MSCP_DONE;
958 
959 	case M_ST_AVAILABLE:
960 		ra->ra_state = DK_CLOSED; /* Force another online */
961 		return MSCP_DONE;
962 
963 	default:
964 		printf("%s:", usc->dv_xname);
965 		break;
966 	}
967 	return (MSCP_FAILED);
968 }
969 
970 /*
971  * Fill in disk addresses in a mscp packet waiting for transfer.
972  */
973 void
974 rrfillin(bp, mp)
975 	struct buf *bp;
976 	struct mscp *mp;
977 {
978 	struct rx_softc *rx = 0; /* Wall */
979 	struct disklabel *lp;
980 	int unit = DISKUNIT(bp->b_dev);
981 	int part = DISKPART(bp->b_dev);
982 
983 #if NRA
984 	if (major(bp->b_dev) == RAMAJOR)
985 		rx = ra_cd.cd_devs[unit];
986 #endif
987 #if NRX
988 	if (major(bp->b_dev) != RAMAJOR)
989 		rx = rx_cd.cd_devs[unit];
990 #endif
991 	lp = rx->ra_disk.dk_label;
992 
993 	mp->mscp_seq.seq_lbn = lp->d_partitions[part].p_offset + bp->b_blkno;
994 	mp->mscp_unit = rx->ra_hwunit;
995 	mp->mscp_seq.seq_bytecount = bp->b_bcount;
996 }
997 
998 /*
999  * A bad block related operation finished.
1000  */
1001 /*ARGSUSED*/
1002 void
1003 rrbb(usc, mp, bp)
1004 	struct device *usc;
1005 	struct mscp *mp;
1006 	struct buf *bp;
1007 {
1008 
1009 	panic("udabb");
1010 }
1011