chris@mimsy.UUCP (Chris Torek) (01/25/88)
I have written about this before, but let me try for concise. The trick is to have two flags per line. One says `pretend carrier is present'; the other says `this line is being used by a dialout program'. In my current implementation, the former is done with the TS_CARR_ON flag, and the latter with an XX_inout[] array (where XX is the device; see below). In the device driver, opening the `normal' line works like this: for (;;) { if (dialout is not in use) { assert ready; /* let the modem answer the phone */ if (there is a carrier) break; } wait; } open the line; The dialout code looks like this: if (the line is in use) error(busy); assert ready, dialout, and software carrier; open the line; The carrier-detect status change code looks like this: if (there is a real carrier) { if (dialout in use) { /* * We must have got through, so let us know when/if * the line drops. * deassert software carrier; * * The software carrier is `deasserted' by doing * nothing. When the carrier status changes * again it will be to `there is no real carrier' * and we will do the `else' below. */ } } else { hang up the line as usual; } and the close code says if (this is the dialout line || hangup-on-close set) { drop the line, pausing long enough for the modem to see it; } do close protocol; if (this is the dialout line) { deassert dialout; reset software carrier from saved original state; wake up anyone waiting for dialin use; /* this last so it can reassert ready */ } In practise, this is implemented as follows, using the DMF driver as an example: dmfopen: if ((tp->t_state & TS_ISOPEN) == 0) { ... set initial state ... } else if ((tp->t_state & TS_XCLUDE || dial) && u.u_uid != 0) return (EBUSY); bit = 1 << (unit & 7); s = spltty(); if (dial) dmf_inout[dmf] |= bit; /* this is an Ultrix compatibility hack. FNDELAY is set if dial */ if (flags & FNDELAY) { (void) dmfmctl(dev, DMF_ON, DMSET); tp->t_state |= TS_CARR_ON; } else { for (;;) { if ((dmf_inout[dmf] & bit) == 0 && (dmfmctl(dev, DMF_ON, DMSET) & (DMF_CAR<<8) || dmfsoftCAR[dmf] & bit)) break; tp->t_state |= TS_WOPEN; sleep((caddr_t)&tp->t_state, TTIPRI); /* stock drivers use &tp->t_rawq; beware */ } tp->t_state |= TS_CARR_ON; } splx(s); return ((*linesw[tp->t_line].l_open)(dev, tp)); dmfclose: (*linesw[tp->t_line].l_close)(tp); (void) dmfmctl(unit, DMF_BRK, DMBIC); if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0 || dial) { (void) dmfmctl(unit, DMF_OFF, DMSET); timeout(wakeup, (caddr_t)&tp->t_flags, hz); sleep((caddr_t)&tp->t_flags, PZERO - 1); } ttyclose(tp); if (dial) { dmf_inout[unit >> 3] &= ~(1 << (unit & 7)); wakeup((caddr_t)&tp->t_state); /* again, 4.3 drivers use &tp->t_rawq */ } return (0); dmfrint, if carrier status changes: if (addr->dmfrms & DMF_CAR) /* have carrier */ (void)(*linesw[tp->t_line].l_modem)(tp, 1); else if ((dmfsoftCAR[dmf] & (1 << unit)) == 0 && (*linesw[tp->t_line].l_modem)(tp, 0) == 0) { ... drop the line ... How `dial' is determined is up to the driver. I used separate major device numbers, fearing to run out of minor devices if I took a bit (particularly in the case of the 4.3BSD dmf driver, which already uses bit 7 to identify the printer port). Since we are now converting to Annex terminal servers, I would probably use a bit now. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
casey@lll-crg.llnl.gov (Casey Leedom) (01/26/88)
In article <10330@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: >I have written about this before, but let me try for concise[ness]. ... The problem with the omitted description is that it's just too complex. There's already a perfectly reasonable way of doing what's necessary and it just isn't being used. The current mechanism used by the 4.3BSD drivers to do soft carrier is really for the birds. All that really needs to be done [for 4.3BSD] is to declare the flags parameters in the various driver routines (openi in sys_inode.c calls all the drivers with the flags word passed in to the original open, but none of the 4.3BSD tty drivers declares that parameter), and use O_NDELAY to indicate one doesn't want to wait for carrier instead of the stupid soft carrier flag arrays currently in use. The only changes necessary at the application level would be to have getty, tip, uucp, etc. all open with O_EXCL and have tip, uucp, etc. also use O_NDELAY. These fixes are trivial, straight forward, easy to understand and use, and are in the original spirit of the open flags parameter. Anything else that plays around with the open code is a kludge. The only other idea I've heard of any merit is to have a modem server/daemon that can be contacted for a modem, but that requires the writing of a whole new program, the design of new paradigms, and probably a significant rewrite of the application programs needing access to modems. Note that the above descriptions all refer explicitly to 4.3BSD but the concepts should be portable to SYSV. Casey
steve@nuchat.UUCP (Steve Nuchia) (02/08/88)
This thread seems to be dancing around the tty driver issues concerning bidirectional use of a line. This is about the only thing Microport got right from the beginning, and seeing how well their mechanism (I don't know where it originated) works I implemented it for my 2.10 BSD client, who is quite pleased also. You use two different device files for each physical line - using a bit in the minor device number as a flag differentiating the incoming and outgoing version. The open on the incoming (usually getty) blocks waiting for carrier. Only one logical device can be open on a line at one time, attempts to open the outgoing side while the incoming side is open (carrier high) fail. One compilcation is that you need to play games with the uucp lock files to make uucp hunt for an open line properly. I've got a DHV11 driver for 2.10 (should work in 4.3 too) that deals with that board's braindamage nicely and implements the scheme described. I've also got a getty replacement for microport that plays the right uucp lockfile games. The driver requires the proper lisence horse hockey but I can give the getty away for the asking. -- Steve Nuchia | [...] but the machine would probably be allowed no mercy. uunet!nuchat!steve | In other words then, if a machine is expected to be (713) 334 6720 | infallible, it cannot be intelligent. - Alan Turing, 1947
sob@academ.UUCP (Stan Barber) (02/11/88)
It should be pointed out that this scheme is much like the SunOS scheme. It should also be pointed out that it is far superior to acucntrl-type approaches. Alas, some of use don't have kernel sources.... sigh. -- Stan uucp:{killer,rice,hoptoad}!academ!sob Opinions expressed here Olan domain:sob@tmc.edu are ONLY mine & Barber CIS:71565,623 BBS:(713)790-9004 noone else's.