|
|
1.1 root 1: /*
2: * Copyright (c) 1988 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Harris Corp.
7: *
8: * Redistribution is only permitted until one year after the first shipment
9: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
10: * binary forms are permitted provided that: (1) source distributions retain
11: * this entire copyright notice and comment, and (2) distributions including
12: * binaries display the following acknowledgement: This product includes
13: * software developed by the University of California, Berkeley and its
14: * contributors'' in the documentation or other materials provided with the
15: * distribution and in all advertising materials mentioning features or use
16: * of this software. Neither the name of the University nor the names of
17: * its contributors may be used to endorse or promote products derived from
18: * this software without specific prior written permission.
19: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22: *
23: * @(#)hd.c 7.11 (Berkeley) 6/28/90
24: */
25:
26: #include "hd.h"
27:
28: #if NHD > 0
29: #include "param.h"
30: #include "buf.h"
31: #include "conf.h"
32: #include "dkstat.h"
33: #include "disklabel.h"
34: #include "file.h"
35: #include "systm.h"
36: #include "vmmac.h"
37: #include "time.h"
38: #include "proc.h"
39: #include "uio.h"
40: #include "syslog.h"
41: #include "kernel.h"
42: #include "ioctl.h"
43: #include "stat.h"
44: #include "errno.h"
45:
46: #include "../tahoe/cpu.h"
47: #include "../tahoe/mtpr.h"
48:
49: #include "../tahoevba/vbavar.h"
50: #include "../tahoevba/hdreg.h"
51:
52: #define b_cylin b_resid
53:
54: #define hdunit(dev) (minor(dev)>>3)
55: #define hdpart(dev) (minor(dev)&0x07)
56: #define hdminor(unit, part) (((unit)<<3)|(part))
57:
58: struct vba_ctlr *hdcminfo[NHDC];
59: struct vba_device *hddinfo[NHD];
60: int hdcprobe(), hdslave(), hdattach(), hddgo(), hdstrategy();
61: long hdstd[] = { 0 };
62: struct vba_driver hdcdriver =
63: { hdcprobe, hdslave, hdattach, hddgo, hdstd, "hd", hddinfo, "hdc", hdcminfo };
64:
65: /*
66: * Per-controller state.
67: */
68: struct hdcsoftc {
69: u_short hdc_flags;
70: #define HDC_INIT 0x01 /* controller initialized */
71: #define HDC_STARTED 0x02 /* start command issued */
72: #define HDC_LOCKED 0x04 /* locked for direct controller access */
73: #define HDC_WAIT 0x08 /* someone needs direct controller access */
74: u_short hdc_wticks; /* timeout */
75: struct master_mcb *hdc_mcbp; /* address of controller mcb */
76: struct registers *hdc_reg; /* base address of i/o regs */
77: struct vb_buf hdc_rbuf; /* vba resources */
78: struct master_mcb hdc_mcb; /* controller mcb */
79: } hdcsoftc[NHDC];
80:
81: #define HDCMAXTIME 20 /* max time for operation, sec. */
82: #define HDCINTERRUPT 0xf0 /* interrupt vector */
83:
84: /*
85: * Per-drive state; probably everything should be "hd_", not "dk_",
86: * but it's not worth it, and dk is a better mnemonic for disk anyway.
87: */
88: struct dksoftc {
89: #ifdef COMPAT_42
90: u_short dk_def_cyl; /* definition track cylinder address */
91: #endif
92: int dk_state; /* open fsm */
93: u_short dk_bshift; /* shift for * (DEV_BSIZE / sectorsize) XXX */
94: int dk_wlabel; /* if label sector is writeable */
95: u_long dk_copenpart; /* character units open on this drive */
96: u_long dk_bopenpart; /* block units open on this drive */
97: u_long dk_openpart; /* all units open on this drive */
98: int dk_unit; /* unit# */
99: int dk_ctlr; /* controller# */
100: int dk_format; /* if format program is using disk */
101: struct buf dk_utab; /* i/o queue header */
102: struct disklabel dk_label; /* disklabel for this disk */
103: struct mcb dk_mcb; /* disk mcb */
104: } dksoftc[NHD];
105:
106: /*
107: * Drive states. Used during steps of open/initialization.
108: * States < OPEN (> 0) are transient, during an open operation.
109: * OPENRAW is used for unlabeled disks, to allow format operations.
110: */
111: #define CLOSED 0 /* disk is closed */
112: #define WANTOPEN 1 /* open requested, not started */
113: #define WANTOPENRAW 2 /* open requested, no label */
114: #define RDLABEL 3 /* reading pack label */
115: #define OPEN 4 /* intialized and ready */
116: #define OPENRAW 5 /* open, no label */
117:
118: int hdcwstart, hdcwatch();
119:
120: /* see if the controller is really there, if so, init it. */
121: /* ARGSUSED */
122: hdcprobe(reg, vm)
123: caddr_t reg;
124: /* register */ struct vba_ctlr *vm;
125: {
126: register int br, cvec; /* must be r12, r11 */
127: register struct hdcsoftc *hdc;
128: static struct module_id id;
129: struct pte *dummypte;
130: caddr_t putl;
131:
132: /* initialize the hdc controller structure. */
133: hdc = &hdcsoftc[vm->um_ctlr];
134: if (!vbmemalloc(1, reg, &dummypte, &putl)) {
135: printf("hdc%d: vbmemalloc failed.\n", vm->um_ctlr);
136: return(0);
137: }
138: hdc->hdc_reg = (struct registers *)putl;
139:
140: /*
141: * try and ping the MID register; side effect of wbadaddr is to read
142: * the module id; the controller is bad if it's not an hdc, the hdc's
143: * writeable control store is not loaded, or the hdc failed the
144: * functional integrity test;
145: */
146: if (wbadaddr(&hdc->hdc_reg->module_id, 4,
147: vtoph((struct process *)NULL, &id)))
148: return(0);
149: DELAY(10000);
150: mtpr(PADC, 0);
151: if (id.module_id != (u_char)HDC_MID) {
152: printf("hdc%d: bad module id; id = %x.\n",
153: vm->um_ctlr, id.module_id);
154: return(0);
155: }
156: if (id.code_rev == (u_char)0xff) {
157: printf("hdc%d: micro-code not loaded.\n", vm->um_ctlr);
158: return(0);
159: }
160: if (id.fit != (u_char)0xff) {
161: printf("hdc%d: FIT test failed.\n", vm->um_ctlr);
162: return(0);
163: }
164:
165: /* reset that pup; flag as inited */
166: hdc->hdc_reg->soft_reset = 0;
167: DELAY(1000000);
168: hdc->hdc_flags |= HDC_INIT;
169:
170: /* allocate page tables and i/o buffer. */
171: if (!vbainit(&hdc->hdc_rbuf, MAXPHYS, VB_32BIT|VB_SCATTER)) {
172: printf("hdc%d: vbainit failed\n", vm->um_ctlr);
173: return (0);
174: }
175:
176: /* set pointer to master control block */
177: hdc->hdc_mcbp =
178: (struct master_mcb *)vtoph((struct proc *)NULL, &hdc->hdc_mcb);
179:
180: br = 0x17, cvec = HDCINTERRUPT + vm->um_ctlr; /* XXX */
181: return(sizeof(struct registers));
182: }
183:
184: /* ARGSUSED */
185: hdslave(vi, vdaddr)
186: struct vba_device *vi;
187: struct vddevice *vdaddr;
188: {
189: register struct mcb *mcb;
190: register struct disklabel *lp;
191: register struct dksoftc *dk;
192: static struct status status;
193:
194: dk = &dksoftc[vi->ui_unit];
195: dk->dk_unit = vi->ui_unit;
196: dk->dk_ctlr = vi->ui_ctlr;
197:
198: mcb = &dk->dk_mcb;
199: mcb->command = HCMD_STATUS;
200: mcb->chain[0].wcount = sizeof(struct status) / sizeof(long);
201: mcb->chain[0].memadr = (u_long)vtoph((struct process *)0, &status);
202: if (hdimcb(dk)) {
203: printf(" (no status)\n");
204: return(0);
205: }
206:
207: /*
208: * Report the drive down if anything in the drive status looks bad.
209: * If the drive is offline and it is not on cylinder, then the drive
210: * is not there. If there is a fault condition, the hdc will try to
211: * clear it when we read the disklabel information.
212: */
213: if (!(status.drs&DRS_ONLINE)) {
214: if (status.drs&DRS_ON_CYLINDER)
215: printf(" (not online)\n");
216: return(0);
217: }
218: if (status.drs&DRS_FAULT)
219: printf(" (clearing fault)");
220:
221: lp = &dk->dk_label;
222: #ifdef RAW_SIZE
223: lp->d_secsize = status.bytes_per_sec;
224: #else
225: lp->d_secsize = 512;
226: #endif
227: lp->d_nsectors = status.max_sector + 1;
228: lp->d_ntracks = status.max_head + 1;
229: lp->d_ncylinders = status.max_cyl + 1;
230: lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
231: lp->d_npartitions = 1;
232: lp->d_partitions[0].p_offset = 0;
233: lp->d_partitions[0].p_size = LABELSECTOR + 1;
234: lp->d_rpm = status.rpm;
235: lp->d_typename[0] = 'h';
236: lp->d_typename[1] = 'd';
237: lp->d_typename[2] = '\0';
238: #ifdef COMPAT_42
239: dk->dk_def_cyl = status.def_cyl;
240: #endif
241: return(1);
242: }
243:
244: hdattach(vi)
245: register struct vba_device *vi;
246: {
247: register struct dksoftc *dk;
248: register struct disklabel *lp;
249: register int unit;
250:
251: unit = vi->ui_unit;
252: if (hdinit(hdminor(unit, 0), 0)) {
253: printf(": unknown drive type");
254: return;
255: }
256: dk = &dksoftc[unit];
257: lp = &dk->dk_label;
258: hd_setsecsize(dk, lp);
259: if (dk->dk_state == OPEN)
260: printf(": %s <secsize %d, ntrak %d, ncyl %d, nsec %d>",
261: lp->d_typename, lp->d_secsize, lp->d_ntracks,
262: lp->d_ncylinders, lp->d_nsectors);
263:
264: /*
265: * (60 / rpm) / (sectors per track * (bytes per sector / 2))
266: */
267: if (vi->ui_dk >= 0)
268: dk_wpms[vi->ui_dk] =
269: (lp->d_rpm * lp->d_nsectors * lp->d_secsize) / 120;
270: #ifdef notyet
271: addswap(makedev(HDMAJOR, hdminor(unit, 0)), lp);
272: #endif
273: }
274:
275: hdopen(dev, flags, fmt)
276: dev_t dev;
277: int flags, fmt;
278: {
279: register struct disklabel *lp;
280: register struct dksoftc *dk;
281: register struct partition *pp;
282: register int unit;
283: struct vba_device *vi;
284: int s, error, part = hdpart(dev), mask = 1 << part;
285: daddr_t start, end;
286:
287: unit = hdunit(dev);
288: if (unit >= NHD || (vi = hddinfo[unit]) == 0 || vi->ui_alive == 0)
289: return(ENXIO);
290: dk = &dksoftc[unit];
291: lp = &dk->dk_label;
292: s = spl7();
293: while (dk->dk_state != OPEN && dk->dk_state != OPENRAW &&
294: dk->dk_state != CLOSED)
295: if (error = tsleep((caddr_t)dk, (PZERO+1) | PCATCH,
296: devopn, 0)) {
297: splx(s);
298: return (error);
299: }
300: splx(s);
301: if (dk->dk_state != OPEN && dk->dk_state != OPENRAW)
302: if (error = hdinit(dev, flags))
303: return(error);
304:
305: if (hdcwstart == 0) {
306: timeout(hdcwatch, (caddr_t)0, hz);
307: hdcwstart++;
308: }
309: /*
310: * Warn if a partion is opened that overlaps another partition
311: * which is open unless one is the "raw" partition (whole disk).
312: */
313: #define RAWPART 8 /* 'x' partition */ /* XXX */
314: if ((dk->dk_openpart & mask) == 0 && part != RAWPART) {
315: pp = &lp->d_partitions[part];
316: start = pp->p_offset;
317: end = pp->p_offset + pp->p_size;
318: for (pp = lp->d_partitions;
319: pp < &lp->d_partitions[lp->d_npartitions]; pp++) {
320: if (pp->p_offset + pp->p_size <= start ||
321: pp->p_offset >= end)
322: continue;
323: if (pp - lp->d_partitions == RAWPART)
324: continue;
325: if (dk->dk_openpart & (1 << (pp - lp->d_partitions)))
326: log(LOG_WARNING,
327: "hd%d%c: overlaps open partition (%c)\n",
328: unit, part + 'a',
329: pp - lp->d_partitions + 'a');
330: }
331: }
332: if (part >= lp->d_npartitions)
333: return(ENXIO);
334: dk->dk_openpart |= mask;
335: switch (fmt) {
336: case S_IFCHR:
337: dk->dk_copenpart |= mask;
338: break;
339: case S_IFBLK:
340: dk->dk_bopenpart |= mask;
341: break;
342: }
343: return(0);
344: }
345:
346: /* ARGSUSED */
347: hdclose(dev, flags, fmt)
348: dev_t dev;
349: int flags, fmt;
350: {
351: register struct dksoftc *dk;
352: int mask;
353:
354: dk = &dksoftc[hdunit(dev)];
355: mask = 1 << hdpart(dev);
356: switch (fmt) {
357: case S_IFCHR:
358: dk->dk_copenpart &= ~mask;
359: break;
360: case S_IFBLK:
361: dk->dk_bopenpart &= ~mask;
362: break;
363: }
364: if (((dk->dk_copenpart | dk->dk_bopenpart) & mask) == 0)
365: dk->dk_openpart &= ~mask;
366: /*
367: * Should wait for i/o to complete on this partition
368: * even if others are open, but wait for work on blkflush().
369: */
370: if (dk->dk_openpart == 0) {
371: int s = spl7();
372: while (dk->dk_utab.b_actf)
373: sleep((caddr_t)dk, PZERO-1);
374: splx(s);
375: dk->dk_state = CLOSED;
376: dk->dk_wlabel = 0;
377: }
378: return(0);
379: }
380:
381: hdinit(dev, flags)
382: dev_t dev;
383: int flags;
384: {
385: register struct dksoftc *dk;
386: register struct disklabel *lp;
387: struct vba_device *vi;
388: int error, unit;
389: char *msg, *readdisklabel();
390: extern int cold;
391:
392: vi = hddinfo[unit = hdunit(dev)];
393: dk = &dksoftc[unit];
394: dk->dk_unit = vi->ui_slave;
395: dk->dk_ctlr = vi->ui_ctlr;
396:
397: if (flags & O_NDELAY) {
398: dk->dk_state = OPENRAW;
399: return(0);
400: }
401:
402: error = 0;
403: lp = &dk->dk_label;
404: dk->dk_state = RDLABEL;
405: if (msg = readdisklabel(dev, hdstrategy, lp)) {
406: if (cold) {
407: printf(": %s\n", msg);
408: dk->dk_state = CLOSED;
409: } else {
410: log(LOG_ERR, "hd%d: %s\n", unit, msg);
411: dk->dk_state = OPENRAW;
412: }
413: #ifdef COMPAT_42
414: hdclock(vi->ui_ctlr);
415: if (!(error = hdreadgeometry(dk)))
416: dk->dk_state = OPEN;
417: hdcunlock(vi->ui_ctlr);
418: #endif
419: } else
420: dk->dk_state = OPEN;
421: wakeup((caddr_t)dk);
422: return(error);
423: }
424:
425: hd_setsecsize(dk, lp)
426: register struct dksoftc *dk;
427: struct disklabel *lp;
428: {
429: register int mul;
430:
431: /*
432: * Calculate scaling shift for mapping
433: * DEV_BSIZE blocks to drive sectors.
434: */
435: mul = DEV_BSIZE / lp->d_secsize;
436: dk->dk_bshift = 0;
437: while ((mul >>= 1) > 0)
438: dk->dk_bshift++;
439: }
440:
441: /* ARGSUSED */
442: hddgo(vm)
443: struct vba_device *vm;
444: {}
445:
446: extern int name_ext;
447: hdstrategy(bp)
448: register struct buf *bp;
449: {
450: register struct vba_device *vi;
451: register struct disklabel *lp;
452: register struct dksoftc *dk;
453: struct buf *dp;
454: register int unit;
455: daddr_t sn, sz, maxsz;
456: int part, s;
457:
458: vi = hddinfo[unit = hdunit(bp->b_dev)];
459: if (unit >= NHD || vi == 0 || vi->ui_alive == 0) {
460: bp->b_error = ENXIO;
461: goto bad;
462: }
463: dk = &dksoftc[unit];
464: if (dk->dk_state < OPEN)
465: goto q;
466: if (dk->dk_state != OPEN && (bp->b_flags & B_READ) == 0) {
467: bp->b_error = EROFS;
468: goto bad;
469: }
470: part = hdpart(bp->b_dev);
471: if ((dk->dk_openpart & (1 << part)) == 0) {
472: bp->b_error = ENODEV;
473: goto bad;
474: }
475: lp = &dk->dk_label;
476: sz = (bp->b_bcount + lp->d_secsize - 1) / lp->d_secsize;
477: maxsz = lp->d_partitions[part].p_size;
478: sn = bp->b_blkno << dk->dk_bshift;
479: if (sn + lp->d_partitions[part].p_offset <= LABELSECTOR &&
480: #if LABELSECTOR != 0
481: sn + lp->d_partitions[part].p_offset + sz > LABELSECTOR &&
482: #endif
483: (bp->b_flags & B_READ) == 0 && dk->dk_wlabel == 0) {
484: bp->b_error = EROFS;
485: goto bad;
486: }
487: if (sn < 0 || sn + sz > maxsz) {
488: if (sn == maxsz) {
489: bp->b_resid = bp->b_bcount;
490: goto done;
491: }
492: sz = maxsz - sn;
493: if (sz <= 0) {
494: bp->b_error = EINVAL;
495: goto bad;
496: }
497: bp->b_bcount = sz * lp->d_secsize;
498: }
499: bp->b_cylin = (sn + lp->d_partitions[part].p_offset) / lp->d_secpercyl;
500:
501: q: s = spl7();
502: dp = &dk->dk_utab;
503: disksort(dp, bp);
504: if (!dp->b_active) {
505: (void)hdustart(vi);
506: if (!vi->ui_mi->um_tab.b_active)
507: hdcstart(vi->ui_mi);
508: }
509: splx(s);
510: return;
511: bad:
512: bp->b_flags |= B_ERROR;
513: done:
514: biodone(bp);
515: }
516:
517: hdustart(vi)
518: register struct vba_device *vi;
519: {
520: register struct buf *bp, *dp;
521: register struct vba_ctlr *vm;
522: register struct dksoftc *dk;
523:
524: dk = &dksoftc[vi->ui_unit];
525: dp = &dk->dk_utab;
526:
527: /* if queue empty, nothing to do. impossible? */
528: if (dp->b_actf == NULL)
529: return;
530:
531: /* place on controller transfer queue */
532: vm = vi->ui_mi;
533: if (vm->um_tab.b_actf == NULL)
534: vm->um_tab.b_actf = dp;
535: else
536: vm->um_tab.b_actl->b_forw = dp;
537: vm->um_tab.b_actl = dp;
538: dp->b_forw = NULL;
539: dp->b_active++;
540: }
541:
542: hdcstart(vm)
543: register struct vba_ctlr *vm;
544: {
545: register struct buf *bp;
546: register struct dksoftc *dk;
547: register struct disklabel *lp;
548: register struct master_mcb *master;
549: register struct mcb *mcb;
550: struct vba_device *vi;
551: struct hdcsoftc *hdc;
552: struct buf *dp;
553: int sn;
554:
555: /* pull a request off the controller queue */
556: for (;;) {
557: if ((dp = vm->um_tab.b_actf) == NULL)
558: return;
559: if (bp = dp->b_actf)
560: break;
561: vm->um_tab.b_actf = dp->b_forw;
562: }
563:
564: /* mark controller active */
565: vm->um_tab.b_active++;
566:
567: vi = hddinfo[hdunit(bp->b_dev)];
568: dk = &dksoftc[vi->ui_unit];
569: lp = &dk->dk_label;
570: sn = bp->b_blkno << dk->dk_bshift;
571:
572: /* fill in mcb */
573: mcb = &dk->dk_mcb;
574: mcb->forw_phaddr = 0;
575: /* mcb->priority = 0; */
576: mcb->interrupt = 1;
577: mcb->command = (bp->b_flags & B_READ) ? HCMD_READ:HCMD_WRITE;
578: mcb->cyl = bp->b_cylin;
579: /* assumes partition starts on cylinder boundary */
580: mcb->head = (sn / lp->d_nsectors) % lp->d_ntracks;
581: mcb->sector = sn % lp->d_nsectors;
582: mcb->drive = vi->ui_slave;
583: /* mcb->context = 0; /* what do we want on interrupt? */
584:
585: hdc = &hdcsoftc[vm->um_ctlr];
586: if (!hd_sgsetup(bp, &hdc->hdc_rbuf, mcb->chain)) {
587: mcb->chain[0].wcount = (bp->b_bcount+3) >> 2;
588: mcb->chain[0].memadr =
589: vbasetup(bp, &hdc->hdc_rbuf, (int)lp->d_secsize);
590: }
591:
592: if (vi->ui_dk >= 0) {
593: dk_busy |= 1<<vi->ui_dk;
594: dk_xfer[vi->ui_dk]++;
595: dk_wds[vi->ui_dk] += bp->b_bcount>>6;
596: }
597:
598: master = &hdc->hdc_mcb;
599: master->mcw = MCL_QUEUED;
600: master->interrupt = HDCINTERRUPT + vm->um_ctlr;
601: master->forw_phaddr = (u_long)vtoph((struct proc *)NULL, mcb);
602: hdc->hdc_reg->master_mcb = (u_long)hdc->hdc_mcbp;
603: }
604:
605: /*
606: * Wait for controller to finish current operation
607: * so that direct controller accesses can be done.
608: */
609: hdclock(ctlr)
610: int ctlr;
611: {
612: register struct vba_ctlr *vm = hdcminfo[ctlr];
613: register struct hdcsoftc *hdc;
614: int s;
615:
616: hdc = &hdcsoftc[ctlr];
617: s = spl7();
618: while (vm->um_tab.b_active || hdc->hdc_flags & HDC_LOCKED) {
619: hdc->hdc_flags |= HDC_WAIT;
620: sleep((caddr_t)hdc, PRIBIO);
621: }
622: hdc->hdc_flags |= HDC_LOCKED;
623: splx(s);
624: }
625:
626: /*
627: * Continue normal operations after pausing for
628: * munging the controller directly.
629: */
630: hdcunlock(ctlr)
631: int ctlr;
632: {
633: register struct vba_ctlr *vm;
634: register struct hdcsoftc *hdc = &hdcsoftc[ctlr];
635:
636: hdc->hdc_flags &= ~HDC_LOCKED;
637: if (hdc->hdc_flags & HDC_WAIT) {
638: hdc->hdc_flags &= ~HDC_WAIT;
639: wakeup((caddr_t)hdc);
640: } else {
641: vm = hdcminfo[ctlr];
642: if (vm->um_tab.b_actf)
643: hdcstart(vm);
644: }
645: }
646:
647: hdintr(ctlr)
648: int ctlr;
649: {
650: register struct buf *bp, *dp;
651: register struct vba_ctlr *vm;
652: register struct vba_device *vi;
653: register struct hdcsoftc *hdc;
654: register struct mcb *mcb;
655: struct master_mcb *master;
656: register int status;
657: int timedout;
658: struct dksoftc *dk;
659:
660: hdc = &hdcsoftc[ctlr];
661: master = &hdc->hdc_mcb;
662: uncache(&master->mcs);
663: uncache(&master->context);
664:
665: vm = hdcminfo[ctlr];
666: if (!vm->um_tab.b_active || !(master->mcs&MCS_DONE)) {
667: printf("hd%d: stray interrupt\n", ctlr);
668: return;
669: }
670:
671: dp = vm->um_tab.b_actf;
672: bp = dp->b_actf;
673: vi = hddinfo[hdunit(bp->b_dev)];
674: dk = &dksoftc[vi->ui_unit];
675: if (vi->ui_dk >= 0)
676: dk_busy &= ~(1<<vi->ui_dk);
677: timedout = (hdc->hdc_wticks >= HDCMAXTIME);
678:
679: mcb = &dk->dk_mcb;
680:
681: if (master->mcs & (MCS_SOFTERROR | MCS_FATALERROR) || timedout)
682: hdcerror(ctlr, *(u_long *)master->xstatus);
683: else
684: hdc->hdc_wticks = 0;
685: if (vm->um_tab.b_active) {
686: vm->um_tab.b_active = 0;
687: vm->um_tab.b_actf = dp->b_forw;
688: dp->b_active = 0;
689: dp->b_errcnt = 0;
690: dp->b_actf = bp->av_forw;
691: bp->b_resid = 0;
692: vbadone(bp, &hdc->hdc_rbuf);
693: biodone(bp);
694: /* start up now, if more work to do */
695: if (dp->b_actf)
696: hdustart(vi);
697: else if (dk->dk_openpart == 0)
698: wakeup((caddr_t)dk);
699: }
700: /* if there are devices ready to transfer, start the controller. */
701: if (hdc->hdc_flags & HDC_WAIT) {
702: hdc->hdc_flags &= ~HDC_WAIT;
703: wakeup((caddr_t)hdc);
704: } else if (vm->um_tab.b_actf)
705: hdcstart(vm);
706: }
707:
708: hdioctl(dev, cmd, data, flag)
709: dev_t dev;
710: int cmd, flag;
711: caddr_t data;
712: {
713: register int unit;
714: register struct dksoftc *dk;
715: register struct disklabel *lp;
716: int error;
717:
718: unit = hdunit(dev);
719: dk = &dksoftc[unit];
720: lp = &dk->dk_label;
721: error = 0;
722: switch (cmd) {
723: case DIOCGDINFO:
724: *(struct disklabel *)data = *lp;
725: break;
726: case DIOCGPART:
727: ((struct partinfo *)data)->disklab = lp;
728: ((struct partinfo *)data)->part =
729: &lp->d_partitions[hdpart(dev)];
730: break;
731: case DIOCSDINFO:
732: if ((flag & FWRITE) == 0)
733: error = EBADF;
734: else
735: error = setdisklabel(lp, (struct disklabel *)data,
736: (dk->dk_state == OPENRAW) ? 0 : dk->dk_openpart);
737: if (error == 0 && dk->dk_state == OPENRAW)
738: dk->dk_state = OPEN;
739: break;
740: case DIOCWLABEL:
741: if ((flag & FWRITE) == 0)
742: error = EBADF;
743: else
744: dk->dk_wlabel = *(int *)data;
745: break;
746: case DIOCWDINFO:
747: if ((flag & FWRITE) == 0)
748: error = EBADF;
749: else if ((error = setdisklabel(lp, (struct disklabel *)data,
750: (dk->dk_state == OPENRAW) ? 0 : dk->dk_openpart)) == 0) {
751: int wlab;
752:
753: if (error == 0 && dk->dk_state == OPENRAW)
754: dk->dk_state = OPEN;
755: /* simulate opening partition 0 so write succeeds */
756: dk->dk_openpart |= (1 << 0); /* XXX */
757: wlab = dk->dk_wlabel;
758: dk->dk_wlabel = 1;
759: error = writedisklabel(dev, hdstrategy, lp);
760: dk->dk_openpart = dk->dk_copenpart | dk->dk_bopenpart;
761: dk->dk_wlabel = wlab;
762: }
763: break;
764: default:
765: error = ENOTTY;
766: break;
767: }
768: return (error);
769: }
770:
771: /*
772: * Watch for lost interrupts.
773: */
774: hdcwatch()
775: {
776: register struct hdcsoftc *hdc;
777: register struct vba_ctlr **vmp;
778: register int ctlr;
779: int s;
780:
781: timeout(hdcwatch, (caddr_t)0, hz);
782: for (vmp = hdcminfo, hdc = hdcsoftc, ctlr = 0; ctlr < NHDC;
783: ++ctlr, ++vmp, ++hdc) {
784: if (*vmp == 0 || (*vmp)->um_alive == 0)
785: continue;
786: s = spl7();
787: if ((*vmp)->um_tab.b_active &&
788: hdc->hdc_wticks++ >= HDCMAXTIME) {
789: printf("hd%d: lost interrupt\n", ctlr);
790: hdintr(ctlr);
791: }
792: splx(s);
793: }
794: }
795:
796: hddump(dev)
797: dev_t dev;
798: {
799: return(ENXIO);
800: }
801:
802: hdsize(dev)
803: dev_t dev;
804: {
805: register int unit = hdunit(dev);
806: register struct dksoftc *dk;
807: struct vba_device *vi;
808: struct disklabel *lp;
809:
810: if (unit >= NHD || (vi = hddinfo[unit]) == 0 || vi->ui_alive == 0 ||
811: (dk = &dksoftc[unit])->dk_state != OPEN)
812: return (-1);
813: lp = &dk->dk_label;
814: return ((int)lp->d_partitions[hdpart(dev)].p_size >> dk->dk_bshift);
815: }
816:
817: hdimcb(dk)
818: register struct dksoftc *dk;
819: {
820: register struct master_mcb *master;
821: register struct mcb *mcb;
822: register struct hdcsoftc *hdc;
823: int timeout;
824:
825: /* fill in mcb */
826: mcb = &dk->dk_mcb;
827: mcb->interrupt = 0;
828: mcb->forw_phaddr = 0;
829: mcb->drive = dk->dk_unit;
830:
831: hdc = &hdcsoftc[dk->dk_ctlr];
832: master = &hdc->hdc_mcb;
833:
834: /* fill in master mcb */
835: master->mcw = MCL_IMMEDIATE;
836: master->forw_phaddr = (u_long)vtoph((struct proc *)NULL, mcb);
837: master->mcs = 0;
838:
839: /* kick controller and wait */
840: hdc->hdc_reg->master_mcb = (u_long)hdc->hdc_mcbp;
841: for (timeout = 15000; timeout; --timeout) {
842: DELAY(1000);
843: mtpr(PADC, 0);
844: if (master->mcs&MCS_FATALERROR) {
845: printf("hdc%d: fatal error\n", dk->dk_ctlr);
846: hdcerror(dk->dk_ctlr, *(u_long *)master->xstatus);
847: return(1);
848: }
849: if (master->mcs&MCS_DONE)
850: return(0);
851: }
852: printf("hdc%d: timed out\n", dk->dk_ctlr);
853: return(1);
854: }
855:
856: hdcerror(ctlr, code)
857: int ctlr;
858: u_long code;
859: {
860: printf("hd%d: error %lx\n", ctlr, code);
861: }
862:
863: #ifdef COMPAT_42
864: hdreadgeometry(dk)
865: struct dksoftc *dk;
866: {
867: static geometry_sector geometry;
868: register struct mcb *mcb;
869: register struct disklabel *lp;
870: geometry_block *geo;
871: int cnt;
872:
873: /*
874: * Read the geometry block (at head = 0 sector = 0 of the drive
875: * definition cylinder), validate it (must have the correct version
876: * number, header, and checksum).
877: */
878: mcb = &dk->dk_mcb;
879: mcb->command = HCMD_READ;
880: mcb->cyl = dk->dk_def_cyl;
881: mcb->head = 0;
882: mcb->sector = 0;
883: mcb->chain[0].wcount = sizeof(geometry_sector) / sizeof(long);
884: mcb->chain[0].memadr = (u_long)vtoph((struct process *)0, &geometry);
885: /* mcb->chain[0].memadr = (long)&geometry; */
886: if (hdimcb(dk)) {
887: printf("hd%d: can't read default geometry.\n", dk->dk_unit);
888: return(1);
889: }
890: geo = &geometry.geometry_block;
891: if (geo->version > 64000 || geo->version < 0) {
892: printf("hd%d: bad default geometry version#.\n", dk->dk_unit);
893: return(1);
894: }
895: if (bcmp(&geo->id[0], GB_ID, GB_ID_LEN)) {
896: printf("hd%d: bad default geometry header.\n", dk->dk_unit);
897: return(1);
898: }
899: GB_CHECKSUM(geo, cnt);
900: if (geometry.checksum != cnt) {
901: printf("hd%d: bad default geometry checksum.\n", dk->dk_unit);
902: return(1);
903: }
904: lp = &dk->dk_label;
905:
906: /* 1K block in Harris geometry; convert to sectors for disklabels */
907: for (cnt = 0; cnt < GB_MAXPART; cnt++) {
908: lp->d_partitions[cnt].p_offset =
909: geo->partition[cnt].start * (1024 / lp->d_secsize);
910: lp->d_partitions[cnt].p_size =
911: geo->partition[cnt].length * (1024 / lp->d_secsize);
912: }
913: lp->d_npartitions = GB_MAXPART;
914: return(0);
915: }
916: #endif /* COMPAT_42 */
917: #endif /* NHD */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.