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