⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fore200e.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  $Id: fore200e.c,v 1.5 2000/04/14 10:10:34 davem Exp $  A FORE Systems 200E-series driver for ATM on Linux.  Christophe Lizzi (lizzi@cnam.fr), October 1999-March 2000.  Based on the PCA-200E driver from Uwe Dannowski (Uwe.Dannowski@inf.tu-dresden.de).  This driver simultaneously supports PCA-200E and SBA-200E adapters  on i386, alpha (untested), powerpc, sparc and sparc64 architectures.  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.  This program is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License for more details.  You should have received a copy of the GNU General Public License  along with this program; if not, write to the Free Software  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/#include <linux/version.h>#include <linux/config.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/capability.h>#include <linux/sched.h>#include <linux/interrupt.h>#include <linux/bitops.h>#include <linux/atmdev.h>#include <linux/sonet.h>#include <linux/atm_suni.h>#include <asm/io.h>#include <asm/string.h>#include <asm/segment.h>#include <asm/page.h>#include <asm/irq.h>#include <asm/dma.h>#include <asm/byteorder.h>#include <asm/uaccess.h>#include <asm/atomic.h>#include <linux/pci.h>#ifdef CONFIG_ATM_FORE200E_SBA#include <asm/idprom.h>#include <asm/sbus.h>#include <asm/openprom.h>#include <asm/oplib.h>#include <asm/pgtable.h>#endif#include <linux/module.h>#include "fore200e.h"#include "suni.h"#if 1   /* ensure correct handling of 52-byte AAL0 SDUs used by atmdump-like apps */#define FORE200E_52BYTE_AAL0_SDU#endif#define FORE200E_VERSION "0.2d"#define FORE200E         "fore200e: "#if defined(CONFIG_ATM_FORE200E_DEBUG) && (CONFIG_ATM_FORE200E_DEBUG > 0)#define DPRINTK(level, format, args...)  do { if (CONFIG_ATM_FORE200E_DEBUG >= (level)) \                                                  printk(FORE200E format, ##args); } while(0)#else#define DPRINTK(level, format, args...)  while(0)#endif#define FORE200E_ALIGN(addr, alignment) \        ((((unsigned long)(addr) + (alignment - 1)) & ~(alignment - 1)) - (unsigned long)(addr))#define FORE200E_DMA_INDEX(dma_addr, type, index)  ((dma_addr) + (index) * sizeof(type))#define FORE200E_INDEX(virt_addr, type, index)     (&((type *)(virt_addr))[ index ])#define FORE200E_NEXT_ENTRY(index, modulo)    (index = ++(index) % (modulo))#define MSECS(ms)  (((ms)*HZ/1000)+1)extern const struct atmdev_ops   fore200e_ops;extern const struct fore200e_bus fore200e_bus[];static struct fore200e* fore200e_boards = NULL;#ifdef MODULEMODULE_AUTHOR("Christophe Lizzi - credits to Uwe Dannowski and Heikki Vatiainen");MODULE_DESCRIPTION("FORE Systems 200E-series ATM driver - version " FORE200E_VERSION);MODULE_SUPPORTED_DEVICE("PCA-200E, SBA-200E");#endifstatic const int fore200e_rx_buf_nbr[ BUFFER_SCHEME_NBR ][ BUFFER_MAGN_NBR ] = {    { BUFFER_S1_NBR, BUFFER_L1_NBR },    { BUFFER_S2_NBR, BUFFER_L2_NBR }};static const int fore200e_rx_buf_size[ BUFFER_SCHEME_NBR ][ BUFFER_MAGN_NBR ] = {    { BUFFER_S1_SIZE, BUFFER_L1_SIZE },    { BUFFER_S2_SIZE, BUFFER_L2_SIZE }};#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 /* currently unused */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;}#endifstatic enum fore200e_aalfore200e_atm2fore_aal(int aal){    switch(aal) {    case ATM_AAL0:  return FORE200E_AAL0;    case ATM_AAL34: return FORE200E_AAL34;    case ATM_AAL1:    case ATM_AAL2:    case ATM_AAL5:  return FORE200E_AAL5;    }    return -EINVAL;}static char*fore200e_irq_itoa(int irq){#if defined(__sparc_v9__)    return __irq_itoa(irq);#else    static char str[8];    sprintf(str, "%d", irq);    return str;#endif}static void*fore200e_kmalloc(int size, int flags){    void* chunk = kmalloc(size, flags);    if (chunk)	memset(chunk, 0x00, size);    else	printk(FORE200E "kmalloc() failed, requested size = %d, flags = 0x%x\n", size, flags);        return chunk;}static voidfore200e_kfree(void* chunk){    kfree(chunk);}/* allocate and align a chunk of memory intended to hold the data behing exchanged   between the driver and the adapter (using streaming DVMA) */static intfore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, int alignment, int direction){    unsigned long offset = 0;    if (alignment <= sizeof(int))	alignment = 0;    chunk->alloc_size = size + alignment;    chunk->align_size = size;    chunk->direction  = direction;    chunk->alloc_addr = fore200e_kmalloc(chunk->alloc_size, GFP_KERNEL | GFP_DMA);    if (chunk->alloc_addr == NULL)	return -ENOMEM;    if (alignment > 0)	offset = FORE200E_ALIGN(chunk->alloc_addr, alignment);         chunk->align_addr = chunk->alloc_addr + offset;    chunk->dma_addr = fore200e->bus->dma_map(fore200e, chunk->align_addr, chunk->align_size, direction);        return 0;}/* free a chunk of memory */static voidfore200e_chunk_free(struct fore200e* fore200e, struct chunk* chunk){    fore200e->bus->dma_unmap(fore200e, chunk->dma_addr, chunk->dma_size, chunk->direction);    fore200e_kfree(chunk->alloc_addr);}#if 0 /* currently unused */static intfore200e_checkup(struct fore200e* fore200e){    u32 hb1, hb2;    hb1 = fore200e->bus->read(&fore200e->cp_queues->heartbeat);    fore200e_spin(10);    hb2 = fore200e->bus->read(&fore200e->cp_queues->heartbeat);        if (hb2 <= hb1) {	printk(FORE200E "device %s heartbeat is not counting upwards, hb1 = %x; hb2 = %x\n",	       fore200e->name, hb1, hb2);	return -EIO;    }    printk(FORE200E "device %s heartbeat is ok\n", fore200e->name);        return 0;}#endif static voidfore200e_spin(int msecs){    unsigned long timeout = jiffies + MSECS(msecs);    while (jiffies < timeout);}static intfore200e_poll(struct fore200e* fore200e, volatile u32* addr, u32 val, int msecs){    unsigned long timeout = jiffies + MSECS(msecs);    int           ok;    mb();    do {	if ((ok = (*addr == val)) || (*addr & STATUS_ERROR))	    break;    } while (jiffies < timeout);#if 1    if (!ok) {	printk(FORE200E "cmd polling failed, got status 0x%08x, expected 0x%08x\n",	       *addr, val);    }#endif    return ok;}static intfore200e_io_poll(struct fore200e* fore200e, volatile u32* addr, u32 val, int msecs){    unsigned long timeout = jiffies + MSECS(msecs);    int           ok;    do {	if ((ok = (fore200e->bus->read(addr) == val)))	    break;    } while (jiffies < timeout);#if 1    if (!ok) {	printk(FORE200E "I/O polling failed, got status 0x%08x, expected 0x%08x\n",	       fore200e->bus->read(addr), val);    }#endif    return ok;}static voidfore200e_free_rx_buf(struct fore200e* fore200e){    int scheme, magn, nbr;    struct buffer* buffer;    for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++) {	for (magn = 0; magn < BUFFER_MAGN_NBR; magn++) {	    if ((buffer = fore200e->host_bsq[ scheme ][ magn ].buffer) != NULL) {		for (nbr = 0; nbr < fore200e_rx_buf_nbr[ scheme ][ magn ]; nbr++) {		    struct chunk* data = &buffer[ nbr ].data;		    if (data->alloc_addr != NULL)			fore200e_chunk_free(fore200e, data);		}	    }	}    }}static voidfore200e_uninit_bs_queue(struct fore200e* fore200e){    int scheme, magn;        for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++) {	for (magn = 0; magn < BUFFER_MAGN_NBR; magn++) {	    struct chunk* status    = &fore200e->host_bsq[ scheme ][ magn ].status;	    struct chunk* rbd_block = &fore200e->host_bsq[ scheme ][ magn ].rbd_block;	    	    if (status->alloc_addr)		fore200e->bus->dma_chunk_free(fore200e, status);	    	    if (rbd_block->alloc_addr)		fore200e->bus->dma_chunk_free(fore200e, rbd_block);	}    }}static intfore200e_reset(struct fore200e* fore200e, int diag){    int ok;    fore200e->cp_monitor = (struct cp_monitor*)(fore200e->virt_base + FORE200E_CP_MONITOR_OFFSET);        fore200e->bus->write(BSTAT_COLD_START, &fore200e->cp_monitor->bstat);    fore200e->bus->reset(fore200e);    if (diag) {	ok = fore200e_io_poll(fore200e, &fore200e->cp_monitor->bstat, BSTAT_SELFTEST_OK, 1000);	if (ok == 0) {	    	    printk(FORE200E "device %s self-test failed\n", fore200e->name);	    return -ENODEV;	}	printk(FORE200E "device %s self-test passed\n", fore200e->name);		fore200e->state = FORE200E_STATE_RESET;    }    return 0;}static voidfore200e_shutdown(struct fore200e* fore200e){    printk(FORE200E "removing device %s at 0x%lx, IRQ %s\n",	   fore200e->name, fore200e->phys_base, 	   fore200e_irq_itoa(fore200e->irq));        if (fore200e->state > FORE200E_STATE_RESET) {	/* first, reset the board to prevent further interrupts or data transfers */	fore200e_reset(fore200e, 0);    }        /* then, release all allocated resources */    switch(fore200e->state) {    case FORE200E_STATE_COMPLETE:	if (fore200e->stats)	    kfree(fore200e->stats);    case FORE200E_STATE_IRQ:	free_irq(fore200e->irq, fore200e->atm_dev);    case FORE200E_STATE_ALLOC_BUF:	fore200e_free_rx_buf(fore200e);    case FORE200E_STATE_INIT_BSQ:	fore200e_uninit_bs_queue(fore200e);    case FORE200E_STATE_INIT_RXQ:	fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_rxq.status);	fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_rxq.rpd);    case FORE200E_STATE_INIT_TXQ:	fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_txq.status);	fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_txq.tpd);    case FORE200E_STATE_INIT_CMDQ:	fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_cmdq.status);    case FORE200E_STATE_INITIALIZE:	/* nothing to do for that state */    case FORE200E_STATE_START_FW:	/* nothing to do for that state */    case FORE200E_STATE_LOAD_FW:	/* nothing to do for that state */    case FORE200E_STATE_RESET:	/* nothing to do for that state */    case FORE200E_STATE_MAP:	fore200e->bus->unmap(fore200e);    case FORE200E_STATE_CONFIGURE:	/* nothing to do for that state */    case FORE200E_STATE_REGISTER:	/* XXX shouldn't we *start* by deregistering the device? */	atm_dev_deregister(fore200e->atm_dev);    case FORE200E_STATE_BLANK:	/* nothing to do for that state */	break;    }}#ifdef CONFIG_ATM_FORE200E_PCAstatic u32 fore200e_pca_read(volatile u32* addr){    /* on big-endian hosts, the board is configured to convert       the endianess of slave RAM accesses  */    return le32_to_cpu(readl(addr));}static void fore200e_pca_write(u32 val, volatile u32* addr){    /* on big-endian hosts, the board is configured to convert       the endianess of slave RAM accesses  */    writel(cpu_to_le32(val), addr);}static u32fore200e_pca_dma_map(struct fore200e* fore200e, void* virt_addr, int size, int direction){    u32 dma_addr = pci_map_single((struct pci_dev*)fore200e->bus_dev, virt_addr, size, direction);    DPRINTK(3, "PCI DVMA mapping: virt_addr = 0x%p, size = %d, direction = %d,  --> dma_addr = 0x%08x\n",	    virt_addr, size, direction, dma_addr);        return dma_addr;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -