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*33408Skarels * @(#)uda.c 7.6 (Berkeley) 01/28/88 723247Smckusick */ 85153Ssam 95153Ssam /* 105153Ssam * UDA50/RAxx disk device driver 115153Ssam */ 129806Ssam #include "../machine/pte.h" 135153Ssam 1432613Sbostic #include "param.h" 1532613Sbostic #include "inode.h" 1632613Sbostic #include "fs.h" 1732613Sbostic #include "disklabel.h" 189186Ssam 195153Ssam #include "saio.h" 205153Ssam #include "savax.h" 215153Ssam 2232613Sbostic #define NRA 8 /* max. unit number on controller */ 2330547Skarels #define SECTSIZ 512 /* sector size in bytes */ 2432613Sbostic 255153Ssam /* 2632613Sbostic * Unused, but needed in udareg.h 275153Ssam */ 2832613Sbostic #define NRSP 1 2932613Sbostic #define NCMD 1 305153Ssam 31*33408Skarels #include "../vaxuba/udareg.h" 329186Ssam #include "../vaxuba/ubareg.h" 33*33408Skarels #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 */ 43*33408Skarels struct udadevice *udaddr[MAXNUBA]; 445153Ssam 4532613Sbostic struct uda1 { 4632613Sbostic struct uda1ca uda1_ca; /* communications area */ 4732613Sbostic struct mscp uda1_rsp; /* response packet */ 4832613Sbostic struct mscp uda1_cmd; /* command packet */ 4932613Sbostic } uda1; 505153Ssam 5132613Sbostic struct uda1 *ud_ubaddr[MAXNUBA]; /* Unibus address of uda structure */ 5230547Skarels struct disklabel ralabel[MAXNUBA * NRA]; 53*33408Skarels static u_int ratype[MAXNUBA * NRA]; 5430547Skarels char lbuf[SECTSIZ]; 555153Ssam 5611111Ssam raopen(io) 575153Ssam register struct iob *io; 585153Ssam { 595153Ssam register struct mscp *mp; 6032613Sbostic register struct disklabel *lp, *dlp; 6130547Skarels register struct udadevice *addr; 6232613Sbostic register struct uda1 *ubaddr; 6330547Skarels register unit; 6432613Sbostic static int udainit[MAXNUBA]; 6530547Skarels int uba; 665153Ssam 6730547Skarels unit = io->i_unit; 6830547Skarels uba = UNITTOUBA(unit); 6930547Skarels if (udaddr[uba] == 0) 7030547Skarels udaddr[uba] = (struct udadevice *)ubamem(unit, udastd[0]); 7130547Skarels addr = udaddr[uba]; 7230547Skarels if (badaddr((char *)addr, sizeof(short))) { 7332194Skarels printf("nonexistent device\n"); 7430547Skarels return (ENXIO); 7530547Skarels } 7630547Skarels if (ud_ubaddr[uba] == 0) { 7717231Smckusick /* 7830547Skarels * Initialize cudbuf.i_unit so that controllers 7917231Smckusick * on UNIBUSes other than 0 can be used. 8017231Smckusick */ 8130547Skarels cudbuf.i_unit = unit; 8232613Sbostic cudbuf.i_ma = (caddr_t)&uda1; 8332613Sbostic cudbuf.i_cc = sizeof(uda1); 8432613Sbostic ud_ubaddr[uba] = (struct uda1 *)ubasetup(&cudbuf, 2); 855153Ssam } 8630547Skarels ubaddr = ud_ubaddr[uba]; 8730547Skarels if (udainit[uba] == 0) { 8830547Skarels addr->udaip = 0; 8930547Skarels while ((addr->udasa & UDA_STEP1) == 0) 9017231Smckusick ; 9130547Skarels addr->udasa = UDA_ERR; 9230547Skarels while ((addr->udasa & UDA_STEP2) == 0) 9317231Smckusick ; 9432613Sbostic addr->udasa = (short)&ubaddr->uda1_ca.ca_rspdsc; 9530547Skarels while ((addr->udasa & UDA_STEP3) == 0) 9617231Smckusick ; 9730547Skarels addr->udasa = 9832613Sbostic (short)(((int)&ubaddr->uda1_ca.ca_rspdsc) >> 16); 9930547Skarels while ((addr->udasa & UDA_STEP4) == 0) 10017231Smckusick ; 10130547Skarels addr->udasa = UDA_GO; 10232613Sbostic uda1.uda1_ca.ca_rspdsc = (long)&ubaddr->uda1_rsp.mscp_cmdref; 10332613Sbostic uda1.uda1_ca.ca_cmddsc = (long)&ubaddr->uda1_cmd.mscp_cmdref; 10432613Sbostic /* uda1.uda1_cmd.mscp_cntflgs = 0; */ 105*33408Skarels if (udcmd(M_OP_SETCTLRC, io)) { 10632613Sbostic printf("ra: open error, SETCTLRC\n"); 10730547Skarels return (EIO); 10817231Smckusick } 10932613Sbostic udainit[uba] = 1; 11027075Skarels } 11130547Skarels lp = &ralabel[unit]; 11232613Sbostic if (ratype[unit] == 0) { 11330547Skarels struct iob tio; 11430547Skarels 11532613Sbostic uda1.uda1_cmd.mscp_unit = UNITTODRIVE(unit); 116*33408Skarels if (udcmd(M_OP_ONLINE, io)) { 11732613Sbostic printf("ra: open error, ONLINE\n"); 11830547Skarels return (EIO); 11917231Smckusick } 120*33408Skarels ratype[unit] = uda1.uda1_rsp.mscp_onle.onle_drivetype; 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*33408Skarels *lp = *(struct disklabel *)(lbuf + LABELOFFSET); 131*33408Skarels if (lp->d_magic != DISKMAGIC || lp->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 138*33408Skarels } 1395153Ssam } 14030547Skarels if ((unsigned)io->i_boff >= lp->d_npartitions || 14130547Skarels (io->i_boff = lp->d_partitions[io->i_boff].p_offset) == -1) { 14232194Skarels printf("ra: bad partition\n"); 14330547Skarels return (EUNIT); 14427075Skarels } 14530547Skarels return (0); 1465153Ssam } 1475153Ssam 148*33408Skarels int 14930547Skarels udcmd(op, io) 1505153Ssam int op; 15130547Skarels register struct iob *io; 1525153Ssam { 153*33408Skarels register struct uda1 *u = &uda1; 15432613Sbostic register struct mscp *mp; 1555153Ssam int i; 1565153Ssam 157*33408Skarels u->uda1_cmd.mscp_opcode = op; 158*33408Skarels u->uda1_cmd.mscp_msglen = MSCP_MSGLEN; 159*33408Skarels u->uda1_rsp.mscp_msglen = MSCP_MSGLEN; 160*33408Skarels u->uda1_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT; 161*33408Skarels u->uda1_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT; 16230547Skarels i = udaddr[UNITTOUBA(io->i_unit)]->udaip; 163*33408Skarels mp = &u->uda1_rsp; 1645153Ssam for (;;) { 165*33408Skarels if (u->uda1_ca.ca_cmdint) 166*33408Skarels u->uda1_ca.ca_cmdint = 0; 167*33408Skarels if (u->uda1_ca.ca_rspint == 0) 16832613Sbostic continue; 169*33408Skarels u->uda1_ca.ca_rspint = 0; 17032613Sbostic if (mp->mscp_opcode == (op | M_OP_END)) 1715153Ssam break; 172*33408Skarels printf("unexpected rsp type %x op %x ignored\n", 173*33408Skarels MSCP_MSGTYPE(mp->mscp_msgtc), mp->mscp_opcode); 174*33408Skarels u->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; 1755153Ssam } 17632613Sbostic if ((mp->mscp_status&M_ST_MASK) != M_ST_SUCCESS) 177*33408Skarels return (-1); 178*33408Skarels return (0); 1795153Ssam } 1805153Ssam 18111111Ssam rastrategy(io, func) 1825153Ssam register struct iob *io; 1835153Ssam { 1845153Ssam register struct mscp *mp; 1855153Ssam int ubinfo; 1865153Ssam 1875153Ssam ubinfo = ubasetup(io, 1); 18832613Sbostic mp = &uda1.uda1_cmd; 18932194Skarels mp->mscp_unit = UNITTODRIVE(io->i_unit); 19032613Sbostic mp->mscp_seq.seq_lbn = io->i_bn; 19132613Sbostic mp->mscp_seq.seq_bytecount = io->i_cc; 19232613Sbostic mp->mscp_seq.seq_buffer = (ubinfo & 0x3ffff) | (((ubinfo>>28)&0xf)<<24); 193*33408Skarels if (udcmd(func == READ ? M_OP_READ : M_OP_WRITE, io)) { 1945153Ssam printf("ra: I/O error\n"); 1955153Ssam ubafree(io, ubinfo); 1965153Ssam return(-1); 1975153Ssam } 1985153Ssam ubafree(io, ubinfo); 1995153Ssam return(io->i_cc); 2005153Ssam } 20110024Ssam 20210024Ssam /*ARGSUSED*/ 20311111Ssam raioctl(io, cmd, arg) 20410024Ssam struct iob *io; 20510024Ssam int cmd; 20610024Ssam caddr_t arg; 20710024Ssam { 20810024Ssam 20910024Ssam return (ECMD); 21010024Ssam } 21130547Skarels 21230547Skarels #ifdef COMPAT_42 21330547Skarels u_long ra25_off[] = { 0, 15884, 0, -1, -1, -1, 25916, -1 }; 21432613Sbostic u_long rx50_off[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 21532613Sbostic u_long rd52_off[] = { 0, 15884, 0, 0, 0, 0, 25650, 0 }; 21632613Sbostic u_long rd53_off[] = { 0, 15884, 0, 0, 0, 33440, 49324, 15884 }; 21730547Skarels u_long ra60_off[] = { 0, 15884, 0, 49324, 131404, 49324, 242606, 49324 }; 21830547Skarels u_long ra80_off[] = { 0, 15884, 0, -1, 49324, 49324, 49910, 131404 }; 21930547Skarels #ifndef UCBRA 22030547Skarels #ifdef RA_COMPAT 22130547Skarels u_long ra81_off[] = { 0, 16422, 0, 49324, 131404, 412490, 375564, 83538 }; 22230547Skarels #else 22330547Skarels u_long ra81_off[] = { 0, 16422, 0, 375564, 391986, 699720, 375564, 83538 }; 22430547Skarels #endif 22530547Skarels #else 22630547Skarels u_long ra81_off[] = { 0, 15884, 0, 242606, 258490, 565690, 242606, 49324 }; 22730547Skarels #endif 22830547Skarels 22932613Sbostic u_long *ra_off[] = { 23032613Sbostic 0, /* 0 = unused */ 23132613Sbostic ra80_off, /* 1 = ra80 */ 23232613Sbostic ra25_off, /* 2 = rc25 removable */ 23332613Sbostic ra25_off, /* 3 = rc25 fixed */ 23432613Sbostic ra60_off, /* 4 = ra60 */ 23532613Sbostic ra81_off, /* 5 = ra81 */ 23632613Sbostic 0, /* 6 = ? */ 23732613Sbostic rx50_off, /* 7 = rx50 */ 23832613Sbostic rd52_off, /* 8 = rd52 */ 23932613Sbostic rd53_off, /* 9 = rd53 */ 24032613Sbostic }; 24132613Sbostic 242*33408Skarels #define NOFFS (sizeof(ra_off)/sizeof(ra_off[0])) 24332613Sbostic 24430547Skarels ramaptype(io, lp) 24530547Skarels register struct iob *io; 24630547Skarels register struct disklabel *lp; 24730547Skarels { 24830547Skarels register struct partition *pp; 249*33408Skarels register u_int i; 25030547Skarels register u_long *off; 25130547Skarels 252*33408Skarels if ((i = ratype[io->i_unit]) >= NOFFS || (off = ra_off[i]) == 0) { 25332613Sbostic printf("ra%d: ra type %d unsupported\n", io->i_unit, i); 25430547Skarels lp->d_npartitions = 0; 25530547Skarels return; 25630547Skarels } 25730547Skarels lp->d_npartitions = 8; 25832613Sbostic for (pp = lp->d_partitions, i = 0; i < 8; pp++, i++) 25930547Skarels pp->p_offset = *off++; 26030547Skarels } 26130547Skarels #endif 262