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