xref: /original-bsd/sys/hp300/stand/rd.c (revision 93152bbe)
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.14 89/02/27$
13  *
14  *	@(#)rd.c	7.3 (Berkeley) 05/05/91
15  */
16 
17 /*
18  * CS80/SS80 disk driver
19  */
20 #include <sys/param.h>
21 #include "saio.h"
22 #include "samachdep.h"
23 
24 #include "../dev/rdreg.h"
25 
26 struct	rd_iocmd rd_ioc;
27 struct	rd_rscmd rd_rsc;
28 struct	rd_stat rd_stat;
29 struct	rd_ssmcmd rd_ssmc;
30 
31 struct	rd_softc {
32 	char	sc_retry;
33 	char	sc_alive;
34 	short	sc_type;
35 } rd_softc[NRD];
36 
37 #define	RDRETRY		5
38 
39 int rdcyloff[][8] = {
40 	{ 1, 143, 0, 143, 0,   0,   323, 503, },	/* 7945A */
41 	{ 1, 167, 0, 0,   0,   0,   0,   0,   },	/* 9134D */
42 	{ 0, 0,   0, 0,   0,   0,   0,   0,   },	/* 9122S */
43 	{ 0, 71,  0, 221, 292, 542, 221, 0,   },	/* 7912P */
44 	{ 1, 72,  0, 72,  362, 802, 252, 362, },	/* 7914P */
45 	{ 1, 28,  0, 140, 167, 444, 140, 721, },	/* 7933H */
46 	{ 1, 200, 0, 200, 0,   0,   450, 600, },	/* 9134L */
47 	{ 1, 105, 0, 105, 380, 736, 265, 380, },	/* 7957A */
48 	{ 1, 65,  0, 65,  257, 657, 193, 257, },	/* 7958A */
49 	{ 1, 128, 0, 128, 518, 918, 388, 518, },	/* 7957B */
50 	{ 1, 44,  0, 44,  174, 496, 131, 174, },	/* 7958B */
51 	{ 1, 44,  0, 44,  218, 918, 174, 218, },	/* 7959B */
52 	{ 1, 20,  0, 98,  117, 256, 98,  397, },	/* 7936H */
53 	{ 1, 11,  0, 53,  63,  217, 53,  371, },	/* 7937H */
54 };
55 
56 struct rdinfo {
57 	int	nbpc;
58 	int	hwid;
59 	int	*cyloff;
60 } rdinfo[] = {
61 	NRD7945ABPT*NRD7945ATRK, RD7946AID, rdcyloff[0],
62 	NRD9134DBPT*NRD9134DTRK, RD9134DID, rdcyloff[1],
63 	NRD9122SBPT*NRD9122STRK, RD9134LID, rdcyloff[2],
64 	NRD7912PBPT*NRD7912PTRK, RD7912PID, rdcyloff[3],
65 	NRD7914PBPT*NRD7914PTRK, RD7914PID, rdcyloff[4],
66 	NRD7958ABPT*NRD7958ATRK, RD7958AID, rdcyloff[8],
67 	NRD7957ABPT*NRD7957ATRK, RD7957AID, rdcyloff[7],
68 	NRD7933HBPT*NRD7933HTRK, RD7933HID, rdcyloff[5],
69 	NRD9134LBPT*NRD9134LTRK, RD9134LID, rdcyloff[6],
70 	NRD7936HBPT*NRD7936HTRK, RD7936HID, rdcyloff[12],
71 	NRD7937HBPT*NRD7937HTRK, RD7937HID, rdcyloff[13],
72 	NRD7914PBPT*NRD7914PTRK, RD7914CTID,rdcyloff[4],
73 	NRD7945ABPT*NRD7945ATRK, RD7946AID, rdcyloff[0],
74 	NRD9122SBPT*NRD9122STRK, RD9134LID, rdcyloff[2],
75 	NRD7957BBPT*NRD7957BTRK, RD7957BID, rdcyloff[9],
76 	NRD7958BBPT*NRD7958BTRK, RD7958BID, rdcyloff[10],
77 	NRD7959BBPT*NRD7959BTRK, RD7959BID, rdcyloff[11],
78 };
79 int	nrdinfo = sizeof(rdinfo) / sizeof(rdinfo[0]);
80 
81 rdinit(unit)
82 	register int unit;
83 {
84 	register struct rd_softc *rs;
85 	u_char stat;
86 
87 	if (unit > NRD)
88 		return (0);
89 	rs = &rd_softc[unit];
90 	rs->sc_type = rdident(unit);
91 	if (rs->sc_type < 0)
92 		return (0);
93 	rs->sc_alive = 1;
94 	return (1);
95 }
96 
97 rdreset(unit)
98 {
99 	u_char stat;
100 
101 	rd_ssmc.c_unit = C_SUNIT(0);
102 	rd_ssmc.c_cmd = C_SSM;
103 	rd_ssmc.c_refm = REF_MASK;
104 	rd_ssmc.c_fefm = FEF_MASK;
105 	rd_ssmc.c_aefm = AEF_MASK;
106 	rd_ssmc.c_iefm = IEF_MASK;
107 	hpibsend(unit, C_CMD, &rd_ssmc, sizeof(rd_ssmc));
108 	hpibswait(unit);
109 	hpibrecv(unit, C_QSTAT, &stat, 1);
110 }
111 
112 rdident(unit)
113 {
114 	struct rd_describe desc;
115 	u_char stat, cmd[3];
116 	char name[7];
117 	register int id, i;
118 
119 	id = hpibid(unit);
120 	if ((id & 0x200) == 0)
121 		return(-1);
122 	for (i = 0; i < nrdinfo; i++)
123 		if (id == rdinfo[i].hwid)
124 			break;
125 	if (i == nrdinfo)
126 		return(-1);
127 	id = i;
128 	rdreset(unit);
129 	cmd[0] = C_SUNIT(0);
130 	cmd[1] = C_SVOL(0);
131 	cmd[2] = C_DESC;
132 	hpibsend(unit, C_CMD, cmd, sizeof(cmd));
133 	hpibrecv(unit, C_EXEC, &desc, 37);
134 	hpibrecv(unit, C_QSTAT, &stat, sizeof(stat));
135 	bzero(name, sizeof(name));
136 	if (!stat) {
137 		register int n = desc.d_name;
138 		for (i = 5; i >= 0; i--) {
139 			name[i] = (n & 0xf) + '0';
140 			n >>= 4;
141 		}
142 	}
143 	/*
144 	 * Take care of a couple of anomolies:
145 	 * 1. 7945A and 7946A both return same HW id
146 	 * 2. 9122S and 9134D both return same HW id
147 	 * 3. 9122D and 9134L both return same HW id
148 	 */
149 	switch (rdinfo[id].hwid) {
150 	case RD7946AID:
151 		if (bcmp(name, "079450", 6) == 0)
152 			id = RD7945A;
153 		else
154 			id = RD7946A;
155 		break;
156 
157 	case RD9134LID:
158 		if (bcmp(name, "091340", 6) == 0)
159 			id = RD9134L;
160 		else
161 			id = RD9122D;
162 		break;
163 
164 	case RD9134DID:
165 		if (bcmp(name, "091220", 6) == 0)
166 			id = RD9122S;
167 		else
168 			id = RD9134D;
169 		break;
170 	}
171 	return(id);
172 }
173 
174 rdopen(io)
175 	struct iob *io;
176 {
177 	register int unit = io->i_unit;
178 	register struct rd_softc *rs = &rd_softc[unit];
179 	struct rdinfo *ri;
180 
181 	if (hpibalive(unit) == 0)
182 		_stop("rd controller not configured");
183 	if (rs->sc_alive == 0)
184 		if (rdinit(unit) == 0)
185 			_stop("rd init failed");
186 	if (io->i_boff < 0 || io->i_boff > 7)
187 		_stop("rd bad minor");
188 	ri = &rdinfo[rs->sc_type];
189 	io->i_boff = ri->cyloff[io->i_boff] * ri->nbpc;
190 }
191 
192 rdstrategy(io, func)
193 	register struct iob *io;
194 	register int func;
195 {
196 	register int unit = io->i_unit;
197 	register struct rd_softc *rs = &rd_softc[unit];
198 	char stat;
199 
200 	rs->sc_retry = 0;
201 	rd_ioc.c_unit = C_SUNIT(0);
202 	rd_ioc.c_volume = C_SVOL(0);
203 	rd_ioc.c_saddr = C_SADDR;
204 	rd_ioc.c_hiaddr = 0;
205 	rd_ioc.c_addr = RDBTOS(io->i_bn);
206 	rd_ioc.c_nop2 = C_NOP;
207 	rd_ioc.c_slen = C_SLEN;
208 	rd_ioc.c_len = io->i_cc;
209 	rd_ioc.c_cmd = func == F_READ ? C_READ : C_WRITE;
210 retry:
211 	hpibsend(unit, C_CMD, &rd_ioc.c_unit, sizeof(rd_ioc)-2);
212 	hpibswait(unit);
213 	hpibgo(unit, C_EXEC, io->i_ma, io->i_cc, func);
214 	hpibswait(unit);
215 	hpibrecv(unit, C_QSTAT, &stat, 1);
216 	if (stat) {
217 		if (rderror(unit) == 0)
218 			return(-1);
219 		if (++rs->sc_retry > RDRETRY)
220 			return(-1);
221 		else
222 			goto retry;
223 	}
224 	return(io->i_cc);
225 }
226 
227 rderror(unit)
228 	register int unit;
229 {
230 	register struct rd_softc *rd = &rd_softc[unit];
231 	char stat;
232 
233 	rd_rsc.c_unit = C_SUNIT(0);
234 	rd_rsc.c_sram = C_SRAM;
235 	rd_rsc.c_ram = C_RAM;
236 	rd_rsc.c_cmd = C_STATUS;
237 	hpibsend(unit, C_CMD, &rd_rsc, sizeof(rd_rsc));
238 	hpibrecv(unit, C_EXEC, &rd_stat, sizeof(rd_stat));
239 	hpibrecv(unit, C_QSTAT, &stat, 1);
240 	if (stat) {
241 		printf("rd(%d,?): request status fail %d\n", unit, stat);
242 		return(0);
243 	}
244 	printf("rd(%d,?) err: vu 0x%x", unit, rd_stat.c_vu);
245 	if ((rd_stat.c_aef & AEF_UD) || (rd_stat.c_ief & (IEF_MD|IEF_RD)))
246 		printf(", block %d", rd_stat.c_blk);
247 	printf(", R0x%x F0x%x A0x%x I0x%x\n",
248 	       rd_stat.c_ref, rd_stat.c_fef, rd_stat.c_aef, rd_stat.c_ief);
249 	return(1);
250 }
251