xref: /csrg-svn/sys/vax/stand/uda.c (revision 33408)
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.6 (Berkeley) 01/28/88
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 "../vaxuba/udareg.h"
32 #include "../vaxuba/ubareg.h"
33 #include "../vax/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];
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	u_int ratype[MAXNUBA * NRA];
54 char	lbuf[SECTSIZ];
55 
56 raopen(io)
57 	register struct iob *io;
58 {
59 	register struct mscp *mp;
60 	register struct disklabel *lp, *dlp;
61 	register struct udadevice *addr;
62 	register struct uda1 *ubaddr;
63 	register unit;
64 	static int udainit[MAXNUBA];
65 	int uba;
66 
67 	unit = io->i_unit;
68 	uba = UNITTOUBA(unit);
69 	if (udaddr[uba] == 0)
70 		udaddr[uba] = (struct udadevice *)ubamem(unit, udastd[0]);
71 	addr = udaddr[uba];
72 	if (badaddr((char *)addr, sizeof(short))) {
73 		printf("nonexistent device\n");
74 		return (ENXIO);
75 	}
76 	if (ud_ubaddr[uba] == 0) {
77 		/*
78 		 * Initialize cudbuf.i_unit so that controllers
79 		 * on UNIBUSes other than 0 can be used.
80 		 */
81 		cudbuf.i_unit = unit;
82 		cudbuf.i_ma = (caddr_t)&uda1;
83 		cudbuf.i_cc = sizeof(uda1);
84 		ud_ubaddr[uba] = (struct uda1 *)ubasetup(&cudbuf, 2);
85 	}
86 	ubaddr = ud_ubaddr[uba];
87 	if (udainit[uba] == 0) {
88 		addr->udaip = 0;
89 		while ((addr->udasa & UDA_STEP1) == 0)
90 			;
91 		addr->udasa = UDA_ERR;
92 		while ((addr->udasa & UDA_STEP2) == 0)
93 			;
94 		addr->udasa = (short)&ubaddr->uda1_ca.ca_rspdsc;
95 		while ((addr->udasa & UDA_STEP3) == 0)
96 			;
97 		addr->udasa =
98 		    (short)(((int)&ubaddr->uda1_ca.ca_rspdsc) >> 16);
99 		while ((addr->udasa & UDA_STEP4) == 0)
100 			;
101 		addr->udasa = UDA_GO;
102 		uda1.uda1_ca.ca_rspdsc = (long)&ubaddr->uda1_rsp.mscp_cmdref;
103 		uda1.uda1_ca.ca_cmddsc = (long)&ubaddr->uda1_cmd.mscp_cmdref;
104 		/* uda1.uda1_cmd.mscp_cntflgs = 0; */
105 		if (udcmd(M_OP_SETCTLRC, io)) {
106 			printf("ra: open error, SETCTLRC\n");
107 			return (EIO);
108 		}
109 		udainit[uba] = 1;
110 	}
111 	lp = &ralabel[unit];
112 	if (ratype[unit] == 0) {
113 		struct iob tio;
114 
115 		uda1.uda1_cmd.mscp_unit = UNITTODRIVE(unit);
116 		if (udcmd(M_OP_ONLINE, io)) {
117 			printf("ra: open error, ONLINE\n");
118 			return (EIO);
119 		}
120 		ratype[unit] = uda1.uda1_rsp.mscp_onle.onle_drivetype;
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 		*lp = *(struct disklabel *)(lbuf + LABELOFFSET);
131 		if (lp->d_magic != DISKMAGIC || lp->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 		}
139 	}
140 	if ((unsigned)io->i_boff >= lp->d_npartitions ||
141 	    (io->i_boff = lp->d_partitions[io->i_boff].p_offset) == -1) {
142 		printf("ra: bad partition\n");
143 		return (EUNIT);
144 	}
145 	return (0);
146 }
147 
148 int
149 udcmd(op, io)
150 	int op;
151 	register struct iob *io;
152 {
153 	register struct uda1 *u = &uda1;
154 	register struct mscp *mp;
155 	int i;
156 
157 	u->uda1_cmd.mscp_opcode = op;
158 	u->uda1_cmd.mscp_msglen = MSCP_MSGLEN;
159 	u->uda1_rsp.mscp_msglen = MSCP_MSGLEN;
160 	u->uda1_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT;
161 	u->uda1_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT;
162 	i = udaddr[UNITTOUBA(io->i_unit)]->udaip;
163 	mp = &u->uda1_rsp;
164 	for (;;) {
165 		if (u->uda1_ca.ca_cmdint)
166 			u->uda1_ca.ca_cmdint = 0;
167 		if (u->uda1_ca.ca_rspint == 0)
168 			continue;
169 		u->uda1_ca.ca_rspint = 0;
170 		if (mp->mscp_opcode == (op | M_OP_END))
171 			break;
172 		printf("unexpected rsp type %x op %x ignored\n",
173 			MSCP_MSGTYPE(mp->mscp_msgtc), mp->mscp_opcode);
174 		u->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT;
175 	}
176 	if ((mp->mscp_status&M_ST_MASK) != M_ST_SUCCESS)
177 		return (-1);
178 	return (0);
179 }
180 
181 rastrategy(io, func)
182 	register struct iob *io;
183 {
184 	register struct mscp *mp;
185 	int ubinfo;
186 
187 	ubinfo = ubasetup(io, 1);
188 	mp = &uda1.uda1_cmd;
189 	mp->mscp_unit = UNITTODRIVE(io->i_unit);
190 	mp->mscp_seq.seq_lbn = io->i_bn;
191 	mp->mscp_seq.seq_bytecount = io->i_cc;
192 	mp->mscp_seq.seq_buffer = (ubinfo & 0x3ffff) | (((ubinfo>>28)&0xf)<<24);
193 	if (udcmd(func == READ ? M_OP_READ : M_OP_WRITE, io)) {
194 		printf("ra: I/O error\n");
195 		ubafree(io, ubinfo);
196 		return(-1);
197 	}
198 	ubafree(io, ubinfo);
199 	return(io->i_cc);
200 }
201 
202 /*ARGSUSED*/
203 raioctl(io, cmd, arg)
204 	struct iob *io;
205 	int cmd;
206 	caddr_t arg;
207 {
208 
209 	return (ECMD);
210 }
211 
212 #ifdef COMPAT_42
213 u_long ra25_off[] = { 0, 15884, 0, -1, -1, -1, 25916, -1 };
214 u_long rx50_off[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
215 u_long rd52_off[] = { 0, 15884, 0, 0, 0, 0, 25650, 0 };
216 u_long rd53_off[] = { 0, 15884, 0, 0, 0, 33440, 49324, 15884 };
217 u_long ra60_off[] = { 0, 15884, 0, 49324, 131404, 49324, 242606, 49324 };
218 u_long ra80_off[] = { 0, 15884, 0, -1, 49324, 49324, 49910, 131404 };
219 #ifndef	UCBRA
220 #ifdef RA_COMPAT
221 u_long ra81_off[] = { 0, 16422, 0, 49324, 131404, 412490, 375564, 83538 };
222 #else
223 u_long ra81_off[] = { 0, 16422, 0, 375564, 391986, 699720, 375564, 83538 };
224 #endif
225 #else
226 u_long ra81_off[] = { 0, 15884, 0, 242606, 258490, 565690, 242606, 49324 };
227 #endif
228 
229 u_long	*ra_off[] = {
230 	0,		/* 0 = unused */
231 	ra80_off,	/* 1 = ra80 */
232 	ra25_off,	/* 2 = rc25 removable */
233 	ra25_off,	/* 3 = rc25 fixed */
234 	ra60_off,	/* 4 = ra60 */
235 	ra81_off,	/* 5 = ra81 */
236 	0,		/* 6 = ? */
237 	rx50_off,	/* 7 = rx50 */
238 	rd52_off,	/* 8 = rd52 */
239 	rd53_off,	/* 9 = rd53 */
240 };
241 
242 #define NOFFS	(sizeof(ra_off)/sizeof(ra_off[0]))
243 
244 ramaptype(io, lp)
245 	register struct iob *io;
246 	register struct disklabel *lp;
247 {
248 	register struct partition *pp;
249 	register u_int i;
250 	register u_long *off;
251 
252 	if ((i = ratype[io->i_unit]) >= NOFFS || (off = ra_off[i]) == 0) {
253 		printf("ra%d: ra type %d unsupported\n", io->i_unit, i);
254 		lp->d_npartitions = 0;
255 		return;
256 	}
257 	lp->d_npartitions = 8;
258 	for (pp = lp->d_partitions, i = 0; i < 8; pp++, i++)
259 		pp->p_offset = *off++;
260 }
261 #endif
262