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