#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/capability.h>
#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/atmdev.h>
#include <linux/sonet.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/pgtable.h>
#include <asm/io.h>
#include <asm/string.h>
#include <asm/page.h>
#include <asm/irq.h>
#include <asm/dma.h>
#include <asm/byteorder.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>
#ifdef CONFIG_SBUS
#include <linux/of.h>
#include <linux/platform_device.h>
#include <asm/idprom.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
#endif
#if defined(CONFIG_ATM_FORE200E_USE_TASKLET)
#define FORE200E_USE_TASKLET
#endif
#if 0
#define FORE200E_BSQ_DEBUG
#endif
#if 1
#define FORE200E_52BYTE_AAL0_SDU
#endif
#include "fore200e.h"
#include "suni.h"
#define FORE200E_VERSION …
#define FORE200E …
#if 0
#define CONFIG_ATM_FORE200E_DEBUG …
#endif
#if defined(CONFIG_ATM_FORE200E_DEBUG) && (CONFIG_ATM_FORE200E_DEBUG > 0)
#define DPRINTK …
#else
#define DPRINTK(level, format, args...) …
#endif
#define FORE200E_ALIGN(addr, alignment) …
#define FORE200E_DMA_INDEX(dma_addr, type, index) …
#define FORE200E_INDEX(virt_addr, type, index) …
#define FORE200E_NEXT_ENTRY(index, modulo) …
#if 1
#define ASSERT(expr) …
#else
#define ASSERT …
#endif
static const struct atmdev_ops fore200e_ops;
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
static const int fore200e_rx_buf_nbr[ BUFFER_SCHEME_NBR ][ BUFFER_MAGN_NBR ] = …;
static const int fore200e_rx_buf_size[ BUFFER_SCHEME_NBR ][ BUFFER_MAGN_NBR ] = …;
#if defined(CONFIG_ATM_FORE200E_DEBUG) && (CONFIG_ATM_FORE200E_DEBUG > 0)
static const char* fore200e_traffic_class[] = { "NONE", "UBR", "CBR", "VBR", "ABR", "ANY" };
#endif
#if 0
static int
fore200e_fore2atm_aal(enum fore200e_aal aal)
{
switch(aal) {
case FORE200E_AAL0: return ATM_AAL0;
case FORE200E_AAL34: return ATM_AAL34;
case FORE200E_AAL5: return ATM_AAL5;
}
return -EINVAL;
}
#endif
static enum fore200e_aal
fore200e_atm2fore_aal(int aal)
{ … }
static char*
fore200e_irq_itoa(int irq)
{ … }
static int
fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, int alignment, int direction)
{ … }
static void
fore200e_chunk_free(struct fore200e* fore200e, struct chunk* chunk)
{ … }
static int
fore200e_dma_chunk_alloc(struct fore200e *fore200e, struct chunk *chunk,
int size, int nbr, int alignment)
{ … }
static void
fore200e_dma_chunk_free(struct fore200e* fore200e, struct chunk* chunk)
{ … }
static void
fore200e_spin(int msecs)
{ … }
static int
fore200e_poll(struct fore200e* fore200e, volatile u32* addr, u32 val, int msecs)
{ … }
static int
fore200e_io_poll(struct fore200e* fore200e, volatile u32 __iomem *addr, u32 val, int msecs)
{ … }
static void
fore200e_free_rx_buf(struct fore200e* fore200e)
{ … }
static void
fore200e_uninit_bs_queue(struct fore200e* fore200e)
{ … }
static int
fore200e_reset(struct fore200e* fore200e, int diag)
{ … }
static void
fore200e_shutdown(struct fore200e* fore200e)
{ … }
#ifdef CONFIG_PCI
static u32 fore200e_pca_read(volatile u32 __iomem *addr)
{ … }
static void fore200e_pca_write(u32 val, volatile u32 __iomem *addr)
{ … }
static int
fore200e_pca_irq_check(struct fore200e* fore200e)
{ … }
static void
fore200e_pca_irq_ack(struct fore200e* fore200e)
{ … }
static void
fore200e_pca_reset(struct fore200e* fore200e)
{ … }
static int fore200e_pca_map(struct fore200e* fore200e)
{ … }
static void
fore200e_pca_unmap(struct fore200e* fore200e)
{ … }
static int fore200e_pca_configure(struct fore200e *fore200e)
{ … }
static int __init
fore200e_pca_prom_read(struct fore200e* fore200e, struct prom_data* prom)
{ … }
static int
fore200e_pca_proc_read(struct fore200e* fore200e, char *page)
{ … }
static const struct fore200e_bus fore200e_pci_ops = …;
#endif
#ifdef CONFIG_SBUS
static u32 fore200e_sba_read(volatile u32 __iomem *addr)
{
return sbus_readl(addr);
}
static void fore200e_sba_write(u32 val, volatile u32 __iomem *addr)
{
sbus_writel(val, addr);
}
static void fore200e_sba_irq_enable(struct fore200e *fore200e)
{
u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY;
fore200e->bus->write(hcr | SBA200E_HCR_INTR_ENA, fore200e->regs.sba.hcr);
}
static int fore200e_sba_irq_check(struct fore200e *fore200e)
{
return fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_INTR_REQ;
}
static void fore200e_sba_irq_ack(struct fore200e *fore200e)
{
u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY;
fore200e->bus->write(hcr | SBA200E_HCR_INTR_CLR, fore200e->regs.sba.hcr);
}
static void fore200e_sba_reset(struct fore200e *fore200e)
{
fore200e->bus->write(SBA200E_HCR_RESET, fore200e->regs.sba.hcr);
fore200e_spin(10);
fore200e->bus->write(0, fore200e->regs.sba.hcr);
}
static int __init fore200e_sba_map(struct fore200e *fore200e)
{
struct platform_device *op = to_platform_device(fore200e->dev);
unsigned int bursts;
fore200e->regs.sba.hcr = of_ioremap(&op->resource[0], 0, SBA200E_HCR_LENGTH, "SBA HCR");
fore200e->regs.sba.bsr = of_ioremap(&op->resource[1], 0, SBA200E_BSR_LENGTH, "SBA BSR");
fore200e->regs.sba.isr = of_ioremap(&op->resource[2], 0, SBA200E_ISR_LENGTH, "SBA ISR");
fore200e->virt_base = of_ioremap(&op->resource[3], 0, SBA200E_RAM_LENGTH, "SBA RAM");
if (!fore200e->virt_base) {
printk(FORE200E "unable to map RAM of device %s\n", fore200e->name);
return -EFAULT;
}
DPRINTK(1, "device %s mapped to 0x%p\n", fore200e->name, fore200e->virt_base);
fore200e->bus->write(0x02, fore200e->regs.sba.isr);
bursts = of_getintprop_default(op->dev.of_node->parent, "burst-sizes", 0x00);
if (sbus_can_dma_64bit())
sbus_set_sbus64(&op->dev, bursts);
fore200e->state = FORE200E_STATE_MAP;
return 0;
}
static void fore200e_sba_unmap(struct fore200e *fore200e)
{
struct platform_device *op = to_platform_device(fore200e->dev);
of_iounmap(&op->resource[0], fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH);
of_iounmap(&op->resource[1], fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH);
of_iounmap(&op->resource[2], fore200e->regs.sba.isr, SBA200E_ISR_LENGTH);
of_iounmap(&op->resource[3], fore200e->virt_base, SBA200E_RAM_LENGTH);
}
static int __init fore200e_sba_configure(struct fore200e *fore200e)
{
fore200e->state = FORE200E_STATE_CONFIGURE;
return 0;
}
static int __init fore200e_sba_prom_read(struct fore200e *fore200e, struct prom_data *prom)
{
struct platform_device *op = to_platform_device(fore200e->dev);
const u8 *prop;
int len;
prop = of_get_property(op->dev.of_node, "madaddrlo2", &len);
if (!prop)
return -ENODEV;
memcpy(&prom->mac_addr[4], prop, 4);
prop = of_get_property(op->dev.of_node, "madaddrhi4", &len);
if (!prop)
return -ENODEV;
memcpy(&prom->mac_addr[2], prop, 4);
prom->serial_number = of_getintprop_default(op->dev.of_node,
"serialnumber", 0);
prom->hw_revision = of_getintprop_default(op->dev.of_node,
"promversion", 0);
return 0;
}
static int fore200e_sba_proc_read(struct fore200e *fore200e, char *page)
{
struct platform_device *op = to_platform_device(fore200e->dev);
const struct linux_prom_registers *regs;
regs = of_get_property(op->dev.of_node, "reg", NULL);
return sprintf(page, " SBUS slot/device:\t\t%d/'%pOFn'\n",
(regs ? regs->which_io : 0), op->dev.of_node);
}
static const struct fore200e_bus fore200e_sbus_ops = {
.model_name = "SBA-200E",
.proc_name = "sba200e",
.descr_alignment = 32,
.buffer_alignment = 64,
.status_alignment = 32,
.read = fore200e_sba_read,
.write = fore200e_sba_write,
.configure = fore200e_sba_configure,
.map = fore200e_sba_map,
.reset = fore200e_sba_reset,
.prom_read = fore200e_sba_prom_read,
.unmap = fore200e_sba_unmap,
.irq_enable = fore200e_sba_irq_enable,
.irq_check = fore200e_sba_irq_check,
.irq_ack = fore200e_sba_irq_ack,
.proc_read = fore200e_sba_proc_read,
};
#endif
static void
fore200e_tx_irq(struct fore200e* fore200e)
{ … }
#ifdef FORE200E_BSQ_DEBUG
int bsq_audit(int where, struct host_bsq* bsq, int scheme, int magn)
{
struct buffer* buffer;
int count = 0;
buffer = bsq->freebuf;
while (buffer) {
if (buffer->supplied) {
printk(FORE200E "bsq_audit(%d): queue %d.%d, buffer %ld supplied but in free list!\n",
where, scheme, magn, buffer->index);
}
if (buffer->magn != magn) {
printk(FORE200E "bsq_audit(%d): queue %d.%d, buffer %ld, unexpected magn = %d\n",
where, scheme, magn, buffer->index, buffer->magn);
}
if (buffer->scheme != scheme) {
printk(FORE200E "bsq_audit(%d): queue %d.%d, buffer %ld, unexpected scheme = %d\n",
where, scheme, magn, buffer->index, buffer->scheme);
}
if ((buffer->index < 0) || (buffer->index >= fore200e_rx_buf_nbr[ scheme ][ magn ])) {
printk(FORE200E "bsq_audit(%d): queue %d.%d, out of range buffer index = %ld !\n",
where, scheme, magn, buffer->index);
}
count++;
buffer = buffer->next;
}
if (count != bsq->freebuf_count) {
printk(FORE200E "bsq_audit(%d): queue %d.%d, %d bufs in free list, but freebuf_count = %d\n",
where, scheme, magn, count, bsq->freebuf_count);
}
return 0;
}
#endif
static void
fore200e_supply(struct fore200e* fore200e)
{ … }
static int
fore200e_push_rpd(struct fore200e* fore200e, struct atm_vcc* vcc, struct rpd* rpd)
{ … }
static void
fore200e_collect_rpd(struct fore200e* fore200e, struct rpd* rpd)
{ … }
static void
fore200e_rx_irq(struct fore200e* fore200e)
{ … }
#ifndef FORE200E_USE_TASKLET
static void
fore200e_irq(struct fore200e* fore200e)
{
unsigned long flags;
spin_lock_irqsave(&fore200e->q_lock, flags);
fore200e_rx_irq(fore200e);
spin_unlock_irqrestore(&fore200e->q_lock, flags);
spin_lock_irqsave(&fore200e->q_lock, flags);
fore200e_tx_irq(fore200e);
spin_unlock_irqrestore(&fore200e->q_lock, flags);
}
#endif
static irqreturn_t
fore200e_interrupt(int irq, void* dev)
{ … }
#ifdef FORE200E_USE_TASKLET
static void
fore200e_tx_tasklet(unsigned long data)
{ … }
static void
fore200e_rx_tasklet(unsigned long data)
{ … }
#endif
static int
fore200e_select_scheme(struct atm_vcc* vcc)
{ … }
static int
fore200e_activate_vcin(struct fore200e* fore200e, int activate, struct atm_vcc* vcc, int mtu)
{ … }
#define FORE200E_MAX_BACK2BACK_CELLS …
static void
fore200e_rate_ctrl(struct atm_qos* qos, struct tpd_rate* rate)
{ … }
static int
fore200e_open(struct atm_vcc *vcc)
{ … }
static void
fore200e_close(struct atm_vcc* vcc)
{ … }
static int
fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
{ … }
static int
fore200e_getstats(struct fore200e* fore200e)
{ … }
#if 0
static int
fore200e_get_oc3(struct fore200e* fore200e, struct oc3_regs* regs)
{
struct host_cmdq* cmdq = &fore200e->host_cmdq;
struct host_cmdq_entry* entry = &cmdq->host_entry[ cmdq->head ];
struct oc3_opcode opcode;
int ok;
u32 oc3_regs_dma_addr;
oc3_regs_dma_addr = fore200e->bus->dma_map(fore200e, regs, sizeof(struct oc3_regs), DMA_FROM_DEVICE);
FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);
opcode.opcode = OPCODE_GET_OC3;
opcode.reg = 0;
opcode.value = 0;
opcode.mask = 0;
fore200e->bus->write(oc3_regs_dma_addr, &entry->cp_entry->cmd.oc3_block.regs_haddr);
*entry->status = STATUS_PENDING;
fore200e->bus->write(*(u32*)&opcode, (u32*)&entry->cp_entry->cmd.oc3_block.opcode);
ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400);
*entry->status = STATUS_FREE;
fore200e->bus->dma_unmap(fore200e, oc3_regs_dma_addr, sizeof(struct oc3_regs), DMA_FROM_DEVICE);
if (ok == 0) {
printk(FORE200E "unable to get OC-3 regs of device %s\n", fore200e->name);
return -EIO;
}
return 0;
}
#endif
static int
fore200e_set_oc3(struct fore200e* fore200e, u32 reg, u32 value, u32 mask)
{ … }
static int
fore200e_setloop(struct fore200e* fore200e, int loop_mode)
{ … }
static int
fore200e_fetch_stats(struct fore200e* fore200e, struct sonet_stats __user *arg)
{ … }
static int
fore200e_ioctl(struct atm_dev* dev, unsigned int cmd, void __user * arg)
{ … }
static int
fore200e_change_qos(struct atm_vcc* vcc,struct atm_qos* qos, int flags)
{ … }
static int fore200e_irq_request(struct fore200e *fore200e)
{ … }
static int fore200e_get_esi(struct fore200e *fore200e)
{ … }
static int fore200e_alloc_rx_buf(struct fore200e *fore200e)
{ … }
static int fore200e_init_bs_queue(struct fore200e *fore200e)
{ … }
static int fore200e_init_rx_queue(struct fore200e *fore200e)
{ … }
static int fore200e_init_tx_queue(struct fore200e *fore200e)
{ … }
static int fore200e_init_cmd_queue(struct fore200e *fore200e)
{ … }
static void fore200e_param_bs_queue(struct fore200e *fore200e,
enum buffer_scheme scheme,
enum buffer_magn magn, int queue_length,
int pool_size, int supply_blksize)
{ … }
static int fore200e_initialize(struct fore200e *fore200e)
{ … }
static void fore200e_monitor_putc(struct fore200e *fore200e, char c)
{ … }
static int fore200e_monitor_getc(struct fore200e *fore200e)
{ … }
static void fore200e_monitor_puts(struct fore200e *fore200e, char *str)
{ … }
#ifdef __LITTLE_ENDIAN
#define FW_EXT …
#else
#define FW_EXT …
#endif
static int fore200e_load_and_start_fw(struct fore200e *fore200e)
{ … }
static int fore200e_register(struct fore200e *fore200e, struct device *parent)
{ … }
static int fore200e_init(struct fore200e *fore200e, struct device *parent)
{ … }
#ifdef CONFIG_SBUS
static int fore200e_sba_probe(struct platform_device *op)
{
struct fore200e *fore200e;
static int index = 0;
int err;
fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL);
if (!fore200e)
return -ENOMEM;
fore200e->bus = &fore200e_sbus_ops;
fore200e->dev = &op->dev;
fore200e->irq = op->archdata.irqs[0];
fore200e->phys_base = op->resource[0].start;
sprintf(fore200e->name, "SBA-200E-%d", index);
err = fore200e_init(fore200e, &op->dev);
if (err < 0) {
fore200e_shutdown(fore200e);
kfree(fore200e);
return err;
}
index++;
dev_set_drvdata(&op->dev, fore200e);
return 0;
}
static void fore200e_sba_remove(struct platform_device *op)
{
struct fore200e *fore200e = dev_get_drvdata(&op->dev);
fore200e_shutdown(fore200e);
kfree(fore200e);
}
static const struct of_device_id fore200e_sba_match[] = {
{
.name = SBA200E_PROM_NAME,
},
{},
};
MODULE_DEVICE_TABLE(of, fore200e_sba_match);
static struct platform_driver fore200e_sba_driver = {
.driver = {
.name = "fore_200e",
.of_match_table = fore200e_sba_match,
},
.probe = fore200e_sba_probe,
.remove_new = fore200e_sba_remove,
};
#endif
#ifdef CONFIG_PCI
static int fore200e_pca_detect(struct pci_dev *pci_dev,
const struct pci_device_id *pci_ent)
{ … }
static void fore200e_pca_remove_one(struct pci_dev *pci_dev)
{ … }
static const struct pci_device_id fore200e_pca_tbl[] = …;
MODULE_DEVICE_TABLE(pci, fore200e_pca_tbl);
static struct pci_driver fore200e_pca_driver = …;
#endif
static int __init fore200e_module_init(void)
{ … }
static void __exit fore200e_module_cleanup(void)
{ … }
static int
fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
{ … }
module_init(…) …;
module_exit(fore200e_module_cleanup);
static const struct atmdev_ops fore200e_ops = …;
MODULE_LICENSE(…) …;
#ifdef CONFIG_PCI
#ifdef __LITTLE_ENDIAN__
MODULE_FIRMWARE(…) …;
#else
MODULE_FIRMWARE("pca200e_ecd.bin2");
#endif
#endif
#ifdef CONFIG_SBUS
MODULE_FIRMWARE("sba200e_ecd.bin2");
#endif