hd64572.c 17.6 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2
 * Hitachi (now Renesas) SCA-II HD64572 driver for Linux
L
Linus Torvalds 已提交
3
 *
4
 * Copyright (C) 1998-2008 Krzysztof Halasa <khc@pm.waw.pl>
L
Linus Torvalds 已提交
5 6 7 8 9
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License
 * as published by the Free Software Foundation.
 *
10
 * Source of information: HD64572 SCA-II User's Manual
L
Linus Torvalds 已提交
11 12 13
 *
 * We use the following SCA memory map:
 *
K
Krzysztof Hałasa 已提交
14
 * Packet buffer descriptor rings - starting from card->rambase:
L
Linus Torvalds 已提交
15 16 17 18 19
 * rx_ring_buffers * sizeof(pkt_desc) = logical channel #0 RX ring
 * tx_ring_buffers * sizeof(pkt_desc) = logical channel #0 TX ring
 * rx_ring_buffers * sizeof(pkt_desc) = logical channel #1 RX ring (if used)
 * tx_ring_buffers * sizeof(pkt_desc) = logical channel #1 TX ring (if used)
 *
K
Krzysztof Hałasa 已提交
20
 * Packet data buffers - starting from card->rambase + buff_offset:
L
Linus Torvalds 已提交
21 22 23 24 25 26
 * rx_ring_buffers * HDLC_MAX_MRU     = logical channel #0 RX buffers
 * tx_ring_buffers * HDLC_MAX_MRU     = logical channel #0 TX buffers
 * rx_ring_buffers * HDLC_MAX_MRU     = logical channel #0 RX buffers (if used)
 * tx_ring_buffers * HDLC_MAX_MRU     = logical channel #0 TX buffers (if used)
 */

27 28
#include <linux/bitops.h>
#include <linux/errno.h>
L
Linus Torvalds 已提交
29
#include <linux/fcntl.h>
30
#include <linux/hdlc.h>
L
Linus Torvalds 已提交
31 32
#include <linux/in.h>
#include <linux/init.h>
33
#include <linux/interrupt.h>
L
Linus Torvalds 已提交
34
#include <linux/ioport.h>
35 36 37
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/module.h>
L
Linus Torvalds 已提交
38 39
#include <linux/netdevice.h>
#include <linux/skbuff.h>
40 41 42 43 44 45 46
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/types.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include "hd64572.h"
L
Linus Torvalds 已提交
47

48 49
#define NAPI_WEIGHT		16

K
Krzysztof Hałasa 已提交
50 51 52
#define get_msci(port)	  (port->chan ?   MSCI1_OFFSET :   MSCI0_OFFSET)
#define get_dmac_rx(port) (port->chan ? DMAC1RX_OFFSET : DMAC0RX_OFFSET)
#define get_dmac_tx(port) (port->chan ? DMAC1TX_OFFSET : DMAC0TX_OFFSET)
L
Linus Torvalds 已提交
53

K
Krzysztof Hałasa 已提交
54 55 56 57 58 59
#define sca_in(reg, card)	     readb(card->scabase + (reg))
#define sca_out(value, reg, card)    writeb(value, card->scabase + (reg))
#define sca_inw(reg, card)	     readw(card->scabase + (reg))
#define sca_outw(value, reg, card)   writew(value, card->scabase + (reg))
#define sca_inl(reg, card)	     readl(card->scabase + (reg))
#define sca_outl(value, reg, card)   writel(value, card->scabase + (reg))
L
Linus Torvalds 已提交
60

K
Krzysztof Hałasa 已提交
61
static int sca_poll(struct napi_struct *napi, int budget);
L
Linus Torvalds 已提交
62 63 64 65 66 67

static inline port_t* dev_to_port(struct net_device *dev)
{
	return dev_to_hdlc(dev)->priv;
}

68 69
static inline void enable_intr(port_t *port)
{
70
	/* enable DMIB and MSCI RXINTA interrupts */
71
	sca_outl(sca_inl(IER0, port->card) |
K
Krzysztof Hałasa 已提交
72
		 (port->chan ? 0x08002200 : 0x00080022), IER0, port->card);
73 74 75 76 77
}

