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