1 /* 2 * Copyright (c) 1982 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 6.3 (Berkeley) 06/08/85 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 18 #include "saio.h" 19 #include "savax.h" 20 21 /* 22 * Parameters for the communications area 23 */ 24 #define NRSPL2 0 25 #define NCMDL2 0 26 #define NRSP (1<<NRSPL2) 27 #define NCMD (1<<NCMDL2) 28 29 #include "../vaxuba/udareg.h" 30 #include "../vaxuba/ubareg.h" 31 #include "../vax/mscp.h" 32 33 u_short udastd[] = { 0772150 }; 34 35 struct iob cudbuf; 36 37 struct udadevice *udaddr = 0; 38 39 struct uda { 40 struct udaca uda_ca; 41 struct mscp uda_rsp; 42 struct mscp uda_cmd; 43 } uda; 44 45 struct uda *ud_ubaddr; /* Unibus address of uda structure */ 46 47 int uda_off[] = { 0, 15884, 0, -1, -1, -1, 49324, 131404 }; 48 49 struct mscp *udcmd(); 50 51 raopen(io) 52 register struct iob *io; 53 { 54 register struct mscp *mp; 55 static int udainit; 56 int i; 57 58 if (udaddr == 0) 59 udaddr = (struct udadevice *)ubamem(io->i_unit, udastd[0]); 60 if (ud_ubaddr == 0) { 61 /* 62 * Initialise cudbuf.i_unit so that controllers 63 * on UNIBUSes other than 0 can be used. 64 */ 65 cudbuf.i_unit = io->i_unit; 66 cudbuf.i_ma = (caddr_t)&uda; 67 cudbuf.i_cc = sizeof(uda); 68 ud_ubaddr = (struct uda *)ubasetup(&cudbuf, 2); 69 } 70 if (udainit == 0) { 71 udaddr->udaip = 0; 72 while ((udaddr->udasa & UDA_STEP1) == 0) 73 ; 74 udaddr->udasa = UDA_ERR; 75 while ((udaddr->udasa & UDA_STEP2) == 0) 76 ; 77 udaddr->udasa = (short)&ud_ubaddr->uda_ca.ca_ringbase; 78 while ((udaddr->udasa & UDA_STEP3) == 0) 79 ; 80 udaddr->udasa = 81 (short)(((int)&ud_ubaddr->uda_ca.ca_ringbase) >> 16); 82 while ((udaddr->udasa & UDA_STEP4) == 0) 83 ; 84 udaddr->udasa = UDA_GO; 85 uda.uda_ca.ca_rspdsc[0] = (long)&ud_ubaddr->uda_rsp.mscp_cmdref; 86 uda.uda_ca.ca_cmddsc[0] = (long)&ud_ubaddr->uda_cmd.mscp_cmdref; 87 uda.uda_cmd.mscp_cntflgs = 0; 88 if (udcmd(M_OP_STCON) == 0) { 89 _stop("ra: open error, STCON"); 90 return; 91 } 92 uda.uda_cmd.mscp_unit = io->i_unit&7; 93 if (udcmd(M_OP_ONLIN) == 0) { 94 _stop("ra: open error, ONLIN"); 95 return; 96 } 97 udainit = 1; 98 } 99 if (io->i_boff < 0 || io->i_boff > 7 || uda_off[io->i_boff] == -1) 100 _stop("ra: bad unit"); 101 io->i_boff = uda_off[io->i_boff]; 102 } 103 104 struct mscp * 105 udcmd(op) 106 int op; 107 { 108 struct mscp *mp; 109 int i; 110 111 uda.uda_cmd.mscp_opcode = op; 112 uda.uda_rsp.mscp_header.uda_msglen = sizeof (struct mscp); 113 uda.uda_cmd.mscp_header.uda_msglen = sizeof (struct mscp); 114 uda.uda_ca.ca_rspdsc[0] |= UDA_OWN|UDA_INT; 115 uda.uda_ca.ca_cmddsc[0] |= UDA_OWN|UDA_INT; 116 i = udaddr->udaip; 117 for (;;) { 118 if (uda.uda_ca.ca_cmdint) 119 uda.uda_ca.ca_cmdint = 0; 120 if (uda.uda_ca.ca_rspint) 121 break; 122 } 123 uda.uda_ca.ca_rspint = 0; 124 mp = &uda.uda_rsp; 125 if (mp->mscp_opcode != (op|M_OP_END) || 126 (mp->mscp_status&M_ST_MASK) != M_ST_SUCC) 127 return(0); 128 return(mp); 129 } 130 131 rastrategy(io, func) 132 register struct iob *io; 133 { 134 register struct mscp *mp; 135 int ubinfo; 136 137 ubinfo = ubasetup(io, 1); 138 mp = &uda.uda_cmd; 139 mp->mscp_lbn = io->i_bn; 140 mp->mscp_unit = io->i_unit&7; 141 mp->mscp_bytecnt = io->i_cc; 142 mp->mscp_buffer = (ubinfo & 0x3ffff) | (((ubinfo>>28)&0xf)<<24); 143 if ((mp = udcmd(func == READ ? M_OP_READ : M_OP_WRITE)) == 0) { 144 printf("ra: I/O error\n"); 145 ubafree(io, ubinfo); 146 return(-1); 147 } 148 ubafree(io, ubinfo); 149 return(io->i_cc); 150 } 151 152 /*ARGSUSED*/ 153 raioctl(io, cmd, arg) 154 struct iob *io; 155 int cmd; 156 caddr_t arg; 157 { 158 159 return (ECMD); 160 } 161