/*
 * SBE 2T3E3 synchronous serial card driver for Linux
 *
 * Copyright (C) 2009-2010 Krzysztof Halasa <khc@pm.waw.pl>
 *
 * 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.
 *
 * This code is based on a driver written by SBE Inc.
 */

#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include "2t3e3.h"

void t3e3_init(struct channel *sc)
{
	cpld_init(sc);
	dc_reset(sc);
	dc_init(sc);
	exar7250_init(sc);
	exar7300_init(sc);
}

int t3e3_if_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct channel *sc = dev_to_priv(dev);
	u32 current_write, last_write;
	unsigned long flags;
	struct sk_buff *skb2;

	if (skb == NULL) {
		sc->s.out_errors++;
		return 0;
	}

	if (sc->p.transmitter_on != SBE_2T3E3_ON) {
		sc->s.out_errors++;
		sc->s.out_dropped++;
		dev_kfree_skb_any(skb);
		return 0;
	}

	if (sc->s.OOF && sc->p.loopback == SBE_2T3E3_LOOPBACK_NONE) {
		sc->s.out_dropped++;
		dev_kfree_skb_any(skb);
		return 0;
	}

	spin_lock_irqsave(&sc->ether.tx_lock, flags);

	current_write = sc->ether.tx_ring_current_write;
	for (skb2 = skb; skb2 != NULL; skb2 = NULL) {
		if (skb2->len) {
			if ((sc->ether.tx_ring[current_write].tdes1 &
			     SBE_2T3E3_TX_DESC_BUFFER_1_SIZE) > 0)
				break;
			current_write = (current_write + 1) % SBE_2T3E3_TX_DESC_RING_SIZE;
			/*
			 * Leave at least 1 tx desc free so that dc_intr_tx() can
			 * identify empty list
			 */
			if (current_write == sc->ether.tx_ring_current_read)
				break;
		}
	}
	if (skb2 != NULL) {
		netif_stop_queue(sc->dev);
		sc->ether.tx_full = 1;
		dev_dbg(&sc->pdev->dev, "SBE 2T3E3: out of descriptors\n");
		spin_unlock_irqrestore(&sc->ether.tx_lock, flags);
		return NETDEV_TX_BUSY;
	}

	current_write = last_write = sc->ether.tx_ring_current_write;
	dev_dbg(&sc->pdev->dev, "sending mbuf (current_write = %d)\n",
		current_write);

	for (skb2 = skb; skb2 != NULL; skb2 = NULL) {
		if (skb2->len) {
			dev_dbg(&sc->pdev->dev,
				"sending mbuf (len = %d, next = %p)\n",
				skb2->len, NULL);

			sc->ether.tx_free_cnt--;
			sc->ether.tx_ring[current_write].tdes0 = 0;
			sc->ether.tx_ring[current_write].tdes1 &=
				SBE_2T3E3_TX_DESC_END_OF_RING |
				SBE_2T3E3_TX_DESC_SECOND_ADDRESS_CHAINED;
/* DISABLE_PADDING sometimes gets lost somehow, hands off... */
			sc->ether.tx_ring[current_write].tdes1 |=
				SBE_2T3E3_TX_DESC_DISABLE_PADDING | skb2->len;

			if (current_write == sc->ether.tx_ring_current_write) {
				sc->ether.tx_ring[current_write].tdes1 |=
					SBE_2T3E3_TX_DESC_FIRST_SEGMENT;
			} else {
				sc->ether.tx_ring[current_write].tdes0 =
					SBE_2T3E3_TX_DESC_21143_OWN;
			}

			sc->ether.tx_ring[current_write].tdes2 = virt_to_phys(skb2->data);
			sc->ether.tx_data[current_write] = NULL;

			last_write = current_write;
			current_write = (current_write + 1) % SBE_2T3E3_TX_DESC_RING_SIZE;
		}
	}

	sc->ether.tx_data[last_write] = skb;
	sc->ether.tx_ring[last_write].tdes1 |=
		SBE_2T3E3_TX_DESC_LAST_SEGMENT |
		SBE_2T3E3_TX_DESC_INTERRUPT_ON_COMPLETION;
	sc->ether.tx_ring[sc->ether.tx_ring_current_write].tdes0 |=
		SBE_2T3E3_TX_DESC_21143_OWN;
	sc->ether.tx_ring_current_write = current_write;

	dev_dbg(&sc->pdev->dev, "txput: tdes0 = %08X        tdes1 = %08X\n",
		sc->ether.tx_ring[last_write].tdes0,
		sc->ether.tx_ring[last_write].tdes1);

	dc_write(sc->addr, SBE_2T3E3_21143_REG_TRANSMIT_POLL_DEMAND,
		 0xffffffff);

	spin_unlock_irqrestore(&sc->ether.tx_lock, flags);
	return 0;
}


void t3e3_read_card_serial_number(struct channel *sc)
{
	u32 i;

	for (i = 0; i < 3; i++)
		sc->ether.card_serial_number[i] = t3e3_eeprom_read_word(sc, 10 + i);

	printk(KERN_INFO "SBE wanPMC-2T3E3 serial number: %04X%04X%04X\n",
	       sc->ether.card_serial_number[0], sc->ether.card_serial_number[1],
	       sc->ether.card_serial_number[2]);
}

/*
  bit 0 led1 (green)
  bit 1 led1 (yellow)

  bit 2 led2 (green)
  bit 3 led2 (yellow)

  bit 4 led3 (green)
  bit 5 led3 (yellow)

  bit 6 led4 (green)
  bit 7 led4 (yellow)
*/

void update_led(struct channel *sc, int blinker)
{
	int leds;
	if (sc->s.LOS)
		leds = 0; /* led1 = off */
	else if (sc->s.OOF)
		leds = 2; /* led1 = yellow */
	else if ((blinker & 1) && sc->rcv_count) {
		leds = 0; /* led1 = off */
		sc->rcv_count = 0;
	} else
		leds = 1; /* led1 = green */
	cpld_write(sc, SBE_2T3E3_CPLD_REG_LEDR, leds);
	sc->leds = leds;
}
