Commit 1c67e74a authored by Ben Collins's avatar Ben Collins

IEEE1394(r1118): Addition of new config-rom processing code

parent 862e3994
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
# #
ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \ ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \
highlevel.o csr.o nodemgr.o oui.o dma.o iso.o highlevel.o csr.o nodemgr.o oui.o dma.o iso.o \
csr1212.o
obj-$(CONFIG_IEEE1394) += ieee1394.o obj-$(CONFIG_IEEE1394) += ieee1394.o
obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/param.h> #include <linux/param.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include "csr1212.h"
#include "ieee1394_types.h" #include "ieee1394_types.h"
#include "hosts.h" #include "hosts.h"
#include "ieee1394.h" #include "ieee1394.h"
...@@ -35,7 +36,10 @@ static int fcp = 1; ...@@ -35,7 +36,10 @@ static int fcp = 1;
module_param(fcp, int, 0444); module_param(fcp, int, 0444);
MODULE_PARM_DESC(fcp, "Map FCP registers (default = 1, disable = 0)."); MODULE_PARM_DESC(fcp, "Map FCP registers (default = 1, disable = 0).");
static struct csr1212_keyval *node_cap = NULL;
static void add_host(struct hpsb_host *host); static void add_host(struct hpsb_host *host);
static void remove_host(struct hpsb_host *host);
static void host_reset(struct hpsb_host *host); static void host_reset(struct hpsb_host *host);
static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer, static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
u64 addr, size_t length, u16 fl); u64 addr, size_t length, u16 fl);
...@@ -49,10 +53,15 @@ static int lock_regs(struct hpsb_host *host, int nodeid, quadlet_t *store, ...@@ -49,10 +53,15 @@ static int lock_regs(struct hpsb_host *host, int nodeid, quadlet_t *store,
u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 fl); u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 fl);
static int lock64_regs(struct hpsb_host *host, int nodeid, octlet_t * store, static int lock64_regs(struct hpsb_host *host, int nodeid, octlet_t * store,
u64 addr, octlet_t data, octlet_t arg, int extcode, u16 fl); u64 addr, octlet_t data, octlet_t arg, int extcode, u16 fl);
static int read_config_rom(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
u64 addr, size_t length, u16 fl);
static u64 allocate_addr_range(u64 size, u32 alignment, void *__host);
static void release_addr_range(u64 addr, void *__host);
static struct hpsb_highlevel csr_highlevel = { static struct hpsb_highlevel csr_highlevel = {
.name = "standard registers", .name = "standard registers",
.add_host = add_host, .add_host = add_host,
.remove_host = remove_host,
.host_reset = host_reset, .host_reset = host_reset,
}; };
...@@ -71,6 +80,15 @@ static struct hpsb_address_ops reg_ops = { ...@@ -71,6 +80,15 @@ static struct hpsb_address_ops reg_ops = {
.lock64 = lock64_regs, .lock64 = lock64_regs,
}; };
static struct hpsb_address_ops config_rom_ops = {
.read = read_config_rom,
};
struct csr1212_bus_ops csr_bus_ops = {
.allocate_addr_range = allocate_addr_range,
.release_addr = release_addr_range,
};
static u16 csr_crc16(unsigned *data, int length) static u16 csr_crc16(unsigned *data, int length)
{ {
...@@ -162,10 +180,13 @@ static inline void calculate_expire(struct csr_control *csr) ...@@ -162,10 +180,13 @@ static inline void calculate_expire(struct csr_control *csr)
static void add_host(struct hpsb_host *host) static void add_host(struct hpsb_host *host)
{ {
struct csr1212_keyval *root;
quadlet_t bus_info[CSR_BUS_INFO_SIZE];
hpsb_register_addrspace(&csr_highlevel, host, &reg_ops, hpsb_register_addrspace(&csr_highlevel, host, &reg_ops,
CSR_REGISTER_BASE, CSR_REGISTER_BASE,
CSR_REGISTER_BASE + CSR_CONFIG_ROM); CSR_REGISTER_BASE + CSR_CONFIG_ROM);
hpsb_register_addrspace(&csr_highlevel, host, &map_ops, hpsb_register_addrspace(&csr_highlevel, host, &config_rom_ops,
CSR_REGISTER_BASE + CSR_CONFIG_ROM, CSR_REGISTER_BASE + CSR_CONFIG_ROM,
CSR_REGISTER_BASE + CSR_CONFIG_ROM_END); CSR_REGISTER_BASE + CSR_CONFIG_ROM_END);
if (fcp) { if (fcp) {
...@@ -182,8 +203,6 @@ static void add_host(struct hpsb_host *host) ...@@ -182,8 +203,6 @@ static void add_host(struct hpsb_host *host)
host->csr.lock = SPIN_LOCK_UNLOCKED; 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.state = 0;
host->csr.node_ids = 0; host->csr.node_ids = 0;
host->csr.split_timeout_hi = 0; host->csr.split_timeout_hi = 0;
...@@ -202,43 +221,100 @@ static void add_host(struct hpsb_host *host) ...@@ -202,43 +221,100 @@ static void add_host(struct hpsb_host *host)
host->driver->hw_csr_reg(host, 2, 0xfffffffe, ~0); host->driver->hw_csr_reg(host, 2, 0xfffffffe, ~0);
} }
} }
if (host->csr.max_rec >= 9)
host->csr.max_rom = 2;
else if (host->csr.max_rec >= 5)
host->csr.max_rom = 1;
else
host->csr.max_rom = 0;
host->csr.generation = 2;
bus_info[1] = __constant_cpu_to_be32(0x31333934);
bus_info[2] = cpu_to_be32((1 << CSR_IRMC_SHIFT) |
(1 << CSR_CMC_SHIFT) |
(1 << CSR_ISC_SHIFT) |
(0 << CSR_BMC_SHIFT) |
(0 << CSR_PMC_SHIFT) |
(host->csr.cyc_clk_acc << CSR_CYC_CLK_ACC_SHIFT) |
(host->csr.max_rec << CSR_MAX_REC_SHIFT) |
(host->csr.max_rom << CSR_MAX_ROM_SHIFT) |
(host->csr.generation << CSR_GENERATION_SHIFT) |
host->csr.lnk_spd);
bus_info[3] = cpu_to_be32(host->csr.guid_hi);
bus_info[4] = cpu_to_be32(host->csr.guid_lo);
/* The hardware copy of the bus info block will be set later when a
* bus reset is issued. */
csr1212_init_local_csr(host->csr.rom, bus_info, host->csr.max_rom);
host->csr.rom->max_rom = host->csr.max_rom;
root = host->csr.rom->root_kv;
if(csr1212_attach_keyval_to_directory(root, node_cap) != CSR1212_SUCCESS) {
HPSB_ERR("Failed to attach Node Capabilities to root directory");
}
host->update_config_rom = 1;
} }
int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom, static void remove_host(struct hpsb_host *host)
size_t size, unsigned char rom_version)
{ {
unsigned long flags; quadlet_t bus_info[CSR_BUS_INFO_SIZE];
int ret;
bus_info[1] = __constant_cpu_to_be32(0x31333934);
spin_lock_irqsave(&host->csr.lock, flags); bus_info[2] = cpu_to_be32((0 << CSR_IRMC_SHIFT) |
if (rom_version != host->csr.rom_version) (0 << CSR_CMC_SHIFT) |
ret = -1; (0 << CSR_ISC_SHIFT) |
else if (size > (CSR_CONFIG_ROM_SIZE << 2)) (0 << CSR_BMC_SHIFT) |
ret = -2; (0 << CSR_PMC_SHIFT) |
else { (host->csr.cyc_clk_acc << CSR_CYC_CLK_ACC_SHIFT) |
memcpy(host->csr.rom,new_rom,size); (host->csr.max_rec << CSR_MAX_REC_SHIFT) |
host->csr.rom_size=size; (0 << CSR_MAX_ROM_SHIFT) |
host->csr.rom_version++; (0 << CSR_GENERATION_SHIFT) |
ret=0; host->csr.lnk_spd);
}
spin_unlock_irqrestore(&host->csr.lock, flags); bus_info[3] = cpu_to_be32(host->csr.guid_hi);
return ret; bus_info[4] = cpu_to_be32(host->csr.guid_lo);
csr1212_detach_keyval_from_directory(host->csr.rom->root_kv, node_cap);
csr1212_init_local_csr(host->csr.rom, bus_info, 0);
host->update_config_rom = 1;
} }
int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer,
size_t buffersize, size_t *rom_size, unsigned char *rom_version) int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom,
size_t buffersize, unsigned char rom_version)
{ {
unsigned long flags; unsigned long flags;
int ret; int ret;
HPSB_NOTICE("hpsb_update_config_rom() is deprecated");
spin_lock_irqsave(&host->csr.lock, flags); spin_lock_irqsave(&host->csr.lock, flags);
*rom_version=host->csr.rom_version; if (rom_version != host->csr.generation)
*rom_size=host->csr.rom_size; ret = -1;
if (buffersize < host->csr.rom_size) else if (buffersize > host->csr.rom->cache_head->size)
ret = -1; ret = -2;
else { else {
memcpy(buffer,host->csr.rom,host->csr.rom_size); /* Just overwrite the generated ConfigROM image with new data,
ret=0; * it can be regenerated later. */
memcpy(host->csr.rom->cache_head->data, new_rom, buffersize);
host->csr.rom->cache_head->len = buffersize;
if (host->driver->set_hw_config_rom)
host->driver->set_hw_config_rom(host, host->csr.rom->bus_info_data);
/* Increment the generation number to keep some sort of sync
* with the newer ConfigROM manipulation method. */
host->csr.generation++;
if (host->csr.generation > 0xf || host->csr.generation < 2)
host->csr.generation = 2;
ret=0;
} }
spin_unlock_irqrestore(&host->csr.lock, flags); spin_unlock_irqrestore(&host->csr.lock, flags);
return ret; return ret;
...@@ -255,13 +331,7 @@ static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer, ...@@ -255,13 +331,7 @@ static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
spin_lock_irqsave(&host->csr.lock, flags); spin_lock_irqsave(&host->csr.lock, flags);
if (csraddr < CSR_TOPOLOGY_MAP) { if (csraddr < CSR_SPEED_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 src = ((char *)host->csr.topology_map) + csraddr
- CSR_TOPOLOGY_MAP; - CSR_TOPOLOGY_MAP;
} else { } else {
...@@ -738,14 +808,52 @@ static int write_fcp(struct hpsb_host *host, int nodeid, int dest, ...@@ -738,14 +808,52 @@ static int write_fcp(struct hpsb_host *host, int nodeid, int dest,
return RCODE_COMPLETE; return RCODE_COMPLETE;
} }
static int read_config_rom(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
u64 addr, size_t length, u16 fl)
{
u32 offset = addr - CSR1212_REGISTER_SPACE_BASE;
if (csr1212_read(host->csr.rom, offset, buffer, length) == CSR1212_SUCCESS)
return RCODE_COMPLETE;
else
return RCODE_ADDRESS_ERROR;
}
static u64 allocate_addr_range(u64 size, u32 alignment, void *__host)
{
struct hpsb_host *host = (struct hpsb_host*)__host;
return hpsb_allocate_and_register_addrspace(&csr_highlevel,
host,
&config_rom_ops,
size, alignment,
CSR1212_UNITS_SPACE_BASE,
CSR1212_UNITS_SPACE_END);
}
static void release_addr_range(u64 addr, void *__host)
{
struct hpsb_host *host = (struct hpsb_host*)__host;
hpsb_unregister_addrspace(&csr_highlevel, host, addr);
}
void init_csr(void) int init_csr(void)
{ {
node_cap = csr1212_new_immediate(CSR1212_KV_ID_NODE_CAPABILITIES, 0x0083c0);
if (!node_cap) {
HPSB_ERR("Failed to allocate memory for Node Capabilties ConfigROM entry!");
return -ENOMEM;
}
hpsb_register_highlevel(&csr_highlevel); hpsb_register_highlevel(&csr_highlevel);
return 0;
} }
void cleanup_csr(void) void cleanup_csr(void)
{ {
if (node_cap)
csr1212_release_keyval(node_cap);
hpsb_unregister_highlevel(&csr_highlevel); hpsb_unregister_highlevel(&csr_highlevel);
} }
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#include <linux/sched.h> #include <linux/sched.h>
#endif #endif
#include "csr1212.h"
#define CSR_REGISTER_BASE 0xfffff0000000ULL #define CSR_REGISTER_BASE 0xfffff0000000ULL
/* register offsets relative to CSR_REGISTER_BASE */ /* register offsets relative to CSR_REGISTER_BASE */
...@@ -34,6 +36,27 @@ ...@@ -34,6 +36,27 @@
#define CSR_SPEED_MAP 0x2000 #define CSR_SPEED_MAP 0x2000
#define CSR_SPEED_MAP_END 0x3000 #define CSR_SPEED_MAP_END 0x3000
/* IEEE 1394 bus specific Configuration ROM Key IDs */
#define IEEE1394_KV_ID_POWER_REQUIREMENTS (0x30)
/* IEEE 1394 Bus Inforamation Block specifics */
#define CSR_BUS_INFO_SIZE (5 * sizeof(quadlet_t))
#define CSR_IRMC_SHIFT 31
#define CSR_CMC_SHIFT 30
#define CSR_ISC_SHIFT 29
#define CSR_BMC_SHIFT 28
#define CSR_PMC_SHIFT 27
#define CSR_CYC_CLK_ACC_SHIFT 16
#define CSR_MAX_REC_SHIFT 12
#define CSR_MAX_ROM_SHIFT 8
#define CSR_GENERATION_SHIFT 4
#define CSR_SET_BUS_INFO_GENERATION(csr, gen) \
((csr)->bus_info_data[2] = \
cpu_to_be32((be32_to_cpu((csr)->bus_info_data[2]) & \
~(0xf << CSR_GENERATION_SHIFT)) | \
(gen) << CSR_GENERATION_SHIFT))
struct csr_control { struct csr_control {
spinlock_t lock; spinlock_t lock;
...@@ -49,17 +72,25 @@ struct csr_control { ...@@ -49,17 +72,25 @@ struct csr_control {
quadlet_t channels_available_hi, channels_available_lo; quadlet_t channels_available_hi, channels_available_lo;
quadlet_t broadcast_channel; quadlet_t broadcast_channel;
quadlet_t *rom; /* Bus Info */
size_t rom_size; quadlet_t guid_hi, guid_lo;
unsigned char rom_version; u8 cyc_clk_acc;
u8 max_rec;
u8 max_rom;
u8 generation; /* Only use values between 0x2 and 0xf */
u8 lnk_spd;
unsigned long gen_timestamp[16];
struct csr1212_csr *rom;
quadlet_t topology_map[256]; quadlet_t topology_map[256];
quadlet_t speed_map[1024]; quadlet_t speed_map[1024];
}; };
extern struct csr1212_bus_ops csr_bus_ops;
void init_csr(void); int init_csr(void);
void cleanup_csr(void); void cleanup_csr(void);
#endif /* _IEEE1394_CSR_H */ #endif /* _IEEE1394_CSR_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -29,8 +29,8 @@ ...@@ -29,8 +29,8 @@
/* Register for incoming packets. This is 4096 bytes, which supports up to /* Register for incoming packets. This is 4096 bytes, which supports up to
* S3200 (per Table 16-3 of IEEE 1394b-2002). */ * S3200 (per Table 16-3 of IEEE 1394b-2002). */
#define ETHER1394_REGION_ADDR_LEN 4096 #define ETHER1394_REGION_ADDR_LEN 4096
#define ETHER1394_REGION_ADDR 0xfffff0200000ULL
#define ETHER1394_REGION_ADDR_END (ETHER1394_REGION_ADDR + ETHER1394_REGION_ADDR_LEN) #define ETHER1394_INVALID_ADDR ~0ULL
/* GASP identifier numbers for IPv4 over IEEE 1394 */ /* GASP identifier numbers for IPv4 over IEEE 1394 */
#define ETHER1394_GASP_SPECIFIER_ID 0x00005E #define ETHER1394_GASP_SPECIFIER_ID 0x00005E
...@@ -40,37 +40,30 @@ ...@@ -40,37 +40,30 @@
#define ETHER1394_GASP_OVERHEAD (2 * sizeof(quadlet_t)) /* GASP header overhead */ #define ETHER1394_GASP_OVERHEAD (2 * sizeof(quadlet_t)) /* GASP header overhead */
#define ETHER1394_GASP_BUFFERS 16
/* Node set == 64 */ /* Node set == 64 */
#define NODE_SET (ALL_NODES + 1) #define NODE_SET (ALL_NODES + 1)
enum eth1394_bc_states { ETHER1394_BC_CLOSED, ETHER1394_BC_OPENED, enum eth1394_bc_states { ETHER1394_BC_ERROR,
ETHER1394_BC_CHECK }; ETHER1394_BC_RUNNING,
ETHER1394_BC_STOPPED };
struct pdg_list {
struct list_head list; /* partial datagram list per node */
unsigned int sz; /* partial datagram list size per node */
spinlock_t lock; /* partial datagram lock */
};
/* Private structure for our ethernet driver */ /* Private structure for our ethernet driver */
struct eth1394_priv { struct eth1394_priv {
struct net_device_stats stats; /* Device stats */ struct net_device_stats stats; /* Device stats */
struct hpsb_host *host; /* The card for this dev */ struct hpsb_host *host; /* The card for this dev */
u16 maxpayload[NODE_SET]; /* Max payload per node */ u16 bc_maxpayload; /* Max broadcast payload */
unsigned char sspd[NODE_SET]; /* Max speed per node */ u8 bc_sspd; /* Max broadcast speed */
u64 fifo[ALL_NODES]; /* FIFO offset per node */ u64 local_fifo; /* Local FIFO Address */
u64 eui[ALL_NODES]; /* EUI-64 per node */
spinlock_t lock; /* Private lock */ spinlock_t lock; /* Private lock */
int broadcast_channel; /* Async stream Broadcast Channel */ int broadcast_channel; /* Async stream Broadcast Channel */
enum eth1394_bc_states bc_state; /* broadcast channel state */ enum eth1394_bc_states bc_state; /* broadcast channel state */
struct hpsb_iso *iso; /* Async stream recv handle */ struct hpsb_iso *iso; /* Async stream recv handle */
struct pdg_list pdg[ALL_NODES]; /* partial RX datagram lists */ int bc_dgl; /* Outgoing broadcast datagram label */
int dgl[NODE_SET]; /* Outgoing datagram label per node */ struct list_head ip_node_list; /* List of IP capable nodes */
}; struct unit_directory *ud_list[ALL_NODES]; /* Cached unit dir list */
struct host_info {
struct hpsb_host *host;
struct net_device *dev;
}; };
......
This diff is collapsed.
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
struct hpsb_address_serve { struct hpsb_address_serve {
struct list_head as_list; /* global list */ struct list_head host_list; /* per host list */
struct list_head addr_list; /* hpsb_highlevel list */ struct list_head hl_list; /* hpsb_highlevel list */
struct hpsb_address_ops *op; struct hpsb_address_ops *op;
...@@ -140,6 +140,11 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl); ...@@ -140,6 +140,11 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl);
* It returns true for successful allocation. There is no unregister function, * It returns true for successful allocation. There is no unregister function,
* all address spaces are deallocated together with the hpsb_highlevel. * all address spaces are deallocated together with the hpsb_highlevel.
*/ */
u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
struct hpsb_host *host,
struct hpsb_address_ops *ops,
u64 size, u64 alignment,
u64 start, u64 end);
int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
struct hpsb_address_ops *ops, u64 start, u64 end); struct hpsb_address_ops *ops, u64 start, u64 end);
......
...@@ -17,14 +17,47 @@ ...@@ -17,14 +17,47 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/timer.h>
#include "csr1212.h"
#include "ieee1394.h"
#include "ieee1394_types.h" #include "ieee1394_types.h"
#include "hosts.h" #include "hosts.h"
#include "ieee1394_core.h" #include "ieee1394_core.h"
#include "highlevel.h" #include "highlevel.h"
#include "nodemgr.h" #include "nodemgr.h"
#include "csr.h"
static void delayed_reset_bus(unsigned long __reset_info)
{
struct hpsb_host *host = (struct hpsb_host*)__reset_info;
int generation = host->csr.generation + 1;
/* The generation field rolls over to 2 rather than 0 per IEEE
* 1394a-2000. */
if (generation > 0xf || generation < 2)
generation = 2;
CSR_SET_BUS_INFO_GENERATION(host->csr.rom, generation);
if (csr1212_generate_csr_image(host->csr.rom) != CSR1212_SUCCESS) {
/* CSR image creation failed, reset generation field and do not
* issue a bus reset. */
CSR_SET_BUS_INFO_GENERATION(host->csr.rom, host->csr.generation);
return;
}
host->csr.generation = generation;
host->update_config_rom = 0;
if (host->driver->set_hw_config_rom)
host->driver->set_hw_config_rom(host, host->csr.rom->bus_info_data);
host->csr.gen_timestamp[host->csr.generation] = jiffies;
hpsb_reset_bus(host, SHORT_RESET);
}
static int dummy_transmit_packet(struct hpsb_host *h, struct hpsb_packet *p) static int dummy_transmit_packet(struct hpsb_host *h, struct hpsb_packet *p)
{ {
return 0; return 0;
...@@ -83,6 +116,12 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, ...@@ -83,6 +116,12 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
if (!h) return NULL; if (!h) return NULL;
memset(h, 0, sizeof(struct hpsb_host) + extra); memset(h, 0, sizeof(struct hpsb_host) + extra);
h->csr.rom = csr1212_create_csr(&csr_bus_ops, CSR_BUS_INFO_SIZE, h);
if (!h->csr.rom) {
kfree(h);
return NULL;
}
h->hostdata = h + 1; h->hostdata = h + 1;
h->driver = drv; h->driver = drv;
...@@ -91,6 +130,12 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, ...@@ -91,6 +130,12 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
INIT_LIST_HEAD(&h->addr_space); INIT_LIST_HEAD(&h->addr_space);
init_timer(&h->delayed_reset);
h->delayed_reset.function = delayed_reset_bus;
h->delayed_reset.data = (unsigned long)h;
for (i = 2; i < 16; i++)
h->csr.gen_timestamp[i] = jiffies - 60 * HZ;
for (i = 0; i < ARRAY_SIZE(h->tpool); i++) for (i = 0; i < ARRAY_SIZE(h->tpool); i++)
HPSB_TPOOL_INIT(&h->tpool[i]); HPSB_TPOOL_INIT(&h->tpool[i]);
...@@ -124,7 +169,6 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, ...@@ -124,7 +169,6 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
void hpsb_add_host(struct hpsb_host *host) void hpsb_add_host(struct hpsb_host *host)
{ {
highlevel_add_host(host); highlevel_add_host(host);
host->driver->devctl(host, RESET_BUS, LONG_RESET);
} }
void hpsb_remove_host(struct hpsb_host *host) void hpsb_remove_host(struct hpsb_host *host)
...@@ -136,3 +180,35 @@ void hpsb_remove_host(struct hpsb_host *host) ...@@ -136,3 +180,35 @@ void hpsb_remove_host(struct hpsb_host *host)
device_unregister(&host->device); device_unregister(&host->device);
} }
int hpsb_update_config_rom_image(struct hpsb_host *host)
{
unsigned long reset_time;
int next_gen = host->csr.generation + 1;
if (!host->update_config_rom)
return -EINVAL;
if (next_gen > 0xf)
next_gen = 2;
/* Stop the delayed interrupt, we're about to change the config rom and
* it would be a waste to do a bus reset twice. */
del_timer_sync(&host->delayed_reset);
/* IEEE 1394a-2000 prohibits using the same generation number
* twice in a 60 second period. */
if (jiffies - host->csr.gen_timestamp[next_gen] < 60 * HZ)
/* Wait 60 seconds from the last time this generation number was
* used. */
reset_time = (60 * HZ) + host->csr.gen_timestamp[next_gen];
else
/* Wait 1 second in case some other code wants to change the
* Config ROM in the near future. */
reset_time = jiffies + HZ;
/* This will add the timer as well as modify it */
mod_timer(&host->delayed_reset, reset_time);
return 0;
}
...@@ -10,14 +10,6 @@ ...@@ -10,14 +10,6 @@
#include "ieee1394_types.h" #include "ieee1394_types.h"
#include "csr.h" #include "csr.h"
/* size of the array used to store config rom (in quadlets)
maximum is 0x100. About 0x40 is needed for the default
entries. So 0x80 should provide enough space for additional
directories etc.
Note: All lowlevel drivers are required to allocate at least
this amount of memory for the configuration rom!
*/
#define CSR_CONFIG_ROM_SIZE 0x100
struct hpsb_packet; struct hpsb_packet;
struct hpsb_iso; struct hpsb_iso;
...@@ -70,6 +62,9 @@ struct hpsb_host { ...@@ -70,6 +62,9 @@ struct hpsb_host {
struct device device; struct device device;
int update_config_rom;
struct timer_list delayed_reset;
struct list_head addr_space; struct list_head addr_space;
}; };
...@@ -153,12 +148,10 @@ struct hpsb_host_driver { ...@@ -153,12 +148,10 @@ struct hpsb_host_driver {
struct module *owner; struct module *owner;
const char *name; const char *name;
/* This function must store a pointer to the configuration ROM into the /* The hardware driver may optionally support a function that is used
* location referenced to by pointer and return the size of the ROM. It * to set the hardware ConfigROM if the hardware supports handling
* may not fail. If any allocation is required, it must be done * reads to the ConfigROM on its own. */
* earlier. void (*set_hw_config_rom) (struct hpsb_host *host, quadlet_t *config_rom);
*/
size_t (*get_rom) (struct hpsb_host *host, quadlet_t **pointer);
/* This function shall implement packet transmission based on /* This function shall implement packet transmission based on
* packet->type. It shall CRC both parts of the packet (unless * packet->type. It shall CRC both parts of the packet (unless
...@@ -200,24 +193,18 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, ...@@ -200,24 +193,18 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
void hpsb_add_host(struct hpsb_host *host); void hpsb_add_host(struct hpsb_host *host);
void hpsb_remove_host(struct hpsb_host *h); void hpsb_remove_host(struct hpsb_host *h);
/* updates the configuration rom of a host. /* The following 2 functions are deprecated and will be removed when the
* rom_version must be the current version, * raw1394/libraw1394 update is complete. */
* otherwise it will fail with return value -1.
* Return value -2 indicates that the new
* rom version is too big.
* Return value 0 indicates success
*/
int hpsb_update_config_rom(struct hpsb_host *host, int hpsb_update_config_rom(struct hpsb_host *host,
const quadlet_t *new_rom, size_t size, unsigned char rom_version); const quadlet_t *new_rom, size_t size, unsigned char rom_version);
/* reads the current version of the configuration rom of a host.
* buffersize is the size of the buffer, rom_size
* returns the size of the current rom image.
* rom_version is the version number of the fetched rom.
* return value -1 indicates, that the buffer was
* too small, 0 indicates success.
*/
int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer, int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer,
size_t buffersize, size_t *rom_size, unsigned char *rom_version); size_t buffersize, size_t *rom_size, unsigned char *rom_version);
/* Updates the configuration rom image of a host. rom_version must be the
* current version, otherwise it will fail with return value -1. If this
* host does not support config-rom-update, it will return -EINVAL.
* Return value 0 indicates success.
*/
int hpsb_update_config_rom_image(struct hpsb_host *host);
#endif /* _IEEE1394_HOSTS_H */ #endif /* _IEEE1394_HOSTS_H */
...@@ -1009,7 +1009,8 @@ static int __init ieee1394_init(void) ...@@ -1009,7 +1009,8 @@ static int __init ieee1394_init(void)
bus_register(&ieee1394_bus_type); bus_register(&ieee1394_bus_type);
init_csr(); if (init_csr())
return -ENOMEM;
if (!disable_nodemgr) if (!disable_nodemgr)
init_ieee1394_nodemgr(); init_ieee1394_nodemgr();
...@@ -1043,6 +1044,7 @@ module_exit(ieee1394_cleanup); ...@@ -1043,6 +1044,7 @@ module_exit(ieee1394_cleanup);
EXPORT_SYMBOL(hpsb_alloc_host); EXPORT_SYMBOL(hpsb_alloc_host);
EXPORT_SYMBOL(hpsb_add_host); EXPORT_SYMBOL(hpsb_add_host);
EXPORT_SYMBOL(hpsb_remove_host); EXPORT_SYMBOL(hpsb_remove_host);
EXPORT_SYMBOL(hpsb_update_config_rom_image);
/** ieee1394_core.c **/ /** ieee1394_core.c **/
EXPORT_SYMBOL(hpsb_speedto_str); EXPORT_SYMBOL(hpsb_speedto_str);
...@@ -1081,6 +1083,7 @@ EXPORT_SYMBOL(hpsb_register_highlevel); ...@@ -1081,6 +1083,7 @@ EXPORT_SYMBOL(hpsb_register_highlevel);
EXPORT_SYMBOL(hpsb_unregister_highlevel); EXPORT_SYMBOL(hpsb_unregister_highlevel);
EXPORT_SYMBOL(hpsb_register_addrspace); EXPORT_SYMBOL(hpsb_register_addrspace);
EXPORT_SYMBOL(hpsb_unregister_addrspace); EXPORT_SYMBOL(hpsb_unregister_addrspace);
EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace);
EXPORT_SYMBOL(hpsb_listen_channel); EXPORT_SYMBOL(hpsb_listen_channel);
EXPORT_SYMBOL(hpsb_unlisten_channel); EXPORT_SYMBOL(hpsb_unlisten_channel);
EXPORT_SYMBOL(hpsb_get_hostinfo); EXPORT_SYMBOL(hpsb_get_hostinfo);
...@@ -1113,7 +1116,6 @@ EXPORT_SYMBOL(nodemgr_for_each_host); ...@@ -1113,7 +1116,6 @@ EXPORT_SYMBOL(nodemgr_for_each_host);
/** csr.c **/ /** csr.c **/
EXPORT_SYMBOL(hpsb_update_config_rom); EXPORT_SYMBOL(hpsb_update_config_rom);
EXPORT_SYMBOL(hpsb_get_config_rom);
/** dma.c **/ /** dma.c **/
EXPORT_SYMBOL(dma_prog_region_init); EXPORT_SYMBOL(dma_prog_region_init);
...@@ -1144,3 +1146,34 @@ EXPORT_SYMBOL(hpsb_iso_packet_sent); ...@@ -1144,3 +1146,34 @@ EXPORT_SYMBOL(hpsb_iso_packet_sent);
EXPORT_SYMBOL(hpsb_iso_packet_received); EXPORT_SYMBOL(hpsb_iso_packet_received);
EXPORT_SYMBOL(hpsb_iso_wake); EXPORT_SYMBOL(hpsb_iso_wake);
EXPORT_SYMBOL(hpsb_iso_recv_flush); EXPORT_SYMBOL(hpsb_iso_recv_flush);
/** csr1212.c **/
EXPORT_SYMBOL(csr1212_create_csr);
EXPORT_SYMBOL(csr1212_init_local_csr);
EXPORT_SYMBOL(csr1212_new_immediate);
EXPORT_SYMBOL(csr1212_new_leaf);
EXPORT_SYMBOL(csr1212_new_csr_offset);
EXPORT_SYMBOL(csr1212_new_directory);
EXPORT_SYMBOL(csr1212_associate_keyval);
EXPORT_SYMBOL(csr1212_attach_keyval_to_directory);
EXPORT_SYMBOL(csr1212_new_extended_immediate);
EXPORT_SYMBOL(csr1212_new_extended_leaf);
EXPORT_SYMBOL(csr1212_new_descriptor_leaf);
EXPORT_SYMBOL(csr1212_new_textual_descriptor_leaf);
EXPORT_SYMBOL(csr1212_new_string_descriptor_leaf);
EXPORT_SYMBOL(csr1212_new_icon_descriptor_leaf);
EXPORT_SYMBOL(csr1212_new_modifiable_descriptor_leaf);
EXPORT_SYMBOL(csr1212_new_keyword_leaf);
EXPORT_SYMBOL(csr1212_detach_keyval_from_directory);
EXPORT_SYMBOL(csr1212_disassociate_keyval);
EXPORT_SYMBOL(csr1212_release_keyval);
EXPORT_SYMBOL(csr1212_destroy_csr);
EXPORT_SYMBOL(csr1212_read);
EXPORT_SYMBOL(csr1212_generate_positions);
EXPORT_SYMBOL(csr1212_generate_layout_order);
EXPORT_SYMBOL(csr1212_fill_cache);
EXPORT_SYMBOL(csr1212_generate_csr_image);
EXPORT_SYMBOL(csr1212_parse_keyval);
EXPORT_SYMBOL(csr1212_parse_csr);
EXPORT_SYMBOL(_csr1212_read_keyval);
EXPORT_SYMBOL(_csr1212_destroy_keyval);
This diff is collapsed.
...@@ -21,50 +21,12 @@ ...@@ -21,50 +21,12 @@
#define _IEEE1394_NODEMGR_H #define _IEEE1394_NODEMGR_H
#include <linux/device.h> #include <linux/device.h>
#include "csr1212.h"
#include "ieee1394_core.h" #include "ieee1394_core.h"
#include "ieee1394_hotplug.h" #include "ieee1394_hotplug.h"
#define CONFIG_ROM_BUS_INFO_LENGTH(q) ((q) >> 24)
#define CONFIG_ROM_BUS_CRC_LENGTH(q) (((q) >> 16) & 0xff)
#define CONFIG_ROM_BUS_CRC(q) ((q) & 0xffff)
#define CONFIG_ROM_ROOT_LENGTH(q) ((q) >> 16)
#define CONFIG_ROM_ROOT_CRC(q) ((q) & 0xffff)
#define CONFIG_ROM_DIRECTORY_LENGTH(q) ((q) >> 16)
#define CONFIG_ROM_DIRECTORY_CRC(q) ((q) & 0xffff)
#define CONFIG_ROM_LEAF_LENGTH(q) ((q) >> 16)
#define CONFIG_ROM_LEAF_CRC(q) ((q) & 0xffff)
#define CONFIG_ROM_DESCRIPTOR_TYPE(q) ((q) >> 24)
#define CONFIG_ROM_DESCRIPTOR_SPECIFIER_ID(q) ((q) & 0xffffff)
#define CONFIG_ROM_DESCRIPTOR_WIDTH(q) ((q) >> 28)
#define CONFIG_ROM_DESCRIPTOR_CHAR_SET(q) (((q) >> 16) & 0xfff)
#define CONFIG_ROM_DESCRIPTOR_LANG(q) ((q) & 0xffff)
#define CONFIG_ROM_KEY_ID_MASK 0x3f
#define CONFIG_ROM_KEY_TYPE_MASK 0xc0
#define CONFIG_ROM_KEY_TYPE_IMMEDIATE 0x00
#define CONFIG_ROM_KEY_TYPE_OFFSET 0x40
#define CONFIG_ROM_KEY_TYPE_LEAF 0x80
#define CONFIG_ROM_KEY_TYPE_DIRECTORY 0xc0
#define CONFIG_ROM_KEY(q) ((q) >> 24)
#define CONFIG_ROM_VALUE(q) ((q) & 0xffffff)
#define CONFIG_ROM_VENDOR_ID 0x03
#define CONFIG_ROM_MODEL_ID 0x17
#define CONFIG_ROM_NODE_CAPABILITES 0x0C
#define CONFIG_ROM_UNIT_DIRECTORY 0xd1
#define CONFIG_ROM_LOGICAL_UNIT_DIRECTORY 0xd4
#define CONFIG_ROM_SPECIFIER_ID 0x12
#define CONFIG_ROM_UNIT_SW_VERSION 0x13
#define CONFIG_ROM_DESCRIPTOR_LEAF 0x81
#define CONFIG_ROM_DESCRIPTOR_DIRECTORY 0xc1
/* '1' '3' '9' '4' in ASCII */ /* '1' '3' '9' '4' in ASCII */
#define IEEE1394_BUSID_MAGIC 0x31333934 #define IEEE1394_BUSID_MAGIC __constant_cpu_to_be32(0x31333934)
/* This is the start of a Node entry structure. It should be a stable API /* This is the start of a Node entry structure. It should be a stable API
* for which to gather info from the Node Manager about devices attached * for which to gather info from the Node Manager about devices attached
...@@ -76,6 +38,7 @@ struct bus_options { ...@@ -76,6 +38,7 @@ struct bus_options {
u8 bmc; /* Bus Master Capable */ u8 bmc; /* Bus Master Capable */
u8 pmc; /* Power Manager Capable (PNP spec) */ u8 pmc; /* Power Manager Capable (PNP spec) */
u8 cyc_clk_acc; /* Cycle clock accuracy */ u8 cyc_clk_acc; /* Cycle clock accuracy */
u8 max_rom; /* Maximum block read supported in the CSR */
u8 generation; /* Incremented when configrom changes */ u8 generation; /* Incremented when configrom changes */
u8 lnkspd; /* Link speed */ u8 lnkspd; /* Link speed */
u16 max_rec; /* Maximum packet size node can receive */ u16 max_rec; /* Maximum packet size node can receive */
...@@ -86,10 +49,8 @@ struct bus_options { ...@@ -86,10 +49,8 @@ struct bus_options {
#define UNIT_DIRECTORY_MODEL_ID 0x02 #define UNIT_DIRECTORY_MODEL_ID 0x02
#define UNIT_DIRECTORY_SPECIFIER_ID 0x04 #define UNIT_DIRECTORY_SPECIFIER_ID 0x04
#define UNIT_DIRECTORY_VERSION 0x08 #define UNIT_DIRECTORY_VERSION 0x08
#define UNIT_DIRECTORY_VENDOR_TEXT 0x10 #define UNIT_DIRECTORY_HAS_LUN_DIRECTORY 0x10
#define UNIT_DIRECTORY_MODEL_TEXT 0x20 #define UNIT_DIRECTORY_LUN_DIRECTORY 0x20
#define UNIT_DIRECTORY_HAS_LUN_DIRECTORY 0x40
#define UNIT_DIRECTORY_LUN_DIRECTORY 0x80
/* /*
* A unit directory corresponds to a protocol supported by the * A unit directory corresponds to a protocol supported by the
...@@ -98,17 +59,15 @@ struct bus_options { ...@@ -98,17 +59,15 @@ struct bus_options {
*/ */
struct unit_directory { struct unit_directory {
struct node_entry *ne; /* The node which this directory belongs to */ struct node_entry *ne; /* The node which this directory belongs to */
octlet_t address; /* Address of the unit directory on the node */ octlet_t address; /* Address of the unit directory on the node */
u8 flags; /* Indicates which entries were read */ u8 flags; /* Indicates which entries were read */
quadlet_t vendor_id; quadlet_t vendor_id;
const char *vendor_name; struct csr1212_keyval *vendor_name_kv;
const char *vendor_oui; const char *vendor_oui;
int vendor_name_size;
quadlet_t model_id; quadlet_t model_id;
const char *model_name; struct csr1212_keyval *model_name_kv;
int model_name_size;
quadlet_t specifier_id; quadlet_t specifier_id;
quadlet_t version; quadlet_t version;
...@@ -118,8 +77,7 @@ struct unit_directory { ...@@ -118,8 +77,7 @@ struct unit_directory {
struct device device; struct device device;
/* XXX Must be last in the struct! */ struct csr1212_keyval *ud_kv;
quadlet_t quadlets[0];
}; };
struct node_entry { struct node_entry {
...@@ -135,7 +93,7 @@ struct node_entry { ...@@ -135,7 +93,7 @@ struct node_entry {
/* The following is read from the config rom */ /* The following is read from the config rom */
u32 vendor_id; u32 vendor_id;
const char *vendor_name; struct csr1212_keyval *vendor_name_kv;
const char *vendor_oui; const char *vendor_oui;
u32 capabilities; u32 capabilities;
...@@ -143,8 +101,7 @@ struct node_entry { ...@@ -143,8 +101,7 @@ struct node_entry {
struct device device; struct device device;
/* XXX Must be last in the struct! */ struct csr1212_csr *csr;
quadlet_t quadlets[0];
}; };
struct hpsb_protocol_driver { struct hpsb_protocol_driver {
......
...@@ -115,6 +115,7 @@ ...@@ -115,6 +115,7 @@
#include <asm/pci-bridge.h> #include <asm/pci-bridge.h>
#endif #endif
#include "csr1212.h"
#include "ieee1394.h" #include "ieee1394.h"
#include "ieee1394_types.h" #include "ieee1394_types.h"
#include "hosts.h" #include "hosts.h"
...@@ -161,7 +162,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args) ...@@ -161,7 +162,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args) printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
static char version[] __devinitdata = static char version[] __devinitdata =
"$Rev: 1097 $ Ben Collins <bcollins@debian.org>"; "$Rev: 1118 $ Ben Collins <bcollins@debian.org>";
/* Module Parameters */ /* Module Parameters */
static int phys_dma = 1; static int phys_dma = 1;
...@@ -495,8 +496,6 @@ static int get_nb_iso_ctx(struct ti_ohci *ohci, int reg) ...@@ -495,8 +496,6 @@ static int get_nb_iso_ctx(struct ti_ohci *ohci, int reg)
return ctx; return ctx;
} }
static void ohci_init_config_rom(struct ti_ohci *ohci);
/* Global initialization */ /* Global initialization */
static void ohci_initialize(struct ti_ohci *ohci) static void ohci_initialize(struct ti_ohci *ohci)
{ {
...@@ -540,9 +539,6 @@ static void ohci_initialize(struct ti_ohci *ohci) ...@@ -540,9 +539,6 @@ static void ohci_initialize(struct ti_ohci *ohci)
/* Set the Config ROM mapping register */ /* Set the Config ROM mapping register */
reg_write(ohci, OHCI1394_ConfigROMmap, ohci->csr_config_rom_bus); reg_write(ohci, OHCI1394_ConfigROMmap, ohci->csr_config_rom_bus);
/* Initialize the Config ROM */
ohci_init_config_rom(ohci);
/* Now get our max packet size */ /* Now get our max packet size */
ohci->max_packet_size = ohci->max_packet_size =
1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1); 1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1);
...@@ -3085,154 +3081,16 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d, ...@@ -3085,154 +3081,16 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
return 0; return 0;
} }
static u16 ohci_crc16 (u32 *ptr, int length) static void ohci_set_hw_config_rom(struct hpsb_host *host, quadlet_t *config_rom)
{
int shift;
u32 crc, sum, data;
crc = 0;
for (; length > 0; length--) {
data = be32_to_cpu(*ptr++);
for (shift = 28; shift >= 0; shift -= 4) {
sum = ((crc >> 12) ^ (data >> shift)) & 0x000f;
crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum;
}
crc &= 0xffff;
}
return crc;
}
/* Config ROM macro implementation influenced by NetBSD OHCI driver */
struct config_rom_unit {
u32 *start;
u32 *refer;
int length;
int refunit;
};
struct config_rom_ptr {
u32 *data;
int unitnum;
struct config_rom_unit unitdir[10];
};
#define cf_put_1quad(cr, q) (((cr)->data++)[0] = cpu_to_be32(q))
#define cf_put_4bytes(cr, b1, b2, b3, b4) \
(((cr)->data++)[0] = cpu_to_be32(((b1) << 24) | ((b2) << 16) | ((b3) << 8) | (b4)))
#define cf_put_keyval(cr, key, val) (((cr)->data++)[0] = cpu_to_be32(((key) << 24) | (val)))
static inline void cf_put_str(struct config_rom_ptr *cr, const char *str)
{
int t;
char fourb[4];
while (str[0]) {
memset(fourb, 0, 4);
for (t = 0; t < 4 && str[t]; t++)
fourb[t] = str[t];
cf_put_4bytes(cr, fourb[0], fourb[1], fourb[2], fourb[3]);
str += strlen(str) < 4 ? strlen(str) : 4;
}
return;
}
static inline void cf_put_crc16(struct config_rom_ptr *cr, int unit)
{
*cr->unitdir[unit].start =
cpu_to_be32((cr->unitdir[unit].length << 16) |
ohci_crc16(cr->unitdir[unit].start + 1,
cr->unitdir[unit].length));
}
static inline void cf_unit_begin(struct config_rom_ptr *cr, int unit)
{
if (cr->unitdir[unit].refer != NULL) {
*cr->unitdir[unit].refer |=
cpu_to_be32 (cr->data - cr->unitdir[unit].refer);
cf_put_crc16(cr, cr->unitdir[unit].refunit);
}
cr->unitnum = unit;
cr->unitdir[unit].start = cr->data++;
}
static inline void cf_put_refer(struct config_rom_ptr *cr, char key, int unit)
{ {
cr->unitdir[unit].refer = cr->data; struct ti_ohci *ohci = host->hostdata;
cr->unitdir[unit].refunit = cr->unitnum;
(cr->data++)[0] = cpu_to_be32(key << 24);
}
static inline void cf_unit_end(struct config_rom_ptr *cr)
{
cr->unitdir[cr->unitnum].length = cr->data -
(cr->unitdir[cr->unitnum].start + 1);
cf_put_crc16(cr, cr->unitnum);
}
/* End of NetBSD derived code. */ reg_write(ohci, OHCI1394_ConfigROMhdr, be32_to_cpu(config_rom[0]));
reg_write(ohci, OHCI1394_BusOptions, be32_to_cpu(config_rom[2]));
static void ohci_init_config_rom(struct ti_ohci *ohci) memcpy(ohci->csr_config_rom_cpu, config_rom, OHCI_CONFIG_ROM_LEN);
{
struct config_rom_ptr cr;
memset(&cr, 0, sizeof(cr));
memset(ohci->csr_config_rom_cpu, 0, OHCI_CONFIG_ROM_LEN);
cr.data = ohci->csr_config_rom_cpu;
/* Bus info block */
cf_unit_begin(&cr, 0);
cf_put_1quad(&cr, reg_read(ohci, OHCI1394_BusID));
cf_put_1quad(&cr, reg_read(ohci, OHCI1394_BusOptions));
cf_put_1quad(&cr, reg_read(ohci, OHCI1394_GUIDHi));
cf_put_1quad(&cr, reg_read(ohci, OHCI1394_GUIDLo));
cf_unit_end(&cr);
DBGMSG(ohci->id, "GUID: %08x:%08x", reg_read(ohci, OHCI1394_GUIDHi),
reg_read(ohci, OHCI1394_GUIDLo));
/* IEEE P1212 suggests the initial ROM header CRC should only
* cover the header itself (and not the entire ROM). Since we do
* this, then we can make our bus_info_len the same as the CRC
* length. */
ohci->csr_config_rom_cpu[0] |= cpu_to_be32(
(be32_to_cpu(ohci->csr_config_rom_cpu[0]) & 0x00ff0000) << 8);
reg_write(ohci, OHCI1394_ConfigROMhdr,
be32_to_cpu(ohci->csr_config_rom_cpu[0]));
/* Root directory */
cf_unit_begin(&cr, 1);
/* Vendor ID */
cf_put_keyval(&cr, 0x03, reg_read(ohci,OHCI1394_VendorID) & 0xFFFFFF);
cf_put_refer(&cr, 0x81, 2); /* Textual description unit */
cf_put_keyval(&cr, 0x0c, 0x0083c0); /* Node capabilities */
/* NOTE: Add other unit referers here, and append at bottom */
cf_unit_end(&cr);
/* Textual description - "Linux 1394" */
cf_unit_begin(&cr, 2);
cf_put_keyval(&cr, 0, 0);
cf_put_1quad(&cr, 0);
cf_put_str(&cr, "Linux OHCI-1394");
cf_unit_end(&cr);
ohci->csr_config_rom_length = cr.data - ohci->csr_config_rom_cpu;
} }
static size_t ohci_get_rom(struct hpsb_host *host, quadlet_t **ptr)
{
struct ti_ohci *ohci=host->hostdata;
DBGMSG(ohci->id, "request csr_rom address: %p",
ohci->csr_config_rom_cpu);
*ptr = ohci->csr_config_rom_cpu;
return ohci->csr_config_rom_length * 4;
}
static quadlet_t ohci_hw_csr_reg(struct hpsb_host *host, int reg, static quadlet_t ohci_hw_csr_reg(struct hpsb_host *host, int reg,
quadlet_t data, quadlet_t compare) quadlet_t data, quadlet_t compare)
...@@ -3257,7 +3115,7 @@ static quadlet_t ohci_hw_csr_reg(struct hpsb_host *host, int reg, ...@@ -3257,7 +3115,7 @@ static quadlet_t ohci_hw_csr_reg(struct hpsb_host *host, int reg,
static struct hpsb_host_driver ohci1394_driver = { static struct hpsb_host_driver ohci1394_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = OHCI1394_DRIVER_NAME, .name = OHCI1394_DRIVER_NAME,
.get_rom = ohci_get_rom, .set_hw_config_rom = ohci_set_hw_config_rom,
.transmit_packet = ohci_transmit, .transmit_packet = ohci_transmit,
.devctl = ohci_devctl, .devctl = ohci_devctl,
.isoctl = ohci_isoctl, .isoctl = ohci_isoctl,
...@@ -3280,6 +3138,11 @@ do { \ ...@@ -3280,6 +3138,11 @@ do { \
static int __devinit ohci1394_pci_probe(struct pci_dev *dev, static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
struct csr1212_keyval *root;
struct csr1212_keyval *vend_id = NULL;
struct csr1212_keyval *text = NULL;
int ret;
static int version_printed = 0; static int version_printed = 0;
struct hpsb_host *host; struct hpsb_host *host;
...@@ -3458,6 +3321,45 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev, ...@@ -3458,6 +3321,45 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
ohci->init_state = OHCI_INIT_HAVE_IRQ; ohci->init_state = OHCI_INIT_HAVE_IRQ;
ohci_initialize(ohci); ohci_initialize(ohci);
/* Setup initial root directory entries */
root = host->csr.rom->root_kv;
vend_id = csr1212_new_immediate(CSR1212_KV_ID_VENDOR,
reg_read(ohci, OHCI1394_GUIDHi) >> 8);
text = csr1212_new_string_descriptor_leaf("Linux 1394 - OHCI");
if (!vend_id || !text) {
if (vend_id) {
csr1212_release_keyval(vend_id);
}
if (text) {
csr1212_release_keyval(text);
}
FAIL(-ENOMEM, "Failed to allocate memory for mandatory ConfigROM entries!");
}
ret = csr1212_associate_keyval(vend_id, text);
csr1212_release_keyval(text);
if(ret != CSR1212_SUCCESS) {
csr1212_release_keyval(vend_id);
FAIL(ret, "Failed to associate text descriptor to vendor id");
}
ret = csr1212_attach_keyval_to_directory(root, vend_id);
if(ret != CSR1212_SUCCESS) {
csr1212_release_keyval(vend_id);
FAIL(ret, "Failed to attach vendor id to root directory");
}
host->update_config_rom = 1;
/* Set certain csr values */
host->csr.guid_hi = reg_read(ohci, OHCI1394_GUIDHi);
host->csr.guid_lo = reg_read(ohci, OHCI1394_GUIDLo);
host->csr.cyc_clk_acc = 100; /* how do we determine clk accuracy? */
host->csr.max_rec = (reg_read(ohci, OHCI1394_BusOptions) >> 12) & 0xf;
host->csr.lnk_spd = reg_read(ohci, OHCI1394_BusOptions) & 0x7;
/* Tell the highlevel this host is ready */ /* Tell the highlevel this host is ready */
hpsb_add_host(host); hpsb_add_host(host);
ohci->init_state = OHCI_INIT_DONE; ohci->init_state = OHCI_INIT_DONE;
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "csr1212.h"
#include "ieee1394.h" #include "ieee1394.h"
#include "ieee1394_types.h" #include "ieee1394_types.h"
#include "hosts.h" #include "hosts.h"
...@@ -1515,6 +1516,11 @@ static int __devinit add_card(struct pci_dev *dev, ...@@ -1515,6 +1516,11 @@ static int __devinit add_card(struct pci_dev *dev,
return error; \ return error; \
} while (0) } while (0)
struct csr1212_keyval *root;
struct csr1212_keyval *vend_id = NULL;
struct csr1212_keyval *text = NULL;
int ret;
char irq_buf[16]; char irq_buf[16];
struct hpsb_host *host; struct hpsb_host *host;
struct ti_lynx *lynx; /* shortcut to currently handled device */ struct ti_lynx *lynx; /* shortcut to currently handled device */
...@@ -1527,8 +1533,6 @@ static int __devinit add_card(struct pci_dev *dev, ...@@ -1527,8 +1533,6 @@ static int __devinit add_card(struct pci_dev *dev,
struct i2c_adapter i2c_adapter; struct i2c_adapter i2c_adapter;
struct i2c_algo_bit_data i2c_adapter_data; struct i2c_algo_bit_data i2c_adapter_data;
int got_valid_bus_info_block = 0; /* set to 1, if we were able to get a valid bus info block from serial eeprom */
error = -ENXIO; error = -ENXIO;
if (pci_set_dma_mask(dev, 0xffffffff)) if (pci_set_dma_mask(dev, 0xffffffff))
...@@ -1814,14 +1818,15 @@ static int __devinit add_card(struct pci_dev *dev, ...@@ -1814,14 +1818,15 @@ static int __devinit add_card(struct pci_dev *dev,
if (i2c_bit_add_bus(&i2c_adapter) < 0) if (i2c_bit_add_bus(&i2c_adapter) < 0)
{ {
PRINT(KERN_ERR, lynx->id, "unable to register i2c"); error = -ENXIO;
FAIL("unable to register i2c");
} }
else else
{ {
/* do i2c stuff */ /* do i2c stuff */
unsigned char i2c_cmd = 0x10; unsigned char i2c_cmd = 0x10;
struct i2c_msg msg[2] = { { 0x50, 0, 1, &i2c_cmd }, struct i2c_msg msg[2] = { { 0x50, 0, 1, &i2c_cmd },
{ 0x50, I2C_M_RD, 20, (unsigned char*) lynx->config_rom } { 0x50, I2C_M_RD, 20, (unsigned char*) lynx->bus_info_block }
}; };
...@@ -1858,16 +1863,16 @@ static int __devinit add_card(struct pci_dev *dev, ...@@ -1858,16 +1863,16 @@ static int __devinit add_card(struct pci_dev *dev,
for (i = 0; i < 5 ; i++) for (i = 0; i < 5 ; i++)
PRINTD(KERN_DEBUG, lynx->id, "Businfo block quadlet %i: %08x", PRINTD(KERN_DEBUG, lynx->id, "Businfo block quadlet %i: %08x",
i, be32_to_cpu(lynx->config_rom[i])); i, be32_to_cpu(lynx->bus_info_block[i]));
/* info_length, crc_length and 1394 magic number to check, if it is really a bus info block */ /* info_length, crc_length and 1394 magic number to check, if it is really a bus info block */
if (((be32_to_cpu(lynx->config_rom[0]) & 0xffff0000) == 0x04040000) && if (((be32_to_cpu(lynx->bus_info_block[0]) & 0xffff0000) == 0x04040000) &&
(lynx->config_rom[1] == __constant_cpu_to_be32(0x31333934))) (lynx->bus_info_block[1] == __constant_cpu_to_be32(0x31333934)))
{ {
PRINT(KERN_DEBUG, lynx->id, "read a valid bus info block from"); PRINT(KERN_DEBUG, lynx->id, "read a valid bus info block from");
got_valid_bus_info_block = 1;
} else { } else {
PRINT(KERN_WARNING, lynx->id, "read something from serial eeprom, but it does not seem to be a valid bus info block"); error = -ENXIO;
FAIL("read something from serial eeprom, but it does not seem to be a valid bus info block");
} }
} }
...@@ -1876,29 +1881,55 @@ static int __devinit add_card(struct pci_dev *dev, ...@@ -1876,29 +1881,55 @@ static int __devinit add_card(struct pci_dev *dev,
} }
} }
if (got_valid_bus_info_block) { host->csr.guid_hi = be32_to_cpu(lynx->bus_info_block[3]);
memcpy(lynx->config_rom+5,lynx_csr_rom+5,sizeof(lynx_csr_rom)-20); host->csr.guid_lo = be32_to_cpu(lynx->bus_info_block[4]);
} else { host->csr.cyc_clk_acc = (be32_to_cpu(lynx->bus_info_block[2]) >> 16) & 0xff;
PRINT(KERN_INFO, lynx->id, "since we did not get a bus info block from serial eeprom, we use a generic one with a hard coded GUID"); host->csr.max_rec = (be32_to_cpu(lynx->bus_info_block[2]) >> 12) & 0xf;
memcpy(lynx->config_rom,lynx_csr_rom,sizeof(lynx_csr_rom)); if (!lynx->phyic.reg_1394a)
} host->csr.lnk_spd = (get_phy_reg(lynx, 2) & 0xc0) >> 6;
else
hpsb_add_host(host); host->csr.lnk_spd = be32_to_cpu(lynx->bus_info_block[2]) & 0x7;
lynx->state = is_host;
/* Setup initial root directory entries */
root = host->csr.rom->root_kv;
vend_id = csr1212_new_immediate(CSR1212_KV_ID_VENDOR,
be32_to_cpu(lynx->bus_info_block[3]) >> 8);
text = csr1212_new_string_descriptor_leaf("Linux 1394 - PCI-Lynx");
if (!vend_id || !text) {
if (vend_id)
csr1212_release_keyval(vend_id);
if (text)
csr1212_release_keyval(text);
error = -ENOMEM;
FAIL("Failed to allocate memory for mandatory ConfigROM entries!");
}
return 0; ret = csr1212_associate_keyval(vend_id, text);
#undef FAIL csr1212_release_keyval(text); /* no longer needed locally. */
} if(ret != CSR1212_SUCCESS) {
csr1212_release_keyval(vend_id);
error = ret;
FAIL("Failed to associate text descriptor to vendor id");
}
ret = csr1212_attach_keyval_to_directory(root, vend_id);
csr1212_release_keyval(vend_id); /* no longer needed locally. */
if(ret != CSR1212_SUCCESS) {
error = ret;
FAIL("Failed to attach vendor id to root directory");
}
host->update_config_rom = 1;
hpsb_add_host(host);
lynx->state = is_host;
static size_t get_lynx_rom(struct hpsb_host *host, quadlet_t **ptr) return ret;
{ #undef FAIL
struct ti_lynx *lynx = host->hostdata;
*ptr = lynx->config_rom;
return sizeof(lynx_csr_rom);
} }
static struct pci_device_id pci_table[] = { static struct pci_device_id pci_table[] = {
{ {
.vendor = PCI_VENDOR_ID_TI, .vendor = PCI_VENDOR_ID_TI,
...@@ -1919,7 +1950,7 @@ static struct pci_driver lynx_pci_driver = { ...@@ -1919,7 +1950,7 @@ static struct pci_driver lynx_pci_driver = {
static struct hpsb_host_driver lynx_driver = { static struct hpsb_host_driver lynx_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = PCILYNX_DRIVER_NAME, .name = PCILYNX_DRIVER_NAME,
.get_rom = get_lynx_rom, .set_hw_config_rom = NULL,
.transmit_packet = lynx_transmit, .transmit_packet = lynx_transmit,
.devctl = lynx_devctl, .devctl = lynx_devctl,
.isoctl = NULL, .isoctl = NULL,
......
#ifndef __PCILYNX_H__
#define __PCILYNX_H__
#include <linux/config.h> #include <linux/config.h>
#define PCILYNX_DRIVER_NAME "pcilynx" #define PCILYNX_DRIVER_NAME "pcilynx"
...@@ -50,7 +53,7 @@ struct ti_lynx { ...@@ -50,7 +53,7 @@ struct ti_lynx {
void *local_rom; void *local_rom;
void *local_ram; void *local_ram;
void *aux_port; void *aux_port;
quadlet_t config_rom[PCILYNX_CONFIG_ROM_LENGTH/4]; quadlet_t bus_info_block[5];
#ifdef CONFIG_IEEE1394_PCILYNX_PORTS #ifdef CONFIG_IEEE1394_PCILYNX_PORTS
atomic_t aux_intr_seen; atomic_t aux_intr_seen;
...@@ -510,76 +513,4 @@ static inline void run_pcl(const struct ti_lynx *lynx, pcl_t pclid, int dmachan) ...@@ -510,76 +513,4 @@ static inline void run_pcl(const struct ti_lynx *lynx, pcl_t pclid, int dmachan)
#define PCL_BIGENDIAN (1<<16) #define PCL_BIGENDIAN (1<<16)
#define PCL_ISOMODE (1<<12) #define PCL_ISOMODE (1<<12)
#endif
#define _(x) (__constant_cpu_to_be32(x))
static quadlet_t lynx_csr_rom[] = {
/* bus info block offset (hex) */
_(0x04046aaf), /* info/CRC length, CRC 400 */
_(0x31333934), /* 1394 magic number 404 */
_(0xf064a000), /* misc. settings 408 */
_(0x08002850), /* vendor ID, chip ID high 40c */
_(0x0000ffff), /* chip ID low 410 */
/* root directory */
_(0x00095778), /* directory length, CRC 414 */
_(0x03080028), /* vendor ID (Texas Instr.) 418 */
_(0x81000008), /* offset to textual ID 41c */
_(0x0c000200), /* node capabilities 420 */
_(0x8d00000e), /* offset to unique ID 424 */
_(0xc7000010), /* offset to module independent info 428 */
_(0x04000000), /* module hardware version 42c */
_(0x81000014), /* offset to textual ID 430 */
_(0x09000000), /* node hardware version 434 */
_(0x81000018), /* offset to textual ID 438 */
/* module vendor ID textual */
_(0x00070812), /* CRC length, CRC 43c */
_(0x00000000), /* 440 */
_(0x00000000), /* 444 */
_(0x54455841), /* "Texas Instruments" 448 */
_(0x5320494e), /* 44c */
_(0x53545255), /* 450 */
_(0x4d454e54), /* 454 */
_(0x53000000), /* 458 */
/* node unique ID leaf */
_(0x00022ead), /* CRC length, CRC 45c */
_(0x08002850), /* vendor ID, chip ID high 460 */
_(0x0000ffff), /* chip ID low 464 */
/* module dependent info */
_(0x0005d837), /* CRC length, CRC 468 */
_(0x81000012), /* offset to module textual ID 46c */
_(0x81000017), /* textual descriptor 470 */
_(0x39010000), /* SRAM size 474 */
_(0x3a010000), /* AUXRAM size 478 */
_(0x3b000000), /* AUX device 47c */
/* module textual ID */
_(0x000594df), /* CRC length, CRC 480 */
_(0x00000000), /* 484 */
_(0x00000000), /* 488 */
_(0x54534231), /* "TSB12LV21" 48c */
_(0x324c5632), /* 490 */
_(0x31000000), /* 494 */
/* part number */
_(0x00068405), /* CRC length, CRC 498 */
_(0x00000000), /* 49c */
_(0x00000000), /* 4a0 */
_(0x39383036), /* "9806000-0001" 4a4 */
_(0x3030302d), /* 4a8 */
_(0x30303031), /* 4ac */
_(0x20000001), /* 4b0 */
/* module hardware version textual */
_(0x00056501), /* CRC length, CRC 4b4 */
_(0x00000000), /* 4b8 */
_(0x00000000), /* 4bc */
_(0x5453424b), /* "TSBKPCITST" 4c0 */
_(0x50434954), /* 4c4 */
_(0x53540000), /* 4c8 */
/* node hardware version textual */
_(0x0005d805), /* CRC length, CRC 4d0 */
_(0x00000000), /* 4d4 */
_(0x00000000), /* 4d8 */
_(0x54534232), /* "TSB21LV03" 4dc */
_(0x314c5630), /* 4e0 */
_(0x33000000) /* 4e4 */
};
#undef _
This diff is collapsed.
This diff is collapsed.
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#define RAW1394_REQ_GET_ROM 203 #define RAW1394_REQ_GET_ROM 203
#define RAW1394_REQ_UPDATE_ROM 204 #define RAW1394_REQ_UPDATE_ROM 204
#define RAW1394_REQ_ECHO 205 #define RAW1394_REQ_ECHO 205
#define RAW1394_REQ_MODIFY_ROM 206
#define RAW1394_REQ_ARM_REGISTER 300 #define RAW1394_REQ_ARM_REGISTER 300
#define RAW1394_REQ_ARM_UNREGISTER 301 #define RAW1394_REQ_ARM_UNREGISTER 301
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment