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

📄 csr.c

📁 IEE1394 火线接口驱动 for linux
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * IEEE 1394 for Linux * * CSR implementation, iso/bus manager implementation. * * Copyright (C) 1999 Andreas E. Bombe *               2002 Manfred Weihs <weihs@ict.tuwien.ac.at> * * This code is licensed under the GPL.  See the file COPYING in the root * directory of the kernel sources for details. * * * Contributions: * * Manfred Weihs <weihs@ict.tuwien.ac.at> *        configuration ROM manipulation * */#include <linux/string.h>#include <linux/module.h> /* needed for MODULE_PARM */#include <linux/param.h>#include <linux/spinlock.h>#include "ieee1394_types.h"#include "hosts.h"#include "ieee1394.h"#include "highlevel.h"/* Module Parameters *//* this module parameter can be used to disable mapping of the FCP registers */MODULE_PARM(fcp,"i");MODULE_PARM_DESC(fcp, "FCP-registers");static int fcp = 1;static u16 csr_crc16(unsigned *data, int length){        int check=0, i;        int shift, sum, next=0;        for (i = length; i; i--) {                for (next = check, shift = 28; shift >= 0; shift -= 4 ) {                        sum = ((next >> 12) ^ (be32_to_cpu(*data) >> shift)) & 0xf;                        next = (next << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);                }                check = next & 0xffff;                data++;        }        return check;}static void host_reset(struct hpsb_host *host){        host->csr.state &= 0x300;        host->csr.bus_manager_id = 0x3f;        host->csr.bandwidth_available = 4915;	host->csr.channels_available_hi = 0xfffffffe;	/* pre-alloc ch 31 per 1394a-2000 */        host->csr.channels_available_lo = ~0;	host->csr.broadcast_channel = 0x80000000 | 31;	if (host->is_irm) {		if (host->driver->hw_csr_reg) {			host->driver->hw_csr_reg(host, 2, 0xfffffffe, ~0);		}	}        host->csr.node_ids = host->node_id << 16;        if (!host->is_root) {                /* clear cmstr bit */                host->csr.state &= ~0x100;        }        host->csr.topology_map[1] =                 cpu_to_be32(be32_to_cpu(host->csr.topology_map[1]) + 1);        host->csr.topology_map[2] = cpu_to_be32(host->node_count << 16                                                 | host->selfid_count);        host->csr.topology_map[0] =                 cpu_to_be32((host->selfid_count + 2) << 16                            | csr_crc16(host->csr.topology_map + 1,                                        host->selfid_count + 2));        host->csr.speed_map[1] =                 cpu_to_be32(be32_to_cpu(host->csr.speed_map[1]) + 1);        host->csr.speed_map[0] = cpu_to_be32(0x3f1 << 16                                              | csr_crc16(host->csr.speed_map+1,                                                         0x3f1));}/*  * HI == seconds (bits 0:2) * LO == fraction units of 1/8000 of a second, as per 1394 (bits 19:31) * * Convert to units and then to HZ, for comparison to jiffies. * * By default this will end up being 800 units, or 100ms (125usec per * unit). * * NOTE: The spec says 1/8000, but also says we can compute based on 1/8192 * like CSR specifies. Should make our math less complex. */static inline void calculate_expire(struct csr_control *csr){	unsigned long units;		/* Take the seconds, and convert to units */	units = (unsigned long)(csr->split_timeout_hi & 0x07) << 13;	/* Add in the fractional units */	units += (unsigned long)(csr->split_timeout_lo >> 19);	/* Convert to jiffies */	csr->expire = (unsigned long)(units * HZ) >> 13UL;	/* Just to keep from rounding low */	csr->expire++;	HPSB_VERBOSE("CSR: setting expire to %lu, HZ=%lu", csr->expire, HZ);}static void add_host(struct hpsb_host *host){        host->csr.lock = SPIN_LOCK_UNLOCKED;        host->csr.rom_size = host->driver->get_rom(host, &host->csr.rom);        host->csr.rom_version           = 0;        host->csr.state                 = 0;        host->csr.node_ids              = 0;        host->csr.split_timeout_hi      = 0;        host->csr.split_timeout_lo      = 800 << 19;	calculate_expire(&host->csr);        host->csr.cycle_time            = 0;        host->csr.bus_time              = 0;        host->csr.bus_manager_id        = 0x3f;        host->csr.bandwidth_available   = 4915;	host->csr.channels_available_hi = 0xfffffffe;	/* pre-alloc ch 31 per 1394a-2000 */        host->csr.channels_available_lo = ~0;	host->csr.broadcast_channel = 0x80000000 | 31;	if (host->is_irm) {		if (host->driver->hw_csr_reg) {			host->driver->hw_csr_reg(host, 2, 0xfffffffe, ~0);		}	}}int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom, 	size_t size, unsigned char rom_version){	unsigned long flags;	int ret;        spin_lock_irqsave(&host->csr.lock, flags);         if (rom_version != host->csr.rom_version)                 ret = -1;        else if (size > (CSR_CONFIG_ROM_SIZE << 2))                 ret = -2;        else {                 memcpy(host->csr.rom,new_rom,size);                 host->csr.rom_size=size;                 host->csr.rom_version++;                 ret=0;        }        spin_unlock_irqrestore(&host->csr.lock, flags);        return ret;}int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer, 	size_t buffersize, size_t *rom_size, unsigned char *rom_version){	unsigned long flags;	int ret;        spin_lock_irqsave(&host->csr.lock, flags);         *rom_version=host->csr.rom_version;        *rom_size=host->csr.rom_size;        if (buffersize < host->csr.rom_size)                 ret = -1;        else {                 memcpy(buffer,host->csr.rom,host->csr.rom_size);                 ret=0;        }        spin_unlock_irqrestore(&host->csr.lock, flags);        return ret;}/* Read topology / speed maps and configuration ROM */static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer,                     u64 addr, size_t length, u16 fl){	unsigned long flags;        int csraddr = addr - CSR_REGISTER_BASE;        const char *src;        spin_lock_irqsave(&host->csr.lock, flags);         if (csraddr < CSR_TOPOLOGY_MAP) {                if (csraddr + length > CSR_CONFIG_ROM + host->csr.rom_size) {                        spin_unlock_irqrestore(&host->csr.lock, flags);                        return RCODE_ADDRESS_ERROR;                }                src = ((char *)host->csr.rom) + csraddr - CSR_CONFIG_ROM;        } else if (csraddr < CSR_SPEED_MAP) {                src = ((char *)host->csr.topology_map) + csraddr                         - CSR_TOPOLOGY_MAP;        } else {                src = ((char *)host->csr.speed_map) + csraddr - CSR_SPEED_MAP;        }        memcpy(buffer, src, length);        spin_unlock_irqrestore(&host->csr.lock, flags);        return RCODE_COMPLETE;}#define out if (--length == 0) breakstatic int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf,                     u64 addr, size_t length, u16 flags){        int csraddr = addr - CSR_REGISTER_BASE;        int oldcycle;        quadlet_t ret;                if ((csraddr | length) & 0x3)                return RCODE_TYPE_ERROR;        length /= 4;        switch (csraddr) {        case CSR_STATE_CLEAR:                *(buf++) = cpu_to_be32(host->csr.state);                out;        case CSR_STATE_SET:                *(buf++) = cpu_to_be32(host->csr.state);                out;        case CSR_NODE_IDS:                *(buf++) = cpu_to_be32(host->csr.node_ids);                out;        case CSR_RESET_START:                return RCODE_TYPE_ERROR;                /* address gap - handled by default below */        case CSR_SPLIT_TIMEOUT_HI:                *(buf++) = cpu_to_be32(host->csr.split_timeout_hi);                out;        case CSR_SPLIT_TIMEOUT_LO:                *(buf++) = cpu_to_be32(host->csr.split_timeout_lo);                out;                /* address gap */                return RCODE_ADDRESS_ERROR;        case CSR_CYCLE_TIME:                oldcycle = host->csr.cycle_time;                host->csr.cycle_time =                        host->driver->devctl(host, GET_CYCLE_COUNTER, 0);                if (oldcycle > host->csr.cycle_time) {                        /* cycle time wrapped around */                        host->csr.bus_time += 1 << 7;                }                *(buf++) = cpu_to_be32(host->csr.cycle_time);                out;        case CSR_BUS_TIME:                oldcycle = host->csr.cycle_time;                host->csr.cycle_time =                        host->driver->devctl(host, GET_CYCLE_COUNTER, 0);                if (oldcycle > host->csr.cycle_time) {                        /* cycle time wrapped around */                        host->csr.bus_time += (1 << 7);                }                *(buf++) = cpu_to_be32(host->csr.bus_time                                        | (host->csr.cycle_time >> 25));                out;                /* address gap */                return RCODE_ADDRESS_ERROR;        case CSR_BUSY_TIMEOUT:                /* not yet implemented */                return RCODE_ADDRESS_ERROR;        case CSR_BUS_MANAGER_ID:                if (host->driver->hw_csr_reg)                        ret = host->driver->hw_csr_reg(host, 0, 0, 0);                else                        ret = host->csr.bus_manager_id;                *(buf++) = cpu_to_be32(ret);                out;        case CSR_BANDWIDTH_AVAILABLE:                if (host->driver->hw_csr_reg)                        ret = host->driver->hw_csr_reg(host, 1, 0, 0);                else                        ret = host->csr.bandwidth_available;                *(buf++) = cpu_to_be32(ret);                out;        case CSR_CHANNELS_AVAILABLE_HI:                if (host->driver->hw_csr_reg)                        ret = host->driver->hw_csr_reg(host, 2, 0, 0);                else                        ret = host->csr.channels_available_hi;                *(buf++) = cpu_to_be32(ret);                out;        case CSR_CHANNELS_AVAILABLE_LO:                if (host->driver->hw_csr_reg)                        ret = host->driver->hw_csr_reg(host, 3, 0, 0);                else                        ret = host->csr.channels_available_lo;                *(buf++) = cpu_to_be32(ret);                out;	case CSR_BROADCAST_CHANNEL:		*(buf++) = cpu_to_be32(host->csr.broadcast_channel);		out;                /* address gap to end - fall through to default */        default:                return RCODE_ADDRESS_ERROR;        }        return RCODE_COMPLETE;}static int write_regs(struct hpsb_host *host, int nodeid, int destid,		      quadlet_t *data, u64 addr, size_t length, u16 flags){        int csraddr = addr - CSR_REGISTER_BASE;                if ((csraddr | length) & 0x3)                return RCODE_TYPE_ERROR;        length /= 4;        switch (csraddr) {        case CSR_STATE_CLEAR:                /* FIXME FIXME FIXME */                printk("doh, someone wants to mess with state clear\n");                out;        case CSR_STATE_SET:                printk("doh, someone wants to mess with state set\n");                out;        case CSR_NODE_IDS:                host->csr.node_ids &= NODE_MASK << 16;                host->csr.node_ids |= be32_to_cpu(*(data++)) & (BUS_MASK << 16);                host->node_id = host->csr.node_ids >> 16;                host->driver->devctl(host, SET_BUS_ID, host->node_id >> 6);                out;        case CSR_RESET_START:                /* FIXME - perform command reset */                out;                /* address gap */                return RCODE_ADDRESS_ERROR;

⌨️ 快捷键说明

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