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