update from Mike Hibler
[unix-history] / usr / src / sys / hp300 / dev / rd.c
CommitLineData
60f56dfc
KM
1/*
2 * Copyright (c) 1988 University of Utah.
3 * Copyright (c) 1982, 1990 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * the Systems Programming Group of the University of Utah Computer
8 * Science Department.
9 *
10 * %sccs.include.redist.c%
11 *
12 * from: Utah $Hdr: rd.c 1.30 89/09/17$
13 *
339a5f2c 14 * @(#)rd.c 7.3 (Berkeley) %G%
60f56dfc
KM
15 */
16
17/*
18 * CS80/SS80 disk driver
19 */
20#include "rd.h"
21#if NRD > 0
22
23#include "param.h"
24#include "systm.h"
25#include "errno.h"
26#include "dkstat.h"
27#include "disklabel.h"
28#include "buf.h"
29#include "uio.h"
30
31#include "device.h"
32#include "rdreg.h"
33
34int rdinit(), rdstart(), rdgo(), rdintr();
35struct driver rddriver = {
36 rdinit, "rd", rdstart, rdgo, rdintr,
37};
38
39struct rd_softc {
40 struct hp_device *sc_hd;
339a5f2c
KM
41 int sc_flags;
42 short sc_type;
43 short sc_punit;
44 char *sc_addr;
45 int sc_resid;
46 u_int sc_wpms;
47 struct rdinfo *sc_info;
48 struct devqueue sc_dq;
60f56dfc
KM
49 struct rd_iocmd sc_ioc;
50 struct rd_rscmd sc_rsc;
51 struct rd_stat sc_stat;
52 struct rd_ssmcmd sc_ssmc;
53 struct rd_srcmd sc_src;
54 struct rd_clearcmd sc_clear;
60f56dfc
KM
55} rd_softc[NRD];
56
57/* sc_flags values */
58#define RDF_ALIVE 0x1
59#define RDF_SEEK 0x2
60#define RDF_SWAIT 0x4
61
62struct size {
63 daddr_t nblocks;
64 int cyloff;
65};
66
67#ifdef DEBUG
68int rddebug = 0x80;
69#define RDB_FOLLOW 0x01
70#define RDB_STATUS 0x02
71#define RDB_IDENT 0x04
72#define RDB_IO 0x08
73#define RDB_ASYNC 0x10
74#define RDB_ERROR 0x80
75#define RDB_DUMP 0x80000000
76
77struct rdstats {
78 long rdretries;
79 long rdresets;
80 long rdtimeouts;
81 long rdpolltries;
82 long rdpollwaits;
83} rdstats[NRD];
84
85/* error message tables */
86char *err_reject[] = {
87 0, 0,
88 "channel parity error", /* 0x2000 */
89 0, 0,
90 "illegal opcode", /* 0x0400 */
91 "module addressing", /* 0x0200 */
92 "address bounds", /* 0x0100 */
93 "parameter bounds", /* 0x0080 */
94 "illegal parameter", /* 0x0040 */
95 "message sequence", /* 0x0020 */
96 0,
97 "message length", /* 0x0008 */
98 0, 0, 0
99};
100
101char *err_fault[] = {
102 0,
103 "cross unit", /* 0x4000 */
104 0,
105 "controller fault", /* 0x1000 */
106 0, 0,
107 "unit fault", /* 0x0200 */
108 0,
109 "diagnostic result", /* 0x0080 */
110 0,
111 "operator release request", /* 0x0020 */
112 "diagnostic release request", /* 0x0010 */
113 "internal maintenance release request", /* 0x0008 */
114 0,
115 "power fail", /* 0x0002 */
116 "retransmit" /* 0x0001 */
117};
118
119char *err_access[] = {
120 "illegal parallel operation", /* 0x8000 */
121 "uninitialized media", /* 0x4000 */
122 "no spares available", /* 0x2000 */
123 "not ready", /* 0x1000 */
124 "write protect", /* 0x0800 */
125 "no data found", /* 0x0400 */
126 0, 0,
127 "unrecoverable data overflow", /* 0x0080 */
128 "unrecoverable data", /* 0x0040 */
129 0,
130 "end of file", /* 0x0010 */
131 "end of volume", /* 0x0008 */
132 0, 0, 0
133};
134
135char *err_info[] = {
136 "operator release request", /* 0x8000 */
137 "diagnostic release request", /* 0x4000 */
138 "internal maintenance release request", /* 0x2000 */
139 "media wear", /* 0x1000 */
140 "latency induced", /* 0x0800 */
141 0, 0,
142 "auto sparing invoked", /* 0x0100 */
143 0,
144 "recoverable data overflow", /* 0x0040 */
145 "marginal data", /* 0x0020 */
146 "recoverable data", /* 0x0010 */
147 0,
148 "maintenance track overflow", /* 0x0004 */
149 0, 0
150};
151#endif
152
153/*
154 * CS/80 partitions. We reserve the first cylinder for a LIF
155 * style boot directory (the 8k allowed in the BSD filesystem
156 * is just way too small). This boot area is outside of all but
157 * the C partition. This implies that you cannot use the C
158 * partition on a bootable disk since the filesystem would overlay
159 * the boot area. You must use the A partition.
160 *
161 * These maps support four basic layouts:
162 *
163 * A/B/G: This is the "traditional" setup for a bootable disk.
164 * A is the root partition, B the swap, and G a user partition.
165 * A/D/H: This is a setup for bootable systems requiring more swap
166 * (e.g. those who use HPCL). It has A as the root, D as a
167 * larger swap, and H as a smaller user partition.
168 * A/D/E/F: Similar to A/D/H with E and F breaking H into two partitions.
169 * E could be used for /usr and F for users.
170 * C: This gives a single, non-bootable, large user filesystem.
171 * Good for second drives on a machine (e.g. /usr/src).
172 */
173struct size rd7945A_sizes[8] = {
174 RDSZ(15904), 1, /* A=cyl 1 thru 142 */
175 RDSZ(20160), 143, /* B=cyl 143 thru 322 */
176 RDSZ(108416), 0, /* C=cyl 0 thru 967 */
177 RDSZ(40320), 143, /* D=cyl 143 thru 502 */
178 RDSZ(0), 0, /* E=<undefined> */
179 RDSZ(0), 0, /* F=<undefined> */
180 RDSZ(72240), 323, /* G=cyl 323 thru 967 */
181 RDSZ(52080), 503, /* H=cyl 503 thru 967 */
182}, rd9134D_sizes[8] = {
183 RDSZ(15936), 1, /* A=cyl 1 thru 166 */
184 RDSZ(13056), 167, /* B=cyl 167 thru 302 */
185 RDSZ(29088), 0, /* C=cyl 0 thru 302 */
186 RDSZ(0), 0, /* D=<undefined> */
187 RDSZ(0), 0, /* E=<undefined> */
188 RDSZ(0), 0, /* F=<undefined> */
189 RDSZ(0), 0, /* G=<undefined> */
190 RDSZ(0), 0, /* H=<undefined> */
191}, rd9122S_sizes[8] = {
192 RDSZ(0), 0, /* A=<undefined> */
193 RDSZ(0), 0, /* B=<undefined> */
194 RDSZ(1232), 0, /* C=cyl 0 thru 76 */
195 RDSZ(0), 0, /* D=<undefined> */
196 RDSZ(0), 0, /* E=<undefined> */
197 RDSZ(0), 0, /* F=<undefined> */
198 RDSZ(0), 0, /* G=<undefined> */
199 RDSZ(0), 0, /* H=<undefined> */
200}, rd7912P_sizes[8] = {
201 RDSZ(15904), 0, /* A=cyl 1 thru 71 */
202 RDSZ(22400), 72, /* B=cyl 72 thru 171 */
203 RDSZ(128128), 0, /* C=cyl 0 thru 571 */
204 RDSZ(42560), 72, /* D=cyl 72 thru 261 */
205 RDSZ(0), 292, /* E=<undefined> */
206 RDSZ(0), 542, /* F=<undefined> */
207 RDSZ(89600), 172, /* G=cyl 221 thru 571 */
208 RDSZ(69440), 262, /* H=cyl 262 thru 571 */
209}, rd7914P_sizes[8] = {
210 RDSZ(15904), 1, /* A=cyl 1 thru 71 */
211 RDSZ(40320), 72, /* B=cyl 72 thru 251 */
212 RDSZ(258048), 0, /* C=cyl 0 thru 1151 */
213 RDSZ(64960), 72, /* D=cyl 72 thru 361 */
214 RDSZ(98560), 362, /* E=cyl 362 thru 801 */
215 RDSZ(78400), 802, /* F=cyl 802 thru 1151 */
216 RDSZ(201600), 252, /* G=cyl 221 thru 1151 */
217 RDSZ(176960), 362, /* H=cyl 362 thru 1151 */
218}, rd7933H_sizes[8] = {
219 RDSZ(16146), 1, /* A=cyl 1 thru 27 */
220 RDSZ(66976), 28, /* B=cyl 28 thru 139 */
221 RDSZ(789958), 0, /* C=cyl 0 thru 1320 */
222 RDSZ(16146), 140, /* D=cyl 140 thru 166 */
223 RDSZ(165646), 167, /* E=cyl 167 thru 443 */
224 RDSZ(165646), 444, /* F=cyl 444 thru 720 */
225 RDSZ(706238), 140, /* G=cyl 140 thru 1320 */
226 RDSZ(358800), 721, /* H=cyl 721 thru 1320 */
227}, rd9134L_sizes[8] = {
228 RDSZ(15920), 1, /* A=cyl 1 thru 199 */
229 RDSZ(20000), 200, /* B=cyl 200 thru 449 */
230 RDSZ(77840), 0, /* C=cyl 0 thru 972 */
231 RDSZ(32000), 200, /* D=cyl 200 thru 599 */
232 RDSZ(0), 0, /* E=<undefined> */
233 RDSZ(0), 0, /* F=<undefined> */
234 RDSZ(41840), 450, /* G=cyl 450 thru 972 */
235 RDSZ(29840), 600, /* H=cyl 600 thru 972 */
236}, rd7957A_sizes[8] = {
237 RDSZ(16016), 1, /* A=cyl 1 thru 104 */
238 RDSZ(24640), 105, /* B=cyl 105 thru 264 */
239 RDSZ(159544), 0, /* C=cyl 0 thru 1035 */
240 RDSZ(42350), 105, /* D=cyl 105 thru 379 */
241 RDSZ(54824), 380, /* E=cyl 380 thru 735 */
242 RDSZ(46200), 736, /* F=cyl 736 thru 1035 */
243 RDSZ(118734), 265, /* G=cyl 265 thru 1035 */
244 RDSZ(101024), 380, /* H=cyl 380 thru 1035 */
245}, rd7958A_sizes[8] = {
246 RDSZ(16128), 1, /* A=cyl 1 thru 64 */
247 RDSZ(32256), 65, /* B=cyl 65 thru 192 */
248 RDSZ(255276), 0, /* C=cyl 0 thru 1012 */
249 RDSZ(48384), 65, /* D=cyl 65 thru 256 */
250 RDSZ(100800), 257, /* E=cyl 257 thru 656 */
251 RDSZ(89712), 657, /* F=cyl 657 thru 1012 */
252 RDSZ(206640), 193, /* G=cyl 193 thru 1012 */
253 RDSZ(190512), 257, /* H=cyl 257 thru 1012 */
254}, rd7957B_sizes[8] = {
255 RDSZ(16002), 1, /* A=cyl 1 thru 127 */
256 RDSZ(32760), 128, /* B=cyl 128 thru 387 */
257 RDSZ(159894), 0, /* C=cyl 0 thru 1268 */
258 RDSZ(49140), 128, /* D=cyl 128 thru 517 */
259 RDSZ(50400), 518, /* E=cyl 518 thru 917 */
260 RDSZ(44226), 918, /* F=cyl 918 thru 1268 */
261 RDSZ(111006), 388, /* G=cyl 388 thru 1268 */
262 RDSZ(94626), 518, /* H=cyl 518 thru 1268 */
263}, rd7958B_sizes[8] = {
264 RDSZ(16254), 1, /* A=cyl 1 thru 43 */
265 RDSZ(32886), 44, /* B=cyl 44 thru 130 */
266 RDSZ(297108), 0, /* C=cyl 0 thru 785 */
267 RDSZ(49140), 44, /* D=cyl 44 thru 173 */
268 RDSZ(121716), 174, /* E=cyl 174 thru 495 */
269 RDSZ(109620), 496, /* F=cyl 496 thru 785 */
270 RDSZ(247590), 131, /* G=cyl 131 thru 785 */
271 RDSZ(231336), 174, /* H=cyl 174 thru 785 */
272}, rd7959B_sizes[8] = {
273 RDSZ(16254), 1, /* A=cyl 1 thru 43 */
274 RDSZ(49140), 44, /* B=cyl 44 thru 173 */
275 RDSZ(594216), 0, /* C=cyl 0 thru 1571 */
276 RDSZ(65772), 44, /* D=cyl 44 thru 217 */
277 RDSZ(303912), 218, /* E=cyl 218 thru 1021 */
278 RDSZ(207900), 1022, /* F=cyl 1022 thru 1571 */
279 RDSZ(528444), 174, /* G=cyl 174 thru 1571 */
280 RDSZ(511812), 218, /* H=cyl 218 thru 1571 */
281
282#if DEV_BSIZE == 512
283/*
284 * These values would not work for 1k,
285 * since the number of cylinders would be different.
286 */
287}, rd7936H_sizes[8] = {
288 RDSZ(16359), 1, /* A=cyl 1 thru 19 */
289 RDSZ(67158), 20, /* B=cyl 20 thru 97 */
290 RDSZ(600978), 0, /* C=cyl 0 thru 697 */
291 RDSZ(16359), 98, /* D=cyl 98 thru 116 */
292 RDSZ(120540), 117, /* E=cyl 117 thru 256 */
293 RDSZ(120540), 256, /* F=cyl 256 thru 396 */
294 RDSZ(516600), 98, /* G=cyl 98 thru 697 */
295 RDSZ(259161), 397, /* H=cyl 397 thru 697 */
296}, rd7937H_sizes[8] = {
297#ifdef UTAH
298 RDSZ(15990), 1, /* A=cyl 1 thru 10 */
299 RDSZ(67158), 11, /* B=cyl 11 thru 52 */
300 RDSZ(1116102), 0, /* C=cyl 0 thru 697 */
301 RDSZ(124722), 53, /* D=cyl 53 thru 130 */
302 RDSZ(163098), 131, /* E=cyl 131 thru 232 */
303 RDSZ(287820), 233, /* F=cyl 233 thru 412 */
304 RDSZ(1031355), 53, /* G=cyl 53 thru 697 */
305 RDSZ(455715), 413, /* H=cyl 413 thru 697 */
306#else
307 RDSZ(15990), 1, /* A=cyl 1 thru 10 */
308 RDSZ(67158), 11, /* B=cyl 11 thru 52 */
309 RDSZ(1116102), 0, /* C=cyl 0 thru 697 */
310 RDSZ(15990), 53, /* D=cyl 53 thru 62 */
311 RDSZ(246246), 63, /* E=cyl 63 thru 216 */
312 RDSZ(246246), 217, /* F=cyl 217 thru 370 */
313 RDSZ(1031355), 53, /* G=cyl 53 thru 697 */
314 RDSZ(522873), 371, /* H=cyl 371 thru 697 */
315#endif
316#endif
317};
318
319struct rdinfo {
320 int nbpt; /* DEV_BSIZE blocks per track */
321 int ntpc; /* tracks per cylinder */
322 int nbpc; /* blocks per cylinder */
323 struct size *sizes; /* default partition info (if no disklabel) */
324 short hwid; /* 2 byte HW id */
325 short maxunum; /* maximum allowed unit number */
326 char *desc; /* drive type description */
327};
328
329struct rdinfo rdinfo[] = {
330 NRD7945ABPT, NRD7945ATRK, NRD7945ABPT * NRD7945ATRK,
331 rd7945A_sizes, RD7946AID, 0, "7945A",
332 NRD9134DBPT, NRD9134DTRK, NRD9134DBPT * NRD9134DTRK,
333 rd9134D_sizes, RD9134DID, 1, "9134D",
334 NRD9122SBPT, NRD9122STRK, NRD9122SBPT * NRD9122STRK,
335 rd9122S_sizes, RD9134LID, 1, "9122S",
336 NRD7912PBPT, NRD7912PTRK, NRD7912PBPT * NRD7912PTRK,
337 rd7912P_sizes, RD7912PID, 0, "7912P",
338 NRD7914PBPT, NRD7914PTRK, NRD7914PBPT * NRD7914PTRK,
339 rd7914P_sizes, RD7914PID, 0, "7914P",
340 NRD7958ABPT, NRD7958ATRK, NRD7958ABPT * NRD7958ATRK,
341 rd7958A_sizes, RD7958AID, 0, "7958A",
342 NRD7957ABPT, NRD7957ATRK, NRD7957ABPT * NRD7957ATRK,
343 rd7957A_sizes, RD7957AID, 0, "7957A",
344 NRD7933HBPT, NRD7933HTRK, NRD7933HBPT * NRD7933HTRK,
345 rd7933H_sizes, RD7933HID, 0, "7933H",
346 NRD9134LBPT, NRD9134LTRK, NRD9134LBPT * NRD9134LTRK,
347 rd9134L_sizes, RD9134LID, 1, "9134L",
348 NRD7936HBPT, NRD7936HTRK, NRD7936HBPT * NRD7936HTRK,
349 rd7936H_sizes, RD7936HID, 0, "7936H",
350 NRD7937HBPT, NRD7937HTRK, NRD7937HBPT * NRD7937HTRK,
351 rd7937H_sizes, RD7937HID, 0, "7937H",
352 NRD7914PBPT, NRD7914PTRK, NRD7914PBPT * NRD7914PTRK,
353 rd7914P_sizes, RD7914CTID, 0, "7914CT",
354 NRD7945ABPT, NRD7945ATRK, NRD7945ABPT * NRD7945ATRK,
355 rd7945A_sizes, RD7946AID, 0, "7946A",
356 NRD9122SBPT, NRD9122STRK, NRD9122SBPT * NRD9122STRK,
357 rd9122S_sizes, RD9134LID, 1, "9122D",
358 NRD7957BBPT, NRD7957BTRK, NRD7957BBPT * NRD7957BTRK,
359 rd7957B_sizes, RD7957BID, 0, "7957B",
360 NRD7958BBPT, NRD7958BTRK, NRD7958BBPT * NRD7958BTRK,
361 rd7958B_sizes, RD7958BID, 0, "7958B",
362 NRD7959BBPT, NRD7959BTRK, NRD7959BBPT * NRD7959BTRK,
363 rd7959B_sizes, RD7959BID, 0, "7959B",
364};
365int nrdinfo = sizeof(rdinfo) / sizeof(rdinfo[0]);
366
367struct buf rdtab[NRD];
368struct buf rdbuf[NRD];
369
370#define rdunit(x) ((minor(x) >> 3) & 0xf)
371#define rdpart(x) (minor(x) & 0x7)
372#define rdpunit(x) ((x) & 7)
373#define b_cylin b_resid
374#define RDRETRY 5
375#define RDWAITC 1 /* min time for timeout in seconds */
376
339a5f2c
KM
377int rderrthresh = RDRETRY-1; /* when to start reporting errors */
378
60f56dfc
KM
379rdinit(hd)
380 register struct hp_device *hd;
381{
382 register struct rd_softc *rs = &rd_softc[hd->hp_unit];
383
384 rs->sc_hd = hd;
385 rs->sc_punit = rdpunit(hd->hp_flags);
386 rs->sc_type = rdident(rs, hd);
387 if (rs->sc_type < 0)
388 return(0);
389 rs->sc_dq.dq_ctlr = hd->hp_ctlr;
390 rs->sc_dq.dq_unit = hd->hp_unit;
391 rs->sc_dq.dq_slave = hd->hp_slave;
392 rs->sc_dq.dq_driver = &rddriver;
393 rs->sc_info = &rdinfo[rs->sc_type];
394 rs->sc_flags = RDF_ALIVE;
339a5f2c
KM
395#ifdef DEBUG
396 /* always report errors */
397 if (rddebug & RDB_ERROR)
398 rderrthresh = 0;
399#endif
60f56dfc
KM
400 return(1);
401}
402
403rdident(rs, hd)
404 struct rd_softc *rs;
405 struct hp_device *hd;
406{
407 struct rd_describe desc;
408 u_char stat, cmd[3];
409 int unit, lunit;
410 char name[7];
411 register int ctlr, slave, id, i;
412
413 ctlr = hd->hp_ctlr;
414 slave = hd->hp_slave;
415 unit = rs->sc_punit;
416 lunit = hd->hp_unit;
417
418 /*
419 * Grab device id and make sure:
420 * 1. It is a CS80 device.
421 * 2. It is one of the types we support.
422 * 3. If it is a 7946, we are accessing the disk unit (0)
423 */
424 id = hpibid(ctlr, slave);
425 if ((id & 0x200) == 0)
426 return(-1);
427 for (i = 0; i < nrdinfo; i++)
428 if (id == rdinfo[i].hwid)
429 break;
430 if (i == nrdinfo || unit > rdinfo[i].maxunum)
431 return(-1);
432 id = i;
433
434 /*
435 * Reset drive and collect device description.
436 * Don't really use the description info right now but
437 * might come in handy in the future (for disk labels).
438 */
439 rdreset(rs, hd);
440 cmd[0] = C_SUNIT(unit);
441 cmd[1] = C_SVOL(0);
442 cmd[2] = C_DESC;
443 hpibsend(ctlr, slave, C_CMD, cmd, sizeof(cmd));
444 hpibrecv(ctlr, slave, C_EXEC, &desc, 37);
445 hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
446 bzero(name, sizeof(name));
447 if (!stat) {
448 register int n = desc.d_name;
449 for (i = 5; i >= 0; i--) {
450 name[i] = (n & 0xf) + '0';
451 n >>= 4;
452 }
339a5f2c
KM
453 /* use drive characteristics to calculate xfer rate */
454 rs->sc_wpms = 1000000 * (desc.d_sectsize/2) / desc.d_blocktime;
60f56dfc
KM
455 }
456#ifdef DEBUG
457 if (rddebug & RDB_IDENT) {
458 printf("rd%d: name: %x ('%s')\n",
459 lunit, desc.d_name, name);
460 printf(" iuw %x, maxxfr %d, ctype %d\n",
461 desc.d_iuw, desc.d_cmaxxfr, desc.d_ctype);
462 printf(" utype %d, bps %d, blkbuf %d, burst %d, blktime %d\n",
463 desc.d_utype, desc.d_sectsize,
464 desc.d_blkbuf, desc.d_burstsize, desc.d_blocktime);
465 printf(" avxfr %d, ort %d, atp %d, maxint %d, fv %x, rv %x\n",
466 desc.d_uavexfr, desc.d_retry, desc.d_access,
467 desc.d_maxint, desc.d_fvbyte, desc.d_rvbyte);
468 printf(" maxcyl/head/sect %d/%d/%d, maxvsect %d, inter %d\n",
469 desc.d_maxcyl, desc.d_maxhead, desc.d_maxsect,
470 desc.d_maxvsectl, desc.d_interleave);
471 }
472#endif
473 /*
474 * Take care of a couple of anomolies:
475 * 1. 7945A and 7946A both return same HW id
476 * 2. 9122S and 9134D both return same HW id
477 * 3. 9122D and 9134L both return same HW id
478 */
479 switch (rdinfo[id].hwid) {
480 case RD7946AID:
481 if (bcmp(name, "079450", 6) == 0)
482 id = RD7945A;
483 else
484 id = RD7946A;
485 break;
486
487 case RD9134LID:
488 if (bcmp(name, "091340", 6) == 0)
489 id = RD9134L;
490 else
491 id = RD9122D;
492 break;
493
494 case RD9134DID:
495 if (bcmp(name, "091220", 6) == 0)
496 id = RD9122S;
497 else
498 id = RD9134D;
499 break;
500 }
501 printf("rd%d: %s\n", lunit, rdinfo[id].desc);
502 return(id);
503}
504
505rdreset(rs, hd)
506 register struct rd_softc *rs;
507 register struct hp_device *hd;
508{
509 u_char stat;
510
511 rs->sc_clear.c_unit = C_SUNIT(rs->sc_punit);
512 rs->sc_clear.c_cmd = C_CLEAR;
513 hpibsend(hd->hp_ctlr, hd->hp_slave, C_TCMD, &rs->sc_clear,
514 sizeof(rs->sc_clear));
515 hpibswait(hd->hp_ctlr, hd->hp_slave);
516 hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
517 rs->sc_src.c_unit = C_SUNIT(RDCTLR);
518 rs->sc_src.c_nop = C_NOP;
519 rs->sc_src.c_cmd = C_SREL;
520 rs->sc_src.c_param = C_REL;
521 hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &rs->sc_src,
522 sizeof(rs->sc_src));
523 hpibswait(hd->hp_ctlr, hd->hp_slave);
524 hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
525 rs->sc_ssmc.c_unit = C_SUNIT(rs->sc_punit);
526 rs->sc_ssmc.c_cmd = C_SSM;
527 rs->sc_ssmc.c_refm = REF_MASK;
528 rs->sc_ssmc.c_fefm = FEF_MASK;
529 rs->sc_ssmc.c_aefm = AEF_MASK;
530 rs->sc_ssmc.c_iefm = IEF_MASK;
531 hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &rs->sc_ssmc,
532 sizeof(rs->sc_ssmc));
533 hpibswait(hd->hp_ctlr, hd->hp_slave);
534 hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
535#ifdef DEBUG
536 rdstats[hd->hp_unit].rdresets++;
537#endif
538}
539
540/*ARGSUSED*/
541rdopen(dev, flags)
542 dev_t dev;
543{
544 register int unit = rdunit(dev);
545 register struct rd_softc *rs = &rd_softc[unit];
546
547 if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
548 return(ENXIO);
339a5f2c
KM
549 if (rs->sc_hd->hp_dk >= 0) {
550 /* guess at xfer rate based on 3600 rpm (60 rps) */
551 if (rs->sc_wpms == 0)
552 rs->sc_wpms = 60 * rs->sc_info->nbpt * DEV_BSIZE / 2;
553 dk_wpms[rs->sc_hd->hp_dk] = rs->sc_wpms;
554 }
60f56dfc
KM
555 return(0);
556}
557
558rdstrategy(bp)
559 register struct buf *bp;
560{
561 register int part = rdpart(bp->b_dev);
562 register int unit = rdunit(bp->b_dev);
563 register int bn, sz;
564 register struct rd_softc *rs = &rd_softc[unit];
565 register struct buf *dp = &rdtab[unit];
566 int s;
567
568#ifdef DEBUG
569 if (rddebug & RDB_FOLLOW)
570 printf("rdstrategy(%x): dev %x, bn %x, bcount %x, %c\n",
571 bp, bp->b_dev, bp->b_blkno, bp->b_bcount,
572 (bp->b_flags & B_READ) ? 'R' : 'W');
573#endif
574 bn = bp->b_blkno;
575 sz = (bp->b_bcount + (DEV_BSIZE - 1)) >> DEV_BSHIFT;
576 if (bn < 0 || bn + sz > rs->sc_info->sizes[part].nblocks) {
577 if (bn == rs->sc_info->sizes[part].nblocks) {
578 bp->b_resid = bp->b_bcount;
579 goto done;
580 }
581 bp->b_error = EINVAL;
582 goto bad;
583 }
584 bp->b_cylin = bn / rs->sc_info->nbpc + rs->sc_info->sizes[part].cyloff;
585 s = splbio();
586 disksort(dp, bp);
587 if (dp->b_active == 0) {
588 dp->b_active = 1;
589 rdustart(unit);
590 }
591 splx(s);
592 return;
593bad:
594 bp->b_flags |= B_ERROR;
595done:
596 biodone(bp);
597}
598
599/*
600 * Called from timeout() when handling maintenance releases
601 */
602rdrestart(unit)
603 int unit;
604{
605 int s = splbio();
606 rdustart(unit);
607 splx(s);
608}
609
610rdustart(unit)
611 register int unit;
612{
613 register struct buf *bp;
614 register struct rd_softc *rs = &rd_softc[unit];
615
616 bp = rdtab[unit].b_actf;
617 rs->sc_addr = bp->b_un.b_addr;
618 rs->sc_resid = bp->b_bcount;
619 if (hpibreq(&rs->sc_dq))
620 rdstart(unit);
621}
622
623rdstart(unit)
624 register int unit;
625{
626 register struct rd_softc *rs = &rd_softc[unit];
627 register struct buf *bp = rdtab[unit].b_actf;
628 register struct hp_device *hp = rs->sc_hd;
629 register int part;
630
631again:
632#ifdef DEBUG
633 if (rddebug & RDB_FOLLOW)
634 printf("rdstart(%d): bp %x, %c\n", unit, bp,
635 (bp->b_flags & B_READ) ? 'R' : 'W');
636#endif
637 part = rdpart(bp->b_dev);
638 rs->sc_flags |= RDF_SEEK;
639 rs->sc_ioc.c_unit = C_SUNIT(rs->sc_punit);
640 rs->sc_ioc.c_volume = C_SVOL(0);
641 rs->sc_ioc.c_saddr = C_SADDR;
642 rs->sc_ioc.c_hiaddr = 0;
643 rs->sc_ioc.c_addr = RDBTOS(bp->b_blkno + rs->sc_info->nbpc *
644 rs->sc_info->sizes[part].cyloff);
645 rs->sc_ioc.c_nop2 = C_NOP;
646 rs->sc_ioc.c_slen = C_SLEN;
647 rs->sc_ioc.c_len = rs->sc_resid;
648 rs->sc_ioc.c_cmd = bp->b_flags & B_READ ? C_READ : C_WRITE;
649#ifdef DEBUG
650 if (rddebug & RDB_IO)
651 printf("rdstart: hpibsend(%x, %x, %x, %x, %x)\n",
652 hp->hp_ctlr, hp->hp_slave, C_CMD,
653 &rs->sc_ioc.c_unit, sizeof(rs->sc_ioc)-2);
654#endif
655 if (hpibsend(hp->hp_ctlr, hp->hp_slave, C_CMD, &rs->sc_ioc.c_unit,
656 sizeof(rs->sc_ioc)-2) == sizeof(rs->sc_ioc)-2) {
657 if (hp->hp_dk >= 0) {
658 dk_busy |= 1 << hp->hp_dk;
659 dk_seek[hp->hp_dk]++;
660 }
661#ifdef DEBUG
662 if (rddebug & RDB_IO)
663 printf("rdstart: hpibawait(%x)\n", hp->hp_ctlr);
664#endif
665 hpibawait(hp->hp_ctlr);
666 return;
667 }
668 /*
669 * Experience has shown that the hpibwait in this hpibsend will
670 * occasionally timeout. It appears to occur mostly on old 7914
671 * drives with full maintenance tracks. We should probably
672 * integrate this with the backoff code in rderror.
673 */
674#ifdef DEBUG
675 if (rddebug & RDB_ERROR)
676 printf("rd%d: rdstart: cmd %x adr %d blk %d len %d ecnt %d\n",
677 unit, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr,
678 bp->b_blkno, rs->sc_resid, rdtab[unit].b_errcnt);
679 rdstats[unit].rdretries++;
680#endif
681 rs->sc_flags &= ~RDF_SEEK;
682 rdreset(rs, hp);
683 if (rdtab[unit].b_errcnt++ < RDRETRY)
684 goto again;
685 printf("rd%d: rdstart err: cmd 0x%x sect %d blk %d len %d\n",
686 unit, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr,
687 bp->b_blkno, rs->sc_resid);
688 rdtab[unit].b_errcnt = 0;
689 rdtab[unit].b_actf = bp->b_actf;
690 bp->b_flags |= B_ERROR;
691 bp->b_error = EIO;
692 bp->b_resid = 0;
693 biodone(bp);
694 hpibfree(&rs->sc_dq);
695 bp = rdtab[unit].b_actf;
696 if (bp == NULL) {
697 rdtab[unit].b_active = 0;
698 return;
699 }
700 rs->sc_addr = bp->b_un.b_addr;
701 rs->sc_resid = bp->b_bcount;
702 if (hpibreq(&rs->sc_dq))
703 goto again;
704}
705
706rdgo(unit)
707 register int unit;
708{
709 register struct rd_softc *rs = &rd_softc[unit];
710 register struct hp_device *hp = rs->sc_hd;
711 struct buf *bp = rdtab[unit].b_actf;
712
713 if (hp->hp_dk >= 0) {
714 dk_busy |= 1 << hp->hp_dk;
715 dk_xfer[hp->hp_dk]++;
716 dk_wds[hp->hp_dk] += rs->sc_resid >> 6;
717 }
718 hpibgo(hp->hp_ctlr, hp->hp_slave, C_EXEC,
719 rs->sc_addr, rs->sc_resid, bp->b_flags & B_READ);
720}
721
722rdintr(unit)
723 register int unit;
724{
725 register struct rd_softc *rs = &rd_softc[unit];
726 register struct buf *bp = rdtab[unit].b_actf;
727 register struct hp_device *hp = rs->sc_hd;
728 u_char stat = 13; /* in case hpibrecv fails */
729 int restart;
730
731#ifdef DEBUG
732 if (rddebug & RDB_FOLLOW)
733 printf("rdintr(%d): bp %x, %c, flags %x\n", unit, bp,
734 (bp->b_flags & B_READ) ? 'R' : 'W', rs->sc_flags);
735 if (bp == NULL) {
736 printf("rd%d: bp == NULL\n", unit);
737 return;
738 }
739#endif
740 if (hp->hp_dk >= 0)
741 dk_busy &= ~(1 << hp->hp_dk);
742 if (rs->sc_flags & RDF_SEEK) {
743 rs->sc_flags &= ~RDF_SEEK;
744 if (hpibustart(hp->hp_ctlr))
745 rdgo(unit);
746 return;
747 }
748 if ((rs->sc_flags & RDF_SWAIT) == 0) {
749#ifdef DEBUG
750 rdstats[unit].rdpolltries++;
751#endif
752 if (hpibpptest(hp->hp_ctlr, hp->hp_slave) == 0) {
753#ifdef DEBUG
754 rdstats[unit].rdpollwaits++;
755#endif
756 if (hp->hp_dk >= 0)
757 dk_busy |= 1 << hp->hp_dk;
758 rs->sc_flags |= RDF_SWAIT;
759 hpibawait(hp->hp_ctlr);
760 return;
761 }
762 } else
763 rs->sc_flags &= ~RDF_SWAIT;
764 if (!hpibrecv(hp->hp_ctlr, hp->hp_slave, C_QSTAT, &stat, 1) || stat) {
765#ifdef DEBUG
766 if (rddebug & RDB_ERROR)
767 printf("rdintr: recv failed or bad stat %d\n", stat);
768#endif
769 restart = rderror(unit);
770#ifdef DEBUG
771 rdstats[unit].rdretries++;
772#endif
773 if (rdtab[unit].b_errcnt++ < RDRETRY) {
774 if (restart)
775 rdstart(unit);
776 return;
777 }
778 bp->b_flags |= B_ERROR;
779 bp->b_error = EIO;
780 }
781 rdtab[unit].b_errcnt = 0;
782 rdtab[unit].b_actf = bp->b_actf;
783 bp->b_resid = 0;
784 biodone(bp);
785 hpibfree(&rs->sc_dq);
786 if (rdtab[unit].b_actf)
787 rdustart(unit);
788 else
789 rdtab[unit].b_active = 0;
790}
791
792rdstatus(rs)
793 register struct rd_softc *rs;
794{
795 register int c, s;
796 u_char stat;
797 int rv;
798
799 c = rs->sc_hd->hp_ctlr;
800 s = rs->sc_hd->hp_slave;
801 rs->sc_rsc.c_unit = C_SUNIT(rs->sc_punit);
802 rs->sc_rsc.c_sram = C_SRAM;
803 rs->sc_rsc.c_ram = C_RAM;
804 rs->sc_rsc.c_cmd = C_STATUS;
805 bzero((caddr_t)&rs->sc_stat, sizeof(rs->sc_stat));
806 rv = hpibsend(c, s, C_CMD, &rs->sc_rsc, sizeof(rs->sc_rsc));
807 if (rv != sizeof(rs->sc_rsc)) {
808#ifdef DEBUG
809 if (rddebug & RDB_STATUS)
810 printf("rdstatus: send C_CMD failed %d != %d\n",
811 rv, sizeof(rs->sc_rsc));
812#endif
813 return(1);
814 }
815 rv = hpibrecv(c, s, C_EXEC, &rs->sc_stat, sizeof(rs->sc_stat));
816 if (rv != sizeof(rs->sc_stat)) {
817#ifdef DEBUG
818 if (rddebug & RDB_STATUS)
819 printf("rdstatus: send C_EXEC failed %d != %d\n",
820 rv, sizeof(rs->sc_stat));
821#endif
822 return(1);
823 }
824 rv = hpibrecv(c, s, C_QSTAT, &stat, 1);
825 if (rv != 1 || stat) {
826#ifdef DEBUG
827 if (rddebug & RDB_STATUS)
828 printf("rdstatus: recv failed %d or bad stat %d\n",
829 rv, stat);
830#endif
831 return(1);
832 }
833 return(0);
834}
835
836/*
837 * Deal with errors.
838 * Returns 1 if request should be restarted,
839 * 0 if we should just quietly give up.
840 */
841rderror(unit)
842 int unit;
843{
844 struct rd_softc *rs = &rd_softc[unit];
845 register struct rd_stat *sp;
846 struct buf *bp;
339a5f2c 847 daddr_t hwbn, pbn;
60f56dfc
KM
848
849 if (rdstatus(rs)) {
850#ifdef DEBUG
851 printf("rd%d: couldn't get status\n", unit);
852#endif
853 rdreset(rs, rs->sc_hd);
854 return(1);
855 }
856 sp = &rs->sc_stat;
857 if (sp->c_fef & FEF_REXMT)
858 return(1);
859 if (sp->c_fef & FEF_PF) {
860 rdreset(rs, rs->sc_hd);
861 return(1);
862 }
863 /*
864 * Unit requests release for internal maintenance.
865 * We just delay awhile and try again later. Use expontially
866 * increasing backoff ala ethernet drivers since we don't really
867 * know how long the maintenance will take. With RDWAITC and
868 * RDRETRY as defined, the range is 1 to 32 seconds.
869 */
870 if (sp->c_fef & FEF_IMR) {
871 extern int hz;
872 int rdtimo = RDWAITC << rdtab[unit].b_errcnt;
873#ifdef DEBUG
874 printf("rd%d: internal maintenance, %d second timeout\n",
875 unit, rdtimo);
876 rdstats[unit].rdtimeouts++;
877#endif
878 hpibfree(&rs->sc_dq);
879 timeout(rdrestart, unit, rdtimo*hz);
880 return(0);
881 }
339a5f2c
KM
882 /*
883 * Only report error if we have reached the error reporting
884 * threshhold. By default, this will only report after the
885 * retry limit has been exceeded.
886 */
887 if (rdtab[unit].b_errcnt < rderrthresh)
888 return(1);
889
60f56dfc
KM
890 /*
891 * First conjure up the block number at which the error occured.
892 * Note that not all errors report a block number, in that case
893 * we just use b_blkno.
894 */
339a5f2c
KM
895 bp = rdtab[unit].b_actf;
896 pbn = rs->sc_info->nbpc *
897 rs->sc_info->sizes[rdpart(bp->b_dev)].cyloff;
60f56dfc
KM
898 if ((sp->c_fef & FEF_CU) || (sp->c_fef & FEF_DR) ||
899 (sp->c_ief & IEF_RRMASK)) {
339a5f2c 900 hwbn = RDBTOS(pbn + bp->b_blkno);
60f56dfc
KM
901 pbn = bp->b_blkno;
902 } else {
339a5f2c
KM
903 hwbn = sp->c_blk;
904 pbn = RDSTOB(hwbn) - pbn;
60f56dfc
KM
905 }
906 /*
907 * Now output a generic message suitable for badsect.
908 * Note that we don't use harderr cuz it just prints
909 * out b_blkno which is just the beginning block number
910 * of the transfer, not necessary where the error occured.
911 */
912 printf("rd%d%c: hard error sn%d\n",
913 rdunit(bp->b_dev), 'a'+rdpart(bp->b_dev), pbn);
914 /*
915 * Now report the status as returned by the hardware with
916 * attempt at interpretation (unless debugging).
917 */
918 printf("rd%d %s error:",
919 unit, (bp->b_flags & B_READ) ? "read" : "write");
920#ifdef DEBUG
921 if (rddebug & RDB_ERROR) {
922 /* status info */
923 printf("\n volume: %d, unit: %d\n",
924 (sp->c_vu>>4)&0xF, sp->c_vu&0xF);
925 rdprinterr("reject", sp->c_ref, err_reject);
926 rdprinterr("fault", sp->c_fef, err_fault);
927 rdprinterr("access", sp->c_aef, err_access);
928 rdprinterr("info", sp->c_ief, err_info);
339a5f2c 929 printf(" block: %d, P1-P10: ", hwbn);
60f56dfc
KM
930 printf("%s", hexstr(*(u_int *)&sp->c_raw[0], 8));
931 printf("%s", hexstr(*(u_int *)&sp->c_raw[4], 8));
932 printf("%s\n", hexstr(*(u_short *)&sp->c_raw[8], 4));
933 /* command */
934 printf(" ioc: ");
935 printf("%s", hexstr(*(u_int *)&rs->sc_ioc.c_pad, 8));
936 printf("%s", hexstr(*(u_short *)&rs->sc_ioc.c_hiaddr, 4));
937 printf("%s", hexstr(*(u_int *)&rs->sc_ioc.c_addr, 8));
938 printf("%s", hexstr(*(u_short *)&rs->sc_ioc.c_nop2, 4));
939 printf("%s", hexstr(*(u_int *)&rs->sc_ioc.c_len, 8));
940 printf("%s\n", hexstr(*(u_short *)&rs->sc_ioc.c_cmd, 4));
941 return(1);
942 }
943#endif
944 printf(" v%d u%d, R0x%x F0x%x A0x%x I0x%x\n",
945 (sp->c_vu>>4)&0xF, sp->c_vu&0xF,
946 sp->c_ref, sp->c_fef, sp->c_aef, sp->c_ief);
947 printf("P1-P10: ");
948 printf("%s", hexstr(*(u_int *)&sp->c_raw[0], 8));
949 printf("%s", hexstr(*(u_int *)&sp->c_raw[4], 8));
950 printf("%s\n", hexstr(*(u_short *)&sp->c_raw[8], 4));
951 return(1);
952}
953
954rdread(dev, uio)
955 dev_t dev;
956 struct uio *uio;
957{
958 register int unit = rdunit(dev);
959
960 return(physio(rdstrategy, &rdbuf[unit], dev, B_READ, minphys, uio));
961}
962
963rdwrite(dev, uio)
964 dev_t dev;
965 struct uio *uio;
966{
967 register int unit = rdunit(dev);
968
969 return(physio(rdstrategy, &rdbuf[unit], dev, B_WRITE, minphys, uio));
970}
971
972/*ARGSUSED*/
973rdioctl(dev, cmd, data, flag)
974 dev_t dev;
975 int cmd;
976 caddr_t data;
977 int flag;
978{
979 return(EINVAL);
980}
981
982rdsize(dev)
983 dev_t dev;
984{
985 register int unit = rdunit(dev);
986 register struct rd_softc *rs = &rd_softc[unit];
987
988 if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
989 return(-1);
990 return(rs->sc_info->sizes[rdpart(dev)].nblocks);
991}
992
993#ifdef DEBUG
994rdprinterr(str, err, tab)
995 char *str;
996 short err;
997 char *tab[];
998{
999 register int i;
1000 int printed;
1001
1002 if (err == 0)
1003 return;
1004 printf(" %s error field:", str, err);
1005 printed = 0;
1006 for (i = 0; i < 16; i++)
1007 if (err & (0x8000 >> i))
1008 printf("%s%s", printed++ ? " + " : " ", tab[i]);
1009 printf("\n");
1010}
1011#endif
1012
1013#include "machine/pte.h"
1014#include "machine/vmparam.h"
029e208f 1015#include "../sys/vmmac.h"
60f56dfc
KM
1016
1017/*
1018 * Non-interrupt driven, non-dma dump routine.
1019 */
1020rddump(dev)
1021 dev_t dev;
1022{
1023 int part = rdpart(dev);
1024 int unit = rdunit(dev);
1025 register struct rd_softc *rs = &rd_softc[unit];
1026 register struct hp_device *hp = rs->sc_hd;
1027 register daddr_t baddr;
1028 register int maddr;
1029 register int pages, i;
1030 char stat;
1031 extern int lowram, dumpsize;
1032
1033 pages = dumpsize;
1034#ifdef DEBUG
1035 if (rddebug & RDB_DUMP)
1036 printf("rddump(%x): u %d p %d dumplo %d ram %x pmem %d\n",
1037 dev, unit, part, dumplo, lowram, ctod(pages));
1038#endif
1039 /* is drive ok? */
1040 if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
1041 return (ENXIO);
1042 /* HPIB idle? */
1043 if (!hpibreq(&rs->sc_dq)) {
1044#ifdef DEBUG
1045 /* is this a safe thing to do?? */
1046 hpibreset(hp->hp_ctlr);
1047 rdreset(rs, rs->sc_hd);
1048 printf("[ drive %d reset ] ", unit);
1049#else
1050 return (EFAULT);
1051#endif
1052 }
1053 /* dump parameters in range? */
1054 if (dumplo < 0 || dumplo >= rs->sc_info->sizes[part].nblocks)
1055 return (EINVAL);
1056 if (dumplo + ctod(pages) > rs->sc_info->sizes[part].nblocks)
1057 pages = dtoc(rs->sc_info->sizes[part].nblocks - dumplo);
1058 maddr = lowram;
1059 baddr = dumplo + rs->sc_info->nbpc * rs->sc_info->sizes[part].cyloff;
1060#ifdef DEBUG
1061 if (rddebug & RDB_DUMP)
1062 printf("rddump: dumping %d pages from %x to disk block %d\n",
1063 pages, maddr, baddr);
1064#endif
1065 for (i = 0; i < pages; i++) {
1066#ifdef DEBUG
1067#define NPGMB (1024*1024/NBPG)
1068 /* print out how many Mbs we have dumped */
1069 if (i && (i % NPGMB) == 0)
1070 printf("%d ", i / NPGMB);
1071#undef NPBMG
1072#endif
1073 rs->sc_ioc.c_unit = C_SUNIT(rs->sc_punit);
1074 rs->sc_ioc.c_volume = C_SVOL(0);
1075 rs->sc_ioc.c_saddr = C_SADDR;
1076 rs->sc_ioc.c_hiaddr = 0;
1077 rs->sc_ioc.c_addr = RDBTOS(baddr);
1078 rs->sc_ioc.c_nop2 = C_NOP;
1079 rs->sc_ioc.c_slen = C_SLEN;
1080 rs->sc_ioc.c_len = NBPG;
1081 rs->sc_ioc.c_cmd = C_WRITE;
1082 hpibsend(hp->hp_ctlr, hp->hp_slave, C_CMD,
1083 &rs->sc_ioc.c_unit, sizeof(rs->sc_ioc)-2);
1084 if (hpibswait(hp->hp_ctlr, hp->hp_slave)) {
1085#ifdef DEBUG
1086 if (rddebug & RDB_DUMP)
1087 printf("rddump: IOC wait timeout\n");
1088#endif
1089 return (EIO);
1090 }
1091 mapin(mmap, (u_int)vmmap, btop(maddr), PG_URKR|PG_CI|PG_V);
1092 hpibsend(hp->hp_ctlr, hp->hp_slave, C_EXEC, vmmap, NBPG);
1093 if (hpibswait(hp->hp_ctlr, hp->hp_slave)) {
1094#ifdef DEBUG
1095 if (rddebug & RDB_DUMP)
1096 printf("rddump: write wait timeout\n");
1097#endif
1098 }
1099 hpibrecv(hp->hp_ctlr, hp->hp_slave, C_QSTAT, &stat, 1);
1100 if (stat) {
1101#ifdef DEBUG
1102 if (rddebug & RDB_DUMP)
1103 printf("rddump: write failed, status %x\n",
1104 stat);
1105#endif
1106 return (EIO);
1107 }
1108 maddr += NBPG;
1109 baddr += ctod(1);
1110 }
1111 return (0);
1112}
1113#endif