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