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