1 /* 2 * Datakit driver 3 * SCCSID[] = "@(#)dk.c 2.1 DKHOST 84/07/03" 4 */ 5 6 #include "datakit.h" 7 #if NDATAKIT>0 8 9 #include "../include/pte.h" 10 #include "sys/param.h" 11 #include "sys/signal.h" 12 #include "sys/errno.h" 13 #include "sys/conf.h" 14 #include "sys/user.h" 15 #include "sys/ioctl.h" 16 #include "sys/tty.h" 17 #include "sys/vnode.h" 18 #include "sys/file.h" 19 #include "sys/systm.h" 20 #include "sys/proc.h" 21 #include "sys/mbuf.h" 22 #include "sys/buf.h" 23 #include "sys/uio.h" 24 #include "sys/kernel.h" 25 #include "sys/dkit.h" 26 #include "sys/dkcmc.h" 27 #include "sys/dk.h" 28 #include "sys/dkdev.h" 29 #include "sys/syslog.h" 30 31 extern int dkdebug ; 32 33 #define DKBUFUSE 5 /* max buffers /channel */ 34 35 36 int dk_nchan = NDATAKIT; 37 struct dkdev dkdev[NDATAKIT]; 38 struct dksetupreq *dkreq[NDATAKIT]; 39 40 41 42 43 #ifdef MONITOR 44 int dummy ; 45 int *DKP2 = &dummy ; 46 #define M_ON(a) *DKP2 |= (a) 47 #define M_OFF(a) *DKP2 &= ~(a) 48 49 #define Mread 0400 50 #define Mrslp 01000 51 #define Mrcpy 02000 52 #define Mwrite 04000 53 #define Mwcpy 010000 54 55 #else 56 #define M_ON(a) 57 #define M_OFF(a) 58 #endif 59 60 61 62 /*ARGSUSED*/ 63 dkioctl(dev, cmd, data, flag) 64 register caddr_t data; 65 { 66 register struct dkdev *tp; 67 register chanstat ; 68 int chan, sp_chan; 69 int s, error = 0; 70 register short *pp ; 71 struct dkdev *tsp; 72 extern dkidone() ; 73 struct diocdial dialreq; 74 extern int commchan; 75 76 chan = dev = minor(dev); 77 tp = &dkdev[chan]; 78 pp = (short *) data; 79 switch(cmd) { 80 case DIOCEXCL: 81 tp->d_state |= DKXCLUDE ; 82 break ; 83 case DIOCNXCL: 84 tp->d_state &= ~DKXCLUDE ; 85 break ; 86 case DIOCSETK: 87 dkdebug = pp[0] ; 88 break; 89 case DIOCQQABO: 90 pp[0] = tp->d_rresid; 91 pp[1] = tp->d_rdone; 92 pp[2] = tp->d_rctl; 93 break ; 94 case DIOCRMODE: 95 if (pp[0] & DKR_TIME) 96 tp->d_rmode = (DKR_TIME | DKR_BLOCK); 97 else tp->d_rmode = pp[0] ; 98 break ; 99 case DIOCXCTL: 100 tp->d_xctl = pp[0] ; 101 break ; 102 case DIOCFLUSH: 103 dk_cmd(chan, DKC_XINIT|DKC_FLUSH); 104 break; 105 case KIOCINIT: 106 dk_cmd(chan, DKC_XINIT); 107 break; 108 case DIOCXWIN: 109 return dk_winsize(chan, (struct diocxwin *)data); 110 case DIOCRESET: 111 if (chan != 1 && chan != pp[0]) return EACCES; 112 if (pp[0] > 1 && pp[0] < commchan) return EINVAL; 113 if (pp[0] < 0 || pp[0] >= dk_nchan) return EINVAL; 114 if (pp[0] == 0) return -dk_close(0); 115 else dk_reset(pp[0]); 116 break; 117 case DIOCCTYPE: 118 if (tp->d_ctype == NULL) { 119 struct mbuf *m; 120 121 MGET(m, M_WAIT, DKMT_CTYPE); 122 if (m == NULL) 123 return ENOBUFS; 124 tp->d_ctype = mtod(m, struct diocctype *); 125 } 126 return bcopy(data, (caddr_t) tp->d_ctype, sizeof (struct diocctype)); 127 case DIOCINFO: 128 ((struct diocinfo *)data)->dioc_nchan = dk_nchan; 129 ((struct diocinfo *)data)->dioc_channum = chan; 130 ((struct diocinfo *)data)->dioc_commchan = commchan; 131 break; 132 case DIOCSTAT: 133 if (*((int *)data) < 0 || *((int *)data) >= dk_nchan) 134 return EINVAL; 135 *((int *)data) = dk_status(*((int *)data)); 136 break; 137 case FIONBIO: 138 if (*(int *)data) 139 tp->dc_state |= DK_NDELAY; 140 else 141 tp->dc_state &= ~DK_NDELAY; 142 break; 143 case FIOASYNC: 144 if (*(int *)data) 145 tp->dc_state |= DK_ASYNC; 146 else 147 tp->dc_state &= ~DK_ASYNC; 148 break; 149 case TIOCGPGRP: 150 *(int *)data = tp->d_pgrp; 151 break; 152 case TIOCSPGRP: 153 tp->d_pgrp = *(int *)data; 154 break; 155 156 /* splice chan to file descriptor */ 157 case DKIOCSPL: 158 error = copyin(*(caddr_t *)data, (caddr_t) tp->d_param, 159 3*sizeof (short)); 160 if (error) return error; 161 if ((error = dkgetdev(tp->d_param[0], &sp_chan)) <= 0) 162 return error ; 163 if (sp_chan == chan) 164 return EINVAL ; 165 tsp = &dkdev[sp_chan] ; 166 tp->dc_state |= DKSETUP ; 167 tsp->dc_state |= DKSETUP ; 168 if (dk_splice(chan, sp_chan, dkidone, (caddr_t) tp, 169 (caddr_t) tsp)) { 170 tp->dc_state &= ~DKSETUP ; 171 tsp->dc_state &= ~DKSETUP ; 172 return EIO ; 173 } 174 s = spl5() ; 175 error = 0; 176 while (error == 0 && tp->dc_state & DKSETUP) 177 error = tsleep((caddr_t)tp, TTOPRI, ttopen, 0); 178 while (error == 0 && tsp->dc_state & DKSETUP) 179 error = tsleep((caddr_t)tsp, TTOPRI, ttopen, 0); 180 splx(s) ; 181 if (error) 182 return (error); 183 if ((dk_status(chan) & DK_RESET) || (dk_status(sp_chan) & DK_RESET)) 184 return EIO ; 185 if (tp->d_error || tsp->d_error) 186 return EIO ; 187 error = copyout((caddr_t) tp->d_param, *(caddr_t *)data, 188 3*sizeof (short)); 189 if (error) return error; 190 break ; 191 192 case DIOCSWAIT: 193 error = dksplwait(chan); 194 break ; 195 196 default: 197 if ((cmd & DKIOCMASK) != DKIOCVAL) { 198 return ENOTTY ; 199 } 200 if (cmd == DKIODIAL) { 201 error = copyin(*(caddr_t *)data, (caddr_t) &dialreq, 202 sizeof (struct diocdial)); 203 if (error) return error; 204 if (error = dkiodial(chan, dialreq.dialstring)) 205 return error; 206 tp->dc_state |= DKSETUP ; 207 chanstat = dk_setup(minor(dev), (int) DKIOCREQ, 0, 208 0, 0, (int) u.u_uid, dkidone, (caddr_t)tp) ; 209 } 210 else { 211 error = copyin(*(caddr_t *)data, (caddr_t) tp->d_param, 212 3*sizeof (short)); 213 if (error) return error; 214 tp->dc_state |= DKSETUP ; 215 chanstat = dk_setup(minor(dev), cmd, 0, 0, 0, 216 (int) u.u_uid, dkidone, (caddr_t)tp) ; 217 } 218 if (chanstat) { 219 tp->dc_state &= ~DKSETUP ; 220 return (chanstat < 0 ? ECONNREFUSED : chanstat); 221 } 222 s = spl5() ; 223 error = 0; 224 while (error == 0 && tp->dc_state & DKSETUP) 225 error = tsleep((caddr_t)(tp), TTOPRI, ttyout, 0) ; 226 splx(s) ; 227 if (error) 228 return error; 229 error = copyout((caddr_t) tp->d_param, *(caddr_t *)data, 230 3*sizeof (short)); 231 if (error) return error; 232 if (dk_status(minor(dev)) & DK_RESET) 233 return ENETRESET ; 234 if (tp->d_error) 235 return EIO ; 236 break ; 237 } 238 return error; 239 } 240 241 #define DS_SIZE 64 242 static 243 dkiodial(chan, user_ds) 244 register char *user_ds; 245 { 246 register caddr_t ds; 247 register n; 248 register struct mbuf *mb; 249 int u_count; 250 251 mb = m_get(M_WAIT, DKMT_DATA); 252 if (mb == NULL) return ENOBUFS; 253 ds = mtod(mb, caddr_t); 254 for (u_count = 0; u_count < MLEN - 6; u_count++) { 255 *ds = *user_ds; 256 if (*ds == '\n' || *ds == '\0') break; 257 ds++; 258 user_ds++; 259 } 260 *ds = '\n'; 261 u_count++; 262 263 /* add uid in char decimal */ 264 265 ds++; 266 u_count++; 267 for (n = u.u_uid; n /= 10; ds++) u_count++; 268 for (n = u.u_uid;; ds--) { 269 *ds = n % 10 + '0'; 270 if ((n /= 10) == 0) break; 271 } 272 273 mb->m_len = u_count; 274 if (dk_xmit(chan, mb, 1, 0, (int (*)()) 0, (caddr_t) 0) == 0) { 275 return(EIO); 276 } 277 else return(0); 278 } 279 /* 280 * End action for ioctl completion 281 */ 282 /*ARGSUSED*/ 283 dkidone(tp, chan, err, p0, p1, p2) 284 register struct dkdev *tp ; 285 short chan, p0, p1, p2 ; 286 { 287 tp->d_error = err ; 288 tp->d_param[0] = p0 ; 289 tp->d_param[1] = p1 ; 290 tp->d_param[2] = p2 ; 291 tp->dc_state &= ~DKSETUP ; 292 wakeup((caddr_t)tp) ; 293 } 294 295 296 297 298 /*ARGSUSED*/ 299 dkopen(dev, flag) 300 { 301 USES_VOP_LOCK; 302 USES_VOP_UNLOCK; 303 register struct dkdev *tp; 304 register chan; 305 register struct nameidata *ndp = &u.u_nd; /* XXX */ 306 struct proc *p = u.u_procp; /* XXX */ 307 struct vnode *vp; 308 struct file *fp; 309 int m, error; 310 311 #ifdef lint 312 (void) dk_xint(0, 0); 313 #endif 314 dev = minor(dev); 315 if (dev == 1) { 316 return 0; /* Maintenance channel */ 317 } 318 319 chan = dev; 320 if (chan >= dk_nchan) { 321 /* debug */ log(LOG_ERR, "dkopen bad: chan>=NDKCHANS : %d\n",chan); 322 return ENXIO; 323 } 324 325 tp = &dkdev[chan]; 326 if ((tp->d_state & DKOPEN) == 0) 327 tp->dc_state = 0 ; 328 if (tp->d_state&DKXCLUDE && u.u_procp->p_ruid!=0) { 329 return EBUSY; 330 } 331 332 if ((m = dk_open(chan, (int (*)()) NULL)) < 0) 333 return -m; 334 335 336 /* 337 * Channel 0 is reserved for maintenance. 338 * An open on channel 0 is interpreted as a request 339 * for an unused channel. 340 */ 341 if (chan==0) { 342 char dname[30]; 343 344 chan = m ; 345 tp = &dkdev[chan] ; 346 tp->dc_state = 0 ; 347 /* 348 * throw away vnode for dk0. (/dev/dk/dial) 349 * Build standard name of new one, and ask namei for it. 350 */ 351 fp = u.u_ofile[-1 - p->p_dupfd]; 352 353 dksnamer(dname, chan); 354 /* log(LOG_ERR, "dname=%s chan=%d\n", dname, chan); */ 355 ndp->ni_nameiop = FOLLOW | LOOKUP | LOCKLEAF; 356 ndp->ni_segflg = UIO_SYSSPACE; 357 ndp->ni_dirp = dname; 358 if (error = namei(ndp)) { 359 (void) dk_close(chan) ; 360 return (error); 361 } 362 363 /* Give back old one */ 364 vp = (struct vnode *) fp->f_data; 365 VOP_LOCK(vp); 366 vput(vp); 367 368 vp = ndp->ni_vp; 369 fp->f_data = (caddr_t) vp; 370 VOP_UNLOCK(vp); 371 } 372 if ((tp->d_state & DKOPEN) == 0) { 373 tp->d_state |= DKOPEN ; 374 tp->dc_state = 0; 375 tp->d_rmode = 0 ; 376 tp->d_xctl = 0 ; 377 tp->d_pgrp = 0; 378 } 379 tp->d_prot |= DpURP; 380 return 0; 381 } 382 383 /* Policy decision here -- standard name of dk file known to this routine */ 384 dksnamer(s, n) register char *s; 385 { 386 register char *p = "/dev/dk/dk"; 387 388 while (*s++ = *p++) 389 ; 390 s--; 391 *s++ = '0' + (n/100); n %= 100; 392 *s++ = '0' + (n/10); n %= 10; 393 *s++ = '0' + n; 394 *s = '\0'; 395 } 396 397 /* 398 * Close a channel: 399 */ 400 401 /*ARGSUSED*/ 402 dkclose(dev, flag) 403 dev_t dev; 404 int flag; 405 { 406 register struct dkdev *tp; 407 extern wakeup() ; 408 extern brelse() ; 409 short s, chan ; 410 int i, cl = 0; 411 412 chan = minor(dev); 413 tp = &dkdev[chan]; 414 if (chan == 1) { 415 return 0; /* Maintenance channel */ 416 } 417 s = spl5() ; 418 if (u.u_signal[SIGKILL] != SIG_IGN) { /* detect close from exit() */ 419 while (tp->d_bufct) { 420 tp->d_state |= DKWAIT ; 421 if (tsleep((caddr_t)(&tp->d_state), TTOPRI, ttyout, 0)) 422 break; 423 } 424 } 425 else if (tp->d_bufct) 426 /* Hmm -- buffers queued. Let's wait 15 seconds max */ 427 for (i = 0; tp->d_bufct && i < 15; i++) { 428 tp->d_state |= DKWAIT ; 429 if (tsleep((caddr_t)(&tp->d_state), TTOPRI, ttyout, hz)) 430 break; 431 } 432 splx(s) ; 433 tp->dc_state = 0; 434 tp->d_rmode = 0; 435 tp->d_prot &= ~DpURP; 436 if(!tp->d_prot){ 437 cl = dk_close(chan); 438 (void) dk_takedown(chan); 439 tp->d_state = 0; 440 } 441 return -cl; 442 } 443 444 dkread(dev, uio) 445 dev_t dev ; 446 struct uio *uio; 447 { 448 register struct dkdev *tp ; 449 int err; 450 451 M_ON(Mread) ; 452 tp = &dkdev[minor(dev)] ; 453 err = dkuread(minor(dev), uio) ; 454 tp->d_rresid = uio->uio_resid ; 455 M_OFF(Mread) ; 456 return err; 457 } 458 459 460 dkwrite(dev, uio) 461 struct uio *uio; 462 dev_t dev ; 463 { 464 int err; 465 466 M_ON(Mwrite) ; 467 err = dkuwrite(minor(dev), uio) ; 468 M_OFF(Mwrite) ; 469 return err; 470 } 471 472 #endif 473