xref: /netbsd/sys/arch/vax/boot/boot/ra.c (revision c4a72b64)
1 /*	$NetBSD: ra.c,v 1.11 2002/06/04 15:13:55 ragge Exp $ */
2 /*
3  * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *     This product includes software developed at Ludd, University of Lule}.
17  * 4. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32  /* All bugs are subject to removal without further notice */
33 
34 #define NRSP 1 /* Kludge */
35 #define NCMD 1 /* Kludge */
36 
37 #include "sys/param.h"
38 #include "sys/disklabel.h"
39 
40 #include "lib/libsa/stand.h"
41 
42 #include "lib/libkern/libkern.h"
43 
44 #include "../include/pte.h"
45 #include "../include/rpb.h"
46 
47 #include "dev/mscp/mscp.h"
48 #include "dev/mscp/mscpreg.h"
49 
50 #include "dev/bi/bireg.h"
51 #include "dev/bi/kdbreg.h"
52 
53 #include "vaxstand.h"
54 
55 static void command(int, int);
56 
57 /*
58  * These routines for RA disk standalone boot is wery simple,
59  * assuming a lots of thing like that we only working at one ra disk
60  * a time, no separate routines for uba driver etc..
61  * This code is foolish and should need a cleanup.
62  * But it works :)
63  */
64 
65 static volatile struct uda {
66 	struct	mscp_1ca uda_ca;  /* communications area */
67 	struct	mscp uda_rsp;	  /* response packets */
68 	struct	mscp uda_cmd;	  /* command packets */
69 } uda;
70 
71 static struct disklabel ralabel;
72 static char io_buf[DEV_BSIZE];
73 static int dpart, dunit, remap, is_tmscp, curblock;
74 static volatile u_short *ra_ip, *ra_sa, *ra_sw;
75 static volatile u_int *mapregs;
76 
77 int
78 raopen(struct open_file *f, int adapt, int ctlr, int unit, int part)
79 {
80 	static volatile struct uda *ubauda;
81 	unsigned short johan, johan2;
82 	size_t i;
83 	int err;
84 	char *msg;
85 
86 #ifdef DEV_DEBUG
87 	printf("raopen: adapter %d ctlr %d unit %d part %d\n",
88 	    adapt, ctlr, unit, part);
89 	printf("raopen: csrbase %x nexaddr %x\n", csrbase, nexaddr);
90 #endif
91 	bzero(&ralabel, sizeof(struct disklabel));
92 	bzero((void *)&uda, sizeof(struct uda));
93 	if (bootrpb.devtyp == BDEV_TK)
94 		is_tmscp = 1;
95 	dunit = unit;
96 	dpart = part;
97 	if (ctlr < 0)
98 		ctlr = 0;
99 	remap = csrbase && nexaddr;
100 	curblock = 0;
101 	if (csrbase) { /* On a uda-alike adapter */
102 		if (askname == 0) {
103 			csrbase = bootrpb.csrphy;
104 			dunit = bootrpb.unit;
105 			nexaddr = bootrpb.adpphy;
106 		} else
107 			csrbase += (ctlr ? 000334 : 012150);
108 		ra_ip = (short *)csrbase;
109 		ra_sa = ra_sw = (short *)csrbase + 1;
110 		if (nexaddr) { /* have map registers */
111 			mapregs = (int *)nexaddr + 512;
112 			mapregs[494] = PG_V | (((u_int)&uda) >> 9);
113 			mapregs[495] = mapregs[494] + 1;
114 			(char *)ubauda = (char *)0x3dc00 +
115 			    (((u_int)(&uda))&0x1ff);
116 		} else
117 			ubauda = &uda;
118 		johan = (((u_int)ubauda) & 0xffff) + 8;
119 		johan2 = (((u_int)ubauda) >> 16) & 077;
120 		*ra_ip = 0; /* Start init */
121 		bootrpb.csrphy = csrbase;
122 	} else {
123 		paddr_t kdaddr;
124 		volatile int *w;
125 		volatile int i = 10000;
126 
127 		if (askname == 0) {
128 			nexaddr = bootrpb.csrphy;
129 			dunit = bootrpb.unit;
130 		} else {
131 			nexaddr = (bootrpb.csrphy & ~(BI_NODESIZE - 1)) + KDB_IP;
132 			bootrpb.csrphy = nexaddr;
133 		}
134 
135 		kdaddr = nexaddr & ~(BI_NODESIZE - 1);
136 		ra_ip = (short *)(kdaddr + KDB_IP);
137 		ra_sa = (short *)(kdaddr + KDB_SA);
138 		ra_sw = (short *)(kdaddr + KDB_SW);
139 		johan = ((u_int)&uda.uda_ca.ca_rspdsc) & 0xffff;
140 		johan2 = (((u_int)&uda.uda_ca.ca_rspdsc) & 0xffff0000) >> 16;
141 		w = (int *)(kdaddr + BIREG_VAXBICSR);
142 		*w = *w | BICSR_NRST;
143 		while (i--) /* Need delay??? */
144 			;
145 		w = (int *)(kdaddr + BIREG_BER);
146 		*w = ~(BIBER_MBZ|BIBER_NMR|BIBER_UPEN);/* ??? */
147 		ubauda = &uda;
148 	}
149 
150 #ifdef DEV_DEBUG
151 	printf("start init\n");
152 #endif
153 	/* Init of this uda */
154 	while ((*ra_sa & MP_STEP1) == 0)
155 		;
156 #ifdef DEV_DEBUG
157 	printf("MP_STEP1...");
158 #endif
159 	*ra_sw = 0x8000;
160 	while ((*ra_sa & MP_STEP2) == 0)
161 		;
162 #ifdef DEV_DEBUG
163 	printf("MP_STEP2...");
164 #endif
165 
166 	*ra_sw = johan;
167 	while ((*ra_sa & MP_STEP3) == 0)
168 		;
169 #ifdef DEV_DEBUG
170 	printf("MP_STEP3...");
171 #endif
172 
173 	*ra_sw = johan2;
174 	while ((*ra_sa & MP_STEP4) == 0)
175 		;
176 #ifdef DEV_DEBUG
177 	printf("MP_STEP4\n");
178 #endif
179 
180 	*ra_sw = 0x0001;
181 	uda.uda_ca.ca_rspdsc = (int)&ubauda->uda_rsp.mscp_cmdref;
182 	uda.uda_ca.ca_cmddsc = (int)&ubauda->uda_cmd.mscp_cmdref;
183 	if (is_tmscp) {
184 		uda.uda_cmd.mscp_un.un_seq.seq_addr =
185 		    (long *)&uda.uda_ca.ca_cmddsc;
186 		uda.uda_rsp.mscp_un.un_seq.seq_addr =
187 		    (long *)&uda.uda_ca.ca_rspdsc;
188 		uda.uda_cmd.mscp_vcid = 1;
189 		uda.uda_cmd.mscp_un.un_sccc.sccc_ctlrflags = 0;
190 	}
191 
192 	command(M_OP_SETCTLRC, 0);
193 	uda.uda_cmd.mscp_unit = dunit;
194 	command(M_OP_ONLINE, 0);
195 
196 	if (is_tmscp) {
197 		if (part) {
198 #ifdef DEV_DEBUG
199 			printf("Repos of tape...");
200 #endif
201 			uda.uda_cmd.mscp_un.un_seq.seq_buffer = part;
202 			command(M_OP_POS, 0);
203 			uda.uda_cmd.mscp_un.un_seq.seq_buffer = 0;
204 #ifdef DEV_DEBUG
205 			printf("Done!\n");
206 #endif
207 		}
208 		return 0;
209 	}
210 #ifdef DEV_DEBUG
211 	printf("reading disklabel\n");
212 #endif
213 	err = rastrategy(0, F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i);
214 	if(err){
215 		printf("reading disklabel: %s\n",strerror(err));
216 		return 0;
217 	}
218 
219 #ifdef DEV_DEBUG
220 	printf("getting disklabel\n");
221 #endif
222 	msg = getdisklabel(io_buf+LABELOFFSET, &ralabel);
223 	if (msg)
224 		printf("getdisklabel: %s\n", msg);
225 	return(0);
226 }
227 
228 static void
229 command(int cmd, int arg)
230 {
231 	volatile short hej;
232 	int to;
233 
234 igen:	uda.uda_cmd.mscp_opcode = cmd;
235 	uda.uda_cmd.mscp_modifier = arg;
236 
237 	uda.uda_cmd.mscp_msglen = MSCP_MSGLEN;
238 	uda.uda_rsp.mscp_msglen = MSCP_MSGLEN;
239 	uda.uda_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT;
240 	uda.uda_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT;
241 #ifdef DEV_DEBUG
242 	printf("sending cmd %x...", cmd);
243 #endif
244 	hej = *ra_ip;
245 	to = 10000000;
246 	while (uda.uda_ca.ca_rspdsc < 0) {
247 //		if (uda.uda_ca.ca_cmdint)
248 //			uda.uda_ca.ca_cmdint = 0;
249 		if (--to < 0) {
250 #ifdef DEV_DEBUG
251 			printf("timing out, retry\n");
252 #endif
253 			goto igen;
254 		}
255 	}
256 #ifdef DEV_DEBUG
257 	printf("sent.\n");
258 #endif
259 }
260 
261 int
262 rastrategy(void *f, int func, daddr_t dblk,
263     size_t size, void *buf, size_t *rsize)
264 {
265 	u_int	pfnum, mapnr, nsize;
266 
267 #ifdef DEV_DEBUG
268 	printf("rastrategy: buf %p remap %d is_tmscp %d\n",
269 	    buf, remap, is_tmscp);
270 #endif
271 	if (remap) {
272 		pfnum = (u_int)buf >> VAX_PGSHIFT;
273 
274 		for(mapnr = 0, nsize = size; (nsize + VAX_NBPG) > 0;
275 		    nsize -= VAX_NBPG)
276 			mapregs[mapnr++] = PG_V | pfnum++;
277 		uda.uda_cmd.mscp_seq.seq_buffer = ((u_int)buf) & 0x1ff;
278 	} else
279 		uda.uda_cmd.mscp_seq.seq_buffer = ((u_int)buf);
280 
281 	if (is_tmscp) {
282 		int i;
283 
284 		/*
285 		 * First position tape. Remember where we are.
286 		 */
287 		if (dblk < curblock) {
288 			uda.uda_cmd.mscp_seq.seq_bytecount = curblock - dblk;
289 			command(M_OP_POS, 12); /* 12 == step block backward */
290 		} else {
291 			uda.uda_cmd.mscp_seq.seq_bytecount = dblk - curblock;
292 			command(M_OP_POS, 4); /* 4 == step block forward */
293 		}
294 		curblock = size/512 + dblk;
295 
296 		/*
297 		 * Read in the number of blocks we need.
298 		 * Why doesn't read of multiple blocks work?????
299 		 */
300 		for (i = 0 ; i < size/512 ; i++) {
301 			uda.uda_cmd.mscp_seq.seq_lbn = 1;
302 			uda.uda_cmd.mscp_seq.seq_bytecount = 512;
303 			uda.uda_cmd.mscp_seq.seq_buffer =
304 			    (((u_int)buf) & 0x1ff) + i * 512;
305 			uda.uda_cmd.mscp_unit = dunit;
306 			command(M_OP_READ, 0);
307 		}
308 	} else {
309 
310 		uda.uda_cmd.mscp_seq.seq_lbn =
311 		    dblk + ralabel.d_partitions[dpart].p_offset;
312 		uda.uda_cmd.mscp_seq.seq_bytecount = size;
313 		uda.uda_cmd.mscp_unit = dunit;
314 #ifdef DEV_DEBUG
315 		printf("rastrategy: blk 0x%lx count %lx unit %x\n",
316 		    uda.uda_cmd.mscp_seq.seq_lbn, size, dunit);
317 #endif
318 #ifdef notdef
319 		if (func == F_WRITE)
320 			command(M_OP_WRITE, 0);
321 		else
322 #endif
323 			command(M_OP_READ, 0);
324 	}
325 
326 	*rsize = size;
327 	return 0;
328 }
329