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