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

📄 fore200e.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
static voidfore200e_pca_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size, int direction){    DPRINTK(3, "PCI DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d\n",	    dma_addr, size, direction);    pci_unmap_single((struct pci_dev*)fore200e->bus_dev, dma_addr, size, direction);}static voidfore200e_pca_dma_sync(struct fore200e* fore200e, u32 dma_addr, int size, int direction){    DPRINTK(3, "PCI DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction);    pci_dma_sync_single((struct pci_dev*)fore200e->bus_dev, dma_addr, size, direction);}/* allocate a DMA consistent chunk of memory intended to act as a communication mechanism   (to hold descriptors, status, queues, etc.) shared by the driver and the adapter */static intfore200e_pca_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk,			     int size, int nbr, int alignment){#if defined(__sparc_v9__)    /* returned chunks are page-aligned */    chunk->alloc_addr = pci_alloc_consistent((struct pci_dev*)fore200e->bus_dev,					     chunk->alloc_size,					     &chunk->dma_addr);        if (chunk->alloc_addr == NULL || chunk->dma_addr == 0)	return -ENOMEM;    chunk->align_addr = chunk->alloc_addr;#else    if (fore200e_chunk_alloc(fore200e, chunk, size * nbr, alignment, FORE200E_DMA_BIDIRECTIONAL) < 0)	return -ENOMEM;#endif        return 0;}/* free a DMA consistent chunk of memory */static voidfore200e_pca_dma_chunk_free(struct fore200e* fore200e, struct chunk* chunk){#if defined(__sparc_v9__)    pci_free_consistent((struct pci_dev*)fore200e->bus_dev,			chunk->alloc_size,			chunk->alloc_addr,			chunk->dma_addr);#else    fore200e_chunk_free(fore200e, chunk);#endif}static intfore200e_pca_irq_check(struct fore200e* fore200e){    /* this is a 1 bit register */    return readl(fore200e->regs.pca.psr);}static voidfore200e_pca_irq_ack(struct fore200e* fore200e){    writel(PCA200E_HCR_CLRINTR, fore200e->regs.pca.hcr);}static voidfore200e_pca_reset(struct fore200e* fore200e){    writel(PCA200E_HCR_RESET, fore200e->regs.pca.hcr);    fore200e_spin(10);    writel(0, fore200e->regs.pca.hcr);}static int __initfore200e_pca_map(struct fore200e* fore200e){    DPRINTK(2, "device %s being mapped in memory\n", fore200e->name);    fore200e->virt_base = ioremap(fore200e->phys_base, PCA200E_IOSPACE_LENGTH);        if (fore200e->virt_base == NULL) {	printk(FORE200E "can't map device %s\n", fore200e->name);	return -EFAULT;    }    DPRINTK(1, "device %s mapped to 0x%p\n", fore200e->name, fore200e->virt_base);    /* gain access to the PCA-200E specific registers  */    fore200e->regs.pca.hcr = (u32*)(fore200e->virt_base + PCA200E_HCR_OFFSET);    fore200e->regs.pca.imr = (u32*)(fore200e->virt_base + PCA200E_IMR_OFFSET);    fore200e->regs.pca.psr = (u32*)(fore200e->virt_base + PCA200E_PSR_OFFSET);    fore200e->state = FORE200E_STATE_MAP;    return 0;}static voidfore200e_pca_unmap(struct fore200e* fore200e){    DPRINTK(2, "device %s being unmapped from memory\n", fore200e->name);    /* XXX iounmap() does nothing on PowerPC (at least in 2.2.12 and 2.3.41),       this leads to a kernel panic if the module is loaded and unloaded several times */    if (fore200e->virt_base != NULL)	iounmap(fore200e->virt_base);}static int __initfore200e_pca_configure(struct fore200e* fore200e){    struct pci_dev* pci_dev = (struct pci_dev*)fore200e->bus_dev;    u8              master_ctrl;    DPRINTK(2, "device %s being configured\n", fore200e->name);    if ((pci_dev->irq == 0) || (pci_dev->irq == 0xFF)) {	printk(FORE200E "incorrect IRQ setting - misconfigured PCI-PCI bridge?\n");	return -EIO;    }	pci_read_config_byte(pci_dev, PCA200E_PCI_MASTER_CTRL, &master_ctrl);    master_ctrl = master_ctrl#if 0	| PCA200E_CTRL_DIS_CACHE_RD        | PCA200E_CTRL_DIS_WRT_INVAL#endif#if defined(__BIG_ENDIAN)	/* request the PCA board to convert the endianess of slave RAM accesses */	| PCA200E_CTRL_CONVERT_ENDIAN#endif	| PCA200E_CTRL_LARGE_PCI_BURSTS;        pci_write_config_byte(pci_dev, PCA200E_PCI_MASTER_CTRL, master_ctrl);    fore200e->state = FORE200E_STATE_CONFIGURE;    return 0;}static struct fore200e* __initfore200e_pca_detect(const struct fore200e_bus* bus, int index){    struct fore200e* fore200e;    struct pci_dev*  pci_dev = NULL;    int              count = index;        if (pci_present() == 0) {	printk(FORE200E "no PCI subsystem\n");	return NULL;    }    do {	pci_dev = pci_find_device(PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_PCA200E, pci_dev);	if (pci_dev == NULL)	    return NULL;    } while (count--);    if (pci_enable_device(pci_dev))	return NULL;        fore200e = fore200e_kmalloc(sizeof(struct fore200e), GFP_KERNEL);    if (fore200e == NULL)	return NULL;    fore200e->bus       = bus;    fore200e->bus_dev   = pci_dev;        fore200e->irq       = pci_dev->irq;    fore200e->phys_base = pci_resource_start (pci_dev, 0);#if defined(__powerpc__)    fore200e->phys_base += KERNELBASE;#endif    sprintf(fore200e->name, "%s-%d", bus->model_name, index - 1);    pci_set_master(pci_dev);    return fore200e;}static int __initfore200e_pca_prom_read(struct fore200e* fore200e, struct prom_data* prom){    struct host_cmdq*       cmdq  = &fore200e->host_cmdq;    struct host_cmdq_entry* entry = &cmdq->host_entry[ cmdq->head ];    struct prom_opcode      opcode;    int                     ok;    u32                     prom_dma;    FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);    opcode.opcode = OPCODE_GET_PROM;    opcode.pad    = 0;    prom_dma = fore200e->bus->dma_map(fore200e, prom, sizeof(struct prom_data), FORE200E_DMA_FROMDEVICE);    fore200e->bus->write(prom_dma, &entry->cp_entry->cmd.prom_block.prom_haddr);        *entry->status = STATUS_PENDING;    fore200e->bus->write(*(u32*)&opcode, (u32*)&entry->cp_entry->cmd.prom_block.opcode);    ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400);    *entry->status = STATUS_FREE;    fore200e->bus->dma_unmap(fore200e, prom_dma, sizeof(struct prom_data), FORE200E_DMA_FROMDEVICE);    if (ok == 0) {	printk(FORE200E "unable to get PROM data from device %s\n", fore200e->name);	return -EIO;    }#if defined(__BIG_ENDIAN)    #define swap_here(addr) (*((u32*)(addr)) = swab32( *((u32*)(addr)) ))    /* MAC address is stored as little-endian */    swap_here(&prom->mac_addr[0]);    swap_here(&prom->mac_addr[4]);#endif        return 0;}static intfore200e_pca_proc_read(struct fore200e* fore200e, char *page){    struct pci_dev* pci_dev = (struct pci_dev*)fore200e->bus_dev;    return sprintf(page, "   PCI bus/slot/function:\t%d/%d/%d\n",		   pci_dev->bus->number, PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn));}#endif /* CONFIG_ATM_FORE200E_PCA */#ifdef CONFIG_ATM_FORE200E_SBAstatic u32fore200e_sba_read(volatile u32* addr){    return sbus_readl(addr);}static voidfore200e_sba_write(u32 val, volatile u32* addr){    sbus_writel(val, addr);}static u32fore200e_sba_dma_map(struct fore200e* fore200e, void* virt_addr, int size, int direction){    u32 dma_addr = sbus_map_single((struct sbus_dev*)fore200e->bus_dev, virt_addr, size, direction);    DPRINTK(3, "SBUS DVMA mapping: virt_addr = 0x%p, size = %d, direction = %d --> dma_addr = 0x%08x\n",	    virt_addr, size, direction, dma_addr);        return dma_addr;}static voidfore200e_sba_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size, int direction){    DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n",	    dma_addr, size, direction);    sbus_unmap_single((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction);}static voidfore200e_sba_dma_sync(struct fore200e* fore200e, u32 dma_addr, int size, int direction){    DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction);        sbus_dma_sync_single((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction);}/* allocate a DVMA consistent chunk of memory intended to act as a communication mechanism   (to hold descriptors, status, queues, etc.) shared by the driver and the adapter */static intfore200e_sba_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk,			     int size, int nbr, int alignment){    chunk->alloc_size = chunk->align_size = size * nbr;    /* returned chunks are page-aligned */    chunk->alloc_addr = sbus_alloc_consistent((struct sbus_dev*)fore200e->bus_dev,					      chunk->alloc_size,					      &chunk->dma_addr);    if (chunk->alloc_addr == NULL || chunk->dma_addr == 0)	return -ENOMEM;    chunk->align_addr = chunk->alloc_addr;        return 0;}/* free a DVMA consistent chunk of memory */static voidfore200e_sba_dma_chunk_free(struct fore200e* fore200e, struct chunk* chunk){    sbus_free_consistent((struct sbus_dev*)fore200e->bus_dev,			 chunk->alloc_size,			 chunk->alloc_addr,			 chunk->dma_addr);}static voidfore200e_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 intfore200e_sba_irq_check(struct fore200e* fore200e){    return fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_INTR_REQ;}static voidfore200e_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 voidfore200e_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 __initfore200e_sba_map(struct fore200e* fore200e){    struct sbus_dev* sbus_dev = (struct sbus_dev*)fore200e->bus_dev;    unsigned int bursts;    /* gain access to the SBA-200E specific registers  */        fore200e->regs.sba.hcr = (u32*)sbus_ioremap(&sbus_dev->resource[0], 0, SBA200E_HCR_LENGTH, "SBA HCR");    fore200e->regs.sba.bsr = (u32*)sbus_ioremap(&sbus_dev->resource[1], 0, SBA200E_BSR_LENGTH, "SBA BSR");    fore200e->regs.sba.isr = (u32*)sbus_ioremap(&sbus_dev->resource[2], 0, SBA200E_ISR_LENGTH, "SBA ISR");    fore200e->virt_base    = (u32*)sbus_ioremap(&sbus_dev->resource[3], 0, SBA200E_RAM_LENGTH, "SBA RAM");    if (fore200e->virt_base == NULL) {	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); /* XXX hardwired interrupt level */    /* get the supported DVMA burst sizes */    bursts = prom_getintdefault(sbus_dev->bus->prom_node, "burst-sizes", 0x00);    if (sbus_can_dma_64bit(sbus_dev))	sbus_set_sbus64(sbus_dev, bursts);#if 0    if (bursts & DMA_BURST16)	fore200e->bus->write(SBA200E_BSR_BURST16, fore200e->regs.sba.bsr);    else    if (bursts & DMA_BURST8)       fore200e->bus->write(SBA200E_BSR_BURST8, fore200e->regs.sba.bsr);    else    if (bursts & DMA_BURST4)        fore200e->bus->write(SBA200E_BSR_BURST4, fore200e->regs.sba.bsr);#endif    fore200e->state = FORE200E_STATE_MAP;    return 0;}static voidfore200e_sba_unmap(struct fore200e* fore200e){    sbus_iounmap((ulong)fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH);    sbus_iounmap((ulong)fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH);    sbus_iounmap((ulong)fore200e->regs.sba.isr, SBA200E_ISR_LENGTH);    sbus_iounmap((ulong)fore200e->virt_base,    SBA200E_RAM_LENGTH);}static int __initfore200e_sba_configure(struct fore200e* fore200e){    fore200e->state = FORE200E_STATE_CONFIGURE;    return 0;}static struct fore200e* __initfore200e_sba_detect(const struct fore200e_bus* bus, int index){    struct fore200e*          fore200e;    struct sbus_bus* sbus_bus;    struct sbus_dev* sbus_dev = NULL;        unsigned int     count = 0;        for_each_sbus (sbus_bus) {	for_each_sbusdev (sbus_dev, sbus_bus) {	    if (strcmp(sbus_dev->prom_name, SBA200E_PROM_NAME) == 0) {		if (count >= index)		    goto found;		count++;	    }	}    }    return NULL;      found:#if 1    if (sbus_dev->num_registers != 4) {	printk(FORE200E "this %s device has %d instead of 4 registers\n",	       bus->model_name, sbus_dev->num_registers);	return NULL;    }#endif    fore200e = fore200e_kmalloc(sizeof(struct fore200e), GFP_KERNEL);    if (fore200e == NULL)	return NULL;    fore200e->bus     = bus;    fore200e->bus_dev = sbus_dev;    fore200e->irq     = sbus_dev->irqs[ 0 ];    fore200e->phys_base = (unsigned long)sbus_dev;    sprintf(fore200e->name, "%s-%d", bus->model_name, index - 1);        return fore200e;}

⌨️ 快捷键说明

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