|
|
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.9 (Berkeley) 6/30/90
24: */
25:
26: #include "sys/param.h"
27: #include "sys/time.h"
28: #include "sys/buf.h"
29: #include "sys/ioctl.h"
30: #include "sys/disklabel.h"
31: #include "saio.h"
32: #include "tahoe/mtpr.h"
33: #include "tahoevba/hdreg.h"
34:
35: static struct registers *hdc_regs[HDC_MAXCTLR][HDC_MAXBUS];
36: static struct disklabel dklabel[HDC_MAXDRIVE][HDC_MAXCTLR][HDC_MAXBUS];
37:
38: hdopen(io)
39: register struct iob *io;
40: {
41: register struct disklabel *dlp;
42: struct status status;
43: struct module_id id;
44: struct registers *hr;
45: struct mcb mcb;
46: long junk, dlbuf[DEV_BSIZE/sizeof(long)];
47:
48: /* validate the device specification */
49: if ((u_int)io->i_bus >= HDC_MAXBUS)
50: return(EADAPT);
51: if ((u_int)io->i_ctlr >= HDC_MAXCTLR)
52: return(ECTLR);
53: if ((u_int)io->i_unit >= HDC_MAXDRIVE)
54: return(EUNIT);
55: if ((u_int)io->i_part > 7)
56: return(EPART);
57:
58: /* init drive structure. */
59: hdc_regs[io->i_ctlr][io->i_bus] = hr = (struct registers *)(io->i_bus ?
60: 0x80000000 | io->i_ctlr << 24 | HDC_MID << 16 :
61: 0xC0000000 | io->i_ctlr << 24 | HDC_MID << 16);
62:
63: /* insure that this is an hdc, then reset the hdc. */
64: if (wbadaddr(&hr->module_id, 4, &junk)) {
65: printf("hd%d: %x: invalid csr\n", io->i_ctlr, (u_int)hr);
66: return(ENXIO);
67: }
68: hr->soft_reset = 0;
69: DELAY(1000000);
70:
71: /*
72: * read in the hdc module id word. The controller is bad if the
73: * hdc's writeable control store is not loaded or if the hdc failed
74: * the functional integrity test for any reason.
75: */
76: hr->module_id = (u_long)&id;
77: DELAY(10000);
78: mtpr(PADC, 0);
79: if (id.module_id != (u_char)HDC_MID) {
80: printf("hdc: controller bad module id: id = %x\n",
81: id.module_id);
82: return(ENXIO);
83: }
84: if (id.code_rev == (u_char)0xff) {
85: printf("hdc: controller micro-code is not loaded.\n");
86: return(ENXIO);
87: }
88: if (id.fit != (u_char)0xff) {
89: printf("hdc: controller FIT test failed: error= %x\n",
90: id.fit);
91: return(ENXIO);
92: }
93:
94: /* read the drive status */
95: mcb.command = HCMD_STATUS;
96: mcb.drive = io->i_unit;
97: mcb.cyl = 0;
98: mcb.head = 0;
99: mcb.sector = 0;
100: mcb.chain[0].wcount = (long)(sizeof(struct status) / sizeof(long));
101: mcb.chain[0].memadr = (long)&status;
102: if (hdimcb(&mcb, io))
103: return(EIO);
104:
105: /*
106: * Report drive down if anything in the drive status is bad.
107: * If fault condition, reading will try to clear the fault.
108: */
109: if (status.drs&DRS_FAULT)
110: printf("hdc: clearing drive fault.\n");
111: if (!(status.drs&DRS_ONLINE)) {
112: printf("hdc: drive is not online.\n");
113: return(EIO);
114: }
115:
116: /* read in the pack label */
117: mcb.command = HCMD_READ;
118: mcb.drive = io->i_unit;
119: mcb.cyl = 0;
120: mcb.head = 0;
121: mcb.sector = LABELSECTOR;
122: mcb.chain[0].wcount = (long)(DEV_BSIZE / sizeof(long));
123: mcb.chain[0].memadr = (long)dlbuf;
124: if (hdimcb(&mcb, io))
125: return(ERDLAB);
126: dlp = (struct disklabel *)(dlbuf + (LABELOFFSET / sizeof(long)));
127: if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC)
128: #ifdef COMPAT_42
129: {
130: int error;
131:
132: if (error = hdmaptype(io, dlp, &status, io->i_unit))
133: return(error);
134: }
135: #else
136: return(EUNLAB);
137: #endif
138: dklabel[io->i_unit][io->i_ctlr][io->i_bus] = *dlp;
139: if (io->i_part >= dlp->d_npartitions ||
140: dlp->d_partitions[io->i_part].p_size == 0)
141: return(EPART);
142: io->i_boff = (dlp->d_partitions[io->i_part].p_offset *
143: dlp->d_secsize) / DEV_BSIZE;
144: return(0);
145: }
146:
147: hdstrategy(io, cmd)
148: register struct iob *io;
149: int cmd;
150: {
151: register struct disklabel *dlp;
152: struct mcb mcb;
153: long sector;
154:
155: if (io->i_cc&3) {
156: printf("hd%d: i/o not a longword multiple.\n", io->i_unit);
157: return(0);
158: }
159: dlp = &dklabel[io->i_unit][io->i_ctlr][io->i_bus];
160: sector = io->i_bn * HDC_SPB;
161: mcb.command = (cmd == READ) ? HCMD_READ : HCMD_WRITE;
162: mcb.drive = io->i_unit;
163: mcb.cyl = sector / dlp->d_secpercyl;
164: mcb.head = (sector / dlp->d_nsectors) % dlp->d_ntracks;
165: mcb.sector = sector % dlp->d_nsectors;
166: mcb.chain[0].wcount = io->i_cc / sizeof(long);
167: mcb.chain[0].memadr = (u_long)io->i_ma;
168: return(hdimcb(&mcb, io) ? -1 : io->i_cc);
169: }
170:
171: hdimcb(mcb, io)
172: register struct mcb *mcb;
173: register struct iob *io;
174: {
175: struct master_mcb master;
176: int timeout;
177:
178: /* fill in mcb */
179: mcb->interrupt = 0;
180: mcb->forw_phaddr = 0;
181:
182: /* fill in master mcb */
183: master.mcw = MCL_IMMEDIATE;
184: master.forw_phaddr = (u_long)mcb;
185: master.mcs = 0;
186:
187: hdc_regs[io->i_ctlr][io->i_bus]->master_mcb = (u_long)&master;
188: for (timeout = 15000; timeout; --timeout) {
189: DELAY(1000);
190: mtpr(PADC, 0);
191: if (master.mcs&MCS_FATALERROR) {
192: printf("hdc%d: fatal error.\n", io->i_ctlr);
193: return(1);
194: }
195: if (master.mcs&MCS_DONE)
196: return(0);
197: }
198: printf("hdc%d: timed out.\n", io->i_ctlr);
199: return(1);
200: }
201:
202: #ifdef COMPAT_42
203: hdmaptype(io, dlp, status, unit)
204: register struct iob *io;
205: register struct disklabel *dlp;
206: struct status *status;
207: int unit;
208: {
209: geometry_sector geometry;
210: geometry_block *geo;
211: struct mcb mcb;
212: int cnt;
213: char *strcpy();
214:
215: printf("hd%d: unlabeled\n", unit);
216: /*
217: * Read the geometry block (at head = 0 sector = 0 of the drive
218: * definition cylinder), validate it (must have the correct version
219: * number, header, and checksum).
220: */
221: mcb.command = HCMD_READ;
222: mcb.drive = unit;
223: mcb.cyl = status->def_cyl;
224: mcb.head = 0;
225: mcb.sector = 0;
226: mcb.chain[0].wcount = (long)(sizeof(geometry_sector) / sizeof(long));
227: mcb.chain[0].memadr = (long)&geometry;
228: if (hdimcb(&mcb, io)) {
229: printf("hd%d: can't read default geometry.\n", io->i_unit);
230: return(ERDLAB);
231: }
232: geo = &geometry.geometry_block;
233: if (geo->version > 64000 || geo->version < 0) {
234: printf("hd%d: bad default geometry version#.\n", io->i_unit);
235: return(ENXIO);
236: }
237: if (strcmp(&geo->id[0], GB_ID)) {
238: printf("hd%d: bad default geometry header.\n", io->i_unit);
239: return(ENXIO);
240: }
241: GB_CHECKSUM(geo, cnt);
242: if (geometry.checksum != cnt) {
243: printf("hd%d: bad default geometry checksum.\n", io->i_unit);
244: return(ENXIO);
245: }
246: for (cnt = 0; cnt < GB_MAXPART; cnt++) {
247: dlp->d_partitions[cnt].p_offset = geo->partition[cnt].start;
248: dlp->d_partitions[cnt].p_size = geo->partition[cnt].length;
249: }
250: #ifdef RAW_SIZE
251: dlp->d_secsize = status->bytes_per_sec;
252: #else
253: dlp->d_secsize = 512;
254: #endif
255: dlp->d_nsectors = status->max_sector + 1;
256: dlp->d_ncylinders = status->max_cyl + 1;
257: dlp->d_ntracks = status->max_head + 1;
258: dlp->d_secpercyl = dlp->d_ntracks * dlp->d_nsectors;
259: dlp->d_npartitions = GB_MAXPART;
260: dlp->d_rpm = status->rpm;
261: (void)strcpy(dlp->d_typename, "hdc (prom)");
262: return(0);
263: }
264: #endif /* COMPAT_42 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.