1 /* $NetBSD: ra.c,v 1.10 2002/05/24 21:41:40 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 = 1000000; 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