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