static inline void disable_intr(port_t *port)
{
	sca_outl(sca_inl(IER0, port->card) &
K
Krzysztof Hałasa 已提交
78
		 (port->chan ? 0x00FF00FF : 0xFF00FF00), IER0, port->card);
79 80
}

L
Linus Torvalds 已提交
81 82
static inline u16 desc_abs_number(port_t *port, u16 desc, int transmit)
{
K
Krzysztof Hałasa 已提交
83 84
	u16 rx_buffs = port->card->rx_ring_buffers;
	u16 tx_buffs = port->card->tx_ring_buffers;
L
Linus Torvalds 已提交
85 86

	desc %= (transmit ? tx_buffs : rx_buffs); // called with "X + 1" etc.
K
Krzysztof Hałasa 已提交
87
	return port->chan * (rx_buffs + tx_buffs) + transmit * rx_buffs + desc;
L
Linus Torvalds 已提交
88 89 90 91 92
}


static inline u16 desc_offset(port_t *port, u16 desc, int transmit)
{
93
	/* Descriptor offset always fits in 16 bits */
L
Linus Torvalds 已提交
94 95 96 97
	return desc_abs_number(port, desc, transmit) * sizeof(pkt_desc);
}


98 99
static inline pkt_desc __iomem *desc_address(port_t *port, u16 desc,
					     int transmit)
L
Linus Torvalds 已提交
100
{
K
Krzysztof Hałasa 已提交
101 102
	return (pkt_desc __iomem *)(port->card->rambase +
				    desc_offset(port, desc, transmit));
L
Linus Torvalds 已提交
103 104 105 106 107
}


static inline u32 buffer_offset(port_t *port, u16 desc, int transmit)
{
K
Krzysztof Hałasa 已提交
108
	return port->card->buff_offset +
L
Linus Torvalds 已提交
109 110 111 112
		desc_abs_number(port, desc, transmit) * (u32)HDLC_MAX_MRU;
}


113 114
static inline void sca_set_carrier(port_t *port)
{
K
Krzysztof Hałasa 已提交
115
	if (!(sca_in(get_msci(port) + ST3, port->card) & ST3_DCD)) {
116 117
#ifdef DEBUG_LINK
		printk(KERN_DEBUG "%s: sca_set_carrier on\n",
K
Krzysztof Hałasa 已提交
118
		       port->netdev.name);
119
#endif
K
Krzysztof Hałasa 已提交
120
		netif_carrier_on(port->netdev);
121 122 123
	} else {
#ifdef DEBUG_LINK
		printk(KERN_DEBUG "%s: sca_set_carrier off\n",
K
Krzysztof Hałasa 已提交
124
		       port->netdev.name);
125
#endif
K
Krzysztof Hałasa 已提交
126
		netif_carrier_off(port->netdev);
127 128 129
	}
}

L
Linus Torvalds 已提交
130

