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