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