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