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