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