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