1 /* $NetBSD: ra.c,v 1.23 2025/07/14 12:39:34 hans 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 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 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 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 311 int 312 raclose(struct open_file *f) 313 { 314 /* Reset controller by starting a soft initialization */ 315 *ra_ip = 0; 316 317 return 0; 318 } 319