mscp_disk.c revision 1.25 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