|  | 
		
			|  | Atari coding BBS
 
 
 
| Zilog Falcon | 
|---|
 
| Posted by: earx | Sep,05.2006-09:02 |  
| *
 * Zilog 85X30 serial driver for RTLinux
 * (asynchronous and synchronous modes)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 *
 * This is based on drivers/serial/sunzilog.c by David S. Miller, itself
 * which is based on the old drivers/sbus/char/zs.c code.  A lot
 * of code has been simply moved over directly from there but
 * much has been rewritten.  Credits therefore go out to Eddie
 * C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their
 * work there.
 * And it is not all, it is also based on the rt_com driver from Jens Michaelsen,
 * Jochen Küpper, Hua Mao and Roberto Finazzi.
 *
 *  Copyright (C) 2004-2005 Marc Le Douarain
 */
 
 #include <rtl.h>
 #include <rtl_sched.h>
 #include <asm/io.h>
 #include <linux/ioport.h>
 
 #include "rt_com_zilog.h"
 #include "zilog_and_com.h"
 
 #define RTCZ_NAME "rt_com_zilog"
 #define RTCZ_VERSION "0.2.2"
 
 // I/O ports with D/C pin low
 #define Z_PORT_B_CONTROL	0x210
 #define Z_PORT_A_CONTROL	0x211
 // I/O ports with D/C pin high
 #define Z_PORT_B_DATA	0x212
 #define Z_PORT_A_DATA	0x213
 
 /* if we want to share the irq handler of "rt_com" or not... */
 #define USE_OWN_IRQ_HANDLER
 #define Z_IRQ		12
 
 #define ZS_CLOCK		15974400l /* Zilog input clock rate. */
 #define ZS_CLOCK_DIVISOR	16      /* Default divisor this driver uses (for asynchronous). */
 
 
 #define RT_COM_ZILOG_CNT 2
 
 static struct rt_com_zilog_struct rt_com_table[ RT_COM_ZILOG_CNT ] =
 {
 { Z_PORT_A_CONTROL, Z_PORT_A_DATA },
 { Z_PORT_B_CONTROL, Z_PORT_B_DATA }
 };
 
 /* global variable to know if driver init is ok. */
 int rt_com_zilog_driver_init_error = 0;
 
 static int debugIT = 0;
 
 //freeze if a lot of tasks already switching fastly...
 //#define ZSDELAY() nanosleep( hrt2ts( 5000 ), NULL );
 //seems that no delay is required with our ISA bus?
 #define ZSDELAY()
 
 /* Reading and writing Zilog8530 registers.  The delays are to make this
 * driver work on the Sun4 which needs a settling delay after each chip
 * register access, other machines handle this in hardware via auxiliary
 * flip-flops which implement the settle time we do in software.
 *
 * The port lock must be held and local IRQs must be disabled
 * when {read,write}_zsreg is invoked.
 */
 static inline unsigned char read_zsreg(struct rt_com_zilog_struct *channel,
 unsigned char reg)
 {
 unsigned char retval;
 
 outb(reg, channel->control);
 ZSDELAY();
 retval = inb(channel->control);
 ZSDELAY();
 
 return retval;
 }
 static inline void write_zsreg(struct rt_com_zilog_struct *channel,
 unsigned char reg, unsigned char value)
 {
 outb(reg, channel->control);
 ZSDELAY();
 outb(value, channel->control);
 ZSDELAY();
 }
 static inline int sbus_readb( int * p)
 {
 return inb(*p);
 }
 static inline void sbus_writeb( int d, int * p)
 {
 outb(d,*p);
 }
 #define ZS_WSYNC(__channel) sbus_readb(&((__channel)->control))
 
 
 static void sunzilog_clear_fifo(struct rt_com_zilog_struct *channel)
 {
 int i;
 
 for (i = 0; i < 32; i++) {
 unsigned char regval;
 
 regval = sbus_readb(&channel->control);
 ZSDELAY();
 //v0.2.0		if (regval & Rx_CH_AV)
 if (!(regval & Rx_CH_AV))
 break;
 
 regval = read_zsreg(channel, R1);
 sbus_readb(&channel->data);
 ZSDELAY();
 
 if (regval & (PAR_ERR | Rx_OVR | CRC_ERR)) {
 sbus_writeb(ERR_RES, &channel->control);
 ZSDELAY();
 ZS_WSYNC(channel);
 }
 }
 }
 
 /* This function must only be called when the TX is not busy.  The UART
 * port lock must be held and local interrupts disabled.
 */
 static void __load_zsregs(struct rt_com_zilog_struct *channel)
 {
 int i;
 unsigned char *regs = channel->curregs;
 
 /* Let pending transmits finish.  */
 for (i = 0; i < 1000; i++) {
 unsigned char stat = read_zsreg(channel, R1);
 if (stat & ALL_SNT)
 break;
 udelay(100);
 }
 
 sbus_writeb(ERR_RES, &channel->control);
 ZSDELAY();
 ZS_WSYNC(channel);
 
 sunzilog_clear_fifo(channel);
 
 /* Disable all interrupts.  */
 write_zsreg(channel, R1,
 regs[R1] & ~(RxINT_MASK | TxINT_ENAB | EXT_INT_ENAB));
 
 /* Set parity, sync config, stop bits, and clock divisor.  */
 write_zsreg(channel, R4, regs[R4]);
 //rtl_printf("Init: Write R4=%x\n", regs[R4]);
 
 /* Set TX/RX controls sans the enable bits.  */
 write_zsreg(channel, R3, regs[R3] & ~RxENAB);
 write_zsreg(channel, R5, regs[R5] & ~TxENAB);
 //rtl_printf("Init: Write R3=%x R5=%x R10=%x\n", regs[R3], regs[R5], regs[R10]);
 
 /* Set Rx FIFO interrupt level now for ESCC (old chip will write normal R7) */
 /* R7' is seen with R7 and the bit PRIME of R15 */
 write_zsreg(channel, R15, regs[R15]|PRIME);
 write_zsreg(channel, R7, regs[R7P]);
 write_zsreg(channel, R15, regs[R15]);
 //rtl_printf("Init: Write R7Prime=%x\n", regs[R7P]);
 
 /* Synchronous mode config.  */
 write_zsreg(channel, R6, regs[R6]);
 write_zsreg(channel, R7, regs[R7]);
 
 /* Set misc. TX/RX control bits.  */
 write_zsreg(channel, R10, regs[R10]);
 
 /* Don't mess with the interrupt vector (R2, unused by us) and
 * master interrupt control (R9).  We make sure this is setup
 * properly at probe time then never touch it again.
 */
 
 /* Disable baud generator.  */
 write_zsreg(channel, R14, regs[R14] & ~BRENAB);
 
 /* Clock mode control.  */
 write_zsreg(channel, R11, regs[R11]);
 //rtl_printf("Init: Write R11=%x\n", regs[R11]);
 
 /* Lower and upper byte of baud rate generator divisor.  */
 write_zsreg(channel, R12, regs[R12]);
 write_zsreg(channel, R13, regs[R13]);
 //rtl_printf( "Init: Write R12=%x then Read R12=%x\n", regs[R12], read_zsreg( channel, R12 ) );
 //rtl_printf( "Init: Write R13=%x then Read R13=%x\n", regs[R13], read_zsreg( channel, R13 ) );
 
 /* Now rewrite R14, with BRENAB (if set).  */
 write_zsreg(channel, R14, regs[R14]);
 //rtl_printf("Init: Write R14=%x\n", regs[R14]);
 
 /* External status interrupt control.  */
 write_zsreg(channel, R15, regs[R15]);
 //rtl_printf("Init: Write R15=%x\n", regs[R15]);
 
 /* Reset external status interrupts.  */
 write_zsreg(channel, R0, RES_EXT_INT);
 write_zsreg(channel, R0, RES_EXT_INT);
 
 /* Rewrite R3/R5, this time without enables masked.  */
 write_zsreg(channel, R3, regs[R3]);
 write_zsreg(channel, R5, regs[R5]);
 //rtl_printf("Init: Write R3=%x R5=%x R10=%x\n", regs[R3], regs[R5], regs[R10]);
 
 /* Rewrite R1, this time without IRQ enabled masked.  */
 write_zsreg(channel, R1, regs[R1]);
 //rtl_printf("Init: Write R1=%x\n", regs[R1]);
 }
 
 /* Reprogram the Zilog channel HW registers with the copies found in the
 * software state struct.  If the transmitter is busy, we defer this update
 * until the next TX complete interrupt.  Else, we do it right now.
 *
 * The UART port lock must be held and local interrupts disabled.
 */
 static void sunzilog_maybe_update_regs(struct rt_com_zilog_struct *channel)
 {
 //	if (!ZS_REGS_HELD(up)) {
 //		if (ZS_TX_ACTIVE(up)) {
 //			up->flags |= SUNZILOG_FLAG_REGS_HELD;
 //		} else {
 __load_zsregs(channel);
 //		}
 //	}
 }
 
 /** Get first byte from the write buffer.
 *
 * @param p  rt_com_struct of the line we are writing to.
 * @param c  Address to put the char in.
 * @return   Number of characters we actually got.
 *
 * @author Jens Michaelsen, Jochen Küpper
 * @version 1999/10/01 */
 static inline int rt_com_irq_get( struct rt_com_zilog_struct *p, unsigned char *c )
 {
 struct rt_buf_struct *b = &( p->obuf );
 if( b->head != b->tail ) {
 *c = b->buf[ b->tail++ ];
 b->tail &= ( RT_COM_BUF_SIZ - 1 );
 return( 1 );
 }
 return( 0 );
 }
 
 /** Concatenate a byte to the read buffer.
 *
 * @param p   rt_com_struct of the line we are writing to.
 * @param ch  Byte to put into buffer.
 *
 * @author Jens Michaelsen, Jochen Küpper
 [...]
 
 
 |  
 
 
 
 
 [All messages in this thread]      [Start new thread]
 
 
 
 What's the anti-troll code?
 That's your personal code to be able to add comments and messages on the dhs.nu site.
 Don't have a code or forgot it? Fix it here.
 |  |  |