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