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