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