Index: head/sys/gnu/isdn/if_ii.c =================================================================== --- head/sys/gnu/isdn/if_ii.c (revision 12911) +++ head/sys/gnu/isdn/if_ii.c (revision 12912) @@ -1,264 +1,247 @@ -static char _if_iiid[] = "@(#)$Id: if_ii.c,v 1.3 1995/05/30 07:58:00 rgrimes Exp $"; +static char _if_iiid[] = "@(#)$Id: if_ii.c,v 1.4 1995/11/16 10:10:50 bde Exp $"; /******************************************************************************* - * II - Version 0.1 $Revision: 1.3 $ $State: Exp $ + * II - Version 0.1 $Revision: 1.4 $ $State: Exp $ * * Copyright 1994 Dietmar Friede ******************************************************************************* * Bug reports, patches, comments, suggestions should be sent to: * * jkr@saarlink.de or jkrause@guug.de * ******************************************************************************* - * $Log: if_ii.c,v $ - * Revision 1.3 1995/05/30 07:58:00 rgrimes - * Remove trailing whitespace. - * - * Revision 1.2 1995/02/15 06:28:26 jkh - * Fix up include paths, nuke some warnings. - * - * Revision 1.1 1995/02/14 15:00:27 jkh - * An ISDN driver that supports the EDSS1 and the 1TR6 ISDN interfaces. - * EDSS1 is the "Euro-ISDN", 1TR6 is the soon obsolete german ISDN Interface. - * Obtained from: Dietmar Friede and - * Juergen Krause - * - * This is only one part - the rest to follow in a couple of hours. - * This part is a benign import, since it doesn't affect anything else. - * - * - ******************************************************************************/ + */ /* * Copyright (c) 1994 Dietmar Friede (dietmar@friede.de) All rights reserved. * FSF/FSAG GNU Copyright applies * * A high level ip isdn driver. * * Uses loop driver as template. Small - and simple - is beautiful. */ #include "param.h" #include "systm.h" #include "mbuf.h" #include "socket.h" #include "errno.h" #include "ioctl.h" #include "protosw.h" #include "net/if.h" #include "net/if_types.h" #include "net/netisr.h" #include "net/route.h" #ifdef INET #include "netinet/in.h" #include "netinet/in_systm.h" #include "netinet/in_var.h" #include "netinet/ip.h" #endif #include "ii.h" #include "gnu/isdn/isdn_ioctl.h" #define IIMTU 1500 static struct ifnet ii_if[NII]; static int applnr[NII]; static int next_if = 0; -extern int ii_ioctl __P((struct ifnet *ifp, int cmd, caddr_t data)); -extern int iioutput __P((struct ifnet *ifp, struct mbuf *m, +static int ii_ioctl __P((struct ifnet *ifp, int cmd, caddr_t data)); +static int iioutput __P((struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rtp)); int iiattach(int ap) { register struct ifnet *ifp; if (next_if >= NII) return -1; applnr[next_if] = ap; ifp = &ii_if[next_if]; ifp->if_unit = next_if; ifp->if_name = "ii"; ifp->if_mtu = IIMTU; ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT ; ifp->if_ioctl = ii_ioctl; ifp->if_output = iioutput; ifp->if_type = IFT_ISDNBASIC; ifp->if_hdrlen = 0; ifp->if_addrlen = 0; ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; if_attach(ifp); /* ifp->if_flags |= IFF_RUNNING; */ return next_if++; } -int +static int iioutput(struct ifnet * ifp, struct mbuf * m, struct sockaddr * dst, struct rtentry * rtp) { int s, isr; register struct ifqueue *ifq = 0; if (dst->sa_family != AF_INET) { m_freem(m); return EAFNOSUPPORT; } s = splhigh(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); m_freem(m); ifp->if_oerrors++; isdn_output(applnr[ifp->if_unit]); splx(s); return (ENOBUFS); } IF_ENQUEUE(&ifp->if_snd, m); ifp->if_opackets++; ifp->if_obytes += m->m_pkthdr.len; isdn_output(applnr[ifp->if_unit]); splx(s); return (0); } int ii_input(int no, int len, char *buf, int dir) { int error = 0; struct mbuf *m; struct ifnet *ifp = &(ii_if[no]); int s; s = splhigh(); MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == 0) { splx(s); return (0); } if (len >= MHLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { (void) m_free(m); splx(s); return (0); } } bcopy((caddr_t) buf, mtod(m, caddr_t), len); m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = len; m->m_len = len; if (IF_QFULL(&ipintrq)) { IF_DROP(&ipintrq); ifp->if_ierrors++; m_freem(m); splx(s); return(0); } IF_ENQUEUE(&ipintrq, m); ifp->if_ipackets++; schednetisr(NETISR_IP); splx(s); return(len); } void ii_connect(int no) { struct ifnet *ifp = &ii_if[no]; ifp->if_flags |= IFF_RUNNING; } void ii_disconnect(int no) { struct ifnet *ifp = &ii_if[no]; ifp->if_flags &= ~IFF_RUNNING; } int ii_out(int no, char *buf, int len) { struct ifnet *ifp = &ii_if[no]; struct mbuf *m0, *m; int l; IF_DEQUEUE(&ifp->if_snd, m); if (m == 0) { return (0); } /* * Copy the mbuf chain into the transmit buf */ l = 0; for (m0 = m; m != 0; m = m->m_next) { if((l+= m->m_len) > len) { m_freem(m0); return(0); } bcopy(mtod(m, caddr_t), buf, m->m_len); buf += m->m_len; } m_freem(m0); return (l); } /* * Process an ioctl request. */ -int +static int ii_ioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; { struct ifaddr *ifa = (struct ifaddr *) data; struct ifreq *ifr = (struct ifreq *) data; int s; switch (cmd) { case SIOCSIFDSTADDR: case SIOCAIFADDR: case SIOCSIFADDR: if (ifa->ifa_addr->sa_family != AF_INET) return(EAFNOSUPPORT); ifp->if_flags |= IFF_UP; /* FALLTHROUGH */ case SIOCSIFFLAGS: s= splhigh(); if((!(ifp->if_flags & IFF_UP)) && (ifp->if_flags & IFF_RUNNING)) { isdn_disconnect(applnr[ifp->if_unit],0); ifp->if_flags &= ~IFF_RUNNING; } break; case SIOCSIFMTU: ifr->ifr_metric = ifp->if_mtu; break; case SIOCGIFMTU: if(ifr->ifr_metric < 2048) return(EAFNOSUPPORT); ifp->if_mtu = ifr->ifr_metric; break; default: printf("IIO %x",cmd); return(EINVAL); } return(0); } Index: head/sys/gnu/isdn/iispy.c =================================================================== --- head/sys/gnu/isdn/iispy.c (revision 12911) +++ head/sys/gnu/isdn/iispy.c (revision 12912) @@ -1,269 +1,205 @@ -static char _ispyid[] = "@(#)$Id: iispy.c,v 1.8 1995/12/08 11:12:52 julian Exp $"; +static char _ispyid[] = "@(#)$Id: iispy.c,v 1.9 1995/12/08 23:19:40 phk Exp $"; /******************************************************************************* - * II - Version 0.1 $Revision: 1.8 $ $State: Exp $ + * II - Version 0.1 $Revision: 1.9 $ $State: Exp $ * * Copyright 1994 Dietmar Friede ******************************************************************************* * Bug reports, patches, comments, suggestions should be sent to: * * jkr@saarlink.de or jkrause@guug.de * ******************************************************************************* - * $Log: iispy.c,v $ - * Revision 1.8 1995/12/08 11:12:52 julian - * Pass 3 of the great devsw changes - * most devsw referenced functions are now static, as they are - * in the same file as their devsw structure. I've also added DEVFS - * support for nearly every device in the system, however - * many of the devices have 'incorrect' names under DEVFS - * because I couldn't quickly work out the correct naming conventions. - * (but devfs won't be coming on line for a month or so anyhow so that doesn't - * matter) - * - * If you "OWN" a device which would normally have an entry in /dev - * then search for the devfs_add_devsw() entries and munge to make them right.. - * check out similar devices to see what I might have done in them in you - * can't see what's going on.. - * for a laugh compare conf.c conf.h defore and after... :) - * I have not doen DEVFS entries for any DISKSLICE devices yet as that will be - * a much more complicated job.. (pass 5 :) - * - * pass 4 will be to make the devsw tables of type (cdevsw * ) - * rather than (cdevsw) - * seems to work here.. - * complaints to the usual places.. :) - * - * Revision 1.7 1995/12/06 23:43:37 bde - * Removed unnecessary #includes of . Some of these were just - * to get the definitions of TRUE and FALSE which happen to be defined in - * a deeply nested include. - * - * Added nearby #includes of where appropriate. - * - * Revision 1.6 1995/11/29 14:39:10 julian - * If you're going to mechanically replicate something in 50 files - * it's best to not have a (compiles cleanly) typo in it! (sigh) - * - * Revision 1.5 1995/11/29 10:47:07 julian - * OK, that's it.. - * That's EVERY SINGLE driver that has an entry in conf.c.. - * my next trick will be to define cdevsw[] and bdevsw[] - * as empty arrays and remove all those DAMNED defines as well.. - * - * Revision 1.4 1995/09/08 11:06:56 bde - * Fix benign type mismatches in devsw functions. 82 out of 299 devsw - * functions were wrong. - * - * Revision 1.3 1995/03/28 07:54:40 bde - * Add and move declarations to fix all of the warnings from `gcc -Wimplicit' - * (except in netccitt, netiso and netns) that I didn't notice when I fixed - * "all" such warnings before. - * - * Revision 1.2 1995/02/15 06:28:27 jkh - * Fix up include paths, nuke some warnings. - * - * Revision 1.1 1995/02/14 15:00:29 jkh - * An ISDN driver that supports the EDSS1 and the 1TR6 ISDN interfaces. - * EDSS1 is the "Euro-ISDN", 1TR6 is the soon obsolete german ISDN Interface. - * Obtained from: Dietmar Friede and - * Juergen Krause - * - * This is only one part - the rest to follow in a couple of hours. - * This part is a benign import, since it doesn't affect anything else. - * - * - ******************************************************************************/ + */ #include "ispy.h" #if NISPY > 0 #include #include #include #include #include #include #include #include #include #ifdef DEVFS #include #endif /*DEVFS*/ /*#include "malloc.h"*/ #include -int nispy = NISPY; int ispy_applnr; static int next_if =0; static unsigned long ispy_cnt, ispy_out; static char dir; #define ISPY_SIZE 260 #define OPEN 1 #define READ_WAIT 2 #define ISPYBUF 16 #define ISPYMASK (ISPYBUF-1) /* ISPYBUF has to be a power of 2 */ static struct ispy_data { struct ispy_buf { unsigned long cnt; struct timeval stamp; char ibuf[ISPY_SIZE]; unsigned char dir; int ilen; } b[ISPYBUF]; int state; #ifdef DEVFS void *devfs_token; #endif } ispy_data[NISPY]; static d_open_t ispyopen; static d_close_t ispyclose; static d_read_t ispyread; static d_ioctl_t ispyioctl; #define CDEV_MAJOR 59 static struct cdevsw ispy_cdevsw = { ispyopen, ispyclose, ispyread, nowrite, /*59*/ ispyioctl, nostop, nullreset, nodevtotty,/* ispy */ seltrue, nommap, NULL, "ispy", NULL, -1 }; int ispyattach(int ap) { char name[32]; struct ispy_data *ispy; if(next_if >= NISPY) return(-1); ispy= &ispy_data[next_if]; ispy->state= 0; ispy_applnr= ap; #ifdef DEVFS sprintf(name,"ispy%d",next_if); ispy->devfs_token =devfs_add_devsw("/isdn",name,&ispy_cdevsw,next_if, DV_CHR, 0, 0, 0600); #endif return(next_if++); } int ispy_input(int no, int len, char *buf, int out) { struct ispy_data *ispy= &ispy_data[no]; struct ispy_buf *b= &ispy->b[ispy_cnt&ISPYMASK]; if(len > ISPY_SIZE) return(0); if(len) { b->cnt= ispy_cnt++; b->stamp= time; b->dir= out; bcopy(buf, b->ibuf, len); } b->ilen= len; if(ispy->state & READ_WAIT) { ispy->state &= ~READ_WAIT; wakeup((caddr_t) &ispy->state); } return(len); } static int ispyopen(dev_t dev, int flags, int fmt, struct proc *p) { int err; struct ispy_data *ispy; if (minor(dev)>NISPY) return (ENXIO); ispy= &ispy_data[minor(dev)]; if(ispy->state&OPEN) return(EBUSY); ispy->state |= OPEN; return (0); } static int ispyclose(dev_t dev, int flags, int fmt, struct proc *p) { struct ispy_data *ispy= &ispy_data[minor(dev)]; if(ispy->state & READ_WAIT) wakeup((caddr_t) &ispy->state); ispy->state = 0; return (0); } static int ispyioctl (dev_t dev, int cmd, caddr_t data, int flags, struct proc *p) { int unit = minor(dev); switch (cmd) { default: return (ENOTTY); } return (0); } static int ispyread(dev_t dev, struct uio * uio, int ioflag) { int x; int error = 0; struct ispy_data *ispy= &ispy_data[minor(dev)]; struct ispy_buf *b; if((ispy_cnt-ispy_out) > ISPYBUF) ispy_out= ispy_cnt - ISPYBUF; b= &ispy->b[ispy_out&ISPYMASK]; ispy_out++; while(b->ilen == 0) { ispy->state |= READ_WAIT; if(error= tsleep((caddr_t) &ispy->state, TTIPRI | PCATCH, "ispy", 0 )) return(error); } x = splhigh(); if(b->ilen) { error = uiomove((char *) &b->dir, 1, uio); if(error == 0) error = uiomove((char *) &b->cnt ,sizeof(unsigned long)+sizeof(struct timeval)+b->ilen, uio); b->ilen= 0; } splx(x); return error; } static ispy_devsw_installed = 0; static void ispy_drvinit(void *unused) { dev_t dev; if( ! ispy_devsw_installed ) { dev = makedev(CDEV_MAJOR, 0); cdevsw_add(&dev,&ispy_cdevsw, NULL); ispy_devsw_installed = 1; } } SYSINIT(ispydev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ispy_drvinit,NULL) #endif Index: head/sys/gnu/isdn/iitel.c =================================================================== --- head/sys/gnu/isdn/iitel.c (revision 12911) +++ head/sys/gnu/isdn/iitel.c (revision 12912) @@ -1,334 +1,266 @@ -static char _itelid[] = "@(#)$Id: iitel.c,v 1.9 1995/12/08 11:12:54 julian Exp $"; +static char _itelid[] = "@(#)$Id: iitel.c,v 1.10 1995/12/08 23:19:42 phk Exp $"; /******************************************************************************* - * II - Version 0.1 $Revision: 1.9 $ $State: Exp $ + * II - Version 0.1 $Revision: 1.10 $ $State: Exp $ * * Copyright 1994 Dietmar Friede ******************************************************************************* * Bug reports, patches, comments, suggestions should be sent to: * * jkr@saarlink.de or jkrause@guug.de * ******************************************************************************* - * $Log: iitel.c,v $ - * Revision 1.9 1995/12/08 11:12:54 julian - * Pass 3 of the great devsw changes - * most devsw referenced functions are now static, as they are - * in the same file as their devsw structure. I've also added DEVFS - * support for nearly every device in the system, however - * many of the devices have 'incorrect' names under DEVFS - * because I couldn't quickly work out the correct naming conventions. - * (but devfs won't be coming on line for a month or so anyhow so that doesn't - * matter) - * - * If you "OWN" a device which would normally have an entry in /dev - * then search for the devfs_add_devsw() entries and munge to make them right.. - * check out similar devices to see what I might have done in them in you - * can't see what's going on.. - * for a laugh compare conf.c conf.h defore and after... :) - * I have not doen DEVFS entries for any DISKSLICE devices yet as that will be - * a much more complicated job.. (pass 5 :) - * - * pass 4 will be to make the devsw tables of type (cdevsw * ) - * rather than (cdevsw) - * seems to work here.. - * complaints to the usual places.. :) - * - * Revision 1.8 1995/11/29 14:39:11 julian - * If you're going to mechanically replicate something in 50 files - * it's best to not have a (compiles cleanly) typo in it! (sigh) - * - * Revision 1.7 1995/11/29 10:47:08 julian - * OK, that's it.. - * That's EVERY SINGLE driver that has an entry in conf.c.. - * my next trick will be to define cdevsw[] and bdevsw[] - * as empty arrays and remove all those DAMNED defines as well.. - * - * Revision 1.6 1995/11/16 10:22:29 bde - * Fixed the type of itel_input(). A trailing arg was missing. - * - * Included "conf.h" to get some prototypes. - * - * Removed some useless includes. - * - * Revision 1.5 1995/09/08 11:06:57 bde - * Fix benign type mismatches in devsw functions. 82 out of 299 devsw - * functions were wrong. - * - * Revision 1.4 1995/07/16 10:11:10 bde - * Don't include in drivers that aren't tty drivers or in general - * files that don't depend on the internals of - * - * Revision 1.3 1995/03/28 07:54:41 bde - * Add and move declarations to fix all of the warnings from `gcc -Wimplicit' - * (except in netccitt, netiso and netns) that I didn't notice when I fixed - * "all" such warnings before. - * - * Revision 1.2 1995/02/15 06:28:27 jkh - * Fix up include paths, nuke some warnings. - * - * Revision 1.1 1995/02/14 15:00:30 jkh - * An ISDN driver that supports the EDSS1 and the 1TR6 ISDN interfaces. - * EDSS1 is the "Euro-ISDN", 1TR6 is the soon obsolete german ISDN Interface. - * Obtained from: Dietmar Friede and - * Juergen Krause - * - * This is only one part - the rest to follow in a couple of hours. - * This part is a benign import, since it doesn't affect anything else. - * - * - ******************************************************************************/ + */ #include "itel.h" #if NITEL > 0 #include #include #include #include #include #include #include #include #include #ifdef DEVFS #include #endif /*DEVFS*/ #include "gnu/isdn/isdn_ioctl.h" -int nitel = NITEL; static int applnr[NITEL]; static int next_if =0; #define ITEL_SIZE 1024 #define OPEN 1 #define CONNECT 2 #define READ_WAIT 4 #define WRITE_WAIT 8 #define min(a,b) ((a)<(b)?(a):(b)) static d_open_t itelopen; static d_close_t itelclose; static d_read_t itelread; static d_write_t itelwrite; static d_ioctl_t itelioctl; #define CDEV_MAJOR 57 static struct cdevsw itel_cdevsw = { itelopen, itelclose, itelread, itelwrite, /*57*/ itelioctl, nostop, nullreset, nodevtotty,/* itel */ seltrue, nommap, NULL, "itel", NULL, -1 }; static struct itel_data { char ibuf[ITEL_SIZE]; char obuf[ITEL_SIZE]; int state; int ilen, olen; #ifdef DEVFS void *devfs_token; #endif } itel_data[NITEL]; int itelattach(int ap) { struct itel_data *itel; char name[32]; if(next_if >= NITEL) return(-1); itel= &itel_data[next_if]; itel->ilen= itel->olen= 0; itel->state= 0; applnr[next_if]= ap; #ifdef DEVFS sprintf(name,"itel%d",next_if); itel->devfs_token = devfs_add_devsw("/isdn",name,&itel_cdevsw,next_if, DV_CHR, 0, 0, 0600); #endif return(next_if++); } int itel_input(int no, int len, char *buf, int dir) { struct itel_data *itel= &itel_data[no]; if(itel->ilen || ( len > ITEL_SIZE)) return(0); if(len) bcopy(buf, itel->ibuf, len); itel->ilen= len; if(itel->state & READ_WAIT) { itel->state &= ~READ_WAIT; wakeup((caddr_t) itel->ibuf); } return(len); } int itel_out(int no, char *buf, int len) { struct itel_data *itel= &itel_data[no]; int l; if((itel->state & CONNECT) == 0) return(0); if((l= itel->olen) && (itel->olen <= len)) bcopy(itel->obuf, buf, l); itel->olen= 0; if(itel->state & WRITE_WAIT) { itel->state &= ~WRITE_WAIT; wakeup((caddr_t) itel->obuf); } return(l); } void itel_connect(int no) { itel_data[no].state |= CONNECT; } void itel_disconnect(int no) { struct itel_data *itel= &itel_data[no]; int s; s= itel->state; if(itel->state &= OPEN) { itel->ilen= itel->olen= 0; if(s & READ_WAIT) wakeup((caddr_t) itel->ibuf); if(s & WRITE_WAIT) wakeup((caddr_t) itel->obuf); } } int itelopen(dev_t dev, int flags, int fmt, struct proc *p) { int err; struct itel_data *itel; if (minor(dev)>NITEL) return (ENXIO); itel= &itel_data[minor(dev)]; if((itel->state & CONNECT) == 0) return(EIO); if(itel->state&OPEN) return(0); itel->ilen= itel->olen= 0; itel->state |= OPEN; return (0); } int itelclose(dev_t dev, int flags, int fmt, struct proc *p) { struct itel_data *itel= &itel_data[minor(dev)]; if(itel->state & READ_WAIT) wakeup((caddr_t) itel->ibuf); if(itel->state & WRITE_WAIT) wakeup((caddr_t) itel->obuf); itel_data[minor(dev)].state &= CONNECT; return (0); } int itelioctl (dev_t dev, int cmd, caddr_t data, int flags, struct proc *p) { int unit = minor(dev); switch (cmd) { default: return (ENOTTY); } return (0); } int itelread(dev_t dev, struct uio * uio, int ioflag) { int x; int error = 0; struct itel_data *itel= &itel_data[minor(dev)]; if((itel->state & CONNECT) == 0) return(EIO); while((itel->ilen == 0) && (itel->state & CONNECT)) { itel->state |= READ_WAIT; sleep((caddr_t) itel->ibuf, PZERO | PCATCH); } x = splhigh(); if(itel->ilen) { error = uiomove(itel->ibuf, itel->ilen, uio); itel->ilen= 0; } else error= EIO; splx(x); return error; } int itelwrite(dev_t dev, struct uio * uio, int ioflag) { int x; int error = 0; struct itel_data *itel= &itel_data[minor(dev)]; if((itel->state & CONNECT) == 0) return(EIO); while(itel->olen && (itel->state & CONNECT)) { itel->state |= WRITE_WAIT; sleep((caddr_t) itel->obuf, PZERO | PCATCH); } x = splhigh(); if((itel->state & CONNECT) == 0) { splx(x); return(0); } if(itel->olen == 0) { itel->olen= min(ITEL_SIZE, uio->uio_resid); error = uiomove(itel->obuf, itel->olen, uio); isdn_output(applnr[minor(dev)]); } splx(x); return error; } static itel_devsw_installed = 0; static void itel_drvinit(void *unused) { dev_t dev; if( ! itel_devsw_installed ) { dev = makedev(CDEV_MAJOR, 0); cdevsw_add(&dev,&itel_cdevsw, NULL); itel_devsw_installed = 1; } } SYSINIT(iteldev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,itel_drvinit,NULL) #endif Index: head/sys/gnu/isdn/iitty.c =================================================================== --- head/sys/gnu/isdn/iitty.c (revision 12911) +++ head/sys/gnu/isdn/iitty.c (revision 12912) @@ -1,550 +1,364 @@ -static char _ittyid[] = "@(#)$Id: iitty.c,v 1.17 1995/12/08 23:19:42 phk Exp $"; +static char _ittyid[] = "@(#)$Id: iitty.c,v 1.18 1995/12/10 15:54:13 bde Exp $"; /******************************************************************************* - * II - Version 0.1 $Revision: 1.17 $ $State: Exp $ + * II - Version 0.1 $Revision: 1.18 $ $State: Exp $ * * Copyright 1994 Dietmar Friede ******************************************************************************* * Bug reports, patches, comments, suggestions should be sent to: * * jkr@saarlink.de or jkrause@guug.de * ******************************************************************************* - * $Log: iitty.c,v $ - * Revision 1.17 1995/12/08 23:19:42 phk - * Julian forgot to make the *devsw structures static. - * - * Revision 1.16 1995/12/08 11:12:56 julian - * Pass 3 of the great devsw changes - * most devsw referenced functions are now static, as they are - * in the same file as their devsw structure. I've also added DEVFS - * support for nearly every device in the system, however - * many of the devices have 'incorrect' names under DEVFS - * because I couldn't quickly work out the correct naming conventions. - * (but devfs won't be coming on line for a month or so anyhow so that doesn't - * matter) - * - * If you "OWN" a device which would normally have an entry in /dev - * then search for the devfs_add_devsw() entries and munge to make them right.. - * check out similar devices to see what I might have done in them in you - * can't see what's going on.. - * for a laugh compare conf.c conf.h defore and after... :) - * I have not doen DEVFS entries for any DISKSLICE devices yet as that will be - * a much more complicated job.. (pass 5 :) - * - * pass 4 will be to make the devsw tables of type (cdevsw * ) - * rather than (cdevsw) - * seems to work here.. - * complaints to the usual places.. :) - * - * Revision 1.15 1995/12/05 20:33:47 bde - * Fixed ity's d_stop entry. itystop() wasn't used. itystop() is inadequate - * but probably harmless. It's hard to tell because apparently no one runs - * ity. - * - * Fixed ity's d_reset entry. `nx' entries should never be used for existing - * devices. - * - * conf.c: - * Moved a prototype to a better place. - * - * Removed a stale #define. - * - * Revision 1.14 1995/11/29 14:39:12 julian - * If you're going to mechanically replicate something in 50 files - * it's best to not have a (compiles cleanly) typo in it! (sigh) - * - * Revision 1.13 1995/11/29 10:47:09 julian - * OK, that's it.. - * That's EVERY SINGLE driver that has an entry in conf.c.. - * my next trick will be to define cdevsw[] and bdevsw[] - * as empty arrays and remove all those DAMNED defines as well.. - * - * Revision 1.12 1995/11/16 10:35:29 bde - * Fixed the type of ity_input(). A trailing arg was missing. - * - * Completed function declarations. - * - * Added prototypes. - * - * Removed some useless includes. - * - * Revision 1.11 1995/07/31 21:28:42 bde - * Use tsleep() instead of ttysleep() to wait for carrier since a generation - * change isn't an error. - * - * Revision 1.10 1995/07/31 21:01:03 bde - * Obtained from: partly from ancient patches of mine via 1.1.5 - * - * Introduce TS_CONNECTED and TS_ZOMBIE states. TS_CONNECTED is set - * while a connection is established. It is set while (TS_CARR_ON or - * CLOCAL is set) and TS_ZOMBIE is clear. TS_ZOMBIE is set for on to - * off transitions of TS_CARR_ON that occur when CLOCAL is clear and - * is cleared for off to on transitions of CLOCAL. I/o can only occur - * while TS_CONNECTED is set. TS_ZOMBIE prevents further i/o. - * - * Split the input-event sleep address TSA_CARR_ON(tp) into TSA_CARR_ON(tp) - * and TSA_HUP_OR_INPUT(tp). The former address is now used only for - * off to on carrier transitions and equivalent CLOCAL transitions. - * The latter is used for all input events, all carrier transitions - * and certain CLOCAL transitions. There are some harmless extra - * wakeups for rare connection- related events. Previously there were - * too many extra wakeups for non-rare input events. - * - * Drivers now call l_modem() instead of setting TS_CARR_ON directly - * to handle even the initial off to on transition of carrier. They - * should always have done this. l_modem() now handles TS_CONNECTED - * and TS_ZOMBIE as well as TS_CARR_ON. - * - * gnu/isdn/iitty.c: - * Set TS_CONNECTED for first open ourself to go with bogusly setting - * CLOCAL. - * - * i386/isa/syscons.c, i386/isa/pcvt/pcvt_drv.c: - * We fake carrier, so don't also fake CLOCAL. - * - * kern/tty.c: - * Testing TS_CONNECTED instead of TS_CARR_ON fixes TIOCCONS forgetting to - * test CLOCAL. TS_ISOPEN was tested instead, but that broke when we disabled - * the clearing of TS_ISOPEN for certain transitions of CLOCAL. - * - * Testing TS_CONNECTED fixes ttyselect() returning false success for output - * to devices in state !TS_CARR_ON && !CLOCAL. - * - * Optimize the other selwakeup() call (this is not related to the other - * changes). - * - * kern/tty_pty.c: - * ptcopen() can be declared in traditional C now that dev_t isn't short. - * - * Revision 1.9 1995/07/22 16:44:26 bde - * Obtained from: partly from ancient patches of mine via 1.1.5 - * - * Give names to the magic tty i/o sleep addresses and use them. This makes - * it easier to remember what the addresses are for and to keep them unique. - * - * Revision 1.8 1995/07/22 01:29:28 bde - * Move the inline code for waking up writers to a new function - * ttwwakeup(). The conditions for doing the wakeup will soon become - * more complicated and I don't want them duplicated in all drivers. - * - * It's probably not worth making ttwwakeup() a macro or an inline - * function. The cost of the function call is relatively small when - * there is a process to wake up. There is usually a process to wake - * up for large writes and the system call overhead dwarfs the function - * call overhead for small writes. - * - * Revision 1.7 1995/07/21 20:52:21 bde - * Obtained from: partly from ancient patches by ache and me via 1.1.5 - * - * Nuke `symbolic sleep message strings'. Use unique literal messages so that - * `ps l' shows unambiguously where processes are sleeping. - * - * Revision 1.6 1995/07/21 16:30:37 bde - * Obtained from: partly from an ancient patch of mine via 1.1.5 - * - * Temporarily nuke TS_WOPEN. It was only used for the obscure MDMBUF - * flow control option in the kernel and for informational purposes - * in `pstat -t'. The latter worked properly only for ptys. In - * general there may be multiple processes sleeping in open() and - * multiple processes that successfully opened the tty by opening it - * in O_NONBLOCK mode or during a window when CLOCAL was set. tty.c - * doesn't have enough information to maintain the flag but always - * cleared it in ttyopen(). - * - * TS_WOPEN should be restored someday just so that `pstat -t' can - * display it (MDMBUF is already fixed). Fixing it requires counting - * of processes sleeping in open() in too many serial drivers. - * - * Revision 1.5 1995/03/28 07:54:43 bde - * Add and move declarations to fix all of the warnings from `gcc -Wimplicit' - * (except in netccitt, netiso and netns) that I didn't notice when I fixed - * "all" such warnings before. - * - * Revision 1.4 1995/02/28 00:20:30 pst - * Incorporate bde's code-review comments. - * - * (a) bring back ttselect, now that we have xxxdevtotty() it isn't dangerous. - * (b) remove all of the wrappers that have been replaced by ttselect - * (c) fix formatting in syscons.c and definition in syscons.h - * (d) add cxdevtotty - * - * NOT DONE: - * (e) make pcvt work... it was already broken...when someone fixes pcvt to - * link properly, just rename get_pccons to xxxdevtotty and we're done - * - * Revision 1.3 1995/02/25 20:08:52 pst - * (a) remove the pointer to each driver's tty structure array from cdevsw - * (b) add a function callback vector to tty drivers that will return a pointer - * to a valid tty structure based upon a dev_t - * (c) make syscons structures the same size whether or not APM is enabled so - * utilities don't crash if NAPM changes (and make the damn kernel compile!) - * (d) rewrite /dev/snp ioctl interface so that it is device driver and i386 - * independant - * - * Revision 1.2 1995/02/15 06:28:28 jkh - * Fix up include paths, nuke some warnings. - * - * Revision 1.1 1995/02/14 15:00:32 jkh - * An ISDN driver that supports the EDSS1 and the 1TR6 ISDN interfaces. - * EDSS1 is the "Euro-ISDN", 1TR6 is the soon obsolete german ISDN Interface. - * Obtained from: Dietmar Friede and - * Juergen Krause - * - * This is only one part - the rest to follow in a couple of hours. - * This part is a benign import, since it doesn't affect anything else. - * - * - ******************************************************************************/ + */ #include "ity.h" #if NITY > 0 #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DEVFS #include #endif /*DEVFS*/ #include "gnu/isdn/isdn_ioctl.h" static d_open_t ityopen; static d_close_t ityclose; static d_read_t ityread; static d_write_t itywrite; static d_ioctl_t ityioctl; static d_stop_t itystop; static d_devtotty_t itydevtotty; #define CDEV_MAJOR 56 static struct cdevsw ity_cdevsw = { ityopen, ityclose, ityread, itywrite, /*56*/ ityioctl, itystop, noreset, itydevtotty,/* ity */ ttselect, nommap, NULL, "ity", NULL, -1 }; -extern int ityparam __P((struct tty *tp, struct termios *t)); -extern void itystart __P((struct tty *tp)); +static int ityparam __P((struct tty *tp, struct termios *t)); +static void itystart __P((struct tty *tp)); -int nity = NITY; -int itydefaultrate = 64000; -short ity_addr[NITY]; -struct tty ity_tty[NITY]; +static int itydefaultrate = 64000; +static short ity_addr[NITY]; +static struct tty ity_tty[NITY]; static int applnr[NITY]; static int next_if= 0; #ifdef DEVFS void *devfs_token[NITY]; -void *devfs_token_out[NITY]; +static void *devfs_token_out[NITY]; #endif #define UNIT(x) (minor(x)&0x3f) #define OUTBOUND(x) ((minor(x)&0x80)==0x80) int ityattach(int ap) { char name[32]; if(next_if >= NITY) return(-1); applnr[next_if]= ap; #ifdef DEVFS sprintf(name,"ity%d",next_if); devfs_token[next_if] = devfs_add_devsw("/isdn",name, &ity_cdevsw,next_if, DV_CHR, 0, 0, 0600); sprintf(name,"Oity%d",next_if); /* XXX find out real name */ devfs_token[next_if] = devfs_add_devsw("/isdn",name, &ity_cdevsw,(next_if | 0x80), DV_CHR, 0, 0, 0600); #endif return(next_if++); } /* ARGSUSED */ static int ityopen(dev_t dev, int flag, int mode, struct proc * p) { register struct tty *tp; register int unit; int error = 0; unit = UNIT(dev); if (unit >= next_if) return (ENXIO); tp = &ity_tty[unit]; tp->t_oproc = itystart; tp->t_param = ityparam; tp->t_dev = dev; if ((tp->t_state & TS_ISOPEN) == 0) { ttychars(tp); if (tp->t_ispeed == 0) { tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = TTYDEF_CFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = itydefaultrate; } ityparam(tp, &tp->t_termios); ttsetwater(tp); } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) return (EBUSY); (void) spltty(); if (OUTBOUND(dev)) { /* * XXX should call l_modem() here and not meddle with CLOCAL, * but itystart() wants TS_CARR_ON to give the true carrier. */ tp->t_cflag |= CLOCAL; tp->t_state |= TS_CONNECTED; } while ((flag & O_NONBLOCK) == 0 && (tp->t_cflag & CLOCAL) == 0 && (tp->t_state & TS_CARR_ON) == 0) { error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "iidcd", 0); if (error) break; } (void) spl0(); if (error == 0) error = (*linesw[tp->t_line].l_open) (dev, tp); return (error); } /* ARGSUSED */ static int ityclose(dev, flag, mode, p) dev_t dev; int flag, mode; struct proc *p; { register struct tty *tp; register ity; register int unit; unit = UNIT(dev); ity = ity_addr[unit]; if(tp = &ity_tty[unit]) (*linesw[tp->t_line].l_close) (tp, flag); ttyclose(tp); isdn_disconnect(applnr[unit],0); return (0); } static int ityread(dev, uio, flag) dev_t dev; struct uio *uio; int flag; { register struct tty *tp = &ity_tty[UNIT(dev)]; return ((*linesw[tp->t_line].l_read) (tp, uio, flag)); } static int itywrite(dev, uio, flag) dev_t dev; struct uio *uio; int flag; { int unit = UNIT(dev); register struct tty *tp = &ity_tty[unit]; return ((*linesw[tp->t_line].l_write) (tp, uio, flag)); } int ity_input(int no, int len, char *buf, int dir) { register struct tty *tp = &ity_tty[no]; int i; if (tp->t_state & TS_ISOPEN) for(i= 0; it_line].l_rint)(buf[i], tp); else len= 0; return(len); } -void +static void itystart(struct tty *tp) { int s, unit; unit = UNIT(tp->t_dev); s = splhigh(); if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { splx(s); return; } ttwwakeup(tp); if (tp->t_outq.c_cc) { if(OUTBOUND(tp->t_dev) && (tp->t_cflag & CLOCAL) && ((tp->t_state & TS_CARR_ON) == 0)) isdn_msg(applnr[unit]); else isdn_output(applnr[unit]); tp->t_state |= TS_BUSY; } splx(s); } int ity_out(int no, char *buf, int len) { struct tty *tp = &ity_tty[no]; int i; if(tp == NULL) return(0); if(tp->t_outq.c_cc) { for (i = 0; i < len && tp->t_outq.c_cc; ++i) buf[i]= getc(&tp->t_outq); return(i); } tp->t_state &=~ (TS_BUSY|TS_FLUSH); if (tp->t_line) (*linesw[tp->t_line].l_start)(tp); else itystart(tp); return(0); } void ity_connect(int no) { struct tty *tp = &ity_tty[no]; if(tp == NULL) return; if(OUTBOUND(tp->t_dev)) tp->t_cflag &= ~CLOCAL; (*linesw[tp->t_line].l_modem) (tp, 1); tp->t_state &=~ (TS_BUSY|TS_FLUSH); if (tp->t_line) (*linesw[tp->t_line].l_start)(tp); else itystart(tp); } void ity_disconnect(int no) { struct tty *tp = &ity_tty[no]; if(tp) (*linesw[tp->t_line].l_modem) (tp, 0); } static int ityioctl(dev, cmd, data, flag,p) dev_t dev; int cmd; caddr_t data; int flag; struct proc *p; { register struct tty *tp; register int unit = UNIT(dev); register int error; tp = &ity_tty[unit]; error = (*linesw[tp->t_line].l_ioctl) (tp, cmd, data, flag,p); if (error >= 0) return (error); error = ttioctl(tp, cmd, data, flag); if (error >= 0) return (error); switch (cmd) { default: return (ENOTTY); } return (0); } -int +static int ityparam(tp, t) register struct tty *tp; register struct termios *t; { register ity; register int cfcr, cflag = t->c_cflag; int unit = UNIT(tp->t_dev); int ospeed = t->c_ospeed; /* check requested parameters */ if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) return (EINVAL); /* and copy to tty */ tp->t_ispeed = t->c_ispeed; tp->t_ospeed = t->c_ospeed; tp->t_cflag = cflag; if (ospeed == 0) { isdn_disconnect(applnr[unit],0); return (0); } return (0); } /* * Stop output on a line. */ /* ARGSUSED */ static void itystop(struct tty *tp, int flag) { register int s; s = splhigh(); if (tp->t_state & TS_BUSY) { if ((tp->t_state & TS_TTSTOP) == 0) tp->t_state |= TS_FLUSH; } splx(s); } static struct tty * itydevtotty(dev_t dev) { register int unit = UNIT(dev); if (unit >= next_if) return (NULL); return (&ity_tty[unit]); } static ity_devsw_installed = 0; static void ity_drvinit(void *unused) { dev_t dev; if( ! ity_devsw_installed ) { dev = makedev(CDEV_MAJOR, 0); cdevsw_add(&dev,&ity_cdevsw, NULL); ity_devsw_installed = 1; } } SYSINIT(itydev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ity_drvinit,NULL) #endif Index: head/sys/gnu/isdn/isdn.c =================================================================== --- head/sys/gnu/isdn/isdn.c (revision 12911) +++ head/sys/gnu/isdn/isdn.c (revision 12912) @@ -1,735 +1,660 @@ -static char _isdnid[] = "@(#)$Id: isdn.c,v 1.10 1995/12/08 23:19:44 phk Exp $"; +static char _isdnid[] = "@(#)$Id: isdn.c,v 1.11 1995/12/10 15:54:17 bde Exp $"; /******************************************************************************* - * II - Version 0.1 $Revision: 1.10 $ $State: Exp $ + * II - Version 0.1 $Revision: 1.11 $ $State: Exp $ * * Copyright 1994 Dietmar Friede ******************************************************************************* * Bug reports, patches, comments, suggestions should be sent to: * * jkr@saarlink.de or jkrause@guug.de * ******************************************************************************* - * $Log: isdn.c,v $ - * Revision 1.10 1995/12/08 23:19:44 phk - * Julian forgot to make the *devsw structures static. - * - * Revision 1.9 1995/12/08 11:13:01 julian - * Pass 3 of the great devsw changes - * most devsw referenced functions are now static, as they are - * in the same file as their devsw structure. I've also added DEVFS - * support for nearly every device in the system, however - * many of the devices have 'incorrect' names under DEVFS - * because I couldn't quickly work out the correct naming conventions. - * (but devfs won't be coming on line for a month or so anyhow so that doesn't - * matter) - * - * If you "OWN" a device which would normally have an entry in /dev - * then search for the devfs_add_devsw() entries and munge to make them right.. - * check out similar devices to see what I might have done in them in you - * can't see what's going on.. - * for a laugh compare conf.c conf.h defore and after... :) - * I have not doen DEVFS entries for any DISKSLICE devices yet as that will be - * a much more complicated job.. (pass 5 :) - * - * pass 4 will be to make the devsw tables of type (cdevsw * ) - * rather than (cdevsw) - * seems to work here.. - * complaints to the usual places.. :) - * - * Revision 1.8 1995/11/29 14:39:12 julian - * If you're going to mechanically replicate something in 50 files - * it's best to not have a (compiles cleanly) typo in it! (sigh) - * - * Revision 1.7 1995/11/29 10:47:10 julian - * OK, that's it.. - * That's EVERY SINGLE driver that has an entry in conf.c.. - * my next trick will be to define cdevsw[] and bdevsw[] - * as empty arrays and remove all those DAMNED defines as well.. - * - * Revision 1.6 1995/11/16 10:47:21 bde - * Fixed a call to the listen function. A trailing arg was missing. - * - * Fixed the type of isdn_check(). A trailing arg was missing. - * - * Included "conf.h" to get some prototypes. - * - * Completed function declarations. - * - * Added prototypes. - * - * Removed some useless includes. - * - * Revision 1.5 1995/09/08 11:06:58 bde - * Fix benign type mismatches in devsw functions. 82 out of 299 devsw - * functions were wrong. - * - * Revision 1.4 1995/05/30 07:58:02 rgrimes - * Remove trailing whitespace. - * - * Revision 1.3 1995/03/28 07:54:44 bde - * Add and move declarations to fix all of the warnings from `gcc -Wimplicit' - * (except in netccitt, netiso and netns) that I didn't notice when I fixed - * "all" such warnings before. - * - * Revision 1.2 1995/02/15 06:28:29 jkh - * Fix up include paths, nuke some warnings. - * - * Revision 1.1 1995/02/14 15:00:33 jkh - * An ISDN driver that supports the EDSS1 and the 1TR6 ISDN interfaces. - * EDSS1 is the "Euro-ISDN", 1TR6 is the soon obsolete german ISDN Interface. - * Obtained from: Dietmar Friede and - * Juergen Krause - * - * This is only one part - the rest to follow in a couple of hours. - * This part is a benign import, since it doesn't affect anything else. - * - * - ******************************************************************************/ + */ /* * Copyright (c) 1994 Dietmar Friede (dietmar@friede.de) All rights reserved. * FSF/FSAG GNU Copyright applies * * An intermediate level for ISDN Drivers. * */ #include "isdn.h" #include "ii.h" #include "ity.h" #include "itel.h" #include "ispy.h" #if NISDN > 0 #define TYPNR 4 #define N_ISDN_APPL (NII + NITY + NITEL + NISPY) #include #include #include #include #include #include #ifdef DEVFS #include #endif /*DEVFS*/ #include "gnu/isdn/isdn_ioctl.h" isdn_appl_t isdn_appl[N_ISDN_APPL]; isdn_ctrl_t isdn_ctrl[N_ISDN_CTRL]; -int Isdn_Appl, Isdn_Ctrl, Isdn_Typ; +static int Isdn_Appl, Isdn_Ctrl, Isdn_Typ; -extern void isdn_attach __P((void)); +static void isdn_attach __P((void)); static timeout_t isdn_check; -extern char *isdn_get_prot __P((int ap, int dir)); -extern int isdn_get_prot_size __P((int ap)); -extern int isdn_set_prot __P((int ap, int dir, char *p)); -extern int isdn_stat __P((int cn)); +static char *isdn_get_prot __P((int ap, int dir)); +static int isdn_get_prot_size __P((int ap)); +static int isdn_set_prot __P((int ap, int dir, char *p)); +static int isdn_stat __P((int cn)); static void passout __P((int unit, int l, char *buf)); static d_open_t isdnopen; static d_close_t isdnclose; static d_read_t isdnread; static d_write_t isdnwrite; static d_ioctl_t isdnioctl; #define CDEV_MAJOR 55 static struct cdevsw isdn_cdevsw = { isdnopen, isdnclose, isdnread, nowrite, /*55*/ isdnioctl, nostop, nullreset, nodevtotty,/* isdn */ seltrue, nommap, NULL, "isdn", NULL, -1 }; static int o_flags, r_flags, bufind[TYPNR]; static char buffer[TYPNR][257]; static u_char appl_list[TYPNR]; typedef u_char prot[2]; static u_char prot_size[2] = {0, 2}; static prot passiv[6] = {{0}, {3, 3}}; static prot activ[6] = {{0}, {1, 3}}; u_short isdn_state= 0; static isdn_timeout= 0; -int +static int isdn_get_prot_size(int ap) { return (prot_size[isdn_appl[ap].prot]); } -char * +static char * isdn_get_prot(int ap, int dir) { if(dir) return(activ[isdn_appl[ap].prot]); return(passiv[isdn_appl[ap].prot]); } -int +static int isdn_set_prot(int ap, int dir, char *p) { char *pr; int i, l; if ((l = isdn_get_prot_size(ap)) == 0) return (0); if (dir) pr = passiv[isdn_appl[ap].prot]; else pr = activ[isdn_appl[ap].prot]; for (i = 0; i < l; i++, pr++, p++) *p = *pr; return (l); } -void +static void isdn_attach() { isdn_appl_t *appl; int i, an; appl_list[0]= Isdn_Typ= an= 0; for(i= 0 ; ictrl = -1; appl->state = 0; appl->appl = an; appl->typ = Isdn_Typ; appl->drivno = iiattach(an); appl->PassUp = ii_input; appl->PassDown = ii_out; appl->Connect = ii_connect; appl->DisConn = ii_disconnect; } appl_list[1]= an; Isdn_Typ= 1; for(i= 0 ; ictrl = -1; appl->state = 0; appl->appl = an; appl->typ = Isdn_Typ; appl->drivno = ityattach(an); appl->PassUp = ity_input; appl->PassDown = ity_out; appl->Connect = ity_connect; appl->DisConn = ity_disconnect; } appl_list[2]= an; Isdn_Typ= 2; for(i= 0 ; ictrl = -1; appl->state = 0; appl->appl = an; appl->typ = Isdn_Typ; appl->drivno = itelattach(an); appl->PassUp = itel_input; appl->PassDown = itel_out; appl->Connect = itel_connect; appl->DisConn = itel_disconnect; } appl_list[3]= an; Isdn_Typ= 3; for(i= 0 ; ictrl = -1; appl->state = 0; appl->appl = an; appl->typ = Isdn_Typ; appl->drivno = ispyattach(an); appl->PassUp = ispy_input; } Isdn_Appl= an; } int isdn_ctrl_attach(int n) { int c = Isdn_Ctrl; if(Isdn_Ctrl == 0) isdn_attach(); if ((Isdn_Ctrl += n) <= N_ISDN_CTRL) return (c); Isdn_Ctrl = c; #ifdef DEVFS /*SOMETHING GOES IN HERE I THINK*/ #endif return (-1); } /* * isdnopen() New open on device. * * I forbid all but one open per application. The only programs opening the * isdn device are the ISDN-daemon */ static int isdnopen(dev_t dev, int flags, int fmt, struct proc *p) { int err; if (minor(dev)>Isdn_Typ) return (ENXIO); /* Card busy ? */ if (o_flags & (1 << minor(dev))) return (EBUSY); o_flags |= (1 << minor(dev)); return (0); } static int isdnclose(dev_t dev, int flags, int fmt, struct proc *p) { o_flags &= ~(1 << minor(dev)); return (0); } static int isdnread(dev_t dev, struct uio * uio, int ioflag) { int x; int error = 0; int unit= minor(dev); r_flags &= ~(1 << unit); x = splhigh(); if(bufind[unit] == 0) { r_flags |= (1 << unit); error= tsleep((caddr_t) buffer[unit], PZERO + 1, "isdnin", hz); } if(bufind[unit]) { buffer[unit][bufind[unit]++]= 0; error = uiomove(buffer[unit], bufind[unit], uio); bufind[unit] = 0; } splx(x); return error; } static int isdnioctl(dev_t dev, int cmd, caddr_t data, int flags, struct proc *p) { int err, x, i; isdn_appl_t *appl; isdn_ctrl_t *ctrl; short *val = (short *) data; unsigned ab, an, cn; err = 0; ab= appl_list[minor(dev)]; switch (cmd) { case ISDN_LISTEN: { listen_t *s= (listen_t *) data; an= ab; if (s->ctrl >= Isdn_Ctrl) return (ENODEV); cn= s->ctrl; ctrl = &isdn_ctrl[cn]; x = splhigh(); while(isdn_state) { err = tsleep((caddr_t) ctrl, PZERO | PCATCH, "slisten", 2); if (err != EWOULDBLOCK) { splx(x); return (err); } } isdn_state = 0xffff; while((err = (*ctrl->listen) (s->ctrl, minor(dev) | 0x30 , s->inf_mask ,s->subadr_mask ,s->si_mask, /* XXX */ 0)) == EBUSY) { err = tsleep((caddr_t) ctrl, PZERO | PCATCH, "blisten", 2); if (err != EWOULDBLOCK) { splx(x); return (err); } } if (err) { splx(x); return (err); } while (isdn_state == 0xffff) { err = tsleep((caddr_t) ctrl, PZERO | PCATCH, "ilisten", 2); if (err != EWOULDBLOCK) { splx(x); return (err); } } splx(x); err= isdn_state; isdn_state= 0; return (err); /* tricky but it works */ } break; case ISDN_DIAL: { dial_t *d= (dial_t*)data; telno_t *t= &d->telno; an = d->appl + ab; cn = d->ctrl; if (an >= Isdn_Appl || cn >= Isdn_Ctrl) return (ENODEV); appl = &isdn_appl[an]; if (ISBUSY(appl->ctrl) || appl->state) return (EBUSY); appl->state= 1; x = splhigh(); while((err = (*isdn_ctrl[cn].connect) (cn, an ,d->b_channel, d->inf_mask, d->out_serv ,d->out_serv_add, d->src_subadr, t->length ,t->no, d->spv)) == EBUSY) { err = tsleep((caddr_t) appl, PZERO | PCATCH, "idial", 2); if (err != EWOULDBLOCK) { splx(x); return (err); } } if(err) appl->state= 0; splx(x); return(err); } break; case ISDN_HANGUP: cn = data[0]; if (cn >= Isdn_Ctrl) return (ENODEV); x = splhigh(); while((err = (*isdn_ctrl[cn].disconnect) (cn, data[1])) == EBUSY) { err = tsleep((caddr_t) data, PZERO | PCATCH, "ihang", 2); if (err != EWOULDBLOCK) { splx(x); return (err); } } splx(x); break; case ISDN_ACCEPT: cn = data[0]; an = data[1] + ab; if (cn >= Isdn_Ctrl) return (ENODEV); x = splhigh(); while((err = (*isdn_ctrl[cn].accept) (cn, an, data[2])) == EBUSY) { err = tsleep((caddr_t) data, PZERO | PCATCH, "iaccept", 2); if (err != EWOULDBLOCK) { splx(x); return (err); } } splx(x); break; case ISDN_SET_PARAM: { isdn_param *p = (isdn_param *) data; an = p->appl + ab; if (an >= Isdn_Appl) return (ENODEV); appl = &isdn_appl[an]; bcopy(p, appl, sizeof(isdn_param)); appl->appl+= ab; } break; case ISDN_GET_PARAM: { isdn_param *p = (isdn_param *) data; an = p->appl + ab; if (an >= Isdn_Appl) return (ENODEV); appl = &isdn_appl[an]; bcopy(appl, p, sizeof(isdn_param)); } break; default: err = ENODEV; } return (err); } void isdn_start_out(int cn) { isdn_ctrl_t *ctrl = &isdn_ctrl[cn]; isdn_appl_t *appl = &isdn_appl[ctrl->appl]; int x; x= splhigh(); if (ctrl->o_len == 0) { int l; l = isdn_set_prot(ctrl->appl, ctrl->islisten, ctrl->o_buf); ctrl->o_len = (*appl->PassDown) (appl->drivno, ctrl->o_buf+l,2048-l); if (ctrl->o_len == 0) { splx(x); return; } ctrl->o_len+= l; (*ctrl->output) (cn); } splx(x); } -int +static int isdn_stat(int cn) { isdn_ctrl_t *ctrl = &isdn_ctrl[cn]; return((*ctrl->state) (cn)); } int isdn_output(int an) { isdn_appl_t *appl = &isdn_appl[an]; if (ISFREE(appl->ctrl)) { int l; char buf[10]; if(appl->state) return(0); l = sprintf(buf,"d %d", an-appl_list[appl->typ]); passout(appl->typ,l,buf); return(0); } isdn_start_out(appl->ctrl); return (0); } int isdn_msg(int an) { isdn_appl_t *appl = &isdn_appl[an]; if (ISFREE(appl->ctrl)) { int l; char buf[256]; l = sprintf(buf,"M %d", an-appl_list[appl->typ]); l += (*appl->PassDown) (appl->drivno, buf+l,256-l); passout(appl->typ,l,buf); return(0); } return (1); } int isdn_input(int an, int len, char *buf, int dir) { int l; char *p; isdn_appl_t *appl = &isdn_appl[an]; if (l = isdn_get_prot_size(an)) { p= isdn_get_prot(an,dir); if((p[0] != buf[0]) || (p[1] != buf[1])) return(0); len -= l; buf += l; } return ((*appl->PassUp) (appl->drivno, len, buf, dir)); } void isdn_accept_con_ind(int an, int cn, char serv, char serv_add, char subadr, char nl, char *num) { int l; char buf[32]; an&= 0xf; l = sprintf(buf, "a %d %d %d %d %c %d %d %s", an, cn ,serv, serv_add , subadr,(u_char) num[0], nl, num + 1); passout(an,l,buf); } void isdn_info(int an, int typ, int len, char *data) { int l; char buf[64]; u_short no; if(an < Isdn_Appl) no= isdn_appl[an].typ; else no= an&0xf; if(no > Isdn_Typ) no= 3; if(len>48) len= 48; data[len]= 0; l = sprintf(buf,"i %d %d %d %s", an, typ, len, data); passout(no,l,buf); } static void isdn_check(void *chan) { int i; isdn_timeout= 0; for(i= 0; i < Isdn_Ctrl; i++) { int an; isdn_ctrl_t *ctrl = &isdn_ctrl[i]; if((an= ctrl->appl) < Isdn_Appl) { isdn_appl_t *appl = &isdn_appl[an]; if(appl->timeout) { isdn_timeout= 1; if(time.tv_sec > (ctrl->lastact + (appl->timeout))) { isdn_disconnect(an,0); break; } } } } if(isdn_timeout) { timeout(isdn_check,0,hz/2); } } void isdn_conn_ind(int an, int cn, int dial) { isdn_appl_t *appl = &isdn_appl[an]; int l; char buf[10]; if (appl->Connect) (*appl->Connect) (appl->drivno); l = sprintf(buf,"C %d %d %d", an-appl_list[appl->typ], cn, dial); passout(appl->typ,l,buf); if((isdn_timeout == 0) && appl->timeout) { isdn_timeout= 1; timeout(isdn_check,0,hz/2); } } void isdn_disconn_ind(int an) { isdn_appl_t *appl = &isdn_appl[an]; int l; char buf[10]; if(( an < 0) || (an >= Isdn_Appl)) return; appl->state= 0; if (appl->DisConn) (*appl->DisConn) (appl->drivno); l = sprintf(buf,"D %d", an-appl_list[appl->typ]); passout(appl->typ,l,buf); } void isdn_disconnect(int an, int rea) { isdn_appl_t *appl = &isdn_appl[an]; if (ISBUSY(appl->ctrl)) { int x; x = splhigh(); (*isdn_ctrl[appl->ctrl].disconnect)(appl->ctrl,rea); splx(x); } } static void passout(int unit, int l, char *buf) { int x; x = splhigh(); if ((bufind[unit] + l) >= 256) { splx(x); return; } bcopy(buf,&buffer[unit][bufind[unit]],l); bufind[unit] += l; buffer[unit][bufind[unit]++]= 0; if (r_flags & (1< 0 */