mscp_disk.c revision 1.26 1 /* $NetBSD: mscp_disk.c,v 1.26 2001/01/07 18:09:02 fvdl 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 #ifdef __HAVE_OLD_DISKLABEL
364 struct disklabel newlabel;
365 #endif
366
367 lp = ra->ra_disk.dk_label;
368
369 switch (cmd) {
370
371 case DIOCGDINFO:
372 bcopy(lp, data, sizeof (struct disklabel));
373 break;
374 #ifdef __HAVE_OLD_DISKLABEL
375 case ODIOCGDINFO:
376 bcopy(lp, &newlabel, sizeof disklabel);
377 if (newlabel.d_npartitions > OLDMAXPARTITIONS)
378 newlabel.d_npartitions = OLDMAXPARTITIONS;
379 bcopy(&newlabel, data, sizeof (struct olddisklabel));
380 break;
381 #endif
382
383 case DIOCGPART:
384 ((struct partinfo *)data)->disklab = lp;
385 ((struct partinfo *)data)->part =
386 &lp->d_partitions[DISKPART(dev)];
387 break;
388
389 case DIOCWDINFO:
390 case DIOCSDINFO:
391 #ifdef __HAVE_OLD_DISKLABEL
392 case ODIOCWDINFO:
393 case ODIOCSDINFO:
394 if (cmd == ODIOCSDINFO || xfer == ODIOCWDINFO) {
395 memset(&newlabel, 0, sizeof newlabel);
396 memcpy(&newlabel, data, sizeof (struct olddisklabel));
397 tp = &newlabel;
398 } else
399 #endif
400 tp = (struct disklabel *)data;
401
402 if ((flag & FWRITE) == 0)
403 error = EBADF;
404 else {
405 error = setdisklabel(lp, tp, 0, 0);
406 if ((error == 0) && (cmd == DIOCWDINFO
407 #ifdef __HAVE_OLD_DISKLABEL
408 || cmd == ODIOCWDINFO
409 #else
410 )) {
411 #endif
412 ra->ra_wlabel = 1;
413 error = writedisklabel(dev, rastrategy, lp,0);
414 ra->ra_wlabel = 0;
415 }
416 }
417 break;
418
419 case DIOCWLABEL:
420 if ((flag & FWRITE) == 0)
421 error = EBADF;
422 else
423 ra->ra_wlabel = 1;
424 break;
425
426 case DIOCGDEFLABEL:
427 #ifdef __HAVE_OLD_DISKLABEL
428 case ODIOCGDEFLABEL:
429 if (cmd == ODIOCGDEFLABEL)
430 tp = &newlabel;
431 else
432 #else
433 tp = (struct disklabel *)data;
434 #endif
435 bzero(tp, sizeof(struct disklabel));
436 tp->d_secsize = lp->d_secsize;
437 tp->d_nsectors = lp->d_nsectors;
438 tp->d_ntracks = lp->d_ntracks;
439 tp->d_ncylinders = lp->d_ncylinders;
440 tp->d_secpercyl = lp->d_secpercyl;
441 tp->d_secperunit = lp->d_secperunit;
442 tp->d_type = DTYPE_MSCP;
443 tp->d_rpm = 3600;
444 rrmakelabel(tp, ra->ra_mediaid);
445 #ifdef __HAVE_OLD_DISKLABEL
446 if (cmd == ODIOCGDEFLABEL) {
447 if (tp->d_npartitions > OLDMAXPARTITIONS)
448 tp->d_npartitions = OLDMAXPARTITIONS;
449 memcpy(data, tp, sizeof (struct olddisklabel));
450 }
451 #endif
452 break;
453
454 default:
455 error = ENOTTY;
456 break;
457 }
458 return (error);
459 }
460
461
462 int
463 radump(dev, blkno, va, size)
464 dev_t dev;
465 daddr_t blkno;
466 caddr_t va;
467 size_t size;
468 {
469 return ENXIO;
470 }
471
472 /*
473 * Return the size of a partition, if known, or -1 if not.
474 */
475 int
476 rasize(dev)
477 dev_t dev;
478 {
479 int unit = DISKUNIT(dev);
480 struct ra_softc *ra;
481
482 if (unit >= ra_cd.cd_ndevs || ra_cd.cd_devs[unit] == 0)
483 return -1;
484
485 ra = ra_cd.cd_devs[unit];
486
487 if (ra->ra_state == DK_CLOSED)
488 if (ra_putonline(ra) == MSCP_FAILED)
489 return -1;
490
491 return ra->ra_disk.dk_label->d_partitions[DISKPART(dev)].p_size *
492 (ra->ra_disk.dk_label->d_secsize / DEV_BSIZE);
493 }
494
495 #endif /* NRA */
496
497 #if NRX
498
499 int rxmatch __P((struct device *, struct cfdata *, void *));
500 int rxopen __P((dev_t, int, int, struct proc *));
501 int rxclose __P((dev_t, int, int, struct proc *));
502 void rxstrategy __P((struct buf *));
503 int rxread __P((dev_t, struct uio *));
504 int rxwrite __P((dev_t, struct uio *));
505 int rxioctl __P((dev_t, int, caddr_t, int, struct proc *));
506 int rxdump __P((dev_t, daddr_t, caddr_t, size_t));
507 int rxsize __P((dev_t));
508
509 struct cfattach rx_ca = {
510 sizeof(struct rx_softc), rxmatch, rxattach
511 };
512
513 /*
514 * More driver definitions, for generic MSCP code.
515 */
516
517 int
518 rxmatch(parent, cf, aux)
519 struct device *parent;
520 struct cfdata *cf;
521 void *aux;
522 {
523 struct drive_attach_args *da = aux;
524 struct mscp *mp = da->da_mp;
525
526 if ((da->da_typ & MSCPBUS_DISK) == 0)
527 return 0;
528 if (cf->cf_loc[MSCPBUSCF_DRIVE] != MSCPBUSCF_DRIVE_DEFAULT &&
529 cf->cf_loc[MSCPBUSCF_DRIVE] != mp->mscp_unit)
530 return 0;
531 /*
532 * Check if this disk is a floppy; then configure it.
533 * Seems to be a safe way to test it per Chris Torek.
534 */
535 if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@')
536 return 1;
537 return 0;
538 }
539
540 #endif /* NRX */
541
542 /*
543 * The attach routine only checks and prints drive type.
544 * Bringing the disk online is done when the disk is accessed
545 * the first time.
546 */
547 void
548 rxattach(parent, self, aux)
549 struct device *parent, *self;
550 void *aux;
551 {
552 struct rx_softc *rx = (void *)self;
553 struct drive_attach_args *da = aux;
554 struct mscp *mp = da->da_mp;
555 struct mscp_softc *mi = (void *)parent;
556 struct disklabel *dl;
557
558 rx->ra_mediaid = mp->mscp_guse.guse_mediaid;
559 rx->ra_state = DK_CLOSED;
560 rx->ra_hwunit = mp->mscp_unit;
561 mi->mi_dp[mp->mscp_unit] = self;
562
563 rx->ra_disk.dk_name = rx->ra_dev.dv_xname;
564 disk_attach((struct disk *)&rx->ra_disk);
565
566 /* Fill in what we know. The actual size is gotten later */
567 dl = rx->ra_disk.dk_label;
568
569 dl->d_secsize = DEV_BSIZE;
570 dl->d_nsectors = mp->mscp_guse.guse_nspt;
571 dl->d_ntracks = mp->mscp_guse.guse_ngpc * mp->mscp_guse.guse_group;
572 dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks;
573 disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid);
574 #ifdef DEBUG
575 printf("%s: nspt %d group %d ngpc %d rct %d nrpt %d nrct %d\n",
576 self->dv_xname, mp->mscp_guse.guse_nspt, mp->mscp_guse.guse_group,
577 mp->mscp_guse.guse_ngpc, mp->mscp_guse.guse_rctsize,
578 mp->mscp_guse.guse_nrpt, mp->mscp_guse.guse_nrct);
579 #endif
580 }
581
582 /*
583 * (Try to) put the drive online. This is done the first time the
584 * drive is opened, or if it har fallen offline.
585 */
586 int
587 rx_putonline(rx)
588 struct rx_softc *rx;
589 {
590 struct mscp *mp;
591 struct mscp_softc *mi = (struct mscp_softc *)rx->ra_dev.dv_parent;
592 volatile int i;
593
594 rx->ra_state = DK_CLOSED;
595 mp = mscp_getcp(mi, MSCP_WAIT);
596 mp->mscp_opcode = M_OP_ONLINE;
597 mp->mscp_unit = rx->ra_hwunit;
598 mp->mscp_cmdref = 1;
599 *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
600
601 /* Poll away */
602 i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
603 if (tsleep(&rx->ra_dev.dv_unit, PRIBIO, "rxonline", 100*100))
604 rx->ra_state = DK_CLOSED;
605
606 if (rx->ra_state == DK_CLOSED)
607 return MSCP_FAILED;
608
609 return MSCP_DONE;
610 }
611
612 #if NRX
613
614 /*
615 * Open a drive.
616 */
617 /*ARGSUSED*/
618 int
619 rxopen(dev, flag, fmt, p)
620 dev_t dev;
621 int flag, fmt;
622 struct proc *p;
623 {
624 struct rx_softc *rx;
625 int unit;
626
627 /*
628 * Make sure this is a reasonable open request.
629 */
630 unit = DISKUNIT(dev);
631 if (unit >= rx_cd.cd_ndevs)
632 return ENXIO;
633 rx = rx_cd.cd_devs[unit];
634 if (rx == 0)
635 return ENXIO;
636
637 /*
638 * If this is the first open; we must first try to put
639 * the disk online (and read the label).
640 */
641 if (rx->ra_state == DK_CLOSED)
642 if (rx_putonline(rx) == MSCP_FAILED)
643 return ENXIO;
644
645 return 0;
646 }
647
648 /* ARGSUSED */
649 int
650 rxclose(dev, flags, fmt, p)
651 dev_t dev;
652 int flags, fmt;
653 struct proc *p;
654 {
655 return (0);
656 }
657
658 /*
659 * Queue a transfer request, and if possible, hand it to the controller.
660 *
661 * This routine is broken into two so that the internal version
662 * udastrat1() can be called by the (nonexistent, as yet) bad block
663 * revectoring routine.
664 */
665 void
666 rxstrategy(bp)
667 struct buf *bp;
668 {
669 int unit;
670 struct rx_softc *rx;
671
672 /*
673 * Make sure this is a reasonable drive to use.
674 */
675 unit = DISKUNIT(bp->b_dev);
676 if (unit > rx_cd.cd_ndevs || (rx = rx_cd.cd_devs[unit]) == NULL) {
677 bp->b_error = ENXIO;
678 bp->b_flags |= B_ERROR;
679 goto done;
680 }
681
682 /* If disk is not online, try to put it online */
683 if (rx->ra_state == DK_CLOSED)
684 if (rx_putonline(rx) == MSCP_FAILED) {
685 bp->b_flags |= B_ERROR;
686 bp->b_error = EIO;
687 goto done;
688 }
689
690 /*
691 * Determine the size of the transfer, and make sure it is
692 * within the boundaries of the partition.
693 */
694 if (bp->b_blkno >= rx->ra_disk.dk_label->d_secperunit) {
695 bp->b_resid = bp->b_bcount;
696 goto done;
697 }
698
699 /* Make some statistics... /bqt */
700 rx->ra_disk.dk_xfer++;
701 rx->ra_disk.dk_bytes += bp->b_bcount;
702 mscp_strategy(bp, rx->ra_dev.dv_parent);
703 return;
704
705 done:
706 biodone(bp);
707 }
708
709 int
710 rxread(dev, uio)
711 dev_t dev;
712 struct uio *uio;
713 {
714
715 return (physio(rxstrategy, NULL, dev, B_READ, minphys, uio));
716 }
717
718 int
719 rxwrite(dev, uio)
720 dev_t dev;
721 struct uio *uio;
722 {
723
724 return (physio(rxstrategy, NULL, dev, B_WRITE, minphys, uio));
725 }
726
727 /*
728 * I/O controls.
729 */
730 int
731 rxioctl(dev, cmd, data, flag, p)
732 dev_t dev;
733 int cmd;
734 caddr_t data;
735 int flag;
736 struct proc *p;
737 {
738 int unit = DISKUNIT(dev);
739 struct disklabel *lp;
740 struct rx_softc *rx = rx_cd.cd_devs[unit];
741 int error = 0;
742
743 lp = rx->ra_disk.dk_label;
744
745 switch (cmd) {
746
747 case DIOCGDINFO:
748 bcopy(lp, data, sizeof (struct disklabel));
749 break;
750
751 case DIOCGPART:
752 ((struct partinfo *)data)->disklab = lp;
753 ((struct partinfo *)data)->part =
754 &lp->d_partitions[DISKPART(dev)];
755 break;
756
757
758 case DIOCWDINFO:
759 case DIOCSDINFO:
760 case DIOCWLABEL:
761 break;
762
763 default:
764 error = ENOTTY;
765 break;
766 }
767 return (error);
768 }
769
770 int
771 rxdump(dev, blkno, va, size)
772 dev_t dev;
773 daddr_t blkno;
774 caddr_t va;
775 size_t size;
776 {
777
778 /* Not likely. */
779 return ENXIO;
780 }
781
782 int
783 rxsize(dev)
784 dev_t dev;
785 {
786
787 return -1;
788 }
789
790 #endif /* NRX */
791
792 void rrdgram __P((struct device *, struct mscp *, struct mscp_softc *));
793 void rriodone __P((struct device *, struct buf *));
794 int rronline __P((struct device *, struct mscp *));
795 int rrgotstatus __P((struct device *, struct mscp *));
796 void rrreplace __P((struct device *, struct mscp *));
797 int rrioerror __P((struct device *, struct mscp *, struct buf *));
798 void rrfillin __P((struct buf *, struct mscp *));
799 void rrbb __P((struct device *, struct mscp *, struct buf *));
800
801
802 struct mscp_device ra_device = {
803 rrdgram,
804 rriodone,
805 rronline,
806 rrgotstatus,
807 rrreplace,
808 rrioerror,
809 rrbb,
810 rrfillin,
811 };
812
813 /*
814 * Handle an error datagram.
815 * This can come from an unconfigured drive as well.
816 */
817 void
818 rrdgram(usc, mp, mi)
819 struct device *usc;
820 struct mscp *mp;
821 struct mscp_softc *mi;
822 {
823 if (mscp_decodeerror(usc == NULL?"unconf disk" : usc->dv_xname, mp, mi))
824 return;
825 /*
826 * SDI status information bytes 10 and 11 are the microprocessor
827 * error code and front panel code respectively. These vary per
828 * drive type and are printed purely for field service information.
829 */
830 if (mp->mscp_format == M_FM_SDI)
831 printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n",
832 mp->mscp_erd.erd_sdistat[10],
833 mp->mscp_erd.erd_sdistat[11]);
834 }
835
836 void
837 rriodone(usc, bp)
838 struct device *usc;
839 struct buf *bp;
840 {
841
842 biodone(bp);
843 }
844
845 /*
846 * A drive came on line. Check its type and size. Return DONE if
847 * we think the drive is truly on line. In any case, awaken anyone
848 * sleeping on the drive on-line-ness.
849 */
850 int
851 rronline(usc, mp)
852 struct device *usc;
853 struct mscp *mp;
854 {
855 struct rx_softc *rx = (struct rx_softc *)usc;
856 struct disklabel *dl;
857
858 wakeup((caddr_t)&usc->dv_unit);
859 if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
860 printf("%s: attempt to bring on line failed: ", usc->dv_xname);
861 mscp_printevent(mp);
862 return (MSCP_FAILED);
863 }
864
865 rx->ra_state = DK_OPEN;
866
867 dl = rx->ra_disk.dk_label;
868 dl->d_secperunit = (daddr_t)mp->mscp_onle.onle_unitsize;
869
870 if (dl->d_secpercyl) {
871 dl->d_ncylinders = dl->d_secperunit/dl->d_secpercyl;
872 dl->d_type = DTYPE_MSCP;
873 dl->d_rpm = 3600;
874 } else {
875 dl->d_type = DTYPE_FLOPPY;
876 dl->d_rpm = 300;
877 }
878 rrmakelabel(dl, rx->ra_mediaid);
879
880 return (MSCP_DONE);
881 }
882
883 void
884 rrmakelabel(dl, type)
885 struct disklabel *dl;
886 long type;
887 {
888 int n, p = 0;
889
890 dl->d_bbsize = BBSIZE;
891 dl->d_sbsize = SBSIZE;
892
893 /* Create the disk name for disklabel. Phew... */
894 dl->d_typename[p++] = MSCP_MID_CHAR(2, type);
895 dl->d_typename[p++] = MSCP_MID_CHAR(1, type);
896 if (MSCP_MID_ECH(0, type))
897 dl->d_typename[p++] = MSCP_MID_CHAR(0, type);
898 n = MSCP_MID_NUM(type);
899 if (n > 99) {
900 dl->d_typename[p++] = '1';
901 n -= 100;
902 }
903 if (n > 9) {
904 dl->d_typename[p++] = (n / 10) + '0';
905 n %= 10;
906 }
907 dl->d_typename[p++] = n + '0';
908 dl->d_typename[p] = 0;
909 dl->d_npartitions = MAXPARTITIONS;
910 dl->d_partitions[0].p_size = dl->d_partitions[2].p_size =
911 dl->d_secperunit;
912 dl->d_partitions[0].p_offset = dl->d_partitions[2].p_offset = 0;
913 dl->d_interleave = dl->d_headswitch = 1;
914 dl->d_magic = dl->d_magic2 = DISKMAGIC;
915 dl->d_checksum = dkcksum(dl);
916 }
917
918 /*
919 * We got some (configured) unit's status. Return DONE if it succeeded.
920 */
921 int
922 rrgotstatus(usc, mp)
923 struct device *usc;
924 struct mscp *mp;
925 {
926 if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
927 printf("%s: attempt to get status failed: ", usc->dv_xname);
928 mscp_printevent(mp);
929 return (MSCP_FAILED);
930 }
931 /* record for (future) bad block forwarding and whatever else */
932 #ifdef notyet
933 uda_rasave(ui->ui_unit, mp, 1);
934 #endif
935 return (MSCP_DONE);
936 }
937
938 /*
939 * A replace operation finished.
940 */
941 /*ARGSUSED*/
942 void
943 rrreplace(usc, mp)
944 struct device *usc;
945 struct mscp *mp;
946 {
947
948 panic("udareplace");
949 }
950
951 /*
952 * A transfer failed. We get a chance to fix or restart it.
953 * Need to write the bad block forwaring code first....
954 */
955 /*ARGSUSED*/
956 int
957 rrioerror(usc, mp, bp)
958 struct device *usc;
959 struct mscp *mp;
960 struct buf *bp;
961 {
962 struct ra_softc *ra = (void *)usc;
963 int code = mp->mscp_event;
964
965 switch (code & M_ST_MASK) {
966 /* The unit has fallen offline. Try to figure out why. */
967 case M_ST_OFFLINE:
968 bp->b_flags |= B_ERROR;
969 bp->b_error = EIO;
970 ra->ra_state = DK_CLOSED;
971 if (code & M_OFFLINE_UNMOUNTED)
972 printf("%s: not mounted/spun down\n", usc->dv_xname);
973 if (code & M_OFFLINE_DUPLICATE)
974 printf("%s: duplicate unit number!!!\n", usc->dv_xname);
975 return MSCP_DONE;
976
977 case M_ST_AVAILABLE:
978 ra->ra_state = DK_CLOSED; /* Force another online */
979 return MSCP_DONE;
980
981 default:
982 printf("%s:", usc->dv_xname);
983 break;
984 }
985 return (MSCP_FAILED);
986 }
987
988 /*
989 * Fill in disk addresses in a mscp packet waiting for transfer.
990 */
991 void
992 rrfillin(bp, mp)
993 struct buf *bp;
994 struct mscp *mp;
995 {
996 struct rx_softc *rx = 0; /* Wall */
997 struct disklabel *lp;
998 int unit = DISKUNIT(bp->b_dev);
999 int part = DISKPART(bp->b_dev);
1000
1001 #if NRA
1002 if (major(bp->b_dev) == RAMAJOR)
1003 rx = ra_cd.cd_devs[unit];
1004 #endif
1005 #if NRX
1006 if (major(bp->b_dev) != RAMAJOR)
1007 rx = rx_cd.cd_devs[unit];
1008 #endif
1009 lp = rx->ra_disk.dk_label;
1010
1011 mp->mscp_seq.seq_lbn = lp->d_partitions[part].p_offset + bp->b_blkno;
1012 mp->mscp_unit = rx->ra_hwunit;
1013 mp->mscp_seq.seq_bytecount = bp->b_bcount;
1014 }
1015
1016 /*
1017 * A bad block related operation finished.
1018 */
1019 /*ARGSUSED*/
1020 void
1021 rrbb(usc, mp, bp)
1022 struct device *usc;
1023 struct mscp *mp;
1024 struct buf *bp;
1025 {
1026
1027 panic("udabb");
1028 }
1029