8253xutl.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:34k
- /* -*- linux-c -*- */
- /* $Id: 8253xutl.c,v 1.3 2002/02/10 22:17:26 martillo Exp $
- * 8253xutl.c: SYNC TTY Driver for the SIEMENS SAB8253X DUSCC.
- *
- * Implementation, modifications and extensions
- * Copyright (C) 2001 By Joachim Martillo, Telford Tools, Inc.
- *
- * 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.
- */
- /* Standard in kernel modules */
- #define DEFINE_VARIABLE
- #include <linux/module.h> /* Specifically, a module */
- #include <asm/io.h>
- #include <linux/timer.h>
- #include <linux/interrupt.h>
- #include <linux/tty.h>
- #include <linux/tty_flip.h>
- #include <linux/mm.h>
- #include <linux/version.h>
- #include <asm/uaccess.h>
- #include "8253xctl.h"
- #include "8253x.h"
- #include <linux/pci.h>
- #include <linux/fs.h>
- #include "sp502.h"
- #ifdef MODULE
- #undef XCONFIG_SERIAL_CONSOLE
- #endif
- void sab8253x_start_txS(struct sab_port *port)
- {
- unsigned long flags;
- register int count;
- register int total;
- register int offset;
- char temporary[32];
- register unsigned int slopspace;
- register int sendsize;
- unsigned int totaltransmit;
- unsigned fifospace;
- unsigned loadedcount;
- struct tty_struct *tty = port->tty; /* a little gross tty flags whether
- invoked from a tty or the network */
-
- fifospace = port->xmit_fifo_size; /* This code can handle fragmented frames
- although currently none are generated*/
- loadedcount = 0;
-
- if(port->sabnext2.transmit == NULL)
- {
- return;
- }
-
- save_flags(flags);
- cli();
-
-
- if(count = port->sabnext2.transmit->Count, (count & OWNER) == OWN_SAB)
- {
- count &= ~OWN_SAB; /* OWN_SAB is really 0 but cannot guarantee in the future */
-
- if(port->sabnext2.transmit->HostVaddr)
- {
- total = (port->sabnext2.transmit->HostVaddr->tail -
- port->sabnext2.transmit->HostVaddr->data); /* packet size */
- }
- else
- {
- total = 0; /* the data is only the crc/trailer */
- }
-
- if(tty && (tty->stopped || tty->hw_stopped) && (count == total))
- { /* works for frame that only has a trailer (crc) */
- port->interrupt_mask1 |= SAB82532_IMR1_XPR;
- WRITEB(port, imr1, port->interrupt_mask1);
- restore_flags(flags); /* can't send */
- return;
- }
-
- offset = (total - count); /* offset to data still to send */
-
- port->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS);
- WRITEB(port, imr1, port->interrupt_mask1);
- port->all_sent = 0;
-
- if(READB(port,star) & SAB82532_STAR_XFW)
- {
- if(count <= fifospace)
- {
- port->xmit_cnt = count;
- slopspace = 0;
- sendsize = 0;
- if(port->sabnext2.transmit->sendcrc)
- /* obviously should not happen for async but might use for
- priority transmission */
- {
- slopspace = fifospace - count;
- }
- if(slopspace)
- {
- if(count)
- {
- memcpy(temporary, &port->sabnext2.transmit->HostVaddr->data[offset],
- count);
- }
- sendsize = MIN(slopspace, (4 - port->sabnext2.transmit->crcindex));
- /* how many bytes to send */
- memcpy(&temporary[count],
- &((unsigned char*)(&port->sabnext2.transmit->crc))
- [port->sabnext2.transmit->crcindex],
- sendsize);
- port->sabnext2.transmit->crcindex += sendsize;
- if(port->sabnext2.transmit->crcindex >= 4)
- {
- port->sabnext2.transmit->sendcrc = 0;
- }
- port->xmit_buf = temporary;
- }
- else
- {
- port->xmit_buf = /* set up wrifefifo variables */
- &port->sabnext2.transmit->HostVaddr->data[offset];
- }
- port->xmit_cnt += sendsize;
- count = 0;
- }
- else
- {
- count -= fifospace;
- port->xmit_cnt = fifospace;
- port->xmit_buf = /* set up wrifefifo variables */
- &port->sabnext2.transmit->HostVaddr->data[offset];
-
- }
- port->xmit_tail= 0;
- loadedcount = port->xmit_cnt;
- (*port->writefifo)(port);
- totaltransmit = Sab8253xCountTransmitDescriptors(port);
- if(tty && (totaltransmit < (sab8253xs_listsize/2))) /* only makes sense on a TTY */
- {
- sab8253x_sched_event(port, SAB8253X_EVENT_WRITE_WAKEUP);
- }
-
- if((sab8253xt_listsize - totaltransmit) > (sab8253xt_listsize/2))
- {
- port->buffergreedy = 0;
- }
- else
- {
- port->buffergreedy = 1;
- }
-
- port->xmit_buf = NULL; /* this var is used to indicate whether to call kfree */
-
- /* fifospace -= loadedcount;*/
- /* Here to make mods to handle arbitrarily fragmented frames look to 8253xtty.c for help */
-
- if ((count <= 0) && (port->sabnext2.transmit->sendcrc == 0))
- {
- port->sabnext2.transmit->Count = OWN_DRIVER;
- if(!tty)
- { /* called by network driver */
- ++(port->Counters.transmitpacket);
- }
- #ifdef FREEININTERRUPT /* treat this routine as if taking place in interrupt */
- if(port->sabnext2.transmit->HostVaddr)
- {
- skb_unlink(port->sabnext2.transmit->HostVaddr);
- dev_kfree_skb_any(port->sabnext2.transmit->HostVaddr);
- port->sabnext2.transmit->HostVaddr = 0; /* no skb */
- }
- port->sabnext2.transmit->crcindex = 0; /* no single byte */
- #endif
- sab8253x_cec_wait(port);
- WRITEB(port, cmdr, SAB82532_CMDR_XME|SAB82532_CMDR_XTF); /* Terminate the frame */
-
- port->sabnext2.transmit = port->sabnext2.transmit->VNext;
-
- if(!tty && port->tx_full) /* invoked from the network driver */
- {
- port->tx_full = 0; /* there is a free slot */
- switch(port->open_type)
- {
- case OPEN_SYNC_NET:
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
- port->dev->start = 1;
- port->dev->tbusy = 0; /* maybe need mark_bh here */
- #else
- netif_start_queue(port->dev);
- #endif
- break;
-
- case OPEN_SYNC_CHAR:
- wake_up_interruptible(&port->write_wait);
- break;
-
- default:
- break;
- }
- }
-
- if((port->sabnext2.transmit->Count & OWNER) == OWN_SAB)
- { /* new frame to send */
- port->interrupt_mask1 &= ~(SAB82532_IMR1_XPR);
- WRITEB(port, imr1, port->interrupt_mask1);
- }
- else
- {
- port->interrupt_mask1 |= SAB82532_IMR1_XPR;
- WRITEB(port, imr1, port->interrupt_mask1);
- if((port->open_type == OPEN_SYNC_CHAR) && port->async_queue)
- { /* if indication of transmission is needed by the */
- /* application on a per-frame basis kill_fasync */
- /* can provide it */
- kill_fasync(&port->async_queue, SIGIO, POLL_OUT);
- }
- }
- restore_flags(flags);
- return;
- }
- /* Issue a Transmit FIFO command. */
- sab8253x_cec_wait(port);
- WRITEB(port, cmdr, SAB82532_CMDR_XTF);
- port->sabnext2.transmit->Count = (count|OWN_SAB);
- }
- port->interrupt_mask1 &= ~(SAB82532_IMR1_XPR); /* more to send */
- WRITEB(port, imr1, port->interrupt_mask1);
- }
- else
- { /* nothing to send */
- port->interrupt_mask1 |= SAB82532_IMR1_XPR;
- WRITEB(port, imr1, port->interrupt_mask1);
- }
- restore_flags(flags);
- return;
- }
- void sab8253x_transmit_charsS(struct sab_port *port,
- union sab8253x_irq_status *stat)
- {
- if (stat->sreg.isr1 & SAB82532_ISR1_ALLS)
- {
- port->interrupt_mask1 |= SAB82532_IMR1_ALLS;
- WRITEB(port, imr1, port->interrupt_mask1);
- port->all_sent = 1;
- }
- sab8253x_start_txS(port);
- }
- /*
- * This routine is called to set the UART divisor registers to match
- * the specified baud rate for a serial port.
- */
- /***************************************************************************
- * sab_baudenh: Function to compute the "enhanced" baudrate.
- *
- *
- * Parameters :
- * encbaud 2* the baudrate. We use the
- * double value so as to support 134.5 (in only)
- * clkspeed The board clock speed in Hz.
- * bgr Value of reg BGR for baudrate(output)
- * ccr2 Value of reg // CCR2 for baudrate (output)
- * ccr4 Value of reg CCR4 for baudrate (output)
- * truebaud The actual baudrate achieved (output).
- *
- *
- * Return value : Return FALSE the parameters could not be computed,
- *
- * Prerequisite : The various ports must have been initialized
- *
- * Remark : Stolen from the Aurora ase driver.
- *
- * Author : fw
- *
- * Revision : Oct 9 2000, creation
- ***************************************************************************/
- /*
- * Macro to check to see if the high n bits of the given unsigned long
- * are zero.
- */
- #define HIZERO(x, n) ( ((unsigned long) ((x) << (n)) >> (n)) == (x))
- /* form an n-bit bitmask */
- #define NBM(n) (~(((~(unsigned long) 0) >> (n)) << (n)))
- /* shift x by y bits to right, rounded */
- #define ROUND_SHIFT(x, y) (((unsigned long) (x) + (NBM(y - 1) + 1)) >> (y))
- /* perform rounded division */
- #define ROUND_DIV(x, y) (((x) + ((y) >> 1)) / (y))
- #define ABSDIF(x, y) ((x) > (y) ? ((x) - (y)) : ((y) - (x)))
- static unsigned int
- sab8253x_baudenh(unsigned long encbaud, unsigned long clk_speed,
- unsigned char *bgr, unsigned char *ccr2,
- unsigned long *truebaudp)
- {
- register unsigned short tmp;
- register unsigned char ccr2tmp;
- unsigned long power2, mant;
- unsigned int fastclock;
-
- if (encbaud == 0) {
- return FALSE;
- }
-
- /*
- * Keep dividing quotien by two until it is between the value of 1 and 64,
- * inclusive.
- */
-
- fastclock = (clk_speed >= 10000000); /* >= 10 MHz */
-
- for (power2 = 0; power2 < 16; power2++)
- {
- /* divisor = baud * 2^M * 16 */
- if (!HIZERO(encbaud, power2 + 3))
- {
- if (!HIZERO(encbaud, power2))
- { /* baud rate still too big? */
- mant = ROUND_DIV(ROUND_SHIFT(clk_speed, power2 + 3), encbaud);
-
- /* mant = (clk_speed / (8 * 2^M)) / (baud * 2) */
- /* = clk_speed / (baud * 16 * 2^M) */
- }
- else
- {
- mant = ROUND_DIV(ROUND_SHIFT(clk_speed, 3), encbaud << power2);
- /* mant = (clk_speed / 8) / (baud * 2 * 2^M) */
- /* = clk_speed / (baud * 16 * 2^M) */
- }
- }
- else
- {
- mant = ROUND_DIV(clk_speed, encbaud << (power2 + 3));
- /* mant = clk_speed / (baud * 2 * 8 * 2^M) */
- /* = clk_speed / (baud * 16 * 2^M) */
- }
-
- /* mant = clk_speed / (baud * 2^M * 16) */
-
- if (mant < 2
- || (mant <= 64 && (!fastclock || power2 != 0)))
- {
- break;
- }
- }
-
- /*
- * Did we not succeed? (Baud rate is too small)
- */
- if (mant > 64)
- {
- return FALSE;
- }
-
- /*
- * Now, calculate the true baud rate.
- */
-
- if (mant < 1 || (mant == 1 && power2 == 0))
- {
- /* bgr and ccr2 should be initialized to 0 */
- *truebaudp = ROUND_SHIFT(clk_speed, 4);
- }
- else
- {
- *truebaudp = ROUND_DIV(clk_speed, mant << (4 + power2));
- /* divisor is not zero because mant is [1, 64] */
- mant--; /* now [0, 63] */
-
- /*
- * Encode the N and M values into the bgr and ccr2 registers.
- */
-
- tmp = ((unsigned short) mant) | ((unsigned short) power2 << 6);
-
- ccr2tmp = SAB82532_CCR2_BDF;
- if ((tmp & 0x200) != 0)
- {
- ccr2tmp |= SAB82532_CCR2_BR9;
- }
- if ((tmp & 0x100) != 0)
- {
- ccr2tmp |= SAB82532_CCR2_BR8;
- }
-
- *ccr2 = ccr2tmp | (*ccr2 & ~(SAB82532_CCR2_BDF|SAB82532_CCR2_BR8|SAB82532_CCR2_BR9));
- *bgr = (unsigned char) tmp;
- }
-
- return TRUE;
- }
- /*
- * Calculate the standard mode baud divisor using an integral algorithm.
- */
- /***************************************************************************
- * sab_baudstd: Function to compute the "standard " baudrate.
- *
- *
- * Parameters :
- * encbaud 2* the baudrate. We use the
- * double value so as to support 134.5 (in only)
- * clkspeed The board clock speed in Hz.
- * bgr Value of reg BGR for baudrate(output)
- * ccr2 Value of reg CCR2 for baudrate (output)
- * ccr4 Value of reg CCR4 for baudrate (output)
- * truebaud The actual baudrate achieved (output).
- *
- *
- * Return value : Return FALSE the parameters could not be computed,
- *
- * Prerequisite : The various ports must have been initialized
- *
- * Remark : Stolen from the Aurora ase driver.
- *
- * Author : fw
- *
- * Revision : Oct 9 2000, creation
- ***************************************************************************/
- static unsigned int
- sab8253x_baudstd(unsigned long encbaud, unsigned long clk_speed,
- unsigned char *bgr, unsigned char *ccr2,
- unsigned long *truebaudp)
- {
- register unsigned short quot;
- register unsigned char ccr2tmp;
-
- if (encbaud == 0)
- {
- return FALSE;
- }
-
- /*
- * This divisor algorithm is a little strange. The
- * divisors are all multiples of 2, except for the
- * magic value of 1.
- *
- * What we do is do most of the algorithm for multiples
- * of 1, and then switch at the last minute to multiples
- * of 2.
- */
-
- /*
- * Will we lose any information by left shifting encbaud?
- * If so, then right shift clk_speed instead.
- */
- if (!HIZERO(encbaud, 3))
- {
- quot = (unsigned short) ROUND_DIV(ROUND_SHIFT(clk_speed, 3),
- encbaud);
- /* quot = (clk_speed / 8) / (baud * 2) = clk_speed / (16 * baud) */
- }
- else
- {
- /* encbaud isn't a multiple of 2^29 (baud not mult. of 2^28) */
- quot = (unsigned short) ROUND_DIV(clk_speed, encbaud << 3);
- }
-
- /* quot = clk_speed / (baud * 16) */
- if (quot < 2)
- {
- /* bgr and ccr2 should be initialized to 0 */
- *truebaudp = ROUND_SHIFT(clk_speed, 4);
- return TRUE;
- }
-
- /*
- * Divide the quotient by two.
- */
- quot = ROUND_SHIFT(quot, 1);
-
- if (quot <= 0x400)
- {
- /* quot = [1, 0x400] -> (quot << 5) != 0 */
- *truebaudp = ROUND_DIV(clk_speed, ((unsigned long) quot << 5));
- quot--;
-
- ccr2tmp = SAB82532_CCR2_BDF;
- if ((quot & 0x200) != 0)
- {
- ccr2tmp |= SAB82532_CCR2_BR9;
- }
- if ((quot & 0x100) != 0)
- {
- ccr2tmp |=SAB82532_CCR2_BR8;
- }
-
- *ccr2 = ccr2tmp | (*ccr2 & ~(SAB82532_CCR2_BDF|SAB82532_CCR2_BR8|SAB82532_CCR2_BR9));
- *bgr = (unsigned char) quot;
- }
- else
- { /* the baud rate is too small. */
- return FALSE;
- }
-
- return TRUE;
- }
- /***************************************************************************
- * sab_baud: Function to compute the best register value to achieve
- * a given baudrate.
- *
- *
- * Parameters :
- * port: The port being used (in only)
- * encbaud: 2* the baudrate. We use the
- * double value so as to support 134.5 (in only)
- * bgr Value of reg BGR for baudrate(output)
- * ccr2 Value of reg CCR2 for baudrate (output)
- * ccr4 Value of reg CCR4 for baudrate (output)
- * truebaud The actual baudrate achieved (output).
- *
- *
- * Return value : Return TRUE if the vaudrate can be set, FALSE otherwise
- *
- * Prerequisite : The various ports must have been initialized
- *
- * Remark : Stolen from the Aurora ase driver.
- *
- * Author : fw
- *
- * Revision : Oct 9 2000, creation
- ***************************************************************************/
- unsigned int
- sab8253x_baud(sab_port_t *port, unsigned long encbaud,
- unsigned char *bgr, unsigned char *ccr2,
- unsigned char *ccr4, unsigned long *truebaudp)
- {
- unsigned char bgr_std, bgr_enh, ccr2_std, ccr2_enh, ccr4_enh;
- unsigned int ok_std, ok_enh;
- unsigned long truebaud_std, truebaud_enh, truebaud,clkspeed;
-
- bgr_std = bgr_enh = 0;
- ccr2_std = ccr2_enh = 0;
- ccr4_enh = 0;
-
- /*
- * the port/chip/board structure will tell us:
- * 1) clock speed
- * 2) chip revision (to figure out if the enhanced method is
- * available.
- */
-
- clkspeed = port->chip->c_cim ? port->chip->c_cim->ci_clkspeed : port->board->b_clkspeed;
-
- #ifdef NODEBUGGING
- printk("With clk speed %ld, baud rate = %ldn",clkspeed, encbaud);
- #endif
-
- ok_std = sab8253x_baudstd(encbaud, clkspeed, &bgr_std,
- &ccr2_std, &truebaud_std);
- #ifdef NODEBUGGING
- printk("Std gives bgr = 0x%x, ccr2=0x%x for speed %ldn",bgr_std,ccr2_std,truebaud_std);
- #endif
- if(port->chip->c_revision >= SAB82532_VSTR_VN_3_2)
- {
- ok_enh = sab8253x_baudenh(encbaud, clkspeed,
- &bgr_enh, &ccr2_enh, &truebaud_enh);
- #ifdef NODEBUGGING
- printk("Enh gives bgr = 0x%x, ccr2=0x%x for speed %ldn",bgr_enh,ccr2_enh,truebaud_enh);
- #endif
- }
- else
- ok_enh = FALSE;
-
- /*
- * Did both methods return values?
- */
- if (ok_std && ok_enh)
- {
- /*
- * Find the closest of the two.
- */
- if (ABSDIF((truebaud_enh<<1), encbaud) <
- ABSDIF((truebaud_std<<1), encbaud))
- {
- ok_std = FALSE;
- }
- else
- {
- ok_enh = FALSE;
- }
- }
-
- /*
- * Now return the values.
- */
-
- if (ok_std || ok_enh)
- {
- truebaud = ok_std ? truebaud_std : truebaud_enh;
-
- /*
- * If the true baud rate is off by more than 5%, then
- * we don't support it.
- */
- if (ROUND_DIV(ABSDIF((truebaud<<1), encbaud), encbaud) != 0)
- {
- /*
- * We're not even in the right ballpark. This
- * test is here to deal with overflow conditions.
- */
- return FALSE;
- }
- else if (ROUND_DIV(ABSDIF((truebaud<<1), encbaud) * 100,
- encbaud) >= 5)
- {
- return FALSE;
- }
-
- *truebaudp = truebaud;
-
- if (ok_enh)
- {
- *ccr4 |= SAB82532_CCR4_EBRG;
- *ccr2 = ccr2_enh;
- *bgr = bgr_enh;
- #ifdef DEBUGGING
- printk("Enhanced Baud at %ld, ccr4 = 0x%x, ccr2 = 9x%x, bgr = 0x%xn",
- truebaud,*ccr4,*ccr2,*bgr);
- #endif
- }
- else
- {
- *ccr4 &= ~SAB82532_CCR4_EBRG;
- *ccr2 = ccr2_std;
- *bgr = bgr_std;
- #ifdef DEBUGGING
- printk("Standard Baud at %ld, ccr4 = 0x%x, ccr2 = 9x%x, bgr = 0x%xn",
- truebaud,*ccr4,*ccr2,*bgr);
- #endif
- }
-
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
- int Sab8253xCountTransmit(SAB_PORT *port)
- {
- register RING_DESCRIPTOR *rd;
- register int total;
- register int count;
- unsigned long flags;
- RING_DESCRIPTOR *start;
-
- if(port->sabnext2.transmit == NULL)
- {
- return 0;
- }
-
- save_flags(flags);
- cli();
- rd = port->sabnext2.transmit;
- start = rd;
- total = 0;
- while(1)
- {
- count = rd->Count;
- if((count & OWNER) == OWN_DRIVER)
- {
- break;
- }
- total += (count & ~OWNER);
- if(rd->sendcrc)
- {
- total += (4 - rd->crcindex);
- }
- rd = rd->VNext;
- if(rd == start)
- {
- break;
- }
- }
- restore_flags(flags);
- return total;
- }
- int Sab8253xCountTransmitDescriptors(SAB_PORT *port)
- {
- register RING_DESCRIPTOR *rd;
- register int total;
- register int count;
- unsigned long flags;
- RING_DESCRIPTOR *start;
-
- if(port->sabnext2.transmit == NULL)
- {
- return 0;
- }
-
- save_flags(flags);
- cli();
- rd = port->sabnext2.transmit;
- start = rd;
- total = 0;
- while(1)
- {
- count = rd->Count;
- if((count & OWNER) == OWN_DRIVER)
- {
- break;
- }
- ++total;
- rd = rd->VNext;
- if(rd == start)
- {
- break;
- }
- }
- restore_flags(flags);
- return total;
- }
- int getccr0configS(struct sab_port *port)
- {
- return port->ccontrol.ccr0;
- }
- int getccr1configS(struct sab_port *port)
- {
- return port->ccontrol.ccr1;
- }
- int getccr2configS(struct sab_port *port)
- {
- return port->ccontrol.ccr2;
- }
- int getccr3configS(struct sab_port *port)
- {
- return port->ccontrol.ccr3;
- }
- int getccr4configS(struct sab_port *port)
- {
- return port->ccontrol.ccr4;
- }
- int getrlcrconfigS(struct sab_port *port)
- {
- return port->ccontrol.rlcr;
- }
- int getmodeS(struct sab_port *port)
- {
- return port->ccontrol.mode;
- }
- void sab8253x_init_lineS(struct sab_port *port)
- {
- unsigned char stat;
-
- if(port->chip->c_cim)
- {
- if(port->chip->c_cim->ci_type == CIM_SP502)
- {
- aura_sp502_program(port, SP502_OFF_MODE);
- }
- }
- /*
- * Wait for any commands or immediate characters
- */
- sab8253x_cec_wait(port);
- #if 0
- sab8253x_tec_wait(port); /* I have to think about this one
- * should I assume the line was
- * previously in async mode*/
- #endif
-
- /*
- * Clear the FIFO buffers.
- */
-
- WRITEB(port, cmdr, SAB82532_CMDR_RHR);
- sab8253x_cec_wait(port);
- WRITEB(port,cmdr,SAB82532_CMDR_XRES);
-
-
- /*
- * Clear the interrupt registers.
- */
- stat = READB(port, isr0); /* acks ints */
- stat = READB(port, isr1);
-
- /*
- * Now, initialize the UART
- */
- WRITEB(port, ccr0, 0); /* power-down */
- WRITEB(port, ccr0, getccr0configS(port));
- WRITEB(port, ccr1, getccr1configS(port));
- WRITEB(port, ccr2, getccr2configS(port));
- WRITEB(port, ccr3, getccr3configS(port));
- WRITEB(port, ccr4, getccr4configS(port)); /* 32 byte receive fifo */
- WRITEB(port, mode, getmodeS(port));
- WRITEB(port, tic /* really rlcr */, getrlcrconfigS(port));
- /* power-up */
-
- switch(port->ccontrol.ccr4 & SAB82532_CCR4_RF02)
- {
- case SAB82532_CCR4_RF32:
- port->recv_fifo_size = 32;
- break;
- case SAB82532_CCR4_RF16:
- port->recv_fifo_size = 16;
- break;
- case SAB82532_CCR4_RF04:
- port->recv_fifo_size = 4;
- break;
- case SAB82532_CCR4_RF02:
- port->recv_fifo_size = 2;
- break;
- default:
- port->recv_fifo_size = 32;
- port->ccontrol.ccr4 &= ~SAB82532_CCR4_RF02;
- break;
- }
-
- if(port->ccontrol.ccr2 & SAB82532_CCR2_TOE)
- {
- RAISE(port, txclkdir);
- }
- else
- {
- LOWER(port, txclkdir);
- }
-
- SET_REG_BIT(port,ccr0,SAB82532_CCR0_PU);
- if(port->chip->c_cim)
- {
- if(port->chip->c_cim->ci_type == CIM_SP502)
- {
- aura_sp502_program(port, port->sigmode);
- }
- }
- }
- /* frees up all skbuffs currently */
- /* held by driver */
- void Sab8253xFreeAllFreeListSKBUFFS(SAB_PORT* priv) /* empty the skbuffer list */
- /* either on failed open */
- /* or on close*/
- {
- struct sk_buff* skb;
-
- if(priv->sab8253xbuflist == NULL)
- {
- return;
- }
-
- DEBUGPRINT((KERN_ALERT "sab8253x: freeing %i skbuffs.n",
- skb_queue_len(priv->sab8253xbuflist)));
-
- while(skb_queue_len(priv->sab8253xbuflist) > 0)
- {
- skb = skb_dequeue(priv->sab8253xbuflist);
- dev_kfree_skb_any(skb);
- }
- kfree(priv->sab8253xbuflist);
- priv->sab8253xbuflist = NULL;
- }
- int Sab8253xSetUpLists(SAB_PORT *priv)
- {
- if(priv->sab8253xbuflist)
- {
- if(priv->sab8253xc_rcvbuflist)
- {
- return 0;
- }
- else
- {
- return -1;
- }
- return 0;
- }
- else if(priv->sab8253xc_rcvbuflist)
- {
- return -1;
- }
-
- priv->sab8253xbuflist = (struct sk_buff_head*) kmalloc(sizeof(struct sk_buff_head), GFP_KERNEL);
- if(priv->sab8253xbuflist == NULL)
- {
- return -1;
- }
- priv->sab8253xc_rcvbuflist = (struct sk_buff_head*) kmalloc(sizeof(struct sk_buff_head), GFP_KERNEL);
- if(priv->sab8253xc_rcvbuflist == NULL)
- {
- kfree(priv->sab8253xbuflist);
- return -1;
- }
- skb_queue_head_init(priv->sab8253xbuflist);
- skb_queue_head_init(priv->sab8253xc_rcvbuflist);
- return 0;
- }
- /* sets up transmit ring and one receive sk_buff */
- /* set up transmit and receive
- sk_buff control structures */
- int Sab8253xInitDescriptors2(SAB_PORT *priv, int listsize, int rbufsize)
- {
- RING_DESCRIPTOR *desc;
- RING_DESCRIPTOR *xdesc;
-
- if(priv->dcontrol2.transmit != NULL)
-
- {
- if(priv->dcontrol2.receive != NULL)
- {
- return 0;
- }
- return -1;
- }
- else if(priv->dcontrol2.receive != NULL)
- {
- return -1;
- }
-
- priv->dcontrol2.transmit = (RING_DESCRIPTOR*)
- kmalloc(sizeof(RING_DESCRIPTOR) * listsize, GFP_KERNEL);
- /* dcontrol2 is an historical
- artifact from when the code
- talked to an intelligent controller */
- if(priv->dcontrol2.transmit == NULL)
- {
- return -1;
- }
-
- priv->dcontrol2.receive = (RING_DESCRIPTOR*)
- kmalloc(sizeof(RING_DESCRIPTOR), GFP_KERNEL); /* only one receive sk_buffer */
- if(priv->dcontrol2.receive == NULL)
- {
- kfree(priv->dcontrol2.transmit);
- priv->dcontrol2.transmit = NULL;
- return -1;
- }
-
- for(xdesc = priv->dcontrol2.transmit;
- xdesc < &priv->dcontrol2.transmit[listsize - 1];
- xdesc = &xdesc[1]) /* set up transmit descriptors */
- {
- xdesc->HostVaddr = NULL;
- xdesc->VNext = &xdesc[1];
- xdesc->Count = 0 | OWN_DRIVER;
- xdesc->crc = 0;
- xdesc->sendcrc = 0;
- xdesc->crcindex = 0;
- }
- xdesc->HostVaddr = NULL;
- xdesc->VNext = priv->dcontrol2.transmit; /* circular list */
- xdesc->Count = 0 | OWN_DRIVER;
- xdesc->crc = 0;
- xdesc->sendcrc = 0;
- xdesc->crcindex = 0;
-
- desc = priv->dcontrol2.receive; /* only need one descriptor for receive */
- desc->HostVaddr = NULL;
- desc->VNext = &desc[0];
-
- desc = priv->dcontrol2.receive;
- desc->HostVaddr = dev_alloc_skb(rbufsize);
- if(desc->HostVaddr == NULL)
- {
- printk(KERN_ALERT "Unable to allocate skb_buffers (rx 0).n");
- printk(KERN_ALERT "Driver initialization failed.n");
- kfree(priv->dcontrol2.transmit);
- kfree(priv->dcontrol2.receive);
- priv->dcontrol2.transmit = NULL; /* get rid of descriptor ring */
- priv->dcontrol2.receive = NULL; /* get rid of descriptor */
- /* probably should do some deallocation of sk_buffs*/
- /* but will take place in the open */
- return -1;
- }
- skb_queue_head(priv->sab8253xbuflist, (struct sk_buff*) desc->HostVaddr);
- desc->Count = rbufsize|OWN_SAB; /* belongs to int handler */
- desc->crc = 0;
- desc->sendcrc = 0;
- desc->crcindex = 0;
-
- /* setup the various pointers */
- priv->active2 = priv->dcontrol2; /* insert new skbuff */
- priv->sabnext2 = priv->dcontrol2; /* transmit from here */
-
- return 0;
- }
- /* loads program, waits for PPC */
- /* and completes initialization*/
- void Sab8253xCleanUpTransceiveN(SAB_PORT* priv)
- {
- Sab8253xFreeAllFreeListSKBUFFS(priv);
- Sab8253xFreeAllReceiveListSKBUFFS(priv);
-
- /* these are also cleaned up in the module cleanup routine */
- /* should probably only be done here */
- if(priv->dcontrol2.receive)
- {
- kfree(priv->dcontrol2.receive);
- priv->dcontrol2.receive = NULL;
- }
- if(priv->dcontrol2.transmit)
- {
- kfree(priv->dcontrol2.transmit);
- priv->dcontrol2.transmit = NULL;
- }
- priv->active2 = priv->dcontrol2;
- priv->sabnext2 = priv->dcontrol2;
- }
- void Sab8253xFreeAllReceiveListSKBUFFS(SAB_PORT* priv) /* empty the skbuffer list */
- /* either on failed open */
- /* or on close*/
- {
- struct sk_buff* skb;
-
- if(priv->sab8253xc_rcvbuflist == NULL)
- {
- return;
- }
-
- DEBUGPRINT((KERN_ALERT "sab8253x: freeing %i skbuffs.n",
- skb_queue_len(priv->sab8253xc_rcvbuflist)));
-
- while(skb_queue_len(priv->sab8253xc_rcvbuflist) > 0)
- {
- skb = skb_dequeue(priv->sab8253xc_rcvbuflist);
- dev_kfree_skb_any(skb);
- }
- kfree(priv->sab8253xc_rcvbuflist);
- priv->sab8253xc_rcvbuflist = NULL;
- }
- /*
- * This routine is called to set the UART divisor registers to match
- * the specified baud rate for a serial port.
- */
- void sab8253x_change_speedN(struct sab_port *port)
- {
- unsigned long flags;
- unsigned char ccr2=0, ccr4=0, ebrg=0;
- int bits = 8;
-
- #ifdef DEBUGGING
- printk("Change speed! ");
- #endif
-
- if(!sab8253x_baud(port, (port->baud)*2, &ebrg, &ccr2, &ccr4, &(port->baud)))
- {
- printk("Aurora Warning. baudrate %ld could not be set! Using 115200", port->baud);
- port->baud = 115200;
- sab8253x_baud(port, (port->baud*2), &ebrg, &ccr2, &ccr4, &(port->baud));
- }
-
- if (port->baud)
- {
- port->timeout = (port->xmit_fifo_size * HZ * bits) / port->baud;
- port->cec_timeout = port->tec_timeout >> 2;
- }
- else
- {
- port->timeout = 0;
- port->cec_timeout = SAB8253X_MAX_CEC_DELAY;
- }
- port->timeout += HZ / 50; /* Add .02 seconds of slop */
-
- save_flags(flags);
- cli();
- sab8253x_cec_wait(port);
-
- WRITEB(port, bgr, ebrg);
- WRITEB(port, ccr2, READB(port, ccr2) & ~(0xc0)); /* clear out current baud rage */
- WRITEB(port, ccr2, READB(port, ccr2) | ccr2);
- WRITEB(port, ccr4, (READB(port,ccr4) & ~SAB82532_CCR4_EBRG) | ccr4);
-
- if (port->flags & FLAG8253X_CTS_FLOW)
- {
- WRITEB(port, mode, READB(port,mode) & ~(SAB82532_MODE_RTS));
- port->interrupt_mask1 &= ~(SAB82532_IMR1_CSC);
- WRITEB(port, imr1, port->interrupt_mask1);
- }
- else
- {
- WRITEB(port, mode, READB(port,mode) | SAB82532_MODE_RTS);
- port->interrupt_mask1 |= SAB82532_IMR1_CSC;
- WRITEB(port, imr1, port->interrupt_mask1);
- }
- WRITEB(port, mode, READB(port, mode) | SAB82532_MODE_RAC);
- restore_flags(flags);
- }
- void sab8253x_shutdownN(struct sab_port *port)
- {
- unsigned long flags;
-
- if (!(port->flags & FLAG8253X_INITIALIZED))
- {
- return;
- }
-
- save_flags(flags); cli(); /* Disable interrupts */
-
- /*
- * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
- * here so the queue might never be waken up
- */
- wake_up_interruptible(&port->delta_msr_wait);
-
- /* Disable Interrupts */
-
- port->interrupt_mask0 = 0xff;
- WRITEB(port, imr0, port->interrupt_mask0);
- port->interrupt_mask1 = 0xff;
- WRITEB(port, imr1, port->interrupt_mask1);
-
- LOWER(port,rts);
- LOWER(port,dtr);
-
- /* Disable Receiver */
- CLEAR_REG_BIT(port,mode,SAB82532_MODE_RAC);
-
- /* Power Down */
- CLEAR_REG_BIT(port,ccr0,SAB82532_CCR0_PU);
-
- port->flags &= ~FLAG8253X_INITIALIZED;
- restore_flags(flags);
- }
- int sab8253x_block_til_ready(struct tty_struct *tty, struct file * filp,
- struct sab_port *port)
- {
- DECLARE_WAITQUEUE(wait, current);
- int retval;
- int do_clocal = 0;
- unsigned long flags;
-
- /*
- * If the device is in the middle of being closed, then block
- * until it's done, and then try again.
- */
- if (tty_hung_up_p(filp) ||
- (port->flags & FLAG8253X_CLOSING))
- {
- if (port->flags & FLAG8253X_CLOSING)
- {
- interruptible_sleep_on(&port->close_wait); /* finish up previous close */
- }
- #ifdef SERIAL_DO_RESTART
- if (port->flags & FLAG8253X_HUP_NOTIFY)
- {
- return -EAGAIN;
- }
- else
- {
- return -ERESTARTSYS;
- }
- #else
- return -EAGAIN;
- #endif
- }
-
- /*
- * If this is a callout device, then just make sure the normal
- * device isn't being used.
- */
- if (tty->driver.subtype == SERIAL_TYPE_CALLOUT)
- {
- if (port->flags & FLAG8253X_NORMAL_ACTIVE)
- {
- return -EBUSY; /* async, sync tty or network driver active */
- }
- if ((port->flags & FLAG8253X_CALLOUT_ACTIVE) &&
- (port->flags & FLAG8253X_SESSION_LOCKOUT) &&
- (port->session != current->session))
- {
- return -EBUSY;
- }
- if ((port->flags & FLAG8253X_CALLOUT_ACTIVE) &&
- (port->flags & FLAG8253X_PGRP_LOCKOUT) &&
- (port->pgrp != current->pgrp))
- {
- return -EBUSY;
- }
- port->flags |= FLAG8253X_CALLOUT_ACTIVE; /* doing a callout */
- return 0;
- }
-
- /* sort out async vs sync tty, not call out */
- /*
- * If non-blocking mode is set, or the port is not enabled,
- * then make the check up front and then exit.
- */
-
- if ((filp->f_flags & O_NONBLOCK) ||
- (tty->flags & (1 << TTY_IO_ERROR)))
- {
- if (port->flags & FLAG8253X_CALLOUT_ACTIVE)
- {
- return -EBUSY;
- }
- port->flags |= FLAG8253X_NORMAL_ACTIVE;
- return 0;
- }
-
- if (port->flags & FLAG8253X_CALLOUT_ACTIVE)
- {
- if (port->normal_termios.c_cflag & CLOCAL)
- {
- do_clocal = 1;
- }
- }
- else if (tty->termios->c_cflag & CLOCAL)
- {
- do_clocal = 1;
- }
-
- /*
- * Block waiting for the carrier detect and the line to become
- * free (i.e., not in use by the callout). While we are in
- * this loop, port->count is dropped by one, so that
- * sab8253x_close() knows when to free things. We restore it upon
- * exit, either normal or abnormal.
- */
-
- /* The port decrement logic is probably */
- /* broken -- hence if def'd out -- it does*/
- retval = 0;
- add_wait_queue(&port->open_wait, &wait); /* starts the wait but does not block here */
- port->blocked_open++;
- while (1)
- {
- save_flags(flags);
- cli();
- if (!(port->flags & FLAG8253X_CALLOUT_ACTIVE) &&
- (tty->termios->c_cflag & CBAUD))
- {
- RAISE(port, dtr);
- RAISE(port, rts); /* maybe not correct for sync */
- /*
- * ??? Why changing the mode here?
- * port->regs->rw.mode |= SAB82532_MODE_FRTS;
- * port->regs->rw.mode &= ~(SAB82532_MODE_RTS);
- */
- }
- restore_flags(flags);
- current->state = TASK_INTERRUPTIBLE;
- if (tty_hung_up_p(filp) ||
- !(port->flags & FLAG8253X_INITIALIZED))
- {
- #ifdef SERIAL_DO_RESTART
- if (port->flags & FLAG8253X_HUP_NOTIFY)
- {
- retval = -EAGAIN;
- }
- else
- {
- retval = -ERESTARTSYS;
- }
- #else
- retval = -EAGAIN;
- #endif
- break;
- }
- if (!(port->flags & FLAG8253X_CALLOUT_ACTIVE) &&
- !(port->flags & FLAG8253X_CLOSING) &&
- (do_clocal || ISON(port,dcd)))
- {
- break;
- }
- #ifdef DEBUG_OPEN
- printk("sab8253x_block_til_ready:2 flags = 0x%xn",port->flags);
- #endif
- if (signal_pending(current))
- {
- retval = -ERESTARTSYS;
- break;
- }
- #ifdef DEBUG_OPEN
- printk("sab8253x_block_til_ready blocking: ttyS%d, count = %d, flags = %x, clocal = %d, vstr = %02xn",
- port->line, port->count, port->flags, do_clocal, READB(port,vstr));
- #endif
- schedule();
- }
- current->state = TASK_RUNNING;
- remove_wait_queue(&port->open_wait, &wait);
- port->blocked_open--;
- #ifdef DEBUG_OPEN
- printk("sab8253x_block_til_ready after blocking: ttys%d, count = %dn",
- port->line, port->count);
- #endif
- if (retval)
- {
- return retval;
- }
- port->flags |= FLAG8253X_NORMAL_ACTIVE;
- return 0;
- }
- /*
- * sab8253x_wait_until_sent() --- wait until the transmitter is empty
- */
- void sab8253x_wait_until_sent(struct tty_struct *tty, int timeout)
- {
- struct sab_port *port = (struct sab_port *)tty->driver_data;
- unsigned long orig_jiffies, char_time;
-
- if (sab8253x_serial_paranoia_check(port,tty->device,"sab8253x_wait_until_sent"))
- {
- return;
- }
-
- orig_jiffies = jiffies;
- /*
- * Set the check interval to be 1/5 of the estimated time to
- * send a single character, and make it at least 1. The check
- * interval should also be less than the timeout.
- *
- * Note: we have to use pretty tight timings here to satisfy
- * the NIST-PCTS.
- */
- char_time = (port->timeout - HZ/50) / port->xmit_fifo_size;
- char_time = char_time / 5;
- if (char_time == 0)
- {
- char_time = 1;
- }
- if (timeout)
- {
- char_time = MIN(char_time, timeout);
- }
- while ((Sab8253xCountTransmit(port) > 0) || !port->all_sent)
- {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(char_time);
- if (signal_pending(current))
- {
- break;
- }
- if (timeout && time_after(jiffies, orig_jiffies + timeout))
- {
- break;
- }
- }
- }
- void sab8253x_flush_buffer(struct tty_struct *tty)
- {
- struct sab_port *port = (struct sab_port *)tty->driver_data;
- unsigned long flags;
- register RING_DESCRIPTOR *freeme;
-
- if(sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_flush_buffer"))
- {
- return;
- }
-
- if(port->sabnext2.transmit == NULL)
- {
- return;
- }
-
- save_flags(flags);
- cli(); /* need to turn off ints because mucking
- with sabnext2 */
- #ifndef FREEININTERRUPT
- freeme = port->active2.transmit;
- do /* just go all around */
- {
- if(freeme->HostVaddr)
- {
- skb_unlink((struct sk_buff*)freeme->HostVaddr);
- dev_kfree_skb_any((struct sk_buff*)freeme->HostVaddr);
- freeme->HostVaddr = NULL;
- }
- freeme->sendcrc = 0;
- freeme->crcindex = 0;
- freeme->Count = OWN_DRIVER;
- freeme = (RING_DESCRIPTOR*) freeme->VNext;
- }
- while(freeme != port->active2.transmit);
- #else /* buffers only from sabnext2.transmit to active2.transmit */
- while((port->sabnext2.transmit->Count & OWNER) == OWN_SAB) /* clear out stuff waiting to be transmitted */
- {
- freeme = port->sabnext2.transmit;
- if(freeme->HostVaddr)
- {
- skb_unlink((struct sk_buff*)freeme->HostVaddr);
- dev_kfree_skb_any((struct sk_buff*)freeme->HostVaddr);
- freeme->HostVaddr = NULL;
- }
- freeme->sendcrc = 0;
- freeme->crcindex = 0;
- freeme->Count = OWN_DRIVER;
- port->sabnext2.transmit = freeme->VNext;
- }
- #endif
- port->sabnext2.transmit = port->active2.transmit; /* should already be equal to be sure */
- sab8253x_cec_wait(port);
- WRITEB(port,cmdr,SAB82532_CMDR_XRES);
- restore_flags(flags);
-
- wake_up_interruptible(&tty->write_wait); /* wake up tty driver */
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- tty->ldisc.write_wakeup)
- {
- (*tty->ldisc.write_wakeup)(tty);
- }
- }