From: MERC::"uunet!WKUVX1.BITNET!MacroMan" 17-JAN-1993 09:23:26.91 To: MACRO32@WKUVX1.BITNET CC: Subj: Re: Need faster async board...dlv11-J? Something else? jeh@cmkrnl.com writes: > In article <565014@zl2tnm.gen.nz>, don@zl2tnm.gen.nz (Don Stokes) writes: > > Anyway, I might have a go at fiddling the driver to support 38400 (if I > > can find a terminal that will go that fast!) and see how things get on. > I really don't see the point. Even if you do this the actual throughput for > writes won't exceed 19.2kbps. This is (according to the manual) a limitation > of the on-board DMA logic, so nothing you do to the UART chips will get around > this. You certainly can't test read throughput to 38,400 bps unless you are > planning to type VERY damn fast. Don't knock it. I'm having fun. 8-) Seriously, you can't _read_ that fast. Most terminals don't go that fast. People who want 38400 bps don't want it for terminal traffic. The nature of non-terminal traffic is that people tend to want to receive more than they send. It's called "greed". So, we don't care so much if we can't really transmit at 38400, but it'd be Real Nice if we could receive at that speed. > Gee, Don, sounds like you're reading from the exact same DHV11 manual that > I was. Funny, that. DHV11 Techical Manual, p/n EK-DHV11-TM-001. (c) 1983. > I believe I said that. In fact, I know I did: I lifted all that stuff from some email I was sending to someone on that very subject. I didn't feel like repeating myself.... > Don again: > > It'll receive at 38400 OK, but you'd better have those QIOs > > ready to take the data real fast.... > This is true and it is a major bottleneck with uucp. [discussion about uucp & why really fast is hard deleted] The discussion I was having on the subject of DHV11 speed moved onto the question of flow control for this nice fast interface. You may be interested (or not 8-)... Again, you'll see stuff that you've already said, but it's 01:00 and I really can't be bothered editing it out.... NB: Clive has a VAXstation II as do I; although not explicitly stated the discussion centres around getting the maximum out of a pair of V32bis/V42bis modems on a SLIP link. Faster machines will have less problems. So will doing it properly and using a router.... Quick warning to neophytes: Hacks described below have not been tested. They're not even complete. It's your foot and your gun. From: TOYVAX::DON "Don Stokes" 18-JAN-1993 00:27:24.43 To: UUCP%"Clive.Nicolson@bbs.actrix.gen.nz" CC: DON Subj: Re: DHV11 > I applied your patch to YFDriver.EXE and it works ok at 38400 (or as >well as one might expect). For VMS 5.5 $1DD is $1E9. Have you tried hitting the thing hard with incoming characters? >PS:now how about CTS/RTS flow control in the driver.!! CTS control is there already, implemented in TTDRIVER rather than YFDRIVER. The port driver (YF) just massages the "something has changed" message from the board into a bitmask that the class driver (TT) can deal with, and loss of CTS is treated as "STOP!". Note that CTS, DSR & DCD are only sampled once every 10ms. That's 38 characters worth at 38400, plus the interrupt latency. RTS however isn't. DEC have taken the RS232 spec as gospel, which is designed around using RTS/CTS for half duplex operation. As such, you raise RTS when you're ready to send (and wait for CTS to come up), and drop it when you're ready to receive. This puts things into something of a dilemma for full-duplex, and there isn't any standardisation. Some folk avoid the RTS/CTS issue and use DSR, which isn't entirely correct either. Others go and find an unused pin (pin 11 is popular) and use that, relying on you to go and connect it to something that will do the right thing with that signal. And of course there are those who _raise_ RTS to say "I'm ready to receive", rather than "I'm ready to transmit", and _drop_ RTS to say "Stop transmitting" rather than "I've finished now, you can start." DEC have basically decided in their infinite (huh!) wisdom that the closest thing to the spec is to hold RTS high all the time the line is active (ie carrier is present and the line is allocated). CTS is a non-issue, since its functionality (ie "you can/can't transmit now") doesn't change between full & half duplex, and is implemented. Incidentally, the DHV11 manual states that loss of CTS should be considered an error and the line should be hung up. Fortunately, TTDRIVER doesn't do that.... As to changing YFDRIVER to meet the current de-facto standard..... There are XON/XOFF routines in the port driver which are called by the class driver. If HOSTSYNC is enabled, XON/XOFF flow control is done by calling YF$XON with a DC1 character in R3 and YF$XOFF with a DC3 character in R3. If HOSTSYNC is disabled, YF$XOFF will be called with a BEL. I can't find any evidence of YF$XON being called in this case. The 5.3-1 YF$XOFF and YF$XON routines go like this (cleaned up from SDA output): $UCBDEF $CRBDEF $VECDEF DHUCSR = 0 DHUCSR$M_RCVINT = ^x40 DHUCSR$M_SNDINT = ^x4000 DHUCSR$C_BASE = DHUCSR$M_RCVINT!DHUCSR$M_SNDINT DHULCT = ^x8 DHULCT$M_SNDOFF = ^x20 YF$XON: ; R3 = XON character, R5 = UCB address MOVQ R0,-(SP) ; Save regs BICW2 #TTY$M_TANK_PREEMPT,UCB$W_TT_HOLD(R5) ; Clear XOFF state MOVL UCB$L_CCB(R5),R0 MOVL @CRB$L_INTD+VEC$L_IDB(R0),R0 ; Get CSR address in R0 BISW3 #DHUCSR$C_BASE,UCB$W_UNIT(R5),DHUCSR(R0) ; Select unit on DHV CMPB R3,#17 ; XON/DC1? BNEQ YF$PREEMPT ; No: stuff it in data stream BITW #DHULCT$M_SNDOFF,DHULCT(R0) ; Auto XOFFed? BEQL YF$PREEMPT ; No: stuff it in data stream BICW2 #DHULCT$M_SNDOFF,DHULCT(R0) ; Clear auto XOFF bit MOVQ (SP)+,R0 ; Restore regs RSB ; Done YF$XOFF: ; R3 = XOFF character, R5 = UCB address MOVQ R0, -(SP) ; Save regs MOVL UCB$L_CCB(R5),R0 MOVL @CRB$L_INTD+VEC$L_IDB(R0),R0 ; Get CSR address in R0 BISW3 #DHUCSR$C_BASE,UCB$W_UNIT(R5),DHUCSR(R0) ; Select unit on DHV CMPB R3,#19 ; Is XOFF char DC3? BNEQ YF$PREEMPT ; No, stuff it in output stream BISW2 #DHULCT$M_SNDOFF, DHULCT(R0) ; Force XOFF MOVQ (SP)+,R0 ; Restore regs RSB ; Done YF$PREEMPT: [stuff to shove R3 in output buffer, cancel any other XOFFs already there etc] The SNDOFF (aka FORCE.XOFF) bit sends an XOFF and puts the DVH11 port into a mode where every alternate character received is automatically replied to with an XOFF. Clearing the bit turns off that mode and sends an XON. Note that the board itself will do XOFF if the silo fills to two thirds and XON again when it hits half full. To drop and raise RTS would require that you execute: DHULCT$M_RTS=^x1000 BICW2 #DHULCT$M_RTS, DHULCT(R0) ; Drop RTS and BISW2 #DHULCT$M_RTS, DHULCT(R0) ; Raise RTS Note that these routines are pointed to via the port/class driver interface. Given a UCB address, the following finds the routines: ; R5 = UCB MOVL UCB$L_TT_PORT(R5), R0 MOVL PORT_XON, R0 ; R0 points to address of YF$XON MOVL PORT_XOFF, R0 ; R0 points to address of YF$XOFF The "best" way to add hardware flow control would be to write a couple of routines that intercepted the port driver's routines, checked if they needed to do hardware flow control; if not just passed control back to the original routines, otherwise did the flow control by tweaking the hardware. You could probably find a spare bit in the UCB or somewhere to store whether hardware flow control was needed. You should also be careful to do the stuff prior to the actual "do flow control" stuff, like clearing the XOFF state in UCB$L_STS. I'm sure I don't have to tell you why this has to go in the nonpaged pool.... Something like: $VECDEF $CRBDEF $UCBDEF $TTDEF DHUCSR = 0 DHUCSR$M_RCVINT = ^x40 DHUCSR$M_SNDINT = ^x4000 DHUCSR$C_BASE = DHUCSR$M_RCVINT!DHUCSR$M_SNDINT DHULCT = ^x8 DHULCT$M_RTS = ^x1000 TTY_M_HWFLOW = TT$M_MODEM!TT$M_HOSTSYNC ; Use SET TER/MODEM as our flag CODE: VEC_YF$XON: .BLKL ; Contains vector to real YF$XON VEC_YF$XOFF: .BLKL ; Contains vector to real YF$XOFF MY_YF$XON: BITL #TTY_M_HWFLOW, UCB$L_DEVDEPEND(R5) BNEQ 10$ ; Hardware flow control? JMP @VEC_YF$XON ; N: Normal service please 10$: PUSHL R0 ; Save R0 MOVL UCB$L_CCB(R5),R0 MOVL @CRB$L_INTD+VEC$L_IDB(R0),R0 ; Get CSR address in R0 BISW3 #DHUCSR$C_BASE,UCB$W_UNIT(R5),DHUCSR(R0) ; Select unit on DHV BISW2 #DHULCT$M_RTS, DHULCT(R0) ; Raise RTS POPL R0 ; Restore R0 RET MY_YF$XOFF: BITL #TTY_M_HWFLOW, UCB$L_DEVDEPEND(R5) BNEQ 10$ ; Hardware flow control? JMP @VEC_YF$XOFF ; N: Normal service please 10$: PUSHL R0 ; Save R0 MOVL UCB$L_CCB(R5),R0 MOVL @CRB$L_INTD+VEC$L_IDB(R0),R0 ; Get CSR address in R0 BISW3 #DHUCSR$C_BASE,UCB$W_UNIT(R5),DHUCSR(R0) ; Select unit on DHV BICW2 #DHULCT$M_RTS, DHULCT(R0) ; Drop RTS POPL R0 ; Restore R0 RET CODE_LEN = .-CODE You'd need to call EXE$ALONONPAGED to get some pool and copy the above into it. Then find the address of a UCB for one of the TX (say TXA0:) -- you need to call IOC$SEARCHDEV with the I/O database locked (you also have to make sure you get the _physical_ UCB, not the UCB for a VTA port!). With the UCB in R5 (and the I/O database still locked): MOVL UCB$L_TT_PORT(R5), R0 MOVL PORT_XON(R0), VEC_YF$XON MOVAB MY_XON, PORT_XON(R) MOVL PORT_XOFF(R0), VEC_YF$XOFF MOVAB MY_XOFF, PORT_XOFF(R) Unlock the I/O database and you're away. Use SET TERM/MODEM/HOSTSYNC to enable HW flow control. This doesn't address the issue of flow control when the silo fills. With HOSTSYNC enabled, auto XON/XOFF will also be enabled, so you'll need to keep the silo empty. This probably isn't too much of a problem (see below). Note that I haven't tested any of this. I don't have the need. >Also noticed your post in the VMS news group about faster serial >boards, that thread started about same time I mentioned problem to you. >The real problem is that the DHU hardware doesnt have a big enough >silo to handle 38400 on input for any period of time. 256 entries is about as big as DEC silos get. (And it's 256 _words_, not bytes, so that you can tell data set changes from data, which port they came from etc.) The MicroVAX II will probably be a bigger hindrance. Overall, the size of the silo doesn't matter a lot. If the CPU isn't fast enough to suck the characters out of the device faster than they come in, you're going to lose eventually no matter how big a silo you put on. Upping the size of the silo can only delay the inevitable. If you can process fast enough, the only other variable is how quickly you can get other tasks out of the way and get to the device. With 256 characters at 38400bps, you've got about 67 ms to service the interrupt and start emptying the silo, or about 50ms if you want to get in ahead of the auto-XOFF. By comparison, the single character buffer on the console port works OK at 2400bps as long as nothing else is happening (maybe the odd lost character), ie interrupts are being fielded at the data rate of 240 cps, or one every 4 ms. 256 entries is heaps. The main thing is to make sure you have a QIO outstanding at all times so that characters are written into your buffer rather than into the typeahead, thus saving a copy from the typeahead to your buffer at fork IPL. I'd do this by using two 4-5k buffers with one second timeouts, so the buffers never fill before the next IO is Qed. Then just make damn sure you can process what's coming fast enough! You don't want to be doing lots of little QIOs, because setting 'em up is expensive. If you still can't hack the pace, it may be time to start thinking about alternatives, such as terminal servers or routers. The biggest impediment to using 38400 is the processing speed of the uVAX II itself, not the DHV11. Cheers. -- Don Stokes, ZL2TNM (DS555) don@zl2tnm.gen.nz (home) Network Manager, Computing Services Centre don@vuw.ac.nz (work) Victoria University of Wellington, New Zealand +64-4-495-5052