131
static void sca_init_port(port_t *port)
L
Linus Torvalds 已提交
132
{
K
Krzysztof Hałasa 已提交
133
	card_t *card = port->card;
134
	u16 dmac_rx = get_dmac_rx(port), dmac_tx = get_dmac_tx(port);
L
Linus Torvalds 已提交
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
	int transmit, i;

	port->rxin = 0;
	port->txin = 0;
	port->txlast = 0;

	for (transmit = 0; transmit < 2; transmit++) {
		u16 buffs = transmit ? card->tx_ring_buffers
			: card->rx_ring_buffers;

		for (i = 0; i < buffs; i++) {
			pkt_desc __iomem *desc = desc_address(port, i, transmit);
			u16 chain_off = desc_offset(port, i + 1, transmit);
			u32 buff_off = buffer_offset(port, i, transmit);

150
			writel(chain_off, &desc->cp);
L
Linus Torvalds 已提交
151 152 153 154 155
			writel(buff_off, &desc->bp);
			writew(0, &desc->len);
			writeb(0, &desc->stat);
		}
	}
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185

	/* DMA disable - to halt state */
	sca_out(0, DSR_RX(port->chan), card);
	sca_out(0, DSR_TX(port->chan), card);

	/* software ABORT - to initial state */
	sca_out(DCR_ABORT, DCR_RX(port->chan), card);
	sca_out(DCR_ABORT, DCR_TX(port->chan), card);

	/* current desc addr */
	sca_outl(desc_offset(port, 0, 0), dmac_rx + CDAL, card);
	sca_outl(desc_offset(port, card->tx_ring_buffers - 1, 0),
		 dmac_rx + EDAL, card);
	sca_outl(desc_offset(port, 0, 1), dmac_tx + CDAL, card);
	sca_outl(desc_offset(port, 0, 1), dmac_tx + EDAL, card);

	/* clear frame end interrupt counter */
	sca_out(DCR_CLEAR_EOF, DCR_RX(port->chan), card);
	sca_out(DCR_CLEAR_EOF, DCR_TX(port->chan), card);

	/* Receive */
	sca_outw(HDLC_MAX_MRU, dmac_rx + BFLL, card); /* set buffer length */
	sca_out(0x14, DMR_RX(port->chan), card); /* Chain mode, Multi-frame */
	sca_out(DIR_EOME, DIR_RX(port->chan), card); /* enable interrupts */
	sca_out(DSR_DE, DSR_RX(port->chan), card); /* DMA enable */

	/* Transmit */
	sca_out(0x14, DMR_TX(port->chan), card); /* Chain mode, Multi-frame */
	sca_out(DIR_EOME, DIR_TX(port->chan), card); /* enable interrupts */

186
	sca_set_carrier(port);
K
Krzysztof Hałasa 已提交
187
	netif_napi_add(port->netdev, &port->napi, sca_poll, NAPI_WEIGHT);
L
Linus Torvalds 已提交
188 189 190 191 192 193 194
}


/* MSCI interrupt service */
static inline void sca_msci_intr(port_t *port)
{
	u16 msci = get_msci(port);
K
Krzysztof Hałasa 已提交
195
	card_t* card = port->card;
L
Linus Torvalds 已提交
196

197 198 199
	if (sca_in(msci + ST1, card) & ST1_CDCD) {
		/* Reset MSCI CDCD status bit */
		sca_out(ST1_CDCD, msci + ST1, card);
200
		sca_set_carrier(port);
201
	}
L
Linus Torvalds 已提交
202 203 204
}


205 206
static inline void sca_rx(card_t *card, port_t *port, pkt_desc __iomem *desc,
			  u16 rxin)
L
Linus Torvalds 已提交
207
{
K
Krzysztof Hałasa 已提交
208
	struct net_device *dev = port->netdev;
L
Linus Torvalds 已提交
209 210 211 212 213 214 215
	struct sk_buff *skb;
	u16 len;
	u32 buff;

	len = readw(&desc->len);
	skb = dev_alloc_skb(len);
	if (!skb) {
216
		dev->stats.rx_dropped++;
L
Linus Torvalds 已提交
217 218 219 220
		return;
	}

	buff = buffer_offset(port, rxin, 0);
K
Krzysztof Hałasa 已提交
221
	memcpy_fromio(skb->data, card->rambase + buff, len);
L
Linus Torvalds 已提交
222 223 224 225 226 227

	skb_put(skb, len);
#ifdef DEBUG_PKT
	printk(KERN_DEBUG "%s RX(%i):", dev->name, skb->len);
	debug_frame(skb);
#endif
228 229
	dev->stats.rx_packets++;
	dev->stats.rx_bytes += skb->len;
L
Linus Torvalds 已提交
230
	skb->protocol = hdlc_type_trans(skb, dev);
231
	netif_receive_skb(skb);
L
Linus Torvalds 已提交
232 233 234
}


