1 /* 2 * Datakit driver 3 * Common subroutines for all drivers 4 * SCCSID[] = "@(#)dksub.c 1.2 Garage 84/03/27" 5 * "@(#)dksub.c 1.7 (Berkeley) 12/16/90" 6 */ 7 8 #include "datakit.h" 9 #if NDATAKIT>0 10 11 #include "../include/pte.h" 12 #include "sys/param.h" 13 #include "sys/signal.h" 14 #include "sys/errno.h" 15 #include "sys/seg.h" 16 #include "sys/user.h" 17 #include "sys/ioctl.h" 18 #include "sys/tty.h" 19 #include "sys/syslog.h" 20 #include "sys/conf.h" 21 #include "sys/file.h" 22 #include "sys/systm.h" 23 #include "sys/proc.h" 24 #include "sys/mbuf.h" 25 #include "sys/buf.h" 26 #include "sys/uio.h" 27 #include "sys/vnode.h" 28 #include "sys/specdev.h" 29 #include "dkit.h" 30 #include "dk.h" 31 #include "dkdev.h" 32 33 #define DKBUFUSE 5 /* max buffers /channel */ 34 35 36 extern struct dkdev dkdev[] ; 37 38 int dksubdebug = 512; 39 40 41 dkuread(chan, uio) 42 register struct uio *uio; 43 { 44 register int len, blen ; 45 register struct dkdev *tp ; 46 short chanstat ; 47 struct mbuf *mm ; 48 int err = 0, s; 49 extern wakeup() ; 50 extern dkrdone() ; 51 52 tp = &dkdev[chan]; 53 MGET(mm, M_WAIT, DKMT_DATA); 54 if (mm == NULL) 55 return ENOBUFS; 56 if (uio->uio_resid >= MLEN) { 57 MCLGET(mm, M_WAIT); 58 if ((mm->m_flags & M_EXT) == 0) 59 goto nopages; 60 blen = MCLBYTES; 61 } else { 62 nopages: 63 blen = MIN(MLEN, uio->uio_resid); 64 } 65 66 while (uio->uio_resid && !err) { 67 len = MIN(uio->uio_resid, blen) ; 68 chanstat = dk_recv(chan, mtod(mm, caddr_t), len, tp->d_rmode, dkrdone, (caddr_t) tp) ; 69 if (chanstat == 0) { 70 if ((dk_status(chan) & DK_RESET) == 0) 71 err = EIO ; 72 break; 73 } 74 if ((tp->dc_state & DK_NDELAY) && (dk_status(chan) & DK_RCV)) { 75 err = EWOULDBLOCK; 76 break; 77 } 78 79 s = spl5() ; 80 while (dk_status(chan) & DK_RCV) 81 if (err = tsleep((caddr_t)(tp), TTIPRI, ttyin, 0)) { 82 if (dk_status(chan) & DK_RCV) 83 (void) dk_rabort(chan, dkrdone, 84 (caddr_t) tp); 85 splx(s); 86 goto done; 87 } 88 splx(s) ; 89 90 len -= tp->d_rresid ; 91 if (len) 92 err = uiomove(mtod(mm, caddr_t), len, UIO_READ, uio); 93 if (tp->d_rdone != DKR_FULL) 94 break ; 95 } 96 done: 97 m_freem(mm) ; 98 return err; 99 } 100 101 102 /*ARGSUSED*/ 103 dkrdone(tp, chan, resid, rdone, rctl) 104 register struct dkdev *tp ; 105 { 106 tp->d_rresid = resid ; 107 tp->d_rdone = rdone ; 108 tp->d_rctl = rctl ; 109 wakeup((caddr_t) tp) ; 110 } 111 112 113 114 115 dkuwrite(chan, uio) register struct uio *uio; 116 { 117 extern wakeup() ; 118 extern dkwdone() ; 119 register struct dkdev *tp ; 120 register len ; 121 register struct mbuf *m; 122 register struct iovec *iov; 123 int s, error, eob; 124 short xc; 125 126 tp = &dkdev[chan] ; 127 do { 128 s = spl5() ; 129 while (tp->d_bufct > DKBUFUSE) { 130 if (tp->dc_state & DK_NDELAY) { 131 splx(s); 132 return EWOULDBLOCK; 133 } 134 tp->d_state |= DKWAIT ; 135 if (error = tsleep((caddr_t)(&tp->d_state), TTOPRI, 136 ttyout, 0)) { 137 splx(s); 138 return (error); 139 } 140 } 141 splx(s) ; 142 143 iov = uio->uio_iov; 144 if (iov->iov_len) { 145 MGET(m, M_WAIT, DKMT_DATA); 146 if (m == NULL) 147 return ENOBUFS; 148 if (iov->iov_len >= MLEN) { 149 MCLGET(m, M_WAIT); 150 if ((m->m_flags & M_EXT) == 0) 151 goto nopages; 152 len = MIN(MCLBYTES, iov->iov_len); 153 } else { 154 nopages: 155 len = MIN(MLEN, iov->iov_len); 156 } 157 error = uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 158 if (error) { 159 (void) m_free(m); 160 return error; 161 } 162 m->m_len = len; 163 } 164 else m = NULL; 165 166 s = spl5(); 167 tp->d_bufct++; 168 eob = (uio->uio_resid == 0); 169 if (eob) { 170 xc = tp->d_xctl; 171 tp->d_xctl = 0; 172 } 173 else xc = 0; 174 if (dk_xmit(chan, m, eob, xc, dkwdone, (caddr_t) 0) == 0) { 175 tp->d_bufct-- ; 176 return EIO ; 177 } 178 splx(s); 179 } while (uio->uio_resid); 180 return 0; 181 } 182 183 /*ARGSUSED*/ 184 dkwdone(x, chan) 185 { 186 register struct dkdev *tp ; 187 188 tp = &dkdev[chan] ; 189 if (chan > dksubdebug) 190 log(LOG_ERR, "dkwdone %d: state=0%o bufct=%d\n", chan, tp->d_state, 191 tp->d_bufct); 192 if (tp->d_bufct) 193 tp->d_bufct-- ; 194 if (tp->d_state & DKWAIT) { 195 tp->d_state &= ~DKWAIT ; 196 wakeup((caddr_t) &tp->d_state) ; 197 } 198 } 199 200 /* wakeup and reinitialize channel upon receipt of reconnection message */ 201 dkrsplice(chan) 202 { 203 register struct dkdev *tp ; 204 205 tp = &dkdev[chan] ; 206 tp->d_state |= DKSPLICED ; 207 wakeup((caddr_t) tp) ; 208 dk_cmd(chan, DKC_XINIT) ; 209 } 210 211 /* wait for reconnection message indicating that splice completed */ 212 dksplwait(chan) 213 { 214 register struct dkdev *tp ; 215 int error; 216 217 tp = &dkdev[chan] ; 218 while ((tp->d_state & DKSPLICED) == 0) 219 if (error = tsleep((caddr_t) tp, TTOPRI, ttopen, 0)) 220 return (error); 221 return (0); 222 } 223 224 /* convert file desciptor to Datakit channel */ 225 dkgetdev(fildes, devnop) 226 int fildes, *devnop; 227 { 228 struct file *fp; 229 register struct vnode *vp ; 230 int error; 231 232 if (error = getvnode(u.u_ofile, fildes, &fp)) 233 return error; 234 vp = (struct vnode *)fp->f_data; 235 if (vp->v_type != VCHR) 236 return ENOTTY; 237 if (dkdevtype(vp->v_rdev)) { 238 *devnop = minor(vp->v_rdev); 239 return 0; 240 } 241 return EINVAL; 242 } 243 244 /* validate device number as belonging to Datakit */ 245 dkdevtype(dev) dev_t dev; 246 { 247 extern dkopen(); 248 #if NDKTTY > 0 249 extern dktopen(); 250 #endif 251 #if NDKXQT > 0 252 extern dkxopen(); 253 #endif 254 #if NDKI > 0 255 extern dkiopen(); 256 #endif 257 register md = major(dev) ; 258 259 if ((cdevsw[md].d_open == dkopen) 260 #if NDKTTY > 0 261 || (cdevsw[md].d_open == dktopen) 262 #endif 263 #if NDKI > 0 264 || (cdevsw[md].d_open == dkiopen && md > 0) 265 #endif 266 #if NDKXQT > 0 267 || (cdevsw[md].d_open == dkxopen) 268 #endif 269 ) 270 return(1); 271 else 272 return(0); 273 } 274 275 #endif 276