xref: /csrg-svn/sys/vax/stand/uda.c (revision 30547)
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.2 (Berkeley) 02/21/87
7  */
8 
9 /*
10  * UDA50/RAxx disk device driver
11  */
12 #include "../machine/pte.h"
13 
14 #include "../h/param.h"
15 #include "../h/inode.h"
16 #include "../h/fs.h"
17 #include "../h/disklabel.h"
18 
19 #include "saio.h"
20 #include "savax.h"
21 
22 #define	NRA		4	/* drives per controller */
23 #define	SECTSIZ 	512	/* sector size in bytes */
24 /*
25  * Parameters for the communications area
26  */
27 #define	NRSPL2	0
28 #define	NCMDL2	0
29 #define	NRSP	(1<<NRSPL2)
30 #define	NCMD	(1<<NCMDL2)
31 
32 #include "../vaxuba/udareg.h"
33 #include "../vaxuba/ubareg.h"
34 #include "../vax/mscp.h"
35 
36 u_short udastd[] = { 0772150 };
37 
38 struct iob	cudbuf;
39 
40 /*
41  * Per-controller structures use dimension MAXNUBA,
42  * as only one controller per UNIBUS is supported.
43  */
44 struct udadevice *udaddr[MAXNUBA] = { 0 };
45 
46 struct uda {
47 	struct udaca	uda_ca;
48 	struct mscp	uda_rsp;
49 	struct mscp	uda_cmd;
50 } uda;
51 
52 struct	uda *ud_ubaddr[MAXNUBA];	/* Unibus address of uda structure */
53 struct	disklabel ralabel[MAXNUBA * NRA];
54 static	int ratype[MAXNUBA * NRA];
55 char	lbuf[SECTSIZ];
56 struct	mscp *udcmd();
57 
58 raopen(io)
59 	register struct iob *io;
60 {
61 	register struct mscp *mp;
62 	register struct disklabel *lp;
63 	register struct udadevice *addr;
64 	register struct uda *ubaddr;
65 	register unit;
66 	static int udainit[MAXNUBA], udadriveinit[MAXNUBA * NRA];
67 	int uba;
68 
69 	unit = io->i_unit;
70 	uba = UNITTOUBA(unit);
71 	if (udaddr[uba] == 0)
72 		udaddr[uba] = (struct udadevice *)ubamem(unit, udastd[0]);
73 	addr = udaddr[uba];
74 	if (badaddr((char *)addr, sizeof(short))) {
75 		printf("nonexistent device");
76 		return (ENXIO);
77 	}
78 	if (ud_ubaddr[uba] == 0) {
79 		/*
80 		 * Initialize cudbuf.i_unit so that controllers
81 		 * on UNIBUSes other than 0 can be used.
82 		 */
83 		cudbuf.i_unit = unit;
84 		cudbuf.i_ma = (caddr_t)&uda;
85 		cudbuf.i_cc = sizeof(uda);
86 		ud_ubaddr[uba] = (struct uda *)ubasetup(&cudbuf, 2);
87 	}
88 	ubaddr = ud_ubaddr[uba];
89 	if (udainit[uba] == 0) {
90 		addr->udaip = 0;
91 		while ((addr->udasa & UDA_STEP1) == 0)
92 			;
93 		addr->udasa = UDA_ERR;
94 		while ((addr->udasa & UDA_STEP2) == 0)
95 			;
96 		addr->udasa = (short)&ubaddr->uda_ca.ca_ringbase;
97 		while ((addr->udasa & UDA_STEP3) == 0)
98 			;
99 		addr->udasa =
100 		    (short)(((int)&ubaddr->uda_ca.ca_ringbase) >> 16);
101 		while ((addr->udasa & UDA_STEP4) == 0)
102 			;
103 		addr->udasa = UDA_GO;
104 		uda.uda_ca.ca_rspdsc[0] = (long)&ubaddr->uda_rsp.mscp_cmdref;
105 		uda.uda_ca.ca_cmddsc[0] = (long)&ubaddr->uda_cmd.mscp_cmdref;
106 		uda.uda_cmd.mscp_cntflgs = 0;
107 		if (udcmd(M_OP_STCON, io) == 0) {
108 			printf("ra: open error, STCON");
109 			return (EIO);
110 		}
111 	}
112 	lp = &ralabel[unit];
113 	if (udadriveinit[unit] == 0) {
114 		struct iob tio;
115 
116 		uda.uda_cmd.mscp_unit = UNITTODRIVE(unit);
117 		if (udcmd(M_OP_ONLIN, io) == 0) {
118 			printf("ra: open error, ONLIN");
119 			return (EIO);
120 		}
121 		udainit[uba] = 1;
122 		tio = *io;
123 		tio.i_bn = LABELSECTOR;
124 		tio.i_ma = lbuf;
125 		tio.i_cc = SECTSIZ;
126 		tio.i_flgs |= F_RDDATA;
127 		if (rastrategy(&tio, READ) != SECTSIZ) {
128 			printf("can't read disk label");
129 			return (EIO);
130 		}
131 		*lp = *(struct disklabel *)(lbuf + LABELOFFSET);
132 		if (lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC) {
133 			printf("ra%d: unlabeled\n", unit);
134 #ifdef COMPAT_42
135 			ramaptype(io, lp);
136 #else
137 			return (ENXIO);
138 #endif
139 		}
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");
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 	struct mscp *mp;
155 	int i;
156 
157 	uda.uda_cmd.mscp_opcode = op;
158 	uda.uda_rsp.mscp_header.uda_msglen = sizeof (struct mscp);
159 	uda.uda_cmd.mscp_header.uda_msglen = sizeof (struct mscp);
160 	uda.uda_ca.ca_rspdsc[0] |= UDA_OWN|UDA_INT;
161 	uda.uda_ca.ca_cmddsc[0] |= UDA_OWN|UDA_INT;
162 	i = udaddr[UNITTOUBA(io->i_unit)]->udaip;
163 	for (;;) {
164 		if (uda.uda_ca.ca_cmdint)
165 			uda.uda_ca.ca_cmdint = 0;
166 		if (uda.uda_ca.ca_rspint)
167 			break;
168 	}
169 	uda.uda_ca.ca_rspint = 0;
170 	mp = &uda.uda_rsp;
171 	if (mp->mscp_opcode != (op|M_OP_END) ||
172 	    (mp->mscp_status&M_ST_MASK) != M_ST_SUCC)
173 		return(0);
174 	if (mp->mscp_opcode == (M_OP_ONLIN|M_OP_END))
175 		ratype[io->i_unit] = mp->mscp_mediaid & 0x7f;
176 	return(mp);
177 }
178 
179 rastrategy(io, func)
180 	register struct iob *io;
181 {
182 	register struct mscp *mp;
183 	int ubinfo;
184 
185 	ubinfo = ubasetup(io, 1);
186 	mp = &uda.uda_cmd;
187 	mp->mscp_lbn = io->i_bn;
188 	mp->mscp_unit = io->i_unit&7;
189 	mp->mscp_bytecnt = io->i_cc;
190 	mp->mscp_buffer = (ubinfo & 0x3ffff) | (((ubinfo>>28)&0xf)<<24);
191 	if ((mp = udcmd(func == READ ? M_OP_READ : M_OP_WRITE, io)) == 0) {
192 		printf("ra: I/O error\n");
193 		ubafree(io, ubinfo);
194 		return(-1);
195 	}
196 	ubafree(io, ubinfo);
197 	return(io->i_cc);
198 }
199 
200 /*ARGSUSED*/
201 raioctl(io, cmd, arg)
202 	struct iob *io;
203 	int cmd;
204 	caddr_t arg;
205 {
206 
207 	return (ECMD);
208 }
209 
210 #ifdef COMPAT_42
211 u_long ra25_off[] = { 0, 15884, 0, -1, -1, -1, 25916, -1 };
212 u_long ra60_off[] = { 0, 15884, 0, 49324, 131404, 49324, 242606, 49324 };
213 u_long ra80_off[] = { 0, 15884, 0, -1, 49324, 49324, 49910, 131404 };
214 #ifndef	UCBRA
215 #ifdef RA_COMPAT
216 u_long ra81_off[] = { 0, 16422, 0, 49324, 131404, 412490, 375564, 83538 };
217 #else
218 u_long ra81_off[] = { 0, 16422, 0, 375564, 391986, 699720, 375564, 83538 };
219 #endif
220 #else
221 u_long ra81_off[] = { 0, 15884, 0, 242606, 258490, 565690, 242606, 49324 };
222 #endif
223 
224 ramaptype(io, lp)
225 	register struct iob *io;
226 	register struct disklabel *lp;
227 {
228 	register struct partition *pp;
229 	register i;
230 	register u_long *off;
231 
232 	switch (ratype[io->i_unit]) {
233 	case    25:
234 		off = ra25_off;
235 		break;
236 	case    60:
237 		off = ra60_off;
238 		break;
239 	case    80:
240 		off = ra80_off;
241 		break;
242 	case    81:
243 		off = ra81_off;
244 		break;
245 	default:
246 		printf("uda%d: don't support ra%d's\n",
247 		    io->i_unit, ratype[io->i_unit]);
248 		lp->d_npartitions = 0;
249 		return;
250 	}
251 	lp->d_npartitions = 8;
252 	pp = lp->d_partitions;
253 	for (i = 0; i < 8; i++, pp++)
254 		pp->p_offset = *off++;
255 }
256 #endif
257