ast@cs.vu.nl (Andy Tanenbaum) (01/15/88)
I installed the new tty driver on a Zenith Z-248 (AT clone) using a Paradise Systems Hi Res Graphics Card. This board is compatible with IBM mono and has a Hercules compatible mode. When the system came up, a few lines appeared, then blank lines, then more text, etc. The cursor always seemed to work. The same binary ran perfectly on an XT with a cheap CGA card except for some snow. Standard MINIX runs perfectly on the Paradise card. I would definitely like to get the new tty driver fully debugged. If any one has any observations, comments etc., please post them. If you have tried the new driver, please post your experience, describing the hardware you used. Maybe we can see some pattern. Many people seem to have recently discovered the V1.2 does not work with the EGA card. I posted an improved driver that does software scrolling for EGA cards some months ago. Anyone who can't get it from the archive can get it from me directly. Hopefully the new driver will make this version obsolete, but we are not there yet. Andy Tanenbaum (ast@cs.vu.nl)
housel@ea.ecn.purdue.edu (Peter S. Housel) (01/17/88)
Here's a patch for Jim Paradis' new tty driver to allow it to work on HGC cards (mine anyway). Apply this diff to console.c: -----------------------------cut---------------------------------------- 530,531c530,531 < oque[oque_last].address = cur_start + < ( ((crow * NCOLS) + ccol) << 1); --- > oque[oque_last].address = (cur_start + > ( ((crow * NCOLS) + ccol) << 1)) & SEG_MASK; 542,545c542,545 < (int)(cur_start + (((crow * NCOLS) + ccol) << 1)), < (int)ch); < put_byte(VIDEO_SEG, < (int)(cur_start + (((crow * NCOLS) + ccol) << 1)) + 1, --- > (int)(cur_start + (((crow * NCOLS) + ccol) << 1)) & SEG_MASK, > (int)ch); > put_byte(VIDEO_SEG, > (int)((cur_start + (((crow * NCOLS) + ccol) << 1)) + 1) & SEG_MASK, -----------------------------cut---------------------------------------- Also, if you're going to run without CHEAP_CGA defined, you need to add the following (fairly obvious) routine to klib88.s: -----------------------------cut---------------------------------------- .globl _put_byte |*===========================================================================* |* put_byte * |*===========================================================================* | This routine is used to stuff a byte anywhere in memory. | The call is: | c = put_byte(seg, off, byte) | where | 'seg' is the value to put in es | 'off' is the offset from the es value | 'byte' is the byte to be placed _put_byte: push bp | save bp mov bp,sp | we need to access parameters push es | save es mov es,4(bp) | load es with segment value mov bx,6(bp) | load bx with offset from segment mov ax,8(bp) seg es | go get the byte movb (bx),al | al = byte pop es | restore es pop bp | restore bp ret | return to caller -----------------------------cut---------------------------------------- I haven't had such good luck with the driver itself. Running the "t.c" program, and configuring rs232.c to work at 1200 baud, it misses about three of every five characters. -Peter S. Housel- housel@ei.ecn.purdue.edu ...!pur-ee!housel
paradis@encore.UUCP (Jim Paradis) (01/18/88)
In article <1509@ea.ecn.purdue.edu> housel@ea.ecn.purdue.edu.UUCP (Peter S. Housel) writes: > > I haven't had such good luck with the driver itself. Running >the "t.c" program, and configuring rs232.c to work at 1200 baud, it misses >about three of every five characters. Did you read the section of the "README" file on the subject of handling additional characters on an interrupt? I don't know what kind of machine you're running, but you might want to get rid of the "<< 1" in the latency calculation. Alternately, you might try tweaking MAX_CHARS_PER_INT up or down. Basically, if you wait too long to try and get the next character, you might wind up missing some... and three out of five sounds about right for that. Let me know if this helps... +----------------+ Jim Paradis linus--+ +--+-------------+ | Encore Computer Corp. necntc--| | | E N C O R E | | 257 Cedar Hill St. ihnp4--+-encore!paradis | +-------------+--+ Marlboro MA 01752 decvax--| +----------------+ (617) 460-0500 talcott--+ ...coated with sesame seeds, and garnished with lark's vomit!
brucee@runx.ips.oz (Bruce Evans) (01/19/88)
Here are some patches to help get Jim Paradis' tty driver running on Minix. I am running Minix on a standard PC with a Hercules graphics card and a nonstandard cross-development environment, and this setup exposed a few problems. (1) tty.c uses the wrong syntax to call pointers to functions. This was a minor problem since my Xenix compiler complained immediately. Apparently the Minix compiler generates the correct code from the wrong syntax. It probably needs fixing. The patches to tty.c cover this in great detail (there are lots of pointers). (2) console.c doesn't use SEG_MASK in all cases. Apparently it doesn't matter on a CGA or EGA, but I have an HGA. Hmmm, recent postings say the EGA doesn't really work. Hope this is the only problem. I hate to say this, but Minix should start using the BIOS to handle screen initialisation. There are too many hardware variations. (3) ser_putc and ser_bufin need to lock out interrupts. This was a real problem to debug since it is time-dependent. Must be rare on an AT. What happened was the output ready flag would be FALSE when read at the start of ser_putc but an output interrupt would set it to TRUE and ser_putc would then put a character in the buffer. Then ser_oflush would loop forever. I didn't actually see any problems from ser_bufin but the same lock seems necessary. See patches to rs232.c. I also tried implementing DTR/RTS flow control on input, shown in the diffs. Didn't help at all, because my PC is swamped on single-character input. Output flow control should work, except there seems to be no good way to wait for an external device in Minix (fs tends to block. Comments, Andy?). (4) The new drivers pushed my kernel over 64K, mainly because of a debugger already in it, so I had to use separate I & D. That (the 64K) broke build. Worse, the get_tot_mem routine scribbles on the memory above 128K, including (now) part of init. I am posting a rewrite of get_tot_mem separately. After this exercise I'm not very impressed with having all drivers linked directly to the kernel. It would be nice to keep the old ones around until the new ones are debugged. Also, I slightly prefer the old console driver. Now the arrow keys don't produce ANSI escape sequences. Actually, I hate the ANSI protocol, but it seems to be necessary as a standard. I've been thinking about a scheme where every non-control, non-shift (etc) key returns itself (together with usual control/shift encoding) plus an extra flags byte containing ALL special keys. Much like the standard PC scheme except the flags byte is dynamic and the scan code is not avaiable (but various 1's on the keyboard would be distinguished by the flags byte). A fancy combination like CTRL-ALT-RIGHTSHIFT ESC - would just return ESC (even PC BIOS doesn't return) and the application could decide what to with the control flags. Would need another fancy ioctl ... General ideas the speed problem. I only run Minix on a standard slow PC. It doesn't get close to keeping up even at 2400 Baud (when Xenix sends "\n$ " for a prompt, the " " is consistently missed). I traced the output interrupt routine in detail. It takes about 218 instructions, compared with a similar routine I wrote for a PC terminal program, all in assembler, which took 47. It is unnecessary to call save and restore for the output interrupt, could just push the registers C uses. That would save 50 or so instructions. However, the input interrupt is the real problem. It must be taking over 1000 instructions, mainly message passing. The only thing I can think of is to accumulate input in timed chunks. Actually 1000 is not so many. I also traced the instructions to write 1 character to the (old) console and was underwhelmed when the count was over 4700 or 20 msec (The exact count depends on the compiler. I don't know what it is for standard Minix.) Beep needs rewriting as Jim says. Suggest starting the beep as now but leaving interrupts on and stopping it with an alarm. Ser_oflush really shouldn't do a busy wait, it should give up control if the queue is large (though with external flow control, even 1 character could take a long time to flush). Ser_doint can't get by forever with the clever trick of waiting around a while for the next character to arrive. Interrupts are disabled in it, so interrupts on other serial lines will be missed for sure. Sending a message to wait would be no use since messages take about the same time as the delay between the interrupts. # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by brucee on Mon Jan 18 00:49:13 GMT+11:00 1988 # Contents: console.c.diff rs232.diff tty.c.diff echo x - console.c.diff sed 's/^@//' > "console.c.diff" <<'@//E*O*F console.c.diff//' 45a46 > #undef CHEAP_CGA /* otherwise MONO uses some slow CHEAP_CGA code */ 410c411 < --- > int vidoff; 530,531c531,532 < oque[oque_last].address = cur_start + < ( ((crow * NCOLS) + ccol) << 1); --- > oque[oque_last].address = (cur_start + > (((crow * NCOLS) + ccol)) << 1) & SEG_MASK; 541,546c542,544 < put_byte(VIDEO_SEG, < (int)(cur_start + (((crow * NCOLS) + ccol) << 1)), < (int)ch); < put_byte(VIDEO_SEG, < (int)(cur_start + (((crow * NCOLS) + ccol) << 1)) + 1, < (int)attrib); --- > vidoff = (cur_start + (((crow * NCOLS) + ccol) << 1)) & SEG_MASK; > put_byte(VIDEO_SEG, vidoff, (int)ch); > put_byte(VIDEO_SEG, vidoff + 1, (int)attrib); @//E*O*F console.c.diff// chmod u=rw,g=,o= console.c.diff echo x - rs232.diff sed 's/^@//' > "rs232.diff" <<'@//E*O*F rs232.diff//' 243a244 > lock(); 256c257 < --- > restore(); 457a459 > int nchars; 476a479,484 > nchars = rs->rs_ilast - rs->rs_ifirst; > if(nchars < 0) nchars += CIBUFSZ; > if(nchars == (3 * CIBUFSZ) / 4) > /* high water 3/4 full, drop RTS & DTR */ > port_out(MOD_CTL_REG(rs->rs_line), MC_OUT2); > 562,563c570 < < --- > lock(); 567,568c574,577 < if(maxchars < nchars) nchars = maxchars; < --- > if(nchars >= CIBUFSZ/4 && nchars - maxchars < CIBUFSZ/4) > /* low water 1/4 full, ready for more */ > port_out(MOD_CTL_REG(rs->rs_line), MC_OUT2 | MC_RTS | MC_DTR); > if(maxchars < nchars) nchars = maxchars; 575,578c584,586 < return(nchars); < } < < --- > restore(); > return(nchars); > } @//E*O*F rs232.diff// chmod u=rw,g=,o= rs232.diff echo x - tty.c.diff sed 's/^@//' > "tty.c.diff" <<'@//E*O*F tty.c.diff//' 202,205c202,205 < (tty_list[0].tt_dev_init)(0, 0); < < for(i = 1; i <= NUM_SERIAL_DEV; i++) { < (tty_list[1].tt_dev_init)(i, i - 1); --- > (*tty_list[0].tt_dev_init)(0, 0); > > for(i = 1; i <= NUM_SERIAL_DEV; i++) { > (*tty_list[1].tt_dev_init)(i, i - 1); 236c236 < nchars = (tp->tt_dev_bufin)(tp->tt_minor, cbuf, 132); --- > nchars = (*tp->tt_dev_bufin)(tp->tt_minor, cbuf, 132); 252c252 < (tp->tt_dev_oflush)(tp->tt_minor); --- > (*tp->tt_dev_oflush)(tp->tt_minor); 276c276 < (tp->tt_dev_oflush)(tp->tt_minor); --- > (*tp->tt_dev_oflush)(tp->tt_minor); 298c298 < (tp->tt_dev_oflush)(tp->tt_minor); --- > (*tp->tt_dev_oflush)(tp->tt_minor); 315c315 < (tp->tt_dev_oflush)(tp->tt_minor); --- > (*tp->tt_dev_oflush)(tp->tt_minor); 346c346 < (tp->tt_dev_oflush)(tp->tt_minor); --- > (*tp->tt_dev_oflush)(tp->tt_minor); 388,389c388,389 < (tp->tt_dev_putc)(tp->tt_minor, '\r'); < (tp->tt_dev_putc)(tp->tt_minor, '\n'); --- > (*tp->tt_dev_putc)(tp->tt_minor, '\r'); > (*tp->tt_dev_putc)(tp->tt_minor, '\n'); 394,395c394,395 < (tp->tt_dev_putc)(tp->tt_minor, '\r'); < (tp->tt_dev_putc)(tp->tt_minor, '\n'); --- > (*tp->tt_dev_putc)(tp->tt_minor, '\r'); > (*tp->tt_dev_putc)(tp->tt_minor, '\n'); 402c402 < (tp->tt_dev_oflush)(tp->tt_minor); --- > (*tp->tt_dev_oflush)(tp->tt_minor); 415,417c415,417 < (tp->tt_dev_putc)(tp->tt_minor, '\r'); < (tp->tt_dev_putc)(tp->tt_minor, '\n'); < (tp->tt_dev_oflush)(tp->tt_minor); --- > (*tp->tt_dev_putc)(tp->tt_minor, '\r'); > (*tp->tt_dev_putc)(tp->tt_minor, '\n'); > (*tp->tt_dev_oflush)(tp->tt_minor); 423,424c423,424 < (tp->tt_dev_putc)(tp->tt_minor, ch); < (tp->tt_dev_oflush)(tp->tt_minor); --- > (*tp->tt_dev_putc)(tp->tt_minor, ch); > (*tp->tt_dev_oflush)(tp->tt_minor); 434c434 < (tp->tt_dev_oflush)(tp->tt_minor); --- > (*tp->tt_dev_oflush)(tp->tt_minor); 442c442 < (tp->tt_dev_oflush)(tp->tt_minor); --- > (*tp->tt_dev_oflush)(tp->tt_minor); 515,517c515,517 < (tp->tt_dev_putc)(tp->tt_minor, 8); < (tp->tt_dev_putc)(tp->tt_minor, ' '); < (tp->tt_dev_putc)(tp->tt_minor, 8); --- > (*tp->tt_dev_putc)(tp->tt_minor, 8); > (*tp->tt_dev_putc)(tp->tt_minor, ' '); > (*tp->tt_dev_putc)(tp->tt_minor, 8); 748c748 < (tp->tt_dev_oflush)(tp->tt_minor); --- > (*tp->tt_dev_oflush)(tp->tt_minor); 801,803c801,803 < (tp->tt_dev_putc)(tp->tt_minor, '\r'); < } < (tp->tt_dev_putc)(tp->tt_minor, tty_sbuf[i]); --- > (*tp->tt_dev_putc)(tp->tt_minor, '\r'); > } > (*tp->tt_dev_putc)(tp->tt_minor, tty_sbuf[i]); 1080c1080 < tp->tt_dev_fcon(tp->tt_minor); --- > (*tp->tt_dev_fcon)(tp->tt_minor); 1130c1130 < tp->tt_dev_fcoff(tp->tt_minor); --- > (*tp->tt_dev_fcoff)(tp->tt_minor); 1180c1180 < tp->tt_dev_fcoff(tp->tt_minor); --- > (*tp->tt_dev_fcoff)(tp->tt_minor); 1205,1209c1205,1209 < (tp->tt_dev_putc)(tp->tt_minor, ch); < } < else { < (tp->tt_dev_putc)(tp->tt_minor, '^'); < (tp->tt_dev_putc)(tp->tt_minor, ch + '@'); --- > (*tp->tt_dev_putc)(tp->tt_minor, ch); > } > else { > (*tp->tt_dev_putc)(tp->tt_minor, '^'); > (*tp->tt_dev_putc)(tp->tt_minor, ch + '@'); @//E*O*F tty.c.diff// chmod u=rw,g=,o= tty.c.diff exit 0 Bruce Evans (brucee@runx.ips.oz)