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