xref: /original-bsd/sys/vax/stand/uda.c (revision 92c664ec)
1 /*
2  * Copyright (c) 1982, 1986 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)uda.c	7.5 (Berkeley) 12/12/87
7  */
8 
9 /*
10  * UDA50/RAxx disk device driver
11  */
12 #include "../machine/pte.h"
13 
14 #include "param.h"
15 #include "inode.h"
16 #include "fs.h"
17 #include "disklabel.h"
18 
19 #include "saio.h"
20 #include "savax.h"
21 
22 #define	NRA		8	/* max. unit number on controller */
23 #define	SECTSIZ 	512	/* sector size in bytes */
24 
25 /*
26  * Unused, but needed in udareg.h
27  */
28 #define NRSP	1
29 #define NCMD	1
30 
31 #include "udareg.h"
32 #include "../vaxuba/ubareg.h"
33 #include "mscp.h"
34 
35 u_short udastd[] = { 0772150 };
36 
37 struct iob	cudbuf;
38 
39 /*
40  * Per-controller structures use dimension MAXNUBA,
41  * as only one controller per UNIBUS is supported.
42  */
43 struct udadevice *udaddr[MAXNUBA] = { 0 };
44 
45 struct	uda1 {
46 	struct	uda1ca uda1_ca;	/* communications area */
47 	struct	mscp uda1_rsp;	/* response packet */
48 	struct	mscp uda1_cmd;	/* command packet */
49 } uda1;
50 
51 struct	uda1 *ud_ubaddr[MAXNUBA];	/* Unibus address of uda structure */
52 struct	disklabel ralabel[MAXNUBA * NRA];
53 static	int ratype[MAXNUBA * NRA];
54 char	lbuf[SECTSIZ];
55 struct	mscp *udcmd();
56 
57 raopen(io)
58 	register struct iob *io;
59 {
60 	register struct mscp *mp;
61 	register struct disklabel *lp, *dlp;
62 	register struct udadevice *addr;
63 	register struct uda1 *ubaddr;
64 	register unit;
65 	static int udainit[MAXNUBA];
66 	int uba;
67 
68 	unit = io->i_unit;
69 	uba = UNITTOUBA(unit);
70 	if (udaddr[uba] == 0)
71 		udaddr[uba] = (struct udadevice *)ubamem(unit, udastd[0]);
72 	addr = udaddr[uba];
73 	if (badaddr((char *)addr, sizeof(short))) {
74 		printf("nonexistent device\n");
75 		return (ENXIO);
76 	}
77 	if (ud_ubaddr[uba] == 0) {
78 		/*
79 		 * Initialize cudbuf.i_unit so that controllers
80 		 * on UNIBUSes other than 0 can be used.
81 		 */
82 		cudbuf.i_unit = unit;
83 		cudbuf.i_ma = (caddr_t)&uda1;
84 		cudbuf.i_cc = sizeof(uda1);
85 		ud_ubaddr[uba] = (struct uda1 *)ubasetup(&cudbuf, 2);
86 	}
87 	ubaddr = ud_ubaddr[uba];
88 	if (udainit[uba] == 0) {
89 		addr->udaip = 0;
90 		while ((addr->udasa & UDA_STEP1) == 0)
91 			;
92 		addr->udasa = UDA_ERR;
93 		while ((addr->udasa & UDA_STEP2) == 0)
94 			;
95 		addr->udasa = (short)&ubaddr->uda1_ca.ca_rspdsc;
96 		while ((addr->udasa & UDA_STEP3) == 0)
97 			;
98 		addr->udasa =
99 		    (short)(((int)&ubaddr->uda1_ca.ca_rspdsc) >> 16);
100 		while ((addr->udasa & UDA_STEP4) == 0)
101 			;
102 		addr->udasa = UDA_GO;
103 		uda1.uda1_ca.ca_rspdsc = (long)&ubaddr->uda1_rsp.mscp_cmdref;
104 		uda1.uda1_ca.ca_cmddsc = (long)&ubaddr->uda1_cmd.mscp_cmdref;
105 		/* uda1.uda1_cmd.mscp_cntflgs = 0; */
106 		if (udcmd(M_OP_SETCTLRC, io) == 0) {
107 			printf("ra: open error, SETCTLRC\n");
108 			return (EIO);
109 		}
110 		udainit[uba] = 1;
111 	}
112 	lp = &ralabel[unit];
113 	if (ratype[unit] == 0) {
114 		struct iob tio;
115 
116 		uda1.uda1_cmd.mscp_unit = UNITTODRIVE(unit);
117 		if (udcmd(M_OP_ONLINE, io) == 0) {
118 			printf("ra: open error, ONLINE\n");
119 			return (EIO);
120 		}
121 		tio = *io;
122 		tio.i_bn = LABELSECTOR;
123 		tio.i_ma = lbuf;
124 		tio.i_cc = SECTSIZ;
125 		tio.i_flgs |= F_RDDATA;
126 		if (rastrategy(&tio, READ) != SECTSIZ) {
127 			printf("can't read disk label\n");
128 			return (EIO);
129 		}
130 		dlp = (struct disklabel *)(lbuf + LABELOFFSET);
131 		if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
132 			printf("ra%d: unlabeled\n", unit);
133 #ifdef COMPAT_42
134 			ramaptype(io, lp);
135 #else
136 			return (ENXIO);
137 #endif
138 		} else
139 			*lp = *dlp;
140 	}
141 	if ((unsigned)io->i_boff >= lp->d_npartitions ||
142 	    (io->i_boff = lp->d_partitions[io->i_boff].p_offset) == -1) {
143 		printf("ra: bad partition\n");
144 		return (EUNIT);
145 	}
146 	return (0);
147 }
148 
149 struct mscp *
150 udcmd(op, io)
151 	int op;
152 	register struct iob *io;
153 {
154 	register struct mscp *mp;
155 	int i;
156 
157 	uda1.uda1_cmd.mscp_opcode = op;
158 	uda1.uda1_cmd.mscp_msglen = MSCP_MSGLEN;
159 	uda1.uda1_rsp.mscp_msglen = MSCP_MSGLEN;
160 	uda1.uda1_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT;
161 	uda1.uda1_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT;
162 	i = udaddr[UNITTOUBA(io->i_unit)]->udaip;
163 	mp = &uda1.uda1_rsp;
164 	for (;;) {
165 		if (uda1.uda1_ca.ca_cmdint)
166 			uda1.uda1_ca.ca_cmdint = 0;
167 		if (uda1.uda1_ca.ca_rspint == 0)
168 			continue;
169 		uda1.uda1_ca.ca_rspint = 0;
170 		if (mp->mscp_opcode == (op | M_OP_END))
171 			break;
172 		printf("unexpected mscp response (type 0x%x) ignored",
173 				MSCP_MSGTYPE(mp->mscp_msgtc));
174 		uda1.uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT;
175 	}
176 	if ((mp->mscp_status&M_ST_MASK) != M_ST_SUCCESS)
177 		return(0);
178 	if (mp->mscp_opcode == (M_OP_ONLINE|M_OP_END))
179 		ratype[io->i_unit] = mp->mscp_onle.onle_drivetype;
180 	return(mp);
181 }
182 
183 rastrategy(io, func)
184 	register struct iob *io;
185 {
186 	register struct mscp *mp;
187 	int ubinfo;
188 
189 	ubinfo = ubasetup(io, 1);
190 	mp = &uda1.uda1_cmd;
191 	mp->mscp_unit = UNITTODRIVE(io->i_unit);
192 	mp->mscp_seq.seq_lbn = io->i_bn;
193 	mp->mscp_seq.seq_bytecount = io->i_cc;
194 	mp->mscp_seq.seq_buffer = (ubinfo & 0x3ffff) | (((ubinfo>>28)&0xf)<<24);
195 	if ((mp = udcmd(func == READ ? M_OP_READ : M_OP_WRITE, io)) == 0) {
196 		printf("ra: I/O error\n");
197 		ubafree(io, ubinfo);
198 		return(-1);
199 	}
200 	ubafree(io, ubinfo);
201 	return(io->i_cc);
202 }
203 
204 /*ARGSUSED*/
205 raioctl(io, cmd, arg)
206 	struct iob *io;
207 	int cmd;
208 	caddr_t arg;
209 {
210 
211 	return (ECMD);
212 }
213 
214 #ifdef COMPAT_42
215 u_long ra25_off[] = { 0, 15884, 0, -1, -1, -1, 25916, -1 };
216 u_long rx50_off[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
217 u_long rd52_off[] = { 0, 15884, 0, 0, 0, 0, 25650, 0 };
218 u_long rd53_off[] = { 0, 15884, 0, 0, 0, 33440, 49324, 15884 };
219 u_long ra60_off[] = { 0, 15884, 0, 49324, 131404, 49324, 242606, 49324 };
220 u_long ra80_off[] = { 0, 15884, 0, -1, 49324, 49324, 49910, 131404 };
221 #ifndef	UCBRA
222 #ifdef RA_COMPAT
223 u_long ra81_off[] = { 0, 16422, 0, 49324, 131404, 412490, 375564, 83538 };
224 #else
225 u_long ra81_off[] = { 0, 16422, 0, 375564, 391986, 699720, 375564, 83538 };
226 #endif
227 #else
228 u_long ra81_off[] = { 0, 15884, 0, 242606, 258490, 565690, 242606, 49324 };
229 #endif
230 
231 u_long	*ra_off[] = {
232 	0,		/* 0 = unused */
233 	ra80_off,	/* 1 = ra80 */
234 	ra25_off,	/* 2 = rc25 removable */
235 	ra25_off,	/* 3 = rc25 fixed */
236 	ra60_off,	/* 4 = ra60 */
237 	ra81_off,	/* 5 = ra81 */
238 	0,		/* 6 = ? */
239 	rx50_off,	/* 7 = rx50 */
240 	rd52_off,	/* 8 = rd52 */
241 	rd53_off,	/* 9 = rd53 */
242 };
243 
244 #define NOFFS	(sizeof(ra_off)/sizeof(int))
245 
246 ramaptype(io, lp)
247 	register struct iob *io;
248 	register struct disklabel *lp;
249 {
250 	register struct partition *pp;
251 	register int i;
252 	register u_long *off;
253 
254 	i = ratype[io->i_unit];
255 	if ((unsigned)i >= NOFFS || (off = ra_off[i]) == 0) {
256 		printf("ra%d: ra type %d unsupported\n", io->i_unit, i);
257 		lp->d_npartitions = 0;
258 		return;
259 	}
260 	lp->d_npartitions = 8;
261 	for (pp = lp->d_partitions, i = 0; i < 8; pp++, i++)
262 		pp->p_offset = *off++;
263 }
264 #endif
265