Commit 959a9729 authored by Ben Collins's avatar Ben Collins Committed by Linus Torvalds

[PATCH] IEEE-1394 updates

Syncronizes with our SVN repo. Merged in all changes from your tree.
parent c9c13c7b
This diff is collapsed.
...@@ -19,13 +19,24 @@ ...@@ -19,13 +19,24 @@
* AMDTP_FORMAT_IEC958_AC3 will transmit the samples with the data bit * AMDTP_FORMAT_IEC958_AC3 will transmit the samples with the data bit
* set, suitable for transmitting compressed AC-3 audio. * set, suitable for transmitting compressed AC-3 audio.
* *
* The rate field specifies the transmission rate; supported values are * The rate field specifies the transmission rate; supported values
* AMDTP_RATE_32KHZ, AMDTP_RATE_44K1HZ and AMDTP_RATE_48KHZ. * are 32000, 44100, 48000, 88200, 96000, 176400 and 192000.
* *
* The dimension field specifies the dimension of the signal, that is, * The dimension field specifies the dimension of the signal, that is,
* the number of audio channels. Only AMDTP_FORMAT_RAW supports * the number of audio channels. Only AMDTP_FORMAT_RAW supports
* settings greater than 2. * settings greater than 2.
* *
* The mode field specifies which transmission mode to use. The AMDTP
* specifies two different transmission modes: blocking and
* non-blocking. The blocking transmission mode always send a fixed
* number of samples, typically 8, 16 or 32. To exactly match the
* transmission rate, the driver alternates between sending empty and
* non-empty packets. In non-blocking mode, the driver transmits as
* small packets as possible. For example, for a transmission rate of
* 44100Hz, the driver should send 5 41/80 samples in every cycle, but
* this is not possible so instead the driver alternates between
* sending 5 and 6 samples.
*
* The last thing to specify is either the isochronous channel to use * The last thing to specify is either the isochronous channel to use
* or the output plug to connect to. If you know what channel the * or the output plug to connect to. If you know what channel the
* destination device will listen on, you can specify the channel * destination device will listen on, you can specify the channel
...@@ -60,15 +71,20 @@ enum { ...@@ -60,15 +71,20 @@ enum {
}; };
enum { enum {
AMDTP_RATE_32KHZ, AMDTP_MODE_BLOCKING,
AMDTP_RATE_44K1HZ, AMDTP_MODE_NON_BLOCKING,
AMDTP_RATE_48KHZ, };
enum {
AMDTP_INPUT_LE16,
AMDTP_INPUT_BE16,
}; };
struct amdtp_ioctl { struct amdtp_ioctl {
__u32 format; __u32 format;
__u32 rate; __u32 rate;
__u32 dimension; __u32 dimension;
__u32 mode;
union { __u32 channel; __u32 plug; } u; union { __u32 channel; __u32 plug; } u;
}; };
......
...@@ -299,14 +299,14 @@ static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, ...@@ -299,14 +299,14 @@ static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
static struct hpsb_highlevel_ops cmp_highlevel_ops = { static struct hpsb_highlevel_ops cmp_highlevel_ops = {
add_host: cmp_add_host, .add_host = cmp_add_host,
remove_host: cmp_remove_host, .remove_host = cmp_remove_host,
host_reset: cmp_host_reset, .host_reset = cmp_host_reset,
}; };
static struct hpsb_address_ops pcr_ops = { static struct hpsb_address_ops pcr_ops = {
read: pcr_read, .read = pcr_read,
lock: pcr_lock, .lock = pcr_lock,
}; };
/* Module interface */ /* Module interface */
......
...@@ -70,7 +70,7 @@ static void add_host(struct hpsb_host *host) ...@@ -70,7 +70,7 @@ 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->ops->get_rom(host, &host->csr.rom); host->csr.rom_size = host->driver->get_rom(host, &host->csr.rom);
host->csr.state = 0; host->csr.state = 0;
host->csr.node_ids = 0; host->csr.node_ids = 0;
...@@ -152,7 +152,7 @@ static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf, ...@@ -152,7 +152,7 @@ static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf,
case CSR_CYCLE_TIME: case CSR_CYCLE_TIME:
oldcycle = host->csr.cycle_time; oldcycle = host->csr.cycle_time;
host->csr.cycle_time = host->csr.cycle_time =
host->ops->devctl(host, GET_CYCLE_COUNTER, 0); host->driver->devctl(host, GET_CYCLE_COUNTER, 0);
if (oldcycle > host->csr.cycle_time) { if (oldcycle > host->csr.cycle_time) {
/* cycle time wrapped around */ /* cycle time wrapped around */
...@@ -163,7 +163,7 @@ static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf, ...@@ -163,7 +163,7 @@ static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf,
case CSR_BUS_TIME: case CSR_BUS_TIME:
oldcycle = host->csr.cycle_time; oldcycle = host->csr.cycle_time;
host->csr.cycle_time = host->csr.cycle_time =
host->ops->devctl(host, GET_CYCLE_COUNTER, 0); host->driver->devctl(host, GET_CYCLE_COUNTER, 0);
if (oldcycle > host->csr.cycle_time) { if (oldcycle > host->csr.cycle_time) {
/* cycle time wrapped around */ /* cycle time wrapped around */
...@@ -181,32 +181,32 @@ static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf, ...@@ -181,32 +181,32 @@ static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf,
return RCODE_ADDRESS_ERROR; return RCODE_ADDRESS_ERROR;
case CSR_BUS_MANAGER_ID: case CSR_BUS_MANAGER_ID:
if (host->ops->hw_csr_reg) if (host->driver->hw_csr_reg)
ret = host->ops->hw_csr_reg(host, 0, 0, 0); ret = host->driver->hw_csr_reg(host, 0, 0, 0);
else else
ret = host->csr.bus_manager_id; ret = host->csr.bus_manager_id;
*(buf++) = cpu_to_be32(ret); *(buf++) = cpu_to_be32(ret);
out; out;
case CSR_BANDWIDTH_AVAILABLE: case CSR_BANDWIDTH_AVAILABLE:
if (host->ops->hw_csr_reg) if (host->driver->hw_csr_reg)
ret = host->ops->hw_csr_reg(host, 1, 0, 0); ret = host->driver->hw_csr_reg(host, 1, 0, 0);
else else
ret = host->csr.bandwidth_available; ret = host->csr.bandwidth_available;
*(buf++) = cpu_to_be32(ret); *(buf++) = cpu_to_be32(ret);
out; out;
case CSR_CHANNELS_AVAILABLE_HI: case CSR_CHANNELS_AVAILABLE_HI:
if (host->ops->hw_csr_reg) if (host->driver->hw_csr_reg)
ret = host->ops->hw_csr_reg(host, 2, 0, 0); ret = host->driver->hw_csr_reg(host, 2, 0, 0);
else else
ret = host->csr.channels_available_hi; ret = host->csr.channels_available_hi;
*(buf++) = cpu_to_be32(ret); *(buf++) = cpu_to_be32(ret);
out; out;
case CSR_CHANNELS_AVAILABLE_LO: case CSR_CHANNELS_AVAILABLE_LO:
if (host->ops->hw_csr_reg) if (host->driver->hw_csr_reg)
ret = host->ops->hw_csr_reg(host, 3, 0, 0); ret = host->driver->hw_csr_reg(host, 3, 0, 0);
else else
ret = host->csr.channels_available_lo; ret = host->csr.channels_available_lo;
...@@ -244,7 +244,7 @@ static int write_regs(struct hpsb_host *host, int nodeid, int destid, ...@@ -244,7 +244,7 @@ static int write_regs(struct hpsb_host *host, int nodeid, int destid,
host->csr.node_ids &= NODE_MASK << 16; host->csr.node_ids &= NODE_MASK << 16;
host->csr.node_ids |= be32_to_cpu(*(data++)) & (BUS_MASK << 16); host->csr.node_ids |= be32_to_cpu(*(data++)) & (BUS_MASK << 16);
host->node_id = host->csr.node_ids >> 16; host->node_id = host->csr.node_ids >> 16;
host->ops->devctl(host, SET_BUS_ID, host->node_id >> 6); host->driver->devctl(host, SET_BUS_ID, host->node_id >> 6);
out; out;
case CSR_RESET_START: case CSR_RESET_START:
...@@ -269,7 +269,7 @@ static int write_regs(struct hpsb_host *host, int nodeid, int destid, ...@@ -269,7 +269,7 @@ static int write_regs(struct hpsb_host *host, int nodeid, int destid,
case CSR_CYCLE_TIME: case CSR_CYCLE_TIME:
/* should only be set by cycle start packet, automatically */ /* should only be set by cycle start packet, automatically */
host->csr.cycle_time = be32_to_cpu(*data); host->csr.cycle_time = be32_to_cpu(*data);
host->ops->devctl(host, SET_CYCLE_COUNTER, host->driver->devctl(host, SET_CYCLE_COUNTER,
be32_to_cpu(*(data++))); be32_to_cpu(*(data++)));
out; out;
case CSR_BUS_TIME: case CSR_BUS_TIME:
...@@ -318,10 +318,10 @@ static int lock_regs(struct hpsb_host *host, int nodeid, quadlet_t *store, ...@@ -318,10 +318,10 @@ static int lock_regs(struct hpsb_host *host, int nodeid, quadlet_t *store,
data = be32_to_cpu(data); data = be32_to_cpu(data);
arg = be32_to_cpu(arg); arg = be32_to_cpu(arg);
if (host->ops->hw_csr_reg) { if (host->driver->hw_csr_reg) {
quadlet_t old; quadlet_t old;
old = host->ops-> old = host->driver->
hw_csr_reg(host, (csraddr - CSR_BUS_MANAGER_ID) >> 2, hw_csr_reg(host, (csraddr - CSR_BUS_MANAGER_ID) >> 2,
data, arg); data, arg);
...@@ -402,23 +402,23 @@ static int write_fcp(struct hpsb_host *host, int nodeid, int dest, ...@@ -402,23 +402,23 @@ static int write_fcp(struct hpsb_host *host, int nodeid, int dest,
static struct hpsb_highlevel_ops csr_ops = { static struct hpsb_highlevel_ops csr_ops = {
add_host: add_host, .add_host = add_host,
host_reset: host_reset, .host_reset = host_reset,
}; };
static struct hpsb_address_ops map_ops = { static struct hpsb_address_ops map_ops = {
read: read_maps, .read = read_maps,
}; };
static struct hpsb_address_ops fcp_ops = { static struct hpsb_address_ops fcp_ops = {
write: write_fcp, .write = write_fcp,
}; };
static struct hpsb_address_ops reg_ops = { static struct hpsb_address_ops reg_ops = {
read: read_regs, .read = read_regs,
write: write_regs, .write = write_regs,
lock: lock_regs, .lock = lock_regs,
}; };
static struct hpsb_highlevel *hl; static struct hpsb_highlevel *hl;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#define _DV_1394_PRIVATE_H #define _DV_1394_PRIVATE_H
#include "ieee1394.h" #include "ieee1394.h"
#include "ohci1394.h"
#include <linux/pci.h> #include <linux/pci.h>
#include <asm/scatterlist.h> #include <asm/scatterlist.h>
...@@ -91,20 +92,20 @@ static inline void fill_output_more_immediate(struct output_more_immediate *omi, ...@@ -91,20 +92,20 @@ static inline void fill_output_more_immediate(struct output_more_immediate *omi,
unsigned char sync_tag, unsigned char sync_tag,
unsigned int payload_size) unsigned int payload_size)
{ {
omi->q[0] = 0x02000000 | 8 ; /* OUTPUT_MORE_IMMEDIATE; 8 is the size of the IT header */ omi->q[0] = cpu_to_le32(0x02000000 | 8); /* OUTPUT_MORE_IMMEDIATE; 8 is the size of the IT header */
omi->q[1] = 0; omi->q[1] = 0;
omi->q[2] = 0; omi->q[2] = 0;
omi->q[3] = 0; omi->q[3] = 0;
/* IT packet header */ /* IT packet header */
omi->q[4] = (0x0 << 16) /* DMA_SPEED_100 */ omi->q[4] = cpu_to_le32( (0x0 << 16) /* DMA_SPEED_100 */
| (tag << 14) | (tag << 14)
| (channel << 8) | (channel << 8)
| (TCODE_ISO_DATA << 4) | (TCODE_ISO_DATA << 4)
| (sync_tag); | (sync_tag) );
omi->q[5] = payload_size << 16; /* reserved field; mimic behavior of my Sony DSR-40 */
omi->q[5] |= (0x7F << 8) | 0xA0; /* reserved field; mimic behavior of my Sony DSR-40 */ omi->q[5] = cpu_to_le32((payload_size << 16) | (0x7F << 8) | 0xA0);
omi->q[6] = 0; omi->q[6] = 0;
omi->q[7] = 0; omi->q[7] = 0;
...@@ -114,10 +115,8 @@ static inline void fill_output_more(struct output_more *om, ...@@ -114,10 +115,8 @@ static inline void fill_output_more(struct output_more *om,
unsigned int data_size, unsigned int data_size,
unsigned long data_phys_addr) unsigned long data_phys_addr)
{ {
om->q[0] = 0; /* OUTPUT_MORE */ om->q[0] = cpu_to_le32(data_size);
om->q[0] |= data_size; om->q[1] = cpu_to_le32(data_phys_addr);
om->q[1] = data_phys_addr;
om->q[2] = 0; om->q[2] = 0;
om->q[3] = 0; om->q[3] = 0;
} }
...@@ -128,19 +127,20 @@ static inline void fill_output_last(struct output_last *ol, ...@@ -128,19 +127,20 @@ static inline void fill_output_last(struct output_last *ol,
unsigned int data_size, unsigned int data_size,
unsigned long data_phys_addr) unsigned long data_phys_addr)
{ {
ol->q[0] = 0; u32 temp = 0;
ol->q[0] |= 1 << 28; /* OUTPUT_LAST */ temp |= 1 << 28; /* OUTPUT_LAST */
if(want_timestamp) /* controller will update timestamp at DMA time */ if(want_timestamp) /* controller will update timestamp at DMA time */
ol->q[0] |= 1 << 27; temp |= 1 << 27;
if(want_interrupt) if(want_interrupt)
ol->q[0] |= 3 << 20; temp |= 3 << 20;
ol->q[0] |= 3 << 18; /* must take branch */ temp |= 3 << 18; /* must take branch */
ol->q[0] |= data_size; temp |= data_size;
ol->q[1] = data_phys_addr; ol->q[0] = cpu_to_le32(temp);
ol->q[1] = cpu_to_le32(data_phys_addr);
ol->q[2] = 0; ol->q[2] = 0;
ol->q[3] = 0; ol->q[3] = 0;
} }
...@@ -152,15 +152,16 @@ static inline void fill_input_more(struct input_more *im, ...@@ -152,15 +152,16 @@ static inline void fill_input_more(struct input_more *im,
unsigned int data_size, unsigned int data_size,
unsigned long data_phys_addr) unsigned long data_phys_addr)
{ {
im->q[0] = 2 << 28; /* INPUT_MORE */ u32 temp = 2 << 28; /* INPUT_MORE */
im->q[0] |= 8 << 24; /* s = 1, update xferStatus and resCount */ temp |= 8 << 24; /* s = 1, update xferStatus and resCount */
if (want_interrupt) if (want_interrupt)
im->q[0] |= 0 << 20; /* interrupts, i=0 in packet-per-buffer mode */ temp |= 0 << 20; /* interrupts, i=0 in packet-per-buffer mode */
im->q[0] |= 0x0 << 16; /* disable branch to address for packet-per-buffer mode */ temp |= 0x0 << 16; /* disable branch to address for packet-per-buffer mode */
/* disable wait on sync field, not used in DV :-( */ /* disable wait on sync field, not used in DV :-( */
im->q[0] |= data_size; temp |= data_size;
im->q[1] = data_phys_addr; im->q[0] = cpu_to_le32(temp);
im->q[1] = cpu_to_le32(data_phys_addr);
im->q[2] = 0; /* branchAddress and Z not use in packet-per-buffer mode */ im->q[2] = 0; /* branchAddress and Z not use in packet-per-buffer mode */
im->q[3] = 0; /* xferStatus & resCount, resCount must be initialize to data_size */ im->q[3] = 0; /* xferStatus & resCount, resCount must be initialize to data_size */
} }
...@@ -169,16 +170,17 @@ static inline void fill_input_last(struct input_last *il, ...@@ -169,16 +170,17 @@ static inline void fill_input_last(struct input_last *il,
unsigned int data_size, unsigned int data_size,
unsigned long data_phys_addr) unsigned long data_phys_addr)
{ {
il->q[0] = 3 << 28; /* INPUT_LAST */ u32 temp = 3 << 28; /* INPUT_LAST */
il->q[0] |= 8 << 24; /* s = 1, update xferStatus and resCount */ temp |= 8 << 24; /* s = 1, update xferStatus and resCount */
il->q[0] |= 3 << 20; /* enable interrupts */ temp |= 3 << 20; /* enable interrupts */
il->q[0] |= 0xC << 16; /* enable branch to address */ temp |= 0xC << 16; /* enable branch to address */
/* disable wait on sync field, not used in DV :-( */ /* disable wait on sync field, not used in DV :-( */
il->q[0] |= data_size; temp |= data_size;
il->q[1] = data_phys_addr; il->q[0] = cpu_to_le32(temp);
il->q[2] = 1; /* branchAddress (filled in later) and Z = 1 descriptor in next block */ il->q[1] = cpu_to_le32(data_phys_addr);
il->q[3] = data_size; /* xferStatus & resCount, resCount must be initialize to data_size */ il->q[2] = cpu_to_le32(1); /* branchAddress (filled in later) and Z = 1 descriptor in next block */
il->q[3] = cpu_to_le32(data_size); /* xferStatus & resCount, resCount must be initialize to data_size */
} }
...@@ -434,6 +436,7 @@ struct video_card { ...@@ -434,6 +436,7 @@ struct video_card {
/* OHCI card IT DMA context number, -1 if not in use */ /* OHCI card IT DMA context number, -1 if not in use */
int ohci_it_ctx; int ohci_it_ctx;
struct ohci1394_iso_tasklet it_tasklet;
/* register offsets for current IT DMA context, 0 if not in use */ /* register offsets for current IT DMA context, 0 if not in use */
u32 ohci_IsoXmitContextControlSet; u32 ohci_IsoXmitContextControlSet;
...@@ -441,6 +444,7 @@ struct video_card { ...@@ -441,6 +444,7 @@ struct video_card {
u32 ohci_IsoXmitCommandPtr; u32 ohci_IsoXmitCommandPtr;
/* OHCI card IR DMA context number, -1 if not in use */ /* OHCI card IR DMA context number, -1 if not in use */
struct ohci1394_iso_tasklet ir_tasklet;
int ohci_ir_ctx; int ohci_ir_ctx;
/* register offsets for current IR DMA context, 0 if not in use */ /* register offsets for current IR DMA context, 0 if not in use */
...@@ -476,6 +480,9 @@ struct video_card { ...@@ -476,6 +480,9 @@ struct video_card {
immediately. This is safe because the interrupt handler will never immediately. This is safe because the interrupt handler will never
advance active_frame onto a frame that is not READY (and the spinlock advance active_frame onto a frame that is not READY (and the spinlock
must be held while marking a frame READY). must be held while marking a frame READY).
spinlock is also used to protect ohci_it_ctx and ohci_ir_ctx,
which can be accessed from both process and interrupt context
*/ */
spinlock_t spinlock; spinlock_t spinlock;
...@@ -602,7 +609,7 @@ static int do_dv1394_shutdown(struct video_card *video, int free_user_buf); ...@@ -602,7 +609,7 @@ static int do_dv1394_shutdown(struct video_card *video, int free_user_buf);
calibrated against a Sony DSR-40 DVCAM deck */ calibrated against a Sony DSR-40 DVCAM deck */
#define CIP_N_NTSC 68000000 #define CIP_N_NTSC 68000000
#define CIP_D_NTSC 1000000000 #define CIP_D_NTSC 1068000000
#define CIP_N_PAL 1 #define CIP_N_PAL 1
#define CIP_D_PAL 16 #define CIP_D_PAL 16
......
This diff is collapsed.
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
printk(KERN_ERR fmt, ## args) printk(KERN_ERR fmt, ## args)
static char version[] __devinitdata = static char version[] __devinitdata =
"eth1394.c:v0.50 15/Jul/01 Ben Collins <bcollins@debian.org>"; "$Rev: 546 $ Ben Collins <bcollins@debian.org>";
/* Our ieee1394 highlevel driver */ /* Our ieee1394 highlevel driver */
#define ETHER1394_DRIVER_NAME "ether1394" #define ETHER1394_DRIVER_NAME "ether1394"
...@@ -99,6 +99,7 @@ static int hdr_type_len[] = { ...@@ -99,6 +99,7 @@ static int hdr_type_len[] = {
MODULE_AUTHOR("Ben Collins (bcollins@debian.org)"); MODULE_AUTHOR("Ben Collins (bcollins@debian.org)");
MODULE_DESCRIPTION("IEEE 1394 IPv4 Driver (IPv4-over-1394 as per RFC 2734)"); MODULE_DESCRIPTION("IEEE 1394 IPv4 Driver (IPv4-over-1394 as per RFC 2734)");
MODULE_LICENSE("GPL");
/* Find our host_info struct for a given host pointer. Must be called /* Find our host_info struct for a given host pointer. Must be called
* under spinlock. */ * under spinlock. */
...@@ -276,7 +277,7 @@ static inline void ether1394_register_limits (int nodeid, unsigned char max_rec, ...@@ -276,7 +277,7 @@ static inline void ether1394_register_limits (int nodeid, unsigned char max_rec,
static void ether1394_reset_priv (struct net_device *dev, int set_mtu) static void ether1394_reset_priv (struct net_device *dev, int set_mtu)
{ {
int flags; unsigned long flags;
struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
int phy_id = priv->host->node_id & NODE_MASK; int phy_id = priv->host->node_id & NODE_MASK;
...@@ -477,7 +478,7 @@ static inline unsigned short ether1394_parse_encap (struct sk_buff *skb, struct ...@@ -477,7 +478,7 @@ static inline unsigned short ether1394_parse_encap (struct sk_buff *skb, struct
* use of some of the fields, since they tell us a little bit * use of some of the fields, since they tell us a little bit
* about the sending machine. */ * about the sending machine. */
if (hdr->uf.ether_type == __constant_htons (ETH_P_ARP)) { if (hdr->uf.ether_type == __constant_htons (ETH_P_ARP)) {
int flags; unsigned long flags;
u16 phy_id = srcid & NODE_MASK; u16 phy_id = srcid & NODE_MASK;
struct eth1394_priv *priv = struct eth1394_priv *priv =
(struct eth1394_priv *)dev->priv; (struct eth1394_priv *)dev->priv;
...@@ -525,7 +526,7 @@ static int ether1394_write (struct hpsb_host *host, int srcid, int destid, ...@@ -525,7 +526,7 @@ static int ether1394_write (struct hpsb_host *host, int srcid, int destid,
{ {
struct sk_buff *skb; struct sk_buff *skb;
char *buf = (char *)data; char *buf = (char *)data;
int flags; unsigned long flags;
struct net_device *dev = ether1394_find_dev (host); struct net_device *dev = ether1394_find_dev (host);
struct eth1394_priv *priv; struct eth1394_priv *priv;
...@@ -596,7 +597,7 @@ static void hpsb_write_sched (void *__ptask) ...@@ -596,7 +597,7 @@ static void hpsb_write_sched (void *__ptask)
struct sk_buff *skb = ptask->skb; struct sk_buff *skb = ptask->skb;
struct net_device *dev = ptask->skb->dev; struct net_device *dev = ptask->skb->dev;
struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
int flags; unsigned long flags;
/* Statistics */ /* Statistics */
spin_lock_irqsave (&priv->lock, flags); spin_lock_irqsave (&priv->lock, flags);
...@@ -627,7 +628,8 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev) ...@@ -627,7 +628,8 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
int kmflags = in_interrupt () ? GFP_ATOMIC : GFP_KERNEL; int kmflags = in_interrupt () ? GFP_ATOMIC : GFP_KERNEL;
struct ethhdr *eth; struct ethhdr *eth;
struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
int proto, flags; int proto;
unsigned long flags;
nodeid_t dest_node; nodeid_t dest_node;
u64 addr; u64 addr;
struct packet_task *ptask = NULL; struct packet_task *ptask = NULL;
...@@ -702,14 +704,14 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev) ...@@ -702,14 +704,14 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
/* Function for incoming 1394 packets */ /* Function for incoming 1394 packets */
static struct hpsb_address_ops addr_ops = { static struct hpsb_address_ops addr_ops = {
write: ether1394_write, .write = ether1394_write,
}; };
/* Ieee1394 highlevel driver functions */ /* Ieee1394 highlevel driver functions */
static struct hpsb_highlevel_ops hl_ops = { static struct hpsb_highlevel_ops hl_ops = {
add_host: ether1394_add_host, .add_host = ether1394_add_host,
remove_host: ether1394_remove_host, .remove_host = ether1394_remove_host,
host_reset: ether1394_host_reset, .host_reset = ether1394_host_reset,
}; };
static int __init ether1394_init_module (void) static int __init ether1394_init_module (void)
......
...@@ -139,7 +139,7 @@ void hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, ...@@ -139,7 +139,7 @@ void hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
} }
if (host->iso_listen_count[channel]++ == 0) { if (host->iso_listen_count[channel]++ == 0) {
host->ops->devctl(host, ISO_LISTEN_CHANNEL, channel); host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel);
} }
} }
...@@ -152,7 +152,7 @@ void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, ...@@ -152,7 +152,7 @@ void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
} }
if (--host->iso_listen_count[channel] == 0) { if (--host->iso_listen_count[channel] == 0) {
host->ops->devctl(host, ISO_UNLISTEN_CHANNEL, channel); host->driver->devctl(host, ISO_UNLISTEN_CHANNEL, channel);
} }
} }
......
...@@ -38,9 +38,9 @@ static int dummy_devctl(struct hpsb_host *h, enum devctl_cmd c, int arg) ...@@ -38,9 +38,9 @@ static int dummy_devctl(struct hpsb_host *h, enum devctl_cmd c, int arg)
return -1; return -1;
} }
static struct hpsb_host_operations dummy_ops = { static struct hpsb_host_driver dummy_driver = {
transmit_packet: dummy_transmit_packet, .transmit_packet = dummy_transmit_packet,
devctl: dummy_devctl .devctl = dummy_devctl
}; };
/** /**
...@@ -63,7 +63,7 @@ int hpsb_ref_host(struct hpsb_host *host) ...@@ -63,7 +63,7 @@ int hpsb_ref_host(struct hpsb_host *host)
spin_lock_irqsave(&hosts_lock, flags); spin_lock_irqsave(&hosts_lock, flags);
list_for_each(lh, &hosts) { list_for_each(lh, &hosts) {
if (host == list_entry(lh, struct hpsb_host, host_list)) { if (host == list_entry(lh, struct hpsb_host, host_list)) {
host->ops->devctl(host, MODIFY_USAGE, 1); host->driver->devctl(host, MODIFY_USAGE, 1);
host->refcount++; host->refcount++;
retval = 1; retval = 1;
break; break;
...@@ -87,7 +87,7 @@ void hpsb_unref_host(struct hpsb_host *host) ...@@ -87,7 +87,7 @@ void hpsb_unref_host(struct hpsb_host *host)
{ {
unsigned long flags; unsigned long flags;
host->ops->devctl(host, MODIFY_USAGE, 0); host->driver->devctl(host, MODIFY_USAGE, 0);
spin_lock_irqsave(&hosts_lock, flags); spin_lock_irqsave(&hosts_lock, flags);
host->refcount--; host->refcount--;
...@@ -128,7 +128,6 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra) ...@@ -128,7 +128,6 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra)
h->hostdata = h + 1; h->hostdata = h + 1;
h->driver = drv; h->driver = drv;
h->ops = drv->ops;
h->refcount = 1; h->refcount = 1;
INIT_LIST_HEAD(&h->pending_packets); INIT_LIST_HEAD(&h->pending_packets);
...@@ -152,63 +151,26 @@ void hpsb_add_host(struct hpsb_host *host) ...@@ -152,63 +151,26 @@ void hpsb_add_host(struct hpsb_host *host)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&hosts_lock, flags); spin_lock_irqsave(&hosts_lock, flags);
host->driver->number_of_hosts++;
list_add_tail(&host->driver_list, &host->driver->hosts);
list_add_tail(&host->host_list, &hosts); list_add_tail(&host->host_list, &hosts);
spin_unlock_irqrestore(&hosts_lock, flags); spin_unlock_irqrestore(&hosts_lock, flags);
highlevel_add_host(host); highlevel_add_host(host);
host->ops->devctl(host, RESET_BUS, 0); host->driver->devctl(host, RESET_BUS, 0);
} }
void hpsb_remove_host(struct hpsb_host *host) void hpsb_remove_host(struct hpsb_host *host)
{ {
struct hpsb_host_driver *drv = host->driver;
unsigned long flags; unsigned long flags;
host->is_shutdown = 1; host->is_shutdown = 1;
host->ops = &dummy_ops; host->driver = &dummy_driver;
highlevel_remove_host(host); highlevel_remove_host(host);
spin_lock_irqsave(&hosts_lock, flags); spin_lock_irqsave(&hosts_lock, flags);
list_del(&host->driver_list);
list_del(&host->host_list); list_del(&host->host_list);
drv->number_of_hosts--;
spin_unlock_irqrestore(&hosts_lock, flags); spin_unlock_irqrestore(&hosts_lock, flags);
} }
struct hpsb_host_driver *hpsb_register_lowlevel(struct hpsb_host_operations *op,
const char *name)
{
struct hpsb_host_driver *drv;
drv = kmalloc(sizeof(struct hpsb_host_driver), SLAB_KERNEL);
if (!drv) return NULL;
INIT_LIST_HEAD(&drv->list);
INIT_LIST_HEAD(&drv->hosts);
drv->number_of_hosts = 0;
drv->name = name;
drv->ops = op;
spin_lock(&host_drivers_lock);
list_add_tail(&drv->list, &host_drivers);
spin_unlock(&host_drivers_lock);
return drv;
}
void hpsb_unregister_lowlevel(struct hpsb_host_driver *drv)
{
spin_lock(&host_drivers_lock);
list_del(&drv->list);
spin_unlock(&host_drivers_lock);
kfree(drv);
}
/* /*
* This function calls the given function for every host currently registered. * This function calls the given function for every host currently registered.
*/ */
......
...@@ -15,7 +15,6 @@ struct hpsb_packet; ...@@ -15,7 +15,6 @@ struct hpsb_packet;
struct hpsb_host { struct hpsb_host {
struct list_head host_list; struct list_head host_list;
struct hpsb_host_operations *ops;
void *hostdata; void *hostdata;
atomic_t generation; atomic_t generation;
...@@ -59,7 +58,6 @@ struct hpsb_host { ...@@ -59,7 +58,6 @@ struct hpsb_host {
struct csr_control csr; struct csr_control csr;
struct hpsb_host_driver *driver; struct hpsb_host_driver *driver;
struct list_head driver_list;
struct pci_dev *pdev; struct pci_dev *pdev;
}; };
...@@ -113,7 +111,9 @@ enum reset_types { ...@@ -113,7 +111,9 @@ enum reset_types {
SHORT_RESET SHORT_RESET
}; };
struct hpsb_host_operations { struct hpsb_host_driver {
const char *name;
/* This function must store a pointer to the configuration ROM into the /* This function must store a pointer to the configuration ROM into the
* location referenced to by pointer and return the size of the ROM. It * location referenced to by pointer and return the size of the ROM. It
* may not fail. If any allocation is required, it must be done * may not fail. If any allocation is required, it must be done
...@@ -149,18 +149,6 @@ struct hpsb_host_operations { ...@@ -149,18 +149,6 @@ struct hpsb_host_operations {
quadlet_t data, quadlet_t compare); quadlet_t data, quadlet_t compare);
}; };
struct hpsb_host_driver {
struct list_head list;
struct list_head hosts;
int number_of_hosts;
const char *name;
struct hpsb_host_operations *ops;
};
/* core internal use */ /* core internal use */
void register_builtin_lowlevels(void); void register_builtin_lowlevels(void);
...@@ -184,8 +172,4 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra); ...@@ -184,8 +172,4 @@ 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);
struct hpsb_host_driver *hpsb_register_lowlevel(struct hpsb_host_operations *op,
const char *name);
void hpsb_unregister_lowlevel(struct hpsb_host_driver *drv);
#endif /* _IEEE1394_HOSTS_H */ #endif /* _IEEE1394_HOSTS_H */
...@@ -141,7 +141,7 @@ void free_hpsb_packet(struct hpsb_packet *packet) ...@@ -141,7 +141,7 @@ void free_hpsb_packet(struct hpsb_packet *packet)
int hpsb_reset_bus(struct hpsb_host *host, int type) int hpsb_reset_bus(struct hpsb_host *host, int type)
{ {
if (!host->in_bus_reset) { if (!host->in_bus_reset) {
host->ops->devctl(host, RESET_BUS, type); host->driver->devctl(host, RESET_BUS, type);
return 0; return 0;
} else { } else {
return 1; return 1;
...@@ -354,7 +354,7 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot) ...@@ -354,7 +354,7 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
} }
host->reset_retries = 0; host->reset_retries = 0;
if (isroot) host->ops->devctl(host, ACT_CYCLE_MASTER, 1); if (isroot) host->driver->devctl(host, ACT_CYCLE_MASTER, 1);
atomic_inc(&host->generation); atomic_inc(&host->generation);
host->in_bus_reset = 0; host->in_bus_reset = 0;
highlevel_host_reset(host); highlevel_host_reset(host);
...@@ -440,7 +440,7 @@ int hpsb_send_packet(struct hpsb_packet *packet) ...@@ -440,7 +440,7 @@ int hpsb_send_packet(struct hpsb_packet *packet)
} }
#endif #endif
return host->ops->transmit_packet(host, packet); return host->driver->transmit_packet(host, packet);
} }
static void send_packet_nocare(struct hpsb_packet *packet) static void send_packet_nocare(struct hpsb_packet *packet)
...@@ -736,7 +736,7 @@ void abort_requests(struct hpsb_host *host) ...@@ -736,7 +736,7 @@ void abort_requests(struct hpsb_host *host)
struct list_head *lh; struct list_head *lh;
LIST_HEAD(llist); LIST_HEAD(llist);
host->ops->devctl(host, CANCEL_REQUESTS, 0); host->driver->devctl(host, CANCEL_REQUESTS, 0);
spin_lock_irqsave(&host->pending_pkt_lock, flags); spin_lock_irqsave(&host->pending_pkt_lock, flags);
list_splice(&host->pending_packets, &llist); list_splice(&host->pending_packets, &llist);
...@@ -810,8 +810,8 @@ static rwlock_t ieee1394_chardevs_lock = RW_LOCK_UNLOCKED; ...@@ -810,8 +810,8 @@ static rwlock_t ieee1394_chardevs_lock = RW_LOCK_UNLOCKED;
static int ieee1394_dispatch_open(struct inode *inode, struct file *file); static int ieee1394_dispatch_open(struct inode *inode, struct file *file);
static struct file_operations ieee1394_chardev_ops = { static struct file_operations ieee1394_chardev_ops = {
owner: THIS_MODULE, .owner =THIS_MODULE,
open: ieee1394_dispatch_open, .open = ieee1394_dispatch_open,
}; };
devfs_handle_t ieee1394_devfs_handle; devfs_handle_t ieee1394_devfs_handle;
...@@ -861,19 +861,57 @@ void ieee1394_unregister_chardev(int blocknum) ...@@ -861,19 +861,57 @@ void ieee1394_unregister_chardev(int blocknum)
write_unlock(&ieee1394_chardevs_lock); write_unlock(&ieee1394_chardevs_lock);
} }
/*
ieee1394_get_chardev() - look up and acquire a character device
driver that has previously registered using ieee1394_register_chardev()
On success, returns 1 and sets module and file_ops to the driver.
The module will have an incremented reference count.
On failure, returns 0.
The module will NOT have an incremented reference count.
*/
static int ieee1394_get_chardev(int blocknum,
struct module **module,
struct file_operations **file_ops)
{
int ret = 0;
if( (blocknum < 0) || (blocknum > 15) )
return ret;
read_lock(&ieee1394_chardevs_lock);
*module = ieee1394_chardevs[blocknum].module;
*file_ops = ieee1394_chardevs[blocknum].file_ops;
if(*file_ops == NULL)
goto out;
/* don't need try_inc_mod_count if the driver is non-modular */
if(*module && (try_inc_mod_count(*module) == 0))
goto out;
/* success! */
ret = 1;
out:
read_unlock(&ieee1394_chardevs_lock);
return ret;
}
/* the point of entry for open() on any ieee1394 character device */ /* the point of entry for open() on any ieee1394 character device */
static int ieee1394_dispatch_open(struct inode *inode, struct file *file) static int ieee1394_dispatch_open(struct inode *inode, struct file *file)
{ {
struct file_operations *file_ops; struct file_operations *file_ops;
struct module *module; struct module *module;
int blocknum; int blocknum;
int retval = -ENODEV; int retval;
/* /*
Maintaining correct module reference counts is tricky here! Maintaining correct module reference counts is tricky here!
For Linux v2.4 and later:
The key thing to remember is that the VFS increments the The key thing to remember is that the VFS increments the
reference count of ieee1394 before it calls reference count of ieee1394 before it calls
ieee1394_dispatch_open(). ieee1394_dispatch_open().
...@@ -886,37 +924,18 @@ static int ieee1394_dispatch_open(struct inode *inode, struct file *file) ...@@ -886,37 +924,18 @@ static int ieee1394_dispatch_open(struct inode *inode, struct file *file)
If the open() fails, then the VFS will drop the If the open() fails, then the VFS will drop the
reference count of whatever module file->f_op->owner points reference count of whatever module file->f_op->owner points
to, immediately after this function returns. to, immediately after this function returns.
The comments below refer to the 2.4 case, since the 2.2
case is trivial.
*/ */
#define INCREF(mod_) do { struct module *mod = (struct module*) mod_; \
if(mod != NULL) __MOD_INC_USE_COUNT(mod); } while(0)
#define DECREF(mod_) do { struct module *mod = (struct module*) mod_; \
if(mod != NULL) __MOD_DEC_USE_COUNT(mod); } while(0)
/* shift away lower four bits of the minor /* shift away lower four bits of the minor
to get the index of the ieee1394_driver to get the index of the ieee1394_driver
we want */ we want */
blocknum = (minor(inode->i_rdev) >> 4) & 0xF; blocknum = (minor(inode->i_rdev) >> 4) & 0xF;
/* printk("ieee1394_dispatch_open(%d)", blocknum); */ /* look up the driver */
read_lock(&ieee1394_chardevs_lock);
module = ieee1394_chardevs[blocknum].module;
/* bump the reference count of the driver that
will receive the open() */
INCREF(module);
file_ops = ieee1394_chardevs[blocknum].file_ops;
read_unlock(&ieee1394_chardevs_lock);
if(file_ops == NULL) { if(ieee1394_get_chardev(blocknum, &module, &file_ops) == 0)
DECREF(module); return -ENODEV;
goto out_fail;
}
/* redirect all subsequent requests to the driver's /* redirect all subsequent requests to the driver's
own file_operations */ own file_operations */
...@@ -928,42 +947,42 @@ static int ieee1394_dispatch_open(struct inode *inode, struct file *file) ...@@ -928,42 +947,42 @@ static int ieee1394_dispatch_open(struct inode *inode, struct file *file)
/* follow through with the open() */ /* follow through with the open() */
retval = file_ops->open(inode, file); retval = file_ops->open(inode, file);
if(retval) { if(retval == 0) {
/* if the open() failed, then we need to drop the /* If the open() succeeded, then ieee1394 will be left
extra reference we gave to the task-specific with an extra module reference, so we discard it here.
driver */
DECREF(module); The task-specific driver still has the extra
goto out_fail; reference given to it by ieee1394_get_chardev().
This extra reference prevents the module from
unloading while the file is open, and will be
dropped by the VFS when the file is released.
*/
} else { if(THIS_MODULE)
__MOD_DEC_USE_COUNT((struct module*) THIS_MODULE);
/* if the open() succeeded, then ieee1394 will be left /* note that if ieee1394 is compiled into the kernel,
with an extra module reference, so we discard it here.*/ THIS_MODULE will be (void*) NULL, hence the if and
the cast are necessary */
DECREF(THIS_MODULE); } else {
/* the task-specific driver still has the extra /* if the open() failed, then we need to drop the
reference we gave it. This extra reference prevents extra reference we gave to the task-specific
the module from unloading while the file is open, driver */
and will be dropped by the VFS when the file is
released. */
return 0; if(module)
} __MOD_DEC_USE_COUNT(module);
out_fail:
/* point the file's f_ops back to ieee1394. The VFS will then /* point the file's f_ops back to ieee1394. The VFS will then
decrement ieee1394's reference count immediately after this decrement ieee1394's reference count immediately after this
function returns. */ function returns. */
file->f_op = &ieee1394_chardev_ops; file->f_op = &ieee1394_chardev_ops;
return retval; }
#undef INCREF
#undef DECREF
return retval;
} }
struct proc_dir_entry *ieee1394_procfs_entry; struct proc_dir_entry *ieee1394_procfs_entry;
...@@ -1024,8 +1043,6 @@ module_init(ieee1394_init); ...@@ -1024,8 +1043,6 @@ module_init(ieee1394_init);
module_exit(ieee1394_cleanup); module_exit(ieee1394_cleanup);
/* Exported symbols */ /* Exported symbols */
EXPORT_SYMBOL(hpsb_register_lowlevel);
EXPORT_SYMBOL(hpsb_unregister_lowlevel);
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);
......
...@@ -16,7 +16,7 @@ struct hpsb_packet { ...@@ -16,7 +16,7 @@ struct hpsb_packet {
struct list_head list; struct list_head list;
/* This can be used for host driver internal linking. */ /* This can be used for host driver internal linking. */
struct hpsb_packet *xnext; struct list_head driver_list;
nodeid_t node_id; nodeid_t node_id;
...@@ -77,6 +77,10 @@ struct hpsb_packet { ...@@ -77,6 +77,10 @@ struct hpsb_packet {
quadlet_t embedded_header[5]; quadlet_t embedded_header[5];
}; };
static inline struct hpsb_packet *driver_packet(struct list_head *l)
{
return list_entry(l, struct hpsb_packet, driver_list);
}
void abort_timedouts(struct hpsb_host *host); void abort_timedouts(struct hpsb_host *host);
void abort_requests(struct hpsb_host *host); void abort_requests(struct hpsb_host *host);
......
This diff is collapsed.
This diff is collapsed.
...@@ -127,12 +127,10 @@ struct dma_trm_ctx { ...@@ -127,12 +127,10 @@ struct dma_trm_ctx {
quadlet_t *branchAddrPtr; quadlet_t *branchAddrPtr;
/* list of packets inserted in the AT FIFO */ /* list of packets inserted in the AT FIFO */
struct hpsb_packet *fifo_first; struct list_head fifo_list;
struct hpsb_packet *fifo_last;
/* list of pending packets to be inserted in the AT FIFO */ /* list of pending packets to be inserted in the AT FIFO */
struct hpsb_packet *pending_first; struct list_head pending_list;
struct hpsb_packet *pending_last;
spinlock_t lock; spinlock_t lock;
struct tasklet_struct task; struct tasklet_struct task;
...@@ -141,6 +139,13 @@ struct dma_trm_ctx { ...@@ -141,6 +139,13 @@ struct dma_trm_ctx {
int cmdPtr; int cmdPtr;
}; };
struct ohci1394_iso_tasklet {
struct tasklet_struct tasklet;
struct list_head link;
int context;
enum { OHCI_ISO_TRANSMIT, OHCI_ISO_RECEIVE } type;
};
struct ti_ohci { struct ti_ohci {
int id; /* sequential card number */ int id; /* sequential card number */
...@@ -172,21 +177,23 @@ struct ti_ohci { ...@@ -172,21 +177,23 @@ struct ti_ohci {
unsigned int max_packet_size; unsigned int max_packet_size;
/* async receive */ /* async receive */
struct dma_rcv_ctx *ar_resp_context; struct dma_rcv_ctx ar_resp_context;
struct dma_rcv_ctx *ar_req_context; struct dma_rcv_ctx ar_req_context;
/* async transmit */ /* async transmit */
struct dma_trm_ctx *at_resp_context; struct dma_trm_ctx at_resp_context;
struct dma_trm_ctx *at_req_context; struct dma_trm_ctx at_req_context;
/* iso receive */ /* iso receive */
struct dma_rcv_ctx *ir_context; struct dma_rcv_ctx ir_context;
struct ohci1394_iso_tasklet ir_tasklet;
spinlock_t IR_channel_lock; spinlock_t IR_channel_lock;
int nb_iso_rcv_ctx; int nb_iso_rcv_ctx;
unsigned long ir_ctx_usage; /* use test_and_set_bit() for atomicity */ unsigned long ir_ctx_usage; /* use test_and_set_bit() for atomicity */
/* iso transmit */ /* iso transmit */
struct dma_trm_ctx *it_context; struct dma_trm_ctx it_context;
struct ohci1394_iso_tasklet it_tasklet;
int nb_iso_xmit_ctx; int nb_iso_xmit_ctx;
unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */ unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */
...@@ -202,15 +209,11 @@ struct ti_ohci { ...@@ -202,15 +209,11 @@ struct ti_ohci {
int self_id_errors; int self_id_errors;
/* IRQ hooks, for video1394 and dv1394 */ /* Tasklets for iso receive and transmit, used by video1394,
* amdtp and dv1394 */
#define OHCI1394_MAX_IRQ_HOOKS 16
struct ohci1394_irq_hook { struct list_head iso_tasklet_list;
void (*irq_handler) (int card, quadlet_t isoRecvEvent, spinlock_t iso_tasklet_list_lock;
quadlet_t isoXmitEvent, void *data);
void *data;
} irq_hooks[OHCI1394_MAX_IRQ_HOOKS];
/* Swap the selfid buffer? */ /* Swap the selfid buffer? */
unsigned int selfid_swap:1; unsigned int selfid_swap:1;
...@@ -399,15 +402,17 @@ static inline u32 reg_read(const struct ti_ohci *ohci, int offset) ...@@ -399,15 +402,17 @@ static inline u32 reg_read(const struct ti_ohci *ohci, int offset)
#define OHCI1394_TCODE_PHY 0xE #define OHCI1394_TCODE_PHY 0xE
void ohci1394_stop_context(struct ti_ohci *ohci, int reg, char *msg); void ohci1394_init_iso_tasklet(struct ohci1394_iso_tasklet *tasklet,
struct ti_ohci *ohci1394_get_struct(int card_num); int type,
void (*func)(unsigned long),
unsigned long data);
int ohci1394_register_iso_tasklet(struct ti_ohci *ohci,
struct ohci1394_iso_tasklet *tasklet);
void ohci1394_unregister_iso_tasklet(struct ti_ohci *ohci,
struct ohci1394_iso_tasklet *tasklet);
int ohci1394_hook_irq(struct ti_ohci *ohci, void ohci1394_stop_context (struct ti_ohci *ohci, int reg, char *msg);
void (*irq_handler) (int, quadlet_t, quadlet_t, void *), struct ti_ohci *ohci1394_get_struct(int card_num);
void *data);
void ohci1394_unhook_irq(struct ti_ohci *ohci,
void (*irq_handler) (int, quadlet_t, quadlet_t, void *),
void *data);
#endif #endif
...@@ -65,7 +65,7 @@ MODULE_PARM_DESC(skip_eeprom, "Do not try to read bus info block from serial eep ...@@ -65,7 +65,7 @@ MODULE_PARM_DESC(skip_eeprom, "Do not try to read bus info block from serial eep
static int skip_eeprom = 0; static int skip_eeprom = 0;
static struct hpsb_host_driver *lynx_driver; static struct hpsb_host_driver lynx_driver;
static unsigned int card_id; static unsigned int card_id;
...@@ -466,7 +466,7 @@ static void send_next(struct ti_lynx *lynx, int what) ...@@ -466,7 +466,7 @@ static void send_next(struct ti_lynx *lynx, int what)
struct hpsb_packet *packet; struct hpsb_packet *packet;
d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async); d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async);
packet = d->queue; packet = driver_packet(d->queue.next);
d->header_dma = pci_map_single(lynx->dev, packet->header, d->header_dma = pci_map_single(lynx->dev, packet->header,
packet->header_size, PCI_DMA_TODEVICE); packet->header_size, PCI_DMA_TODEVICE);
...@@ -538,7 +538,6 @@ static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet) ...@@ -538,7 +538,6 @@ static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
return 0; return 0;
} }
packet->xnext = NULL;
if (packet->tcode == TCODE_WRITEQ if (packet->tcode == TCODE_WRITEQ
|| packet->tcode == TCODE_READQ_RESPONSE) { || packet->tcode == TCODE_READQ_RESPONSE) {
cpu_to_be32s(&packet->header[3]); cpu_to_be32s(&packet->header[3]);
...@@ -546,14 +545,9 @@ static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet) ...@@ -546,14 +545,9 @@ static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
spin_lock_irqsave(&d->queue_lock, flags); spin_lock_irqsave(&d->queue_lock, flags);
if (d->queue == NULL) { list_add_tail(&packet->driver_list, &d->queue);
d->queue = packet; if (d->queue.next == &packet->driver_list)
d->queue_last = packet;
send_next(lynx, packet->type); send_next(lynx, packet->type);
} else {
d->queue_last->xnext = packet;
d->queue_last = packet;
}
spin_unlock_irqrestore(&d->queue_lock, flags); spin_unlock_irqrestore(&d->queue_lock, flags);
...@@ -566,7 +560,8 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) ...@@ -566,7 +560,8 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
{ {
struct ti_lynx *lynx = host->hostdata; struct ti_lynx *lynx = host->hostdata;
int retval = 0; int retval = 0;
struct hpsb_packet *packet, *lastpacket; struct hpsb_packet *packet;
LIST_HEAD(packet_list);
unsigned long flags; unsigned long flags;
switch (cmd) { switch (cmd) {
...@@ -620,15 +615,15 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) ...@@ -620,15 +615,15 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
spin_lock_irqsave(&lynx->async.queue_lock, flags); spin_lock_irqsave(&lynx->async.queue_lock, flags);
reg_write(lynx, DMA_CHAN_CTRL(CHANNEL_ASYNC_SEND), 0); reg_write(lynx, DMA_CHAN_CTRL(CHANNEL_ASYNC_SEND), 0);
packet = lynx->async.queue; list_splice(&lynx->async.queue, &packet_list);
lynx->async.queue = NULL; INIT_LIST_HEAD(&lynx->async.queue);
spin_unlock_irqrestore(&lynx->async.queue_lock, flags); spin_unlock_irqrestore(&lynx->async.queue_lock, flags);
while (packet != NULL) { while (!list_empty(&packet_list)) {
lastpacket = packet; packet = driver_packet(packet_list.next);
packet = packet->xnext; list_del(&packet->driver_list);
hpsb_packet_sent(host, lastpacket, ACKX_ABORTED); hpsb_packet_sent(host, packet, ACKX_ABORTED);
} }
break; break;
...@@ -693,13 +688,13 @@ static ssize_t mem_write(struct file*, const char*, size_t, loff_t*); ...@@ -693,13 +688,13 @@ static ssize_t mem_write(struct file*, const char*, size_t, loff_t*);
static struct file_operations aux_ops = { static struct file_operations aux_ops = {
owner: THIS_MODULE, .owner = THIS_MODULE,
read: mem_read, .read = mem_read,
write: mem_write, .write = mem_write,
poll: aux_poll, .poll = aux_poll,
llseek: mem_llseek, .llseek = mem_llseek,
open: mem_open, .open = mem_open,
release: mem_release, .release = mem_release,
}; };
...@@ -896,6 +891,12 @@ static ssize_t mem_read(struct file *file, char *buffer, size_t count, ...@@ -896,6 +891,12 @@ static ssize_t mem_read(struct file *file, char *buffer, size_t count,
ssize_t retval; ssize_t retval;
void *membase; void *membase;
if (*offset != off) /* Check for EOF before we trust wrap */
return 0;
if (off + count > off)
return 0;
if ((off + count) > PCILYNX_MAX_MEMORY + 1) { if ((off + count) > PCILYNX_MAX_MEMORY + 1) {
count = PCILYNX_MAX_MEMORY + 1 - off; count = PCILYNX_MAX_MEMORY + 1 - off;
} }
...@@ -1122,8 +1123,9 @@ static void lynx_irq_handler(int irq, void *dev_id, ...@@ -1122,8 +1123,9 @@ static void lynx_irq_handler(int irq, void *dev_id,
spin_lock(&lynx->async.queue_lock); spin_lock(&lynx->async.queue_lock);
ack = reg_read(lynx, DMA_CHAN_STAT(CHANNEL_ASYNC_SEND)); ack = reg_read(lynx, DMA_CHAN_STAT(CHANNEL_ASYNC_SEND));
packet = lynx->async.queue;
lynx->async.queue = packet->xnext; packet = driver_packet(lynx->async.queue.next);
list_del(&packet->driver_list);
pci_unmap_single(lynx->dev, lynx->async.header_dma, pci_unmap_single(lynx->dev, lynx->async.header_dma,
packet->header_size, PCI_DMA_TODEVICE); packet->header_size, PCI_DMA_TODEVICE);
...@@ -1132,7 +1134,7 @@ static void lynx_irq_handler(int irq, void *dev_id, ...@@ -1132,7 +1134,7 @@ static void lynx_irq_handler(int irq, void *dev_id,
packet->data_size, PCI_DMA_TODEVICE); packet->data_size, PCI_DMA_TODEVICE);
} }
if (lynx->async.queue != NULL) { if (!list_empty(&lynx->async.queue)) {
send_next(lynx, hpsb_async); send_next(lynx, hpsb_async);
} }
...@@ -1154,8 +1156,8 @@ static void lynx_irq_handler(int irq, void *dev_id, ...@@ -1154,8 +1156,8 @@ static void lynx_irq_handler(int irq, void *dev_id,
spin_lock(&lynx->iso_send.queue_lock); spin_lock(&lynx->iso_send.queue_lock);
packet = lynx->iso_send.queue; packet = driver_packet(lynx->iso_send.queue.next);
lynx->iso_send.queue = packet->xnext; list_del(&packet->driver_list);
pci_unmap_single(lynx->dev, lynx->iso_send.header_dma, pci_unmap_single(lynx->dev, lynx->iso_send.header_dma,
packet->header_size, PCI_DMA_TODEVICE); packet->header_size, PCI_DMA_TODEVICE);
...@@ -1164,7 +1166,7 @@ static void lynx_irq_handler(int irq, void *dev_id, ...@@ -1164,7 +1166,7 @@ static void lynx_irq_handler(int irq, void *dev_id,
packet->data_size, PCI_DMA_TODEVICE); packet->data_size, PCI_DMA_TODEVICE);
} }
if (lynx->iso_send.queue != NULL) { if (!list_empty(&lynx->iso_send.queue)) {
send_next(lynx, hpsb_iso); send_next(lynx, hpsb_iso);
} }
...@@ -1327,7 +1329,7 @@ static int __devinit add_card(struct pci_dev *dev, ...@@ -1327,7 +1329,7 @@ static int __devinit add_card(struct pci_dev *dev,
error = -ENOMEM; error = -ENOMEM;
host = hpsb_alloc_host(lynx_driver, sizeof(struct ti_lynx)); host = hpsb_alloc_host(&lynx_driver, sizeof(struct ti_lynx));
if (!host) FAIL("failed to allocate control structure memory"); if (!host) FAIL("failed to allocate control structure memory");
lynx = host->hostdata; lynx = host->hostdata;
...@@ -1471,7 +1473,8 @@ static int __devinit add_card(struct pci_dev *dev, ...@@ -1471,7 +1473,8 @@ static int __devinit add_card(struct pci_dev *dev,
lynx->selfid_size = -1; lynx->selfid_size = -1;
lynx->phy_reg0 = -1; lynx->phy_reg0 = -1;
lynx->async.queue = NULL; INIT_LIST_HEAD(&lynx->async.queue);
INIT_LIST_HEAD(&lynx->iso_send.queue);
pcl.next = pcl_bus(lynx, lynx->rcv_pcl); pcl.next = pcl_bus(lynx, lynx->rcv_pcl);
put_pcl(lynx, lynx->rcv_pcl_start, &pcl); put_pcl(lynx, lynx->rcv_pcl_start, &pcl);
...@@ -1682,25 +1685,26 @@ static size_t get_lynx_rom(struct hpsb_host *host, const quadlet_t **ptr) ...@@ -1682,25 +1685,26 @@ static size_t get_lynx_rom(struct hpsb_host *host, const quadlet_t **ptr)
static struct pci_device_id pci_table[] __devinitdata = { static struct pci_device_id pci_table[] __devinitdata = {
{ {
vendor: PCI_VENDOR_ID_TI, .vendor = PCI_VENDOR_ID_TI,
device: PCI_DEVICE_ID_TI_PCILYNX, .device = PCI_DEVICE_ID_TI_PCILYNX,
subvendor: PCI_ANY_ID, .subvendor = PCI_ANY_ID,
subdevice: PCI_ANY_ID, .subdevice = PCI_ANY_ID,
}, },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
static struct pci_driver lynx_pci_driver = { static struct pci_driver lynx_pci_driver = {
name: PCILYNX_DRIVER_NAME, .name = PCILYNX_DRIVER_NAME,
id_table: pci_table, .id_table = pci_table,
probe: add_card, .probe = add_card,
remove: __devexit_p(remove_card), .remove = __devexit_p(remove_card),
}; };
static struct hpsb_host_operations lynx_ops = { static struct hpsb_host_driver lynx_driver = {
get_rom: get_lynx_rom, .name = PCILYNX_DRIVER_NAME,
transmit_packet: lynx_transmit, .get_rom = get_lynx_rom,
devctl: lynx_devctl, .transmit_packet = lynx_transmit,
.devctl = lynx_devctl,
}; };
MODULE_AUTHOR("Andreas E. Bombe <andreas.bombe@munich.netsurf.de>"); MODULE_AUTHOR("Andreas E. Bombe <andreas.bombe@munich.netsurf.de>");
...@@ -1721,22 +1725,14 @@ static int __init pcilynx_init(void) ...@@ -1721,22 +1725,14 @@ static int __init pcilynx_init(void)
} }
#endif #endif
lynx_driver = hpsb_register_lowlevel(&lynx_ops, PCILYNX_DRIVER_NAME);
if (!lynx_driver) {
ret = -ENOMEM;
goto free_char_dev;
}
ret = pci_module_init(&lynx_pci_driver); ret = pci_module_init(&lynx_pci_driver);
if (ret < 0) { if (ret < 0) {
PRINT_G(KERN_ERR, "PCI module init failed"); PRINT_G(KERN_ERR, "PCI module init failed");
goto unregister_lowlevel; goto free_char_dev;
} }
return 0; return 0;
unregister_lowlevel:
hpsb_unregister_lowlevel(lynx_driver);
free_char_dev: free_char_dev:
#ifdef CONFIG_IEEE1394_PCILYNX_PORTS #ifdef CONFIG_IEEE1394_PCILYNX_PORTS
unregister_chrdev(PCILYNX_MAJOR, PCILYNX_DRIVER_NAME); unregister_chrdev(PCILYNX_MAJOR, PCILYNX_DRIVER_NAME);
...@@ -1748,7 +1744,6 @@ static int __init pcilynx_init(void) ...@@ -1748,7 +1744,6 @@ static int __init pcilynx_init(void)
static void __exit pcilynx_cleanup(void) static void __exit pcilynx_cleanup(void)
{ {
pci_unregister_driver(&lynx_pci_driver); pci_unregister_driver(&lynx_pci_driver);
hpsb_unregister_lowlevel(lynx_driver);
#ifdef CONFIG_IEEE1394_PCILYNX_PORTS #ifdef CONFIG_IEEE1394_PCILYNX_PORTS
unregister_chrdev(PCILYNX_MAJOR, PCILYNX_DRIVER_NAME); unregister_chrdev(PCILYNX_MAJOR, PCILYNX_DRIVER_NAME);
......
...@@ -94,7 +94,7 @@ struct ti_lynx { ...@@ -94,7 +94,7 @@ struct ti_lynx {
struct lynx_send_data { struct lynx_send_data {
pcl_t pcl_start, pcl; pcl_t pcl_start, pcl;
struct hpsb_packet *queue, *queue_last; struct list_head queue;
spinlock_t queue_lock; spinlock_t queue_lock;
dma_addr_t header_dma, data_dma; dma_addr_t header_dma, data_dma;
int channel; int channel;
......
...@@ -985,20 +985,20 @@ static int raw1394_release(struct inode *inode, struct file *file) ...@@ -985,20 +985,20 @@ static int raw1394_release(struct inode *inode, struct file *file)
} }
static struct hpsb_highlevel_ops hl_ops = { static struct hpsb_highlevel_ops hl_ops = {
add_host: add_host, .add_host = add_host,
remove_host: remove_host, .remove_host = remove_host,
host_reset: host_reset, .host_reset = host_reset,
iso_receive: iso_receive, .iso_receive = iso_receive,
fcp_request: fcp_request, .fcp_request = fcp_request,
}; };
static struct file_operations file_ops = { static struct file_operations file_ops = {
owner: THIS_MODULE, .owner = THIS_MODULE,
read: raw1394_read, .read = raw1394_read,
write: raw1394_write, .write = raw1394_write,
poll: raw1394_poll, .poll = raw1394_poll,
open: raw1394_open, .open = raw1394_open,
release: raw1394_release, .release = raw1394_release,
}; };
static int __init init_raw1394(void) static int __init init_raw1394(void)
......
...@@ -320,6 +320,7 @@ ...@@ -320,6 +320,7 @@
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/blk.h>
#include <asm/current.h> #include <asm/current.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -349,7 +350,7 @@ ...@@ -349,7 +350,7 @@
#include "sbp2.h" #include "sbp2.h"
static char version[] __devinitdata = static char version[] __devinitdata =
"$Rev: 507 $ James Goodwin <jamesg@filanet.com>"; "$Rev: 545 $ James Goodwin <jamesg@filanet.com>";
/* /*
* Module load parameter definitions * Module load parameter definitions
...@@ -421,16 +422,25 @@ MODULE_PARM(sbp2_exclusive_login,"i"); ...@@ -421,16 +422,25 @@ MODULE_PARM(sbp2_exclusive_login,"i");
MODULE_PARM_DESC(sbp2_exclusive_login, "Exclusive login to sbp2 device (default = 1)"); MODULE_PARM_DESC(sbp2_exclusive_login, "Exclusive login to sbp2 device (default = 1)");
static int sbp2_exclusive_login = 1; static int sbp2_exclusive_login = 1;
/*
* SCSI inquiry hack for really badly behaved sbp2 devices. Turn this on if your sbp2 device
* is not properly handling the SCSI inquiry command. This hack makes the inquiry look more
* like a typical MS Windows inquiry.
*/
MODULE_PARM(sbp2_force_inquiry_hack,"i");
MODULE_PARM_DESC(sbp2_force_inquiry_hack, "Force SCSI inquiry hack (default = 0)");
static int sbp2_force_inquiry_hack = 0;
/* /*
* Export information about protocols/devices supported by this driver. * Export information about protocols/devices supported by this driver.
*/ */
static struct ieee1394_device_id sbp2_id_table[] = { static struct ieee1394_device_id sbp2_id_table[] = {
{ {
match_flags: IEEE1394_MATCH_SPECIFIER_ID | .match_flags =IEEE1394_MATCH_SPECIFIER_ID |
IEEE1394_MATCH_VERSION, IEEE1394_MATCH_VERSION,
specifier_id: SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff, .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff,
version: SBP2_SW_VERSION_ENTRY & 0xffffff .version = SBP2_SW_VERSION_ENTRY & 0xffffff
}, },
{ } { }
}; };
...@@ -504,14 +514,6 @@ static spinlock_t sbp2_host_info_lock = SPIN_LOCK_UNLOCKED; ...@@ -504,14 +514,6 @@ static spinlock_t sbp2_host_info_lock = SPIN_LOCK_UNLOCKED;
#define sbp2_spin_unlock(lock, flags) do {restore_flags(flags);} while (0) #define sbp2_spin_unlock(lock, flags) do {restore_flags(flags);} while (0)
#endif #endif
/*
* SCSI inquiry hack for really badly behaved sbp2 devices. Turn this on if your sbp2 device
* is not properly handling the SCSI inquiry command. This hack makes the inquiry look more
* like a typical MS Windows inquiry.
*/
/* #define SBP2_FORCE_36_BYTE_INQUIRY */
/* /*
* Globals * Globals
*/ */
...@@ -525,29 +527,35 @@ static LIST_HEAD(sbp2_host_info_list); ...@@ -525,29 +527,35 @@ static LIST_HEAD(sbp2_host_info_list);
static struct hpsb_highlevel *sbp2_hl_handle = NULL; static struct hpsb_highlevel *sbp2_hl_handle = NULL;
static struct hpsb_highlevel_ops sbp2_hl_ops = { static struct hpsb_highlevel_ops sbp2_hl_ops = {
add_host: sbp2_add_host, .add_host = sbp2_add_host,
remove_host: sbp2_remove_host, .remove_host = sbp2_remove_host,
}; };
static struct hpsb_address_ops sbp2_ops = { static struct hpsb_address_ops sbp2_ops = {
write: sbp2_handle_status_write .write = sbp2_handle_status_write
}; };
#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
static struct hpsb_address_ops sbp2_physdma_ops = { static struct hpsb_address_ops sbp2_physdma_ops = {
read: sbp2_handle_physdma_read, .read = sbp2_handle_physdma_read,
write: sbp2_handle_physdma_write, .write = sbp2_handle_physdma_write,
}; };
#endif #endif
static struct hpsb_protocol_driver sbp2_driver = { static struct hpsb_protocol_driver sbp2_driver = {
name: "SBP2 Driver", .name = "SBP2 Driver",
id_table: sbp2_id_table, .id_table = sbp2_id_table,
probe: sbp2_probe, .probe = sbp2_probe,
disconnect: sbp2_disconnect, .disconnect = sbp2_disconnect,
update: sbp2_update .update = sbp2_update
}; };
/* List of device firmware's that require a forced 36 byte inquiry. Note
* the final 0x0 needs to be there for denoting end of list. */
static u32 sbp2_broken_inquiry_list[] = {
0x00002800, /* Stefan Richter <richtest@bauwesen.tu-cottbus.de> */
0x0
};
/************************************** /**************************************
* General utility functions * General utility functions
...@@ -1903,27 +1911,58 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id) ...@@ -1903,27 +1911,58 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id)
break; break;
case SBP2_FIRMWARE_REVISION_KEY: case SBP2_FIRMWARE_REVISION_KEY:
/* /* Firmware revision */
* Firmware revision (used to find broken
* devices). If the vendor id is 0xa0b8
* (Symbios vendor id), then we have a
* bridge with 128KB max transfer size
* limitation.
*/
scsi_id->sbp2_firmware_revision scsi_id->sbp2_firmware_revision
= CONFIG_ROM_VALUE(ud->quadlets[i]); = CONFIG_ROM_VALUE(ud->quadlets[i]);
SBP2_DEBUG("sbp2_firmware_revision = %x", SBP2_DEBUG("sbp2_firmware_revision = %x",
(unsigned int) scsi_id->sbp2_firmware_revision); (unsigned int) scsi_id->sbp2_firmware_revision);
if ((scsi_id->sbp2_firmware_revision & 0xffff00) ==
SBP2_128KB_BROKEN_FIRMWARE) {
SBP2_WARN("warning: Bridge chipset supports 128KB max transfer size");
}
break; break;
default: default:
break; break;
} }
} }
/* This is the start of our broken device checking. We try to hack
* around oddities and known defects. */
scsi_id->workarounds = 0x0;
/* If the vendor id is 0xa0b8 (Symbios vendor id), then we have a
* bridge with 128KB max transfer size limitation. For sanity, we
* only voice this when the current sbp2_max_sectors setting
* exceeds the 128k limit. By default, that is not the case.
*
* It would be really nice if we could detect this before the scsi
* host gets initialized. That way we can down-force the
* sbp2_max_sectors to account for it. That is not currently
* possible. */
if ((scsi_id->sbp2_firmware_revision & 0xffff00) ==
SBP2_128KB_BROKEN_FIRMWARE &&
(sbp2_max_sectors * 512) > (128 * 1024)) {
SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB max transfer size.",
NODE_BUS_ARGS(scsi_id->ne->nodeid));
SBP2_WARN("WARNING: Current sbp2_max_sectors setting is larger than 128KB (%d sectors)!",
sbp2_max_sectors);
scsi_id->workarounds |= SBP2_BREAKAGE_128K_MAX_TRANSFER;
}
/* Check for a blacklisted set of devices that require us to force
* a 36 byte host inquiry. This can be overriden as a module param
* (to force all hosts).
*
* XXX If this does not detect your firmware as being defective,
* but using the sbp2_force_inquiry_hack allows your device to
* work, please submit the value of your firmware revision to the
* linux1394-devel mailing list. */
for (i = 0; sbp2_broken_inquiry_list[i]; i++) {
if ((scsi_id->sbp2_firmware_revision & 0xffff00) ==
sbp2_broken_inquiry_list[i]) {
SBP2_WARN("Node " NODE_BUS_FMT ": Using 36byte inquiry workaround",
NODE_BUS_ARGS(scsi_id->ne->nodeid));
scsi_id->workarounds |= SBP2_BREAKAGE_INQUIRY_HACK;
break; // No need to continue.
}
}
} }
/* /*
...@@ -2400,11 +2439,10 @@ static int sbp2_send_command(struct sbp2scsi_host_info *hi, struct scsi_id_insta ...@@ -2400,11 +2439,10 @@ static int sbp2_send_command(struct sbp2scsi_host_info *hi, struct scsi_id_insta
* reject this inquiry command. Fix the request_bufflen. * reject this inquiry command. Fix the request_bufflen.
*/ */
if (*cmd == INQUIRY) { if (*cmd == INQUIRY) {
#ifdef SBP2_FORCE_36_BYTE_INQUIRY if (sbp2_force_inquiry_hack || scsi_id->workarounds & SBP2_BREAKAGE_INQUIRY_HACK)
request_bufflen = cmd[4] = 0x24; request_bufflen = cmd[4] = 0x24;
#else else
request_bufflen = cmd[4]; request_bufflen = cmd[4];
#endif
} }
/* /*
...@@ -3096,7 +3134,11 @@ static int sbp2scsi_reset (Scsi_Cmnd *SCpnt) ...@@ -3096,7 +3134,11 @@ static int sbp2scsi_reset (Scsi_Cmnd *SCpnt)
/* /*
* Called by scsi stack to get bios parameters (used by fdisk, and at boot). * Called by scsi stack to get bios parameters (used by fdisk, and at boot).
*/ */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28)
static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[])
#else
static int sbp2scsi_biosparam (Scsi_Disk *disk, struct block_device *dev, int geom[]) static int sbp2scsi_biosparam (Scsi_Disk *disk, struct block_device *dev, int geom[])
#endif
{ {
int heads, sectors, cylinders; int heads, sectors, cylinders;
...@@ -3132,7 +3174,14 @@ static int sbp2scsi_detect (Scsi_Host_Template *tpnt) ...@@ -3132,7 +3174,14 @@ static int sbp2scsi_detect (Scsi_Host_Template *tpnt)
* host controller currently registered, and for each of those * host controller currently registered, and for each of those
* we register a scsi host with the scsi stack. * we register a scsi host with the scsi stack.
*/ */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
spin_unlock_irq(&io_request_lock);
sbp2_init(); sbp2_init();
spin_lock_irq(&io_request_lock);
#else
sbp2_init();
#endif
/* We return the number of hosts registered. */ /* We return the number of hosts registered. */
return scsi_driver_template.present; return scsi_driver_template.present;
...@@ -3178,23 +3227,23 @@ MODULE_LICENSE("GPL"); ...@@ -3178,23 +3227,23 @@ MODULE_LICENSE("GPL");
/* SCSI host template */ /* SCSI host template */
static Scsi_Host_Template scsi_driver_template = { static Scsi_Host_Template scsi_driver_template = {
name: "IEEE-1394 SBP-2 protocol driver", .name = "IEEE-1394 SBP-2 protocol driver",
info: sbp2scsi_info, .info = sbp2scsi_info,
detect: sbp2scsi_detect, .detect = sbp2scsi_detect,
queuecommand: sbp2scsi_queuecommand, .queuecommand = sbp2scsi_queuecommand,
eh_abort_handler: sbp2scsi_abort, .eh_abort_handler = sbp2scsi_abort,
eh_device_reset_handler:sbp2scsi_reset, .eh_device_reset_handler =sbp2scsi_reset,
eh_bus_reset_handler: sbp2scsi_reset, .eh_bus_reset_handler = sbp2scsi_reset,
eh_host_reset_handler: sbp2scsi_reset, .eh_host_reset_handler =sbp2scsi_reset,
bios_param: sbp2scsi_biosparam, .bios_param = sbp2scsi_biosparam,
this_id: -1, .this_id = -1,
sg_tablesize: SBP2_MAX_SG_ELEMENTS, .sg_tablesize = SBP2_MAX_SG_ELEMENTS,
use_clustering: SBP2_CLUSTERING, .use_clustering = SBP2_CLUSTERING,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
use_new_eh_code: TRUE, .use_new_eh_code = TRUE,
#endif #endif
emulated: 1, .emulated = 1,
proc_name: SBP2_DEVICE_NAME, .proc_name = SBP2_DEVICE_NAME,
}; };
static int sbp2_module_init(void) static int sbp2_module_init(void)
......
...@@ -357,6 +357,10 @@ struct sbp2_command_info { ...@@ -357,6 +357,10 @@ struct sbp2_command_info {
}; };
/* A list of flags for detected oddities and brokeness. */
#define SBP2_BREAKAGE_128K_MAX_TRANSFER 0x1
#define SBP2_BREAKAGE_INQUIRY_HACK 0x2
/* /*
* Information needed on a per scsi id basis (one for each sbp2 device) * Information needed on a per scsi id basis (one for each sbp2 device)
*/ */
...@@ -412,6 +416,9 @@ struct scsi_id_instance_data { ...@@ -412,6 +416,9 @@ struct scsi_id_instance_data {
/* Node entry, as retrieved from NodeMgr entries */ /* Node entry, as retrieved from NodeMgr entries */
struct node_entry *ne; struct node_entry *ne;
/* Device specific workarounds/brokeness */
u32 workarounds;
}; };
/* /*
...@@ -542,7 +549,11 @@ static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id ...@@ -542,7 +549,11 @@ static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id
static int sbp2scsi_detect (Scsi_Host_Template *tpnt); static int sbp2scsi_detect (Scsi_Host_Template *tpnt);
static const char *sbp2scsi_info (struct Scsi_Host *host); static const char *sbp2scsi_info (struct Scsi_Host *host);
void sbp2scsi_setup(char *str, int *ints); void sbp2scsi_setup(char *str, int *ints);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28)
static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]);
#else
static int sbp2scsi_biosparam (Scsi_Disk *disk, struct block_device *dev, int geom[]); static int sbp2scsi_biosparam (Scsi_Disk *disk, struct block_device *dev, int geom[]);
#endif
static int sbp2scsi_abort (Scsi_Cmnd *SCpnt); static int sbp2scsi_abort (Scsi_Cmnd *SCpnt);
static int sbp2scsi_reset (Scsi_Cmnd *SCpnt); static int sbp2scsi_reset (Scsi_Cmnd *SCpnt);
static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)); static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
......
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