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