mscp_disk.c revision 1.23 1 /* $NetBSD: mscp_disk.c,v 1.23 2000/03/30 12:45:34 augustss 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 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 int unit = DISKUNIT(dev);
270 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 struct buf *bp;
307 {
308 int unit;
309 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 int unit = DISKUNIT(dev);
383 struct disklabel *lp, *tp;
384 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 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 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 struct buf *bp;
650 {
651 int unit;
652 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 int unit = DISKUNIT(dev);
721 struct disklabel *lp;
722 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 struct device *usc;
906 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 struct device *usc;
941 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