235 236
/* Receive DMA service */
static inline int sca_rx_done(port_t *port, int budget)
L
Linus Torvalds 已提交
237
{
K
Krzysztof Hałasa 已提交
238
	struct net_device *dev = port->netdev;
L
Linus Torvalds 已提交
239
	u16 dmac = get_dmac_rx(port);
K
Krzysztof Hałasa 已提交
240 241
	card_t *card = port->card;
	u8 stat = sca_in(DSR_RX(port->chan), card); /* read DMA Status */
242
	int received = 0;
L
Linus Torvalds 已提交
243 244 245

	/* Reset DSR status bits */
	sca_out((stat & (DSR_EOT | DSR_EOM | DSR_BOF | DSR_COF)) | DSR_DWE,
K
Krzysztof Hałasa 已提交
246
		DSR_RX(port->chan), card);
L
Linus Torvalds 已提交
247 248

	if (stat & DSR_BOF)
249 250
		/* Dropped one or more frames */
		dev->stats.rx_over_errors++;
L
Linus Torvalds 已提交
251

252
	while (received < budget) {
L
Linus Torvalds 已提交
253 254
		u32 desc_off = desc_offset(port, port->rxin, 0);
		pkt_desc __iomem *desc;
255
		u32 cda = sca_inl(dmac + CDAL, card);
L
Linus Torvalds 已提交
256 257 258 259 260 261 262 263 264

		if ((cda >= desc_off) && (cda < desc_off + sizeof(pkt_desc)))
			break;	/* No frame received */

		desc = desc_address(port, port->rxin, 0);
		stat = readb(&desc->stat);
		if (!(stat & ST_RX_EOM))
			port->rxpart = 1; /* partial frame received */
		else if ((stat & ST_ERROR_MASK) || port->rxpart) {
265 266 267
			dev->stats.rx_errors++;
			if (stat & ST_RX_OVERRUN)
				dev->stats.rx_fifo_errors++;
L
Linus Torvalds 已提交
268 269
			else if ((stat & (ST_RX_SHORT | ST_RX_ABORT |
					  ST_RX_RESBIT)) || port->rxpart)
270 271 272
				dev->stats.rx_frame_errors++;
			else if (stat & ST_RX_CRC)
				dev->stats.rx_crc_errors++;
L
Linus Torvalds 已提交
273 274
			if (stat & ST_RX_EOM)
				port->rxpart = 0; /* received last fragment */
275
		} else {
L
Linus Torvalds 已提交
276
			sca_rx(card, port, desc, port->rxin);
277 278
			received++;
		}
L
Linus Torvalds 已提交
279 280

		/* Set new error descriptor address */
281
		sca_outl(desc_off, dmac + EDAL, card);
282
		port->rxin = (port->rxin + 1) % card->rx_ring_buffers;
L
Linus Torvalds 已提交
283 284 285
	}

	/* make sure RX DMA is enabled */
K
Krzysztof Hałasa 已提交
286
	sca_out(DSR_DE, DSR_RX(port->chan), card);
287
	return received;
L
Linus Torvalds 已提交
288 289 290
}


291 292
/* Transmit DMA service */
static inline void sca_tx_done(port_t *port)
L
Linus Torvalds 已提交
293
{
K
Krzysztof Hałasa 已提交
294 295
	struct net_device *dev = port->netdev;
	card_t* card = port->card;
L
Linus Torvalds 已提交
296 297 298 299
	u8 stat;

	spin_lock(&port->lock);

K
Krzysztof Hałasa 已提交
300
	stat = sca_in(DSR_TX(port->chan), card); /* read DMA Status */
L
Linus Torvalds 已提交
301 302 303

	/* Reset DSR status bits */
	sca_out((stat & (DSR_EOT | DSR_EOM | DSR_BOF | DSR_COF)) | DSR_DWE,
K
Krzysztof Hałasa 已提交
304
		DSR_TX(port->chan), card);
L
Linus Torvalds 已提交
305 306

	while (1) {
307
		pkt_desc __iomem *desc = desc_address(port, port->txlast, 1);
308
		u8 stat = readb(&desc->stat);
L
Linus Torvalds 已提交
309

310
		if (!(stat & ST_TX_OWNRSHP))
311
			break; /* not yet transmitted */
312 313 314 315 316 317 318
		if (stat & ST_TX_UNDRRUN) {
			dev->stats.tx_errors++;
			dev->stats.tx_fifo_errors++;
		} else {
			dev->stats.tx_packets++;
			dev->stats.tx_bytes += readw(&desc->len);
		}
L
Linus Torvalds 已提交
319
		writeb(0, &desc->stat);	/* Free descriptor */
320
		port->txlast = (port->txlast + 1) % card->tx_ring_buffers;
L
Linus Torvalds 已提交
321 322 323 324 325 326 327
	}

	netif_wake_queue(dev);
	spin_unlock(&port->lock);
}


