Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 25 Nov 1998 15:29:52 -0500
From:      sbabkin@dcn.att.com
To:        myers@iname.com, freebsd-hackers@FreeBSD.ORG
Subject:   RE: Non-kernel hacker needs serial help!
Message-ID:  <C50B6FBA632FD111AF0F0000C0AD71EE018C1DA8@dcn71.dcn.att.com>

next in thread | raw e-mail | index | archive | help
> From:	myers@iname.com [SMTP:myers@iname.com]
> 
>                         if (com->tx_fifo_size > 1) { 
>                                 u_int   ocount; 
>  
>                                 ocount = com->obufq.l_tail - ioptr; 
>                                 if (ocount > com->tx_fifo_size) 
>                                         ocount = com->tx_fifo_size; 
>                                 com->bytes_out += ocount; 
>                                 do { 
>                                   outb(com->data_port, *ioptr++); 
>                                 /* dcm, 11/25/98 */ 
> ----->                            DELAY(1000); 
>                                 } while (--ocount != 0); 
>                         } else { 
>                                 outb(com->data_port, *ioptr++); 
>                                 ++com->bytes_out; 
>                                 /* dcm, 11/25/98 */ 
> ----->                          DELAY(1000); 
>                         } 
> 
> 
> 
> Why DELAY(1000)?  Who knows?  This is blind hacking!  But know what? 
> It works!  Long documents now print out fine from my DeskWriter.  But,
> those of you who *are* kernel hackers are probably snickering in the
> background at the moment.  Unlike me, you realized that introducing a
> delay at this point in the code (interrupt mode, I'm presuming) stalls
> processing for everything else.  Network transfers, for example, become
> annoyingly slow while this box is printing.
> 
> My question, to make a long story short: what is the "proper" way to
> slow down the serial ports in the manner I've described, without bogging
> down all other interrupt processing?
> 
DELAY(1000) makes an approximately 1ms delay. The
best thing you can achieve with the timer clock without
speeding it up is 10ms. You can try something like this
(this is just an example of logic, there is no guarantee
that it will work exactly in this form):

struct somewhat_com {
	...
	int charcnt;
};

static void comdelayedwrite(com)
	struct somewhat_com *com;
{
	int s;
	char *ioptr;

	s=spltty();

	/* calculate ioptr here and make sure the transmitter is idle, then:
*/

	outb(com->data_port, *ioptr++);

	com->charcnt=0;
	splx(s);
}

....
/* in any place before outb(com->data_port, *ioptr++) */
/* you may want to increase the number "10" to get slightly faster printing
*/
	if(com->charcnt<10) { 
			com->charcnt++;
			timeout( (timeout_t *)comdelayedwrite, (void *)com,
HZ/100);
			return;
	} else
		outb(com->data_port, *ioptr++);
....

Or may be you can just get a proper 7-wire cable and configure the RTS/CTS
handshake
on the port (see man stty).

-SB

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?C50B6FBA632FD111AF0F0000C0AD71EE018C1DA8>