123247Smckusick /* 229315Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323247Smckusick * All rights reserved. The Berkeley software License Agreement 423247Smckusick * specifies the terms and conditions for redistribution. 523247Smckusick * 6*32613Sbostic * @(#)uda.c 7.4 (Berkeley) 11/13/87 723247Smckusick */ 85153Ssam 95153Ssam /* 105153Ssam * UDA50/RAxx disk device driver 115153Ssam */ 129806Ssam #include "../machine/pte.h" 135153Ssam 14*32613Sbostic #include "param.h" 15*32613Sbostic #include "inode.h" 16*32613Sbostic #include "fs.h" 17*32613Sbostic #include "disklabel.h" 189186Ssam 195153Ssam #include "saio.h" 205153Ssam #include "savax.h" 215153Ssam 22*32613Sbostic #define NRA 8 /* max. unit number on controller */ 2330547Skarels #define SECTSIZ 512 /* sector size in bytes */ 24*32613Sbostic 255153Ssam /* 26*32613Sbostic * Unused, but needed in udareg.h 275153Ssam */ 28*32613Sbostic #define NRSP 1 29*32613Sbostic #define NCMD 1 305153Ssam 319186Ssam #include "../vaxuba/udareg.h" 329186Ssam #include "../vaxuba/ubareg.h" 339186Ssam #include "../vax/mscp.h" 345153Ssam 3511181Ssam u_short udastd[] = { 0772150 }; 365153Ssam 375153Ssam struct iob cudbuf; 385153Ssam 3930547Skarels /* 4030547Skarels * Per-controller structures use dimension MAXNUBA, 4130547Skarels * as only one controller per UNIBUS is supported. 4230547Skarels */ 4330547Skarels struct udadevice *udaddr[MAXNUBA] = { 0 }; 445153Ssam 45*32613Sbostic struct uda1 { 46*32613Sbostic struct uda1ca uda1_ca; /* communications area */ 47*32613Sbostic struct mscp uda1_rsp; /* response packet */ 48*32613Sbostic struct mscp uda1_cmd; /* command packet */ 49*32613Sbostic } uda1; 505153Ssam 51*32613Sbostic struct uda1 *ud_ubaddr[MAXNUBA]; /* Unibus address of uda structure */ 5230547Skarels struct disklabel ralabel[MAXNUBA * NRA]; 5330547Skarels static int ratype[MAXNUBA * NRA]; 5430547Skarels char lbuf[SECTSIZ]; 5530547Skarels struct mscp *udcmd(); 565153Ssam 5711111Ssam raopen(io) 585153Ssam register struct iob *io; 595153Ssam { 605153Ssam register struct mscp *mp; 61*32613Sbostic register struct disklabel *lp, *dlp; 6230547Skarels register struct udadevice *addr; 63*32613Sbostic register struct uda1 *ubaddr; 6430547Skarels register unit; 65*32613Sbostic static int udainit[MAXNUBA]; 6630547Skarels int uba; 675153Ssam 6830547Skarels unit = io->i_unit; 6930547Skarels uba = UNITTOUBA(unit); 7030547Skarels if (udaddr[uba] == 0) 7130547Skarels udaddr[uba] = (struct udadevice *)ubamem(unit, udastd[0]); 7230547Skarels addr = udaddr[uba]; 7330547Skarels if (badaddr((char *)addr, sizeof(short))) { 7432194Skarels printf("nonexistent device\n"); 7530547Skarels return (ENXIO); 7630547Skarels } 7730547Skarels if (ud_ubaddr[uba] == 0) { 7817231Smckusick /* 7930547Skarels * Initialize cudbuf.i_unit so that controllers 8017231Smckusick * on UNIBUSes other than 0 can be used. 8117231Smckusick */ 8230547Skarels cudbuf.i_unit = unit; 83*32613Sbostic cudbuf.i_ma = (caddr_t)&uda1; 84*32613Sbostic cudbuf.i_cc = sizeof(uda1); 85*32613Sbostic ud_ubaddr[uba] = (struct uda1 *)ubasetup(&cudbuf, 2); 865153Ssam } 8730547Skarels ubaddr = ud_ubaddr[uba]; 8830547Skarels if (udainit[uba] == 0) { 8930547Skarels addr->udaip = 0; 9030547Skarels while ((addr->udasa & UDA_STEP1) == 0) 9117231Smckusick ; 9230547Skarels addr->udasa = UDA_ERR; 9330547Skarels while ((addr->udasa & UDA_STEP2) == 0) 9417231Smckusick ; 95*32613Sbostic addr->udasa = (short)&ubaddr->uda1_ca.ca_rspdsc; 9630547Skarels while ((addr->udasa & UDA_STEP3) == 0) 9717231Smckusick ; 9830547Skarels addr->udasa = 99*32613Sbostic (short)(((int)&ubaddr->uda1_ca.ca_rspdsc) >> 16); 10030547Skarels while ((addr->udasa & UDA_STEP4) == 0) 10117231Smckusick ; 10230547Skarels addr->udasa = UDA_GO; 103*32613Sbostic uda1.uda1_ca.ca_rspdsc = (long)&ubaddr->uda1_rsp.mscp_cmdref; 104*32613Sbostic uda1.uda1_ca.ca_cmddsc = (long)&ubaddr->uda1_cmd.mscp_cmdref; 105*32613Sbostic /* uda1.uda1_cmd.mscp_cntflgs = 0; */ 106*32613Sbostic if (udcmd(M_OP_SETCTLRC, io) == 0) { 107*32613Sbostic printf("ra: open error, SETCTLRC\n"); 10830547Skarels return (EIO); 10917231Smckusick } 110*32613Sbostic udainit[uba] = 1; 11127075Skarels } 11230547Skarels lp = &ralabel[unit]; 113*32613Sbostic if (ratype[unit] == 0) { 11430547Skarels struct iob tio; 11530547Skarels 116*32613Sbostic uda1.uda1_cmd.mscp_unit = UNITTODRIVE(unit); 117*32613Sbostic if (udcmd(M_OP_ONLINE, io) == 0) { 118*32613Sbostic printf("ra: open error, ONLINE\n"); 11930547Skarels return (EIO); 12017231Smckusick } 12130547Skarels tio = *io; 12230547Skarels tio.i_bn = LABELSECTOR; 12330547Skarels tio.i_ma = lbuf; 12430547Skarels tio.i_cc = SECTSIZ; 12530547Skarels tio.i_flgs |= F_RDDATA; 12630547Skarels if (rastrategy(&tio, READ) != SECTSIZ) { 12732194Skarels printf("can't read disk label\n"); 12830547Skarels return (EIO); 12930547Skarels } 130*32613Sbostic dlp = (struct disklabel *)(lbuf + LABELOFFSET); 131*32613Sbostic if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { 13230547Skarels printf("ra%d: unlabeled\n", unit); 13330547Skarels #ifdef COMPAT_42 13430547Skarels ramaptype(io, lp); 13530547Skarels #else 13630547Skarels return (ENXIO); 13730547Skarels #endif 13832194Skarels } else 139*32613Sbostic *lp = *dlp; 1405153Ssam } 14130547Skarels if ((unsigned)io->i_boff >= lp->d_npartitions || 14230547Skarels (io->i_boff = lp->d_partitions[io->i_boff].p_offset) == -1) { 14332194Skarels printf("ra: bad partition\n"); 14430547Skarels return (EUNIT); 14527075Skarels } 14630547Skarels return (0); 1475153Ssam } 1485153Ssam 1495153Ssam struct mscp * 15030547Skarels udcmd(op, io) 1515153Ssam int op; 15230547Skarels register struct iob *io; 1535153Ssam { 154*32613Sbostic register struct mscp *mp; 1555153Ssam int i; 1565153Ssam 157*32613Sbostic uda1.uda1_cmd.mscp_opcode = op; 158*32613Sbostic uda1.uda1_cmd.mscp_msglen = MSCP_MSGLEN; 159*32613Sbostic uda1.uda1_rsp.mscp_msglen = MSCP_MSGLEN; 160*32613Sbostic uda1.uda1_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT; 161*32613Sbostic uda1.uda1_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT; 16230547Skarels i = udaddr[UNITTOUBA(io->i_unit)]->udaip; 163*32613Sbostic mp = &uda1.uda1_rsp; 1645153Ssam for (;;) { 165*32613Sbostic if (uda1.uda1_ca.ca_cmdint) 166*32613Sbostic uda1.uda1_ca.ca_cmdint = 0; 167*32613Sbostic if (uda1.uda1_ca.ca_rspint == 0) 168*32613Sbostic continue; 169*32613Sbostic uda1.uda1_ca.ca_rspint = 0; 170*32613Sbostic if (mp->mscp_opcode == (op | M_OP_END)) 1715153Ssam break; 172*32613Sbostic printf("unexpected mscp response (type 0x%x) ignored", 173*32613Sbostic MSCP_MSGTYPE(mp->mscp_msgtc)); 174*32613Sbostic uda1.uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; 1755153Ssam } 176*32613Sbostic if ((mp->mscp_status&M_ST_MASK) != M_ST_SUCCESS) 1775153Ssam return(0); 178*32613Sbostic if (mp->mscp_opcode == (M_OP_ONLINE|M_OP_END)) 179*32613Sbostic ratype[io->i_unit] = mp->mscp_onle.onle_drivetype; 1805153Ssam return(mp); 1815153Ssam } 1825153Ssam 18311111Ssam rastrategy(io, func) 1845153Ssam register struct iob *io; 1855153Ssam { 1865153Ssam register struct mscp *mp; 1875153Ssam int ubinfo; 1885153Ssam 1895153Ssam ubinfo = ubasetup(io, 1); 190*32613Sbostic mp = &uda1.uda1_cmd; 19132194Skarels mp->mscp_unit = UNITTODRIVE(io->i_unit); 192*32613Sbostic mp->mscp_seq.seq_lbn = io->i_bn; 193*32613Sbostic mp->mscp_seq.seq_bytecount = io->i_cc; 194*32613Sbostic mp->mscp_seq.seq_buffer = (ubinfo & 0x3ffff) | (((ubinfo>>28)&0xf)<<24); 19530547Skarels if ((mp = udcmd(func == READ ? M_OP_READ : M_OP_WRITE, io)) == 0) { 1965153Ssam printf("ra: I/O error\n"); 1975153Ssam ubafree(io, ubinfo); 1985153Ssam return(-1); 1995153Ssam } 2005153Ssam ubafree(io, ubinfo); 2015153Ssam return(io->i_cc); 2025153Ssam } 20310024Ssam 20410024Ssam /*ARGSUSED*/ 20511111Ssam raioctl(io, cmd, arg) 20610024Ssam struct iob *io; 20710024Ssam int cmd; 20810024Ssam caddr_t arg; 20910024Ssam { 21010024Ssam 21110024Ssam return (ECMD); 21210024Ssam } 21330547Skarels 21430547Skarels #ifdef COMPAT_42 21530547Skarels u_long ra25_off[] = { 0, 15884, 0, -1, -1, -1, 25916, -1 }; 216*32613Sbostic u_long rx50_off[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 217*32613Sbostic u_long rd52_off[] = { 0, 15884, 0, 0, 0, 0, 25650, 0 }; 218*32613Sbostic u_long rd53_off[] = { 0, 15884, 0, 0, 0, 33440, 49324, 15884 }; 21930547Skarels u_long ra60_off[] = { 0, 15884, 0, 49324, 131404, 49324, 242606, 49324 }; 22030547Skarels u_long ra80_off[] = { 0, 15884, 0, -1, 49324, 49324, 49910, 131404 }; 22130547Skarels #ifndef UCBRA 22230547Skarels #ifdef RA_COMPAT 22330547Skarels u_long ra81_off[] = { 0, 16422, 0, 49324, 131404, 412490, 375564, 83538 }; 22430547Skarels #else 22530547Skarels u_long ra81_off[] = { 0, 16422, 0, 375564, 391986, 699720, 375564, 83538 }; 22630547Skarels #endif 22730547Skarels #else 22830547Skarels u_long ra81_off[] = { 0, 15884, 0, 242606, 258490, 565690, 242606, 49324 }; 22930547Skarels #endif 23030547Skarels 231*32613Sbostic u_long *ra_off[] = { 232*32613Sbostic 0, /* 0 = unused */ 233*32613Sbostic ra80_off, /* 1 = ra80 */ 234*32613Sbostic ra25_off, /* 2 = rc25 removable */ 235*32613Sbostic ra25_off, /* 3 = rc25 fixed */ 236*32613Sbostic ra60_off, /* 4 = ra60 */ 237*32613Sbostic ra81_off, /* 5 = ra81 */ 238*32613Sbostic 0, /* 6 = ? */ 239*32613Sbostic rx50_off, /* 7 = rx50 */ 240*32613Sbostic rd52_off, /* 8 = rd52 */ 241*32613Sbostic rd53_off, /* 9 = rd53 */ 242*32613Sbostic }; 243*32613Sbostic 244*32613Sbostic #define NOFFS (sizeof(ra_off)/sizeof(int)) 245*32613Sbostic 24630547Skarels ramaptype(io, lp) 24730547Skarels register struct iob *io; 24830547Skarels register struct disklabel *lp; 24930547Skarels { 25030547Skarels register struct partition *pp; 251*32613Sbostic register int i; 25230547Skarels register u_long *off; 25330547Skarels 254*32613Sbostic i = ratype[io->i_unit]; 255*32613Sbostic if ((unsigned)i >= NOFFS || (off = ra_off[i]) == 0) { 256*32613Sbostic printf("ra%d: ra type %d unsupported\n", io->i_unit, i); 25730547Skarels lp->d_npartitions = 0; 25830547Skarels return; 25930547Skarels } 26030547Skarels lp->d_npartitions = 8; 261*32613Sbostic for (pp = lp->d_partitions, i = 0; i < 8; pp++, i++) 26230547Skarels pp->p_offset = *off++; 26330547Skarels } 26430547Skarels #endif 265