328 329 330
static int sca_poll(struct napi_struct *napi, int budget)
{
	port_t *port = container_of(napi, port_t, napi);
331
	u32 isr0 = sca_inl(ISR0, port->card);
332 333
	int received = 0;

K
Krzysztof Hałasa 已提交
334
	if (isr0 & (port->chan ? 0x08000000 : 0x00080000))
335 336
		sca_msci_intr(port);

K
Krzysztof Hałasa 已提交
337
	if (isr0 & (port->chan ? 0x00002000 : 0x00000020))
338 339
		sca_tx_done(port);

K
Krzysztof Hałasa 已提交
340
	if (isr0 & (port->chan ? 0x00000200 : 0x00000002))
341 342 343
		received = sca_rx_done(port, budget);

	if (received < budget) {
344
		napi_complete(napi);
345 346 347 348 349 350
		enable_intr(port);
	}

	return received;
}

351
static irqreturn_t sca_intr(int irq, void *dev_id)
L
Linus Torvalds 已提交
352 353
{
	card_t *card = dev_id;
354 355
	u32 isr0 = sca_inl(ISR0, card);
	int i, handled = 0;
L
Linus Torvalds 已提交
356

357 358
	for (i = 0; i < 2; i++) {
		port_t *port = get_port(card, i);
359
		if (port && (isr0 & (i ? 0x08002200 : 0x00080022))) {
360 361
			handled = 1;
			disable_intr(port);
362
			napi_schedule(&port->napi);
L
Linus Torvalds 已提交
363 364 365 366 367 368 369 370 371
		}
	}

	return IRQ_RETVAL(handled);
}


static void sca_set_port(port_t *port)
{
K
Krzysztof Hałasa 已提交
372
	card_t* card = port->card;
L
Linus Torvalds 已提交
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
	u16 msci = get_msci(port);
	u8 md2 = sca_in(msci + MD2, card);
	unsigned int tmc, br = 10, brv = 1024;


	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->settings.clock_rate;
		}while (br > 1 && tmc <= 128);

		if (tmc < 1) {
			tmc = 1;
			br = 0;	/* For baud=CLOCK_BASE we use tmc=1 br=0 */
			brv = 1;
		} else if (tmc > 255)
			tmc = 256; /* tmc=0 means 256 - low baud rates */

		port->settings.clock_rate = CLOCK_BASE / brv / tmc;
	} else {
		br = 9; /* Minimum clock rate */
		tmc = 256;	/* 8bit = 0 */
		port->settings.clock_rate = CLOCK_BASE / (256 * 512);
	}

	port->rxs = (port->rxs & ~CLK_BRG_MASK) | br;
	port->txs = (port->txs & ~CLK_BRG_MASK) | br;
	port->tmc = tmc;

	/* baud divisor - time constant*/
	sca_out(port->tmc, msci + TMCR, card);
	sca_out(port->tmc, msci + TMCT, card);

	/* 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_open(struct net_device *dev)
{
	port_t *port = dev_to_port(dev);
K
Krzysztof Hałasa 已提交
427
	card_t* card = port->card;
L
Linus Torvalds 已提交
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
	u16 msci = get_msci(port);
	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;
	case PARITY_CRC32_PR1_CCITT: md0 = MD0_HDLC | MD0_CRC_ITU32; break;
	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, 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 */
	/* Skip the rest of underrun frame */
	sca_out(CTL_IDLE | CTL_URCT | CTL_URSKP, msci + CTL, card);
	sca_out(0x0F, msci + RNR, card); /* +1=RX DMA activation 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*/

/* We're using the following interrupts:
464 465
   - RXINTA (DCD changes only)
   - DMIB (EOM - single frame transfer complete)
L
Linus Torvalds 已提交
466
*/
467
	sca_outl(IE0_RXINTA | IE0_CDCD, msci + IE0, card);
L
Linus Torvalds 已提交
468 469 470 471 472 473 474 475

	sca_out(port->tmc, msci + TMCR, card);
	sca_out(port->tmc, msci + TMCT, card);
	sca_out(port->rxs, msci + RXS, card);
	sca_out(port->txs, msci + TXS, card);
	sca_out(CMD_TX_ENABLE, msci + CMD, card);
	sca_out(CMD_RX_ENABLE, msci + CMD, card);

476 477 478
	sca_set_carrier(port);
	enable_intr(port);
	napi_enable(&port->napi);
L
Linus Torvalds 已提交
479 480 481 482 483 484 485 486 487
	netif_start_queue(dev);
}


static void sca_close(struct net_device *dev)
{
	port_t *port = dev_to_port(dev);

	/* reset channel */
K
Krzysztof Hałasa 已提交
488
	sca_out(CMD_RESET, get_msci(port) + CMD, port->card);
489 490
	disable_intr(port);
	napi_disable(&port->napi);
L
Linus Torvalds 已提交
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
	netif_stop_queue(dev);
}


static int sca_attach(struct net_device *dev, 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 &&
	    parity != PARITY_CRC32_PR1_CCITT &&
	    parity != PARITY_CRC16_PR1_CCITT)
		return -EINVAL;

	dev_to_port(dev)->encoding = encoding;
	dev_to_port(dev)->parity = parity;
	return 0;
}


#ifdef DEBUG_RINGS
static void sca_dump_rings(struct net_device *dev)
{
	port_t *port = dev_to_port(dev);
K
Krzysztof Hałasa 已提交
522
	card_t *card = port->card;
L
Linus Torvalds 已提交
523 524 525
	u16 cnt;

	printk(KERN_DEBUG "RX ring: CDA=%u EDA=%u DSR=%02X in=%u %sactive",
526 527
	       sca_inl(get_dmac_rx(port) + CDAL, card),
	       sca_inl(get_dmac_rx(port) + EDAL, card),
K
Krzysztof Hałasa 已提交
528 529 530
	       sca_in(DSR_RX(port->chan), card), port->rxin,
	       sca_in(DSR_RX(port->chan), card) & DSR_DE ? "" : "in");
	for (cnt = 0; cnt < port->card->rx_ring_buffers; cnt++)
L
Linus Torvalds 已提交
531
		printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
532
	printk(KERN_CONT "\n");
L
Linus Torvalds 已提交
533

534
	printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
L
Linus Torvalds 已提交
535
	       "last=%u %sactive",
536 537
	       sca_inl(get_dmac_tx(port) + CDAL, card),
	       sca_inl(get_dmac_tx(port) + EDAL, card),
K
Krzysztof Hałasa 已提交
538 539
	       sca_in(DSR_TX(port->chan), card), port->txin, port->txlast,
	       sca_in(DSR_TX(port->chan), card) & DSR_DE ? "" : "in");
L
Linus Torvalds 已提交
540

K
Krzysztof Hałasa 已提交
541
	for (cnt = 0; cnt < port->card->tx_ring_buffers; cnt++)
L
Linus Torvalds 已提交
542 543 544
		printk(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
	printk("\n");

545 546
	printk(KERN_DEBUG "MSCI: MD: %02x %02x %02x,"
	       " ST: %02x %02x %02x %02x %02x, FST: %02x CST: %02x %02x\n",
L
Linus Torvalds 已提交
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564
	       sca_in(get_msci(port) + MD0, card),
	       sca_in(get_msci(port) + MD1, card),
	       sca_in(get_msci(port) + MD2, card),
	       sca_in(get_msci(port) + ST0, card),
	       sca_in(get_msci(port) + ST1, card),
	       sca_in(get_msci(port) + ST2, card),
	       sca_in(get_msci(port) + ST3, card),
	       sca_in(get_msci(port) + ST4, card),
	       sca_in(get_msci(port) + FST, card),
	       sca_in(get_msci(port) + CST0, card),
	       sca_in(get_msci(port) + CST1, card));

	printk(KERN_DEBUG "ILAR: %02x ISR: %08x %08x\n", sca_in(ILAR, card),
	       sca_inl(ISR0, card), sca_inl(ISR1, card));
}
#endif /* DEBUG_RINGS */


565
static netdev_tx_t sca_xmit(struct sk_buff *skb, struct net_device *dev)
L
Linus Torvalds 已提交
566 567
{
	port_t *port = dev_to_port(dev);
K
Krzysztof Hałasa 已提交
568
	card_t *card = port->card;
L
Linus Torvalds 已提交
569 570 571 572 573 574
	pkt_desc __iomem *desc;
	u32 buff, len;

	spin_lock_irq(&port->lock);

	desc = desc_address(port, port->txin + 1, 1);
575
	BUG_ON(readb(&desc->stat)); /* previous xmit should stop queue */
L
Linus Torvalds 已提交
576 577 578 579 580 581 582 583 584

#ifdef DEBUG_PKT
	printk(KERN_DEBUG "%s TX(%i):", dev->name, skb->len);
	debug_frame(skb);
#endif

	desc = desc_address(port, port->txin, 1);
	buff = buffer_offset(port, port->txin, 1);
	len = skb->len;
K
Krzysztof Hałasa 已提交
585
	memcpy_toio(card->rambase + buff, skb->data, len);
L
Linus Torvalds 已提交
586 587 588 589 590

	writew(len, &desc->len);
	writeb(ST_TX_EOM, &desc->stat);
	dev->trans_start = jiffies;

591
	port->txin = (port->txin + 1) % card->tx_ring_buffers;
592
	sca_outl(desc_offset(port, port->txin, 1),
L
Linus Torvalds 已提交
593 594
		 get_dmac_tx(port) + EDAL, card);

K
Krzysztof Hałasa 已提交
595
	sca_out(DSR_DE, DSR_TX(port->chan), card); /* Enable TX DMA */
L
Linus Torvalds 已提交
596 597 598 599 600 601 602 603

	desc = desc_address(port, port->txin + 1, 1);
	if (readb(&desc->stat)) /* allow 1 packet gap */
		netif_stop_queue(dev);

	spin_unlock_irq(&port->lock);

	dev_kfree_skb(skb);
604
	return NETDEV_TX_OK;
L
Linus Torvalds 已提交
605 606 607
}


608 609
static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase,
				    u32 ramsize)
L
Linus Torvalds 已提交
610 611 612 613 614 615 616
{
	/* Round RAM size to 32 bits, fill from end to start */
	u32 i = ramsize &= ~3;

	do {
		i -= 4;
		writel(i ^ 0x12345678, rambase + i);
617
	} while (i > 0);
L
Linus Torvalds 已提交
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641

	for (i = 0; i < ramsize ; i += 4) {
		if (readl(rambase + i) != (i ^ 0x12345678))
			break;
	}

	return i;
}


static void __devinit sca_init(card_t *card, int wait_states)
{
	sca_out(wait_states, WCRL, card); /* Wait Control */
	sca_out(wait_states, WCRM, card);
	sca_out(wait_states, WCRH, card);

	sca_out(0, DMER, card);	/* DMA Master disable */
	sca_out(0x03, PCR, card); /* DMA priority */
	sca_out(0, DSR_RX(0), card); /* DMA disable - to halt state */
	sca_out(0, DSR_TX(0), card);
	sca_out(0, DSR_RX(1), card);
	sca_out(0, DSR_TX(1), card);
	sca_out(DMER_DME, DMER, card); /* DMA Master enable */
}