patch-2.4.21 linux-2.4.21/drivers/net/wan/hd6457x.c
Next file: linux-2.4.21/drivers/net/wan/hdlc.c
Previous file: linux-2.4.21/drivers/net/wan/hd64570.h
Back to the patch index
Back to the overall index
- Lines: 455
- Date:
2003-06-13 07:51:35.000000000 -0700
- Orig file:
linux-2.4.20/drivers/net/wan/hd6457x.c
- Orig date:
2001-03-06 19:44:36.000000000 -0800
diff -urN linux-2.4.20/drivers/net/wan/hd6457x.c linux-2.4.21/drivers/net/wan/hd6457x.c
@@ -42,13 +42,7 @@
#error Either hd64570.h or hd64572.h must be included
#endif
-
-static card_t *first_card;
-static card_t **new_card = &first_card;
-
-
-/* Maximum events to handle at each interrupt - should I increase it? */
-#define INTR_WORK 4
+static char sca_version[]="1.09";
#define get_msci(port) (phy_node(port) ? MSCI1_OFFSET : MSCI0_OFFSET)
#define get_dmac_rx(port) (phy_node(port) ? DMAC1RX_OFFSET : DMAC0RX_OFFSET)
@@ -63,11 +57,19 @@
#define sca_ina(reg, card) sca_inw(reg, card)
#define writea(value, ptr) writew(value, ptr)
+#else /* HD64572 */
+#define sca_outa(value, reg, card) sca_outl(value, reg, card)
+#define sca_ina(reg, card) sca_inl(reg, card)
+#define writea(value, ptr) writel(value, ptr)
+#endif
+
static inline int sca_intr_status(card_t *card)
{
+ u8 result = 0;
+
+#ifdef __HD64570_H /* HD64570 */
u8 isr0 = sca_in(ISR0, card);
u8 isr1 = sca_in(ISR1, card);
- u8 result = 0;
if (isr1 & 0x03) result |= SCA_INTR_DMAC_RX(0);
if (isr1 & 0x0C) result |= SCA_INTR_DMAC_TX(0);
@@ -76,19 +78,8 @@
if (isr0 & 0x0F) result |= SCA_INTR_MSCI(0);
if (isr0 & 0xF0) result |= SCA_INTR_MSCI(1);
- return result;
-}
-
#else /* HD64572 */
-#define sca_outa(value, reg, card) sca_outl(value, reg, card)
-#define sca_ina(reg, card) sca_inl(reg, card)
-#define writea(value, ptr) writel(value, ptr)
-
-
-static inline int sca_intr_status(card_t *card)
-{
u32 isr0 = sca_inl(ISR0, card);
- u8 result = 0;
if (isr0 & 0x0000000F) result |= SCA_INTR_DMAC_RX(0);
if (isr0 & 0x000000F0) result |= SCA_INTR_DMAC_TX(0);
@@ -97,11 +88,17 @@
if (isr0 & 0x003E0000) result |= SCA_INTR_MSCI(0);
if (isr0 & 0x3E000000) result |= SCA_INTR_MSCI(1);
- return result;
-}
-
#endif /* HD64570 vs HD64572 */
+ if (!(result & SCA_INTR_DMAC_TX(0)))
+ if (sca_in(DSR_TX(0), card) & DSR_EOM)
+ result |= SCA_INTR_DMAC_TX(0);
+ if (!(result & SCA_INTR_DMAC_TX(1)))
+ if (sca_in(DSR_TX(1), card) & DSR_EOM)
+ result |= SCA_INTR_DMAC_TX(1);
+
+ return result;
+}
@@ -250,8 +247,7 @@
-static inline void sca_rx(card_t *card, port_t *port, pkt_desc *desc,
- u8 rxin)
+static inline void sca_rx(card_t *card, port_t *port, pkt_desc *desc, u8 rxin)
{
struct sk_buff *skb;
u16 len;
@@ -289,13 +285,17 @@
openwin(card, 0);
#endif
skb_put(skb, len);
-#ifdef DEBUG_PKT
+#ifdef CONFIG_HDLC_DEBUG_PKT
printk(KERN_DEBUG "%s RX(%i):", hdlc_to_name(&port->hdlc), skb->len);
debug_frame(skb);
#endif
port->hdlc.stats.rx_packets++;
port->hdlc.stats.rx_bytes += skb->len;
- hdlc_netif_rx(&port->hdlc, skb);
+ skb->mac.raw = skb->data;
+ skb->dev = hdlc_to_dev(&port->hdlc);
+ skb->dev->last_rx = jiffies;
+ skb->protocol = htons(ETH_P_HDLC);
+ netif_rx(skb);
}
@@ -320,14 +320,9 @@
pkt_desc *desc;
u32 cda = sca_ina(dmac + CDAL, card);
- if (cda == desc_off)
+ if ((cda >= desc_off) && (cda < desc_off + sizeof(pkt_desc)))
break; /* No frame received */
-#ifdef __HD64572_H
- if (cda == desc_off + 8)
- break; /* SCA-II updates CDA in 2 steps */
-#endif
-
desc = desc_address(port, port->rxin, 0);
stat = readb(&desc->stat);
if (!(stat & ST_RX_EOM))
@@ -371,20 +366,17 @@
DSR_TX(phy_node(port)), card);
while (1) {
- u32 desc_off = desc_offset(port, port->txlast, 1);
pkt_desc *desc;
- u16 len;
- if (sca_ina(dmac + CDAL, card) == desc_off)
+ u32 desc_off = desc_offset(port, port->txlast, 1);
+ u32 cda = sca_ina(dmac + CDAL, card);
+ if ((cda >= desc_off) && (cda < desc_off + sizeof(pkt_desc)))
break; /* Transmitter is/will_be sending this frame */
desc = desc_address(port, port->txlast, 1);
- len = readw(&desc->len);
-
port->hdlc.stats.tx_packets++;
- port->hdlc.stats.tx_bytes += len;
+ port->hdlc.stats.tx_bytes += readw(&desc->len);
writeb(0, &desc->stat); /* Free descriptor */
-
port->txlast = (port->txlast + 1) %
port_to_card(port)->ring_buffers;
}
@@ -398,7 +390,8 @@
static void sca_intr(int irq, void* dev_id, struct pt_regs *regs)
{
card_t *card = dev_id;
- int boguscnt = INTR_WORK;
+/* Maximum events to handle at each interrupt - should I increase it? */
+ int boguscnt = 4;
int i;
u8 stat;
@@ -421,9 +414,11 @@
}
if (--boguscnt < 0) {
+#if 0
printk(KERN_ERR "%s: too much work at "
"interrupt\n",
hdlc_to_name(&port->hdlc));
+#endif
goto exit;
}
}
@@ -433,51 +428,27 @@
#ifndef ALL_PAGES_ALWAYS_MAPPED
openwin(card, page); /* Restore original page */
#endif
+ return;
}
-static inline int sca_set_loopback(port_t *port, int line)
+static void sca_set_port(port_t *port)
{
card_t* card = port_to_card(port);
u8 msci = get_msci(port);
u8 md2 = sca_in(msci + MD2, card);
-
- switch(line) {
- case LINE_DEFAULT:
- md2 &= ~MD2_LOOPBACK;
- port->line &= ~LINE_LOOPBACK;
- break;
-
- case LINE_LOOPBACK:
- md2 |= MD2_LOOPBACK;
- port->line |= LINE_LOOPBACK;
- break;
-
- default:
- return -EINVAL;
- }
-
- sca_out(md2, msci + MD2, card);
- return 0;
-}
-
-
-
-static void sca_set_clock(port_t *port)
-{
- card_t *card = port_to_card(port);
- u8 msci = get_msci(port);
unsigned int tmc, br = 10, brv = 1024;
- if (port->clkrate > 0) {
+
+ if (port->settings.clock_rate > 0) {
/* Try lower br for better accuracy*/
do {
br--;
brv >>= 1; /* brv = 2^9 = 512 max in specs */
/* Baud Rate = CLOCK_BASE / TMC / 2^BR */
- tmc = CLOCK_BASE / (brv * port->clkrate);
+ tmc = CLOCK_BASE / (brv * port->settings.clock_rate);
}while(br > 1 && tmc <= 128);
if (tmc < 1) {
@@ -487,11 +458,11 @@
} else if (tmc > 255)
tmc = 256; /* tmc=0 means 256 - low baud rates */
- port->clkrate = CLOCK_BASE / (brv * tmc);
+ port->settings.clock_rate = CLOCK_BASE / (brv * tmc);
} else {
br = 9; /* Minimum clock rate */
tmc = 256; /* 8bit = 0 */
- port->clkrate = CLOCK_BASE / (256 * 512);
+ port->settings.clock_rate = CLOCK_BASE / (256 * 512);
}
port->rxs = (port->rxs & ~CLK_BRG_MASK) | br;
@@ -509,27 +480,59 @@
/* Set BRG bits */
sca_out(port->rxs, msci + RXS, card);
sca_out(port->txs, msci + TXS, card);
+
+ if (port->settings.loopback)
+ md2 |= MD2_LOOPBACK;
+ else
+ md2 &= ~MD2_LOOPBACK;
+
+ sca_out(md2, msci + MD2, card);
+
}
-static void sca_set_hdlc_mode(port_t *port, u8 idle, u8 crc, u8 nrzi)
+static void sca_open(hdlc_device *hdlc)
{
+ port_t *port = hdlc_to_port(hdlc);
card_t* card = port_to_card(port);
u8 msci = get_msci(port);
- u8 md2 = (nrzi ? MD2_NRZI : 0) |
- ((port->line & LINE_LOOPBACK) ? MD2_LOOPBACK : 0);
- u8 ctl = (idle ? CTL_IDLE : 0);
-#ifdef __HD64572_H
- ctl |= CTL_URCT | CTL_URSKP; /* Skip the rest of underrun frame */
-#endif
+ u8 md0, md2;
+
+ switch(port->encoding) {
+ case ENCODING_NRZ: md2 = MD2_NRZ; break;
+ case ENCODING_NRZI: md2 = MD2_NRZI; break;
+ case ENCODING_FM_MARK: md2 = MD2_FM_MARK; break;
+ case ENCODING_FM_SPACE: md2 = MD2_FM_SPACE; break;
+ default: md2 = MD2_MANCHESTER;
+ }
+
+ if (port->settings.loopback)
+ md2 |= MD2_LOOPBACK;
+
+ switch(port->parity) {
+ case PARITY_CRC16_PR0: md0 = MD0_HDLC | MD0_CRC_16_0; break;
+ case PARITY_CRC16_PR1: md0 = MD0_HDLC | MD0_CRC_16; break;
+#ifdef __HD64570_H
+ case PARITY_CRC16_PR0_CCITT: md0 = MD0_HDLC | MD0_CRC_ITU_0; break;
+#else
+ case PARITY_CRC32_PR1_CCITT: md0 = MD0_HDLC | MD0_CRC_ITU32; break;
+#endif
+ case PARITY_CRC16_PR1_CCITT: md0 = MD0_HDLC | MD0_CRC_ITU; break;
+ default: md0 = MD0_HDLC | MD0_CRC_NONE;
+ }
sca_out(CMD_RESET, msci + CMD, card);
- sca_out(MD0_HDLC | crc, msci + MD0, card);
+ sca_out(md0, msci + MD0, card);
sca_out(0x00, msci + MD1, card); /* no address field check */
sca_out(md2, msci + MD2, card);
sca_out(0x7E, msci + IDL, card); /* flag character 0x7E */
- sca_out(ctl, msci + CTL, card);
+#ifdef __HD64570_H
+ sca_out(CTL_IDLE, msci + CTL, card);
+#else
+ /* Skip the rest of underrun frame */
+ sca_out(CTL_IDLE | CTL_URCT | CTL_URSKP, msci + CTL, card);
+#endif
#ifdef __HD64570_H
/* Allow at least 8 bytes before requesting RX DMA operation */
@@ -539,24 +542,28 @@
sca_out(0x14, msci + TRC1, card); /* +1=TXRDY/DMA deactiv condition */
#else
sca_out(0x0F, msci + RNR, card); /* +1=RX DMA activation condition */
- /* Setting than to larger value may cause Illegal Access */
- sca_out(0x20, msci + TNR0, card); /* =TX DMA activation condition */
- sca_out(0x30, msci + TNR1, card); /* +1=TX DMA deactivation condition*/
- sca_out(0x04, msci + TCR, card); /* =Critical TX DMA activ condition */
+ sca_out(0x3C, msci + TFS, card); /* +1 = TX start */
+ sca_out(0x38, msci + TCR, card); /* =Critical TX DMA activ condition */
+ sca_out(0x38, msci + TNR0, card); /* =TX DMA activation condition */
+ sca_out(0x3F, msci + TNR1, card); /* +1=TX DMA deactivation condition*/
#endif
+/* We're using the following interrupts:
+ - TXINT (DMAC completed all transmisions, underflow or CTS change)
+ - all DMA interrupts
+*/
#ifdef __HD64570_H
/* MSCI TX INT IRQ enable */
sca_out(IE0_TXINT, msci + IE0, card);
- sca_out(IE1_UDRN, msci + IE1, card); /* TX underrun IRQ */
+ sca_out(IE1_UDRN, msci + IE1, card); /* TX underrun -> TXINT */
sca_out(sca_in(IER0, card) | (phy_node(port) ? 0x80 : 0x08),
IER0, card);
/* DMA IRQ enable */
sca_out(sca_in(IER1, card) | (phy_node(port) ? 0xF0 : 0x0F),
IER1, card);
#else
- /* MSCI TX INT and underrrun IRQ enable */
+ /* MSCI TX INT IRQ enable */
sca_outl(IE0_TXINT | IE0_UDRN, msci + IE0, card);
/* DMA & MSCI IRQ enable */
sca_outl(sca_in(IER0, card) |
@@ -573,11 +580,52 @@
sca_out(port->txs, msci + TXS, card);
sca_out(CMD_TX_ENABLE, msci + CMD, card);
sca_out(CMD_RX_ENABLE, msci + CMD, card);
+
+ netif_start_queue(hdlc_to_dev(hdlc));
+}
+
+
+
+static void sca_close(hdlc_device *hdlc)
+{
+ port_t *port = hdlc_to_port(hdlc);
+
+ /* reset channel */
+ netif_stop_queue(hdlc_to_dev(hdlc));
+ sca_out(CMD_RESET, get_msci(port) + CMD, port_to_card(port));
}
-#ifdef DEBUG_RINGS
+static int sca_attach(hdlc_device *hdlc, unsigned short encoding,
+ unsigned short parity)
+{
+ if (encoding != ENCODING_NRZ &&
+ encoding != ENCODING_NRZI &&
+ encoding != ENCODING_FM_MARK &&
+ encoding != ENCODING_FM_SPACE &&
+ encoding != ENCODING_MANCHESTER)
+ return -EINVAL;
+
+ if (parity != PARITY_NONE &&
+ parity != PARITY_CRC16_PR0 &&
+ parity != PARITY_CRC16_PR1 &&
+#ifdef __HD64570_H
+ parity != PARITY_CRC16_PR0_CCITT &&
+#else
+ parity != PARITY_CRC32_PR1_CCITT &&
+#endif
+ parity != PARITY_CRC16_PR1_CCITT)
+ return -EINVAL;
+
+ hdlc_to_port(hdlc)->encoding = encoding;
+ hdlc_to_port(hdlc)->parity = parity;
+ return 0;
+}
+
+
+
+#ifdef CONFIG_HDLC_DEBUG_RINGS
static void sca_dump_rings(hdlc_device *hdlc)
{
port_t *port = hdlc_to_port(hdlc);
@@ -644,34 +692,14 @@
openwin(card, page); /* Restore original page */
#endif
}
-#endif /* DEBUG_RINGS */
-
-
-
-static void sca_open(hdlc_device *hdlc)
-{
- port_t *port = hdlc_to_port(hdlc);
-
- sca_set_hdlc_mode(port, 1, MD0_CRC_ITU, 0);
- netif_start_queue(hdlc_to_dev(hdlc));
-}
-
-
-static void sca_close(hdlc_device *hdlc)
-{
- port_t *port = hdlc_to_port(hdlc);
-
- /* reset channel */
- netif_stop_queue(hdlc_to_dev(hdlc));
- sca_out(CMD_RESET, get_msci(port) + CMD, port_to_card(port));
-}
+#endif /* CONFIG_HDLC_DEBUG_RINGS */
-static int sca_xmit(hdlc_device *hdlc, struct sk_buff *skb)
+static int sca_xmit(struct sk_buff *skb, struct net_device *dev)
{
+ hdlc_device *hdlc = dev_to_hdlc(dev);
port_t *port = hdlc_to_port(hdlc);
- struct net_device *dev = hdlc_to_dev(hdlc);
card_t *card = port_to_card(port);
pkt_desc *desc;
u32 buff, len;
@@ -685,7 +713,7 @@
desc = desc_address(port, port->txin + 1, 1);
if (readb(&desc->stat)) { /* allow 1 packet gap */
/* should never happen - previous xmit should stop queue */
-#ifdef DEBUG_PKT
+#ifdef CONFIG_HDLC_DEBUG_PKT
printk(KERN_DEBUG "%s: transmitter buffer full\n", dev->name);
#endif
netif_stop_queue(dev);
@@ -693,7 +721,7 @@
return 1; /* request packet to be queued */
}
-#ifdef DEBUG_PKT
+#ifdef CONFIG_HDLC_DEBUG_PKT
printk(KERN_DEBUG "%s TX(%i):", hdlc_to_name(hdlc), skb->len);
debug_frame(skb);
#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)