Commit d79d8cc6 authored by Ben Collins's avatar Ben Collins

[PATCH] IEEE1394 updates

- Add ioctl32 compat function registration for video1394, dv1394 and
  amdtp.
- Convert SBP-2 driver to new SCSI hotplug host/device interfaces.
- Initial Async ISO (GASP) support.
parent 3188a3b6
......@@ -74,6 +74,8 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/ioctl32.h>
#include <linux/compat.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
......@@ -1262,8 +1264,11 @@ MODULE_LICENSE("GPL");
static int __init amdtp_init_module (void)
{
if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_AMDTP,
THIS_MODULE, &amdtp_fops)) {
int ret;
ret = ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_AMDTP,
THIS_MODULE, &amdtp_fops);
if (ret) {
HPSB_ERR("amdtp: unable to get minor device block");
return -EIO;
}
......@@ -1276,6 +1281,15 @@ static int __init amdtp_init_module (void)
return -EIO;
}
#ifdef CONFIG_COMPAT
ret = register_ioctl32_conversion(AMDTP_IOC_CHANNEL, NULL);
ret |= register_ioctl32_conversion(AMDTP_IOC_PLUG, NULL);
ret |= register_ioctl32_conversion(AMDTP_IOC_PING, NULL);
ret |= register_ioctl32_conversion(AMDTP_IOC_ZAP, NULL);
if (ret)
HPSB_ERR("amdtp: Error registering ioctl32 translations");
#endif
HPSB_INFO("Loaded AMDTP driver");
return 0;
......@@ -1283,6 +1297,17 @@ static int __init amdtp_init_module (void)
static void __exit amdtp_exit_module (void)
{
#ifdef CONFIG_COMPAT
int ret;
ret = unregister_ioctl32_conversion(AMDTP_IOC_CHANNEL);
ret |= unregister_ioctl32_conversion(AMDTP_IOC_PLUG);
ret |= unregister_ioctl32_conversion(AMDTP_IOC_PING);
ret |= unregister_ioctl32_conversion(AMDTP_IOC_ZAP);
if (ret)
HPSB_ERR("amdtp: Error unregistering ioctl32 translations");
#endif
hpsb_unregister_highlevel(amdtp_highlevel);
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_AMDTP);
......
......@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include "dma.h"
/* dma_prog_region */
......
......@@ -111,6 +111,8 @@
#include <linux/wrapper.h>
#include <linux/vmalloc.h>
#include <linux/string.h>
#include <linux/ioctl32.h>
#include <linux/compat.h>
#include "ieee1394.h"
#include "ieee1394_types.h"
......@@ -2907,6 +2909,98 @@ static struct hpsb_highlevel_ops hl_ops = {
.host_reset = dv1394_host_reset,
};
#ifdef CONFIG_COMPAT
#define DV1394_IOC32_INIT _IOW('#', 0x06, struct dv1394_init32)
#define DV1394_IOC32_GET_STATUS _IOR('#', 0x0c, struct dv1394_status32)
struct dv1394_init32 {
u32 api_version;
u32 channel;
u32 n_frames;
u32 format;
u32 cip_n;
u32 cip_d;
u32 syt_offset;
};
struct dv1394_status32 {
struct dv1394_init32 init;
s32 active_frame;
u32 first_clear_frame;
u32 n_clear_frames;
u32 dropped_frames;
};
static int handle_dv1394_init(unsigned int fd, unsigned int cmd, unsigned long arg,
struct file *file)
{
struct dv1394_init32 dv32;
struct dv1394_init dv;
mm_segment_t old_fs;
int ret;
if (file->f_op->ioctl != dv1394_ioctl)
return -EFAULT;
if (copy_from_user(&dv32, (void *)arg, sizeof(dv32)))
return -EFAULT;
dv.api_version = dv32.api_version;
dv.channel = dv32.channel;
dv.n_frames = dv32.n_frames;
dv.format = dv32.format;
dv.cip_n = (unsigned long)dv32.cip_n;
dv.cip_d = (unsigned long)dv32.cip_d;
dv.syt_offset = dv32.syt_offset;
old_fs = get_fs();
set_fs(KERNEL_DS);
ret = dv1394_ioctl(file->f_dentry->d_inode, file,
DV1394_IOC_INIT, (unsigned long)&dv);
set_fs(old_fs);
return ret;
}
static int handle_dv1394_get_status(unsigned int fd, unsigned int cmd, unsigned long arg,
struct file *file)
{
struct dv1394_status32 dv32;
struct dv1394_status dv;
mm_segment_t old_fs;
int ret;
if (file->f_op->ioctl != dv1394_ioctl)
return -EFAULT;
old_fs = get_fs();
set_fs(KERNEL_DS);
ret = dv1394_ioctl(file->f_dentry->d_inode, file,
DV1394_IOC_GET_STATUS, (unsigned long)&dv);
set_fs(old_fs);
if (!ret) {
dv32.init.api_version = dv.init.api_version;
dv32.init.channel = dv.init.channel;
dv32.init.n_frames = dv.init.n_frames;
dv32.init.format = dv.init.format;
dv32.init.cip_n = (u32)dv.init.cip_n;
dv32.init.cip_d = (u32)dv.init.cip_d;
dv32.init.syt_offset = dv.init.syt_offset;
dv32.active_frame = dv.active_frame;
dv32.first_clear_frame = dv.first_clear_frame;
dv32.n_clear_frames = dv.n_clear_frames;
dv32.dropped_frames = dv.dropped_frames;
if (copy_to_user((struct dv1394_status32 *)arg, &dv32, sizeof(dv32)))
ret = -EFAULT;
}
return ret;
}
#endif /* CONFIG_COMPAT */
/*** KERNEL MODULE HANDLERS ************************************************/
......@@ -2917,6 +3011,20 @@ MODULE_LICENSE("GPL");
static void __exit dv1394_exit_module(void)
{
#ifdef CONFIG_COMPAT
int ret;
ret = unregister_ioctl32_conversion(DV1394_IOC_SHUTDOWN);
ret |= unregister_ioctl32_conversion(DV1394_IOC_SUBMIT_FRAMES);
ret |= unregister_ioctl32_conversion(DV1394_IOC_WAIT_FRAMES);
ret |= unregister_ioctl32_conversion(DV1394_IOC_RECEIVE_FRAMES);
ret |= unregister_ioctl32_conversion(DV1394_IOC_START_RECEIVE);
ret |= unregister_ioctl32_conversion(DV1394_IOC32_INIT);
ret |= unregister_ioctl32_conversion(DV1394_IOC32_GET_STATUS);
if (ret)
printk(KERN_ERR "dv1394: Error unregistering ioctl32 translations\n");
#endif
hpsb_unregister_highlevel (hl_handle);
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
#ifdef CONFIG_DEVFS_FS
......@@ -2929,14 +3037,18 @@ static void __exit dv1394_exit_module(void)
static int __init dv1394_init_module(void)
{
if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_DV1394,
THIS_MODULE, &dv1394_fops)) {
int ret;
ret = ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_DV1394,
THIS_MODULE, &dv1394_fops);
if (ret) {
printk(KERN_ERR "dv1394: unable to register character device\n");
return -EIO;
}
#ifdef CONFIG_DEVFS_FS
if (dv1394_devfs_add_dir("dv", NULL, NULL) < 0) {
ret = dv1394_devfs_add_dir("dv", NULL, NULL);
if (ret < 0) {
printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/dv\n");
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
return -ENOMEM;
......@@ -2944,7 +3056,8 @@ static int __init dv1394_init_module(void)
#endif
#ifdef CONFIG_PROC_FS
if (dv1394_procfs_add_dir("dv",NULL,NULL) < 0) {
ret = dv1394_procfs_add_dir("dv",NULL,NULL);
if (ret < 0) {
printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/dv\n");
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
#ifdef CONFIG_DEVFS_FS
......@@ -2967,9 +3080,23 @@ static int __init dv1394_init_module(void)
return -ENOMEM;
}
#ifdef CONFIG_COMPAT
/* First compatible ones */
ret = register_ioctl32_conversion(DV1394_IOC_SHUTDOWN, NULL);
ret |= register_ioctl32_conversion(DV1394_IOC_SUBMIT_FRAMES, NULL);
ret |= register_ioctl32_conversion(DV1394_IOC_WAIT_FRAMES, NULL);
ret |= register_ioctl32_conversion(DV1394_IOC_RECEIVE_FRAMES, NULL);
ret |= register_ioctl32_conversion(DV1394_IOC_START_RECEIVE, NULL);
/* These need to be handled by translation */
ret |= register_ioctl32_conversion(DV1394_IOC32_INIT, handle_dv1394_init);
ret |= register_ioctl32_conversion(DV1394_IOC32_GET_STATUS, handle_dv1394_get_status);
if (ret)
printk(KERN_ERR "dv1394: Error registering ioctl32 translations\n");
#endif
return 0;
}
module_init(dv1394_init_module);
module_exit(dv1394_exit_module);
This diff is collapsed.
......@@ -30,9 +30,16 @@
#define ETHER1394_REGION_ADDR 0xfffff0200000ULL
#define ETHER1394_REGION_ADDR_END (ETHER1394_REGION_ADDR + ETHER1394_REGION_ADDR_LEN)
/* GASP identifier numbers for IPv4 over IEEE 1394 */
#define ETHER1394_GASP_SPECIFIER_ID 0x00005E
#define ETHER1394_GASP_VERSION 1
/* Node set == 64 */
#define NODE_SET (ALL_NODES + 1)
enum eth1394_bc_states { ETHER1394_BC_CLOSED, ETHER1394_BC_OPENED,
ETHER1394_BC_CHECK };
/* Private structure for our ethernet driver */
struct eth1394_priv {
struct net_device_stats stats; /* Device stats */
......@@ -43,6 +50,9 @@ struct eth1394_priv {
u32 fifo_lo[ALL_NODES]; /* 32bit lo fifo offset per node */
u64 eui[ALL_NODES]; /* EUI-64 per node */
spinlock_t lock; /* Private lock */
int broadcast_channel; /* Async stream Broadcast Channel */
enum eth1394_bc_states bc_state; /* broadcast channel state */
struct hpsb_iso *iso; /* Async stream recv handle */
};
struct host_info {
......@@ -51,12 +61,15 @@ struct host_info {
struct net_device *dev;
};
typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type;
/* This is our task struct. It's used for the packet complete callback. */
struct packet_task {
struct sk_buff *skb; /* Socket buffer we are sending */
nodeid_t dest_node; /* Destination of the packet */
u64 addr; /* Address */
struct hpsb_queue_struct tq; /* The task */
eth1394_tx_type tx_type; /* Send data via GASP or Write Req. */
};
/* IP1394 headers */
......
......@@ -71,9 +71,6 @@ int hpsb_ref_host(struct hpsb_host *host)
list_for_each(lh, &hosts) {
if (host == list_entry(lh, struct hpsb_host, host_list)) {
if (try_module_get(host->driver->owner)) {
/* we're doing this twice and don't seem
to undo it.. --hch */
(void)try_module_get(host->driver->owner);
host->refcount++;
retval = 1;
}
......
......@@ -4,8 +4,8 @@
#ifndef __IEEE1394_IOCTL_H
#define __IEEE1394_IOCTL_H
#include <asm/ioctl.h>
#include <asm/types.h>
#include <linux/ioctl.h>
#include <linux/types.h>
/* AMDTP Gets 6 */
......@@ -91,7 +91,7 @@
#define RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL \
_IOW ('#', 0x23, unsigned char)
#define RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK \
_IOW ('#', 0x24, u64)
_IOW ('#', 0x24, __u64)
#define RAW1394_IOC_ISO_RECV_PACKETS \
_IOW ('#', 0x25, struct raw1394_iso_packets)
#define RAW1394_IOC_ISO_RECV_RELEASE_PACKETS \
......
......@@ -361,7 +361,7 @@ void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid)
host->topology_map[host->selfid_count++] = sid;
} else {
HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d",
sid, (host->node_id & BUS_MASK) >> 6);
sid, NODEID_TO_BUS(host->node_id));
}
}
......@@ -396,9 +396,6 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
/* irm_id is kept up to date by check_selfids() */
if (host->irm_id == host->node_id) {
host->is_irm = 1;
host->is_busmgr = 1;
host->busmgr_id = host->node_id;
host->csr.bus_manager_id = host->node_id;
} else {
host->is_busmgr = 0;
host->is_irm = 0;
......@@ -535,8 +532,8 @@ int hpsb_send_packet(struct hpsb_packet *packet)
if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {
packet->speed_code =
host->speed_map[(host->node_id & NODE_MASK) * 64
+ (packet->node_id & NODE_MASK)];
host->speed_map[NODEID_TO_NODE(host->node_id) * 64
+ NODEID_TO_NODE(packet->node_id)];
}
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
......@@ -748,7 +745,7 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
addr, 4, flags);
if (!write_acked
&& (((data[0] >> 16) & NODE_MASK) != NODE_MASK)
&& (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
&& (rcode >= 0)) {
/* not a broadcast write, reply */
PREP_REPLY_PACKET(0);
......@@ -763,7 +760,7 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
addr, data[3]>>16, flags);
if (!write_acked
&& (((data[0] >> 16) & NODE_MASK) != NODE_MASK)
&& (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
&& (rcode >= 0)) {
/* not a broadcast write, reply */
PREP_REPLY_PACKET(0);
......@@ -1248,6 +1245,7 @@ EXPORT_SYMBOL(hpsb_read);
EXPORT_SYMBOL(hpsb_write);
EXPORT_SYMBOL(hpsb_lock);
EXPORT_SYMBOL(hpsb_lock64);
EXPORT_SYMBOL(hpsb_send_gasp);
EXPORT_SYMBOL(hpsb_packet_success);
/** highlevel.c **/
......
......@@ -98,6 +98,17 @@ static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
packet->speed_code = SPEED_100; /* Force speed to be 100Mbps */
}
static void fill_async_stream_packet(struct hpsb_packet *packet, int length,
int channel, int tag, int sync)
{
packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
| (TCODE_STREAM_DATA << 4) | sync;
packet->header_size = 4;
packet->data_size = length;
packet->type = hpsb_async;
packet->tcode = TCODE_ISO_DATA;
}
/**
* hpsb_get_tlabel - allocate a transaction label
......@@ -495,7 +506,6 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
}
/* We need a hpsb_lock64 function for the 64 bit equivalent. Probably. */
int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, int extcode, quadlet_t *data, quadlet_t arg)
{
......@@ -558,3 +568,58 @@ int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation,
return retval;
}
int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
quadlet_t *buffer, size_t length, u32 specifier_id,
unsigned int version)
{
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
int i;
#endif
struct hpsb_packet *packet;
int retval = 0;
u16 specifier_id_hi = (specifier_id & 0x00ffff00) >> 8;
u8 specifier_id_lo = specifier_id & 0xff;
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
HPSB_DEBUG("Send GASP: channel = %d, length = %d", channel, length);
#endif
length += 8;
packet = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0));
if (!packet)
return -ENOMEM;
if (length % 4) {
packet->data[length / 4] = 0;
}
packet->host = host;
fill_async_stream_packet(packet, length, channel, 3, 0);
packet->data[0] = cpu_to_be32((host->node_id << 16) | specifier_id_hi);
packet->data[1] = cpu_to_be32((specifier_id_lo << 24) | (version & 0x00ffffff));
memcpy(&(packet->data[2]), buffer, length - 4);
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
HPSB_DEBUG("GASP: packet->header_size = %d", packet->header_size);
HPSB_DEBUG("GASP: packet->data_size = %d", packet->data_size);
for(i=0; i<(packet->data_size/4); i++)
HPSB_DEBUG("GASP: data[%d]: 0x%08x", i*4, be32_to_cpu(packet->data[i]));
#endif
packet->generation = generation;
packet->no_waiter = 1;
if (!hpsb_send_packet(packet)) {
free_hpsb_packet(packet);
retval = -EINVAL;
}
return retval;
}
......@@ -55,5 +55,8 @@ int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, int extcode, quadlet_t *data, quadlet_t arg);
int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, int extcode, octlet_t *data, octlet_t arg);
int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
quadlet_t *buffer, size_t length, u32 specifier_id,
unsigned int version);
#endif /* _IEEE1394_TRANSACTIONS_H */
......@@ -97,14 +97,17 @@ typedef u64 nodeaddr_t;
typedef u16 arm_length_t;
#define BUS_MASK 0xffc0
#define BUS_SHIFT 6
#define NODE_MASK 0x003f
#define LOCAL_BUS 0xffc0
#define ALL_NODES 0x003f
#define NODEID_TO_BUS(nodeid) ((nodeid & BUS_MASK) >> BUS_SHIFT)
#define NODEID_TO_NODE(nodeid) (nodeid & NODE_MASK)
/* Can be used to consistently print a node/bus ID. */
#define NODE_BUS_FMT "%02d:%04d"
#define NODE_BUS_ARGS(nodeid) \
(nodeid & NODE_MASK), ((nodeid & BUS_MASK) >> 6)
#define NODE_BUS_ARGS(nodeid) NODEID_TO_NODE(nodeid), NODEID_TO_BUS(nodeid)
#define HPSB_PRINT(level, fmt, args...) printk(level "ieee1394: " fmt "\n" , ## args)
......
......@@ -1210,6 +1210,52 @@ static void nodemgr_node_probe(struct hpsb_host *host)
return;
}
/* Because we are a 1394a-2000 compliant IRM, we need to inform all the other
* nodes of the broadcast channel. (Really we're only setting the validity
* bit). */
static void nodemgr_do_irm_duties(struct hpsb_host *host)
{
quadlet_t bc;
if (!host->is_irm)
return;
host->csr.broadcast_channel |= 0x40000000; /* set validity bit */
bc = cpu_to_be32(host->csr.broadcast_channel);
hpsb_write(host, LOCAL_BUS | ALL_NODES, get_hpsb_generation(host),
(CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL),
&bc,
sizeof(quadlet_t));
}
/* We need to ensure that if we are not the IRM, that the IRM node is capable of
* everything we can do, otherwise issue a bus reset and try to become the IRM
* ourselves. */
static int nodemgr_check_root_capability(struct hpsb_host *host)
{
quadlet_t bc;
int status;
if (host->is_irm)
return 1;
status = hpsb_read(host, LOCAL_BUS | (host->irm_id),
get_hpsb_generation(host),
(CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL),
&bc, sizeof(quadlet_t));
if (status < 0 || !(be32_to_cpu(bc) & 0x80000000)) {
/* The root node does not have a valid BROADCAST_CHANNEL
* register and we do, so reset the bus with force_root set */
HPSB_INFO("Remote root is not IRM capable, resetting...");
hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT);
return 0;
}
return 1;
}
static int nodemgr_host_thread(void *__hi)
{
struct host_info *hi = (struct host_info *)__hi;
......@@ -1222,7 +1268,16 @@ static int nodemgr_host_thread(void *__hi)
* happens when we get a bus reset. */
while (!down_interruptible(&hi->reset_sem) &&
!down_interruptible(&nodemgr_serialize)) {
if (!nodemgr_check_root_capability(hi->host)) {
/* Do nothing, we are resetting */
up(&nodemgr_serialize);
continue;
}
nodemgr_node_probe(hi->host);
nodemgr_do_irm_duties(hi->host);
up(&nodemgr_serialize);
}
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
......
......@@ -31,9 +31,9 @@
*
* Things implemented, but still in test phase:
* . Iso Transmit
* . Async Stream Packets Transmit (Receive done via Iso interface)
*
* Things not implemented:
* . Async Stream Packets
* . DMA error recovery
*
* Known bugs:
......@@ -160,7 +160,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
static char version[] __devinitdata =
"$Rev: 762 $ Ben Collins <bcollins@debian.org>";
"$Rev: 801 $ Ben Collins <bcollins@debian.org>";
/* Module Parameters */
MODULE_PARM(phys_dma,"i");
......@@ -649,18 +649,31 @@ static void insert_packet(struct ti_ohci *ohci,
} else {
d->prg_cpu[idx]->data[0] = packet->speed_code<<16 |
(packet->header[0] & 0xFFFF);
if (packet->tcode == TCODE_ISO_DATA) {
/* Sending an async stream packet */
d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000;
} else {
/* Sending a normal async request or response */
d->prg_cpu[idx]->data[1] =
(packet->header[1] & 0xFFFF) |
(packet->header[0] & 0xFFFF0000);
d->prg_cpu[idx]->data[2] = packet->header[2];
d->prg_cpu[idx]->data[3] = packet->header[3];
}
packet_swab(d->prg_cpu[idx]->data, packet->tcode);
}
if (packet->data_size) { /* block transmit */
if (packet->tcode == TCODE_STREAM_DATA){
d->prg_cpu[idx]->begin.control =
cpu_to_le32(DMA_CTL_OUTPUT_MORE |
DMA_CTL_IMMEDIATE | 0x8);
} else {
d->prg_cpu[idx]->begin.control =
cpu_to_le32(DMA_CTL_OUTPUT_MORE |
DMA_CTL_IMMEDIATE | 0x10);
}
d->prg_cpu[idx]->end.control =
cpu_to_le32(DMA_CTL_OUTPUT_LAST |
DMA_CTL_IRQ |
......@@ -830,7 +843,7 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
/* Decide whether we have an iso, a request, or a response packet */
if (packet->type == hpsb_raw)
d = &ohci->at_req_context;
else if (packet->tcode == TCODE_ISO_DATA) {
else if ((packet->tcode == TCODE_ISO_DATA) && (packet->type == hpsb_iso)) {
/* The legacy IT DMA context is initialized on first
* use. However, the alloc cannot be run from
* interrupt context, so we bail out if that is the
......@@ -856,7 +869,7 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
}
d = &ohci->it_legacy_context;
} else if (packet->tcode & 0x02)
} else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
d = &ohci->at_resp_context;
else
d = &ohci->at_req_context;
......@@ -1295,6 +1308,8 @@ static void ohci_iso_recv_program(struct hpsb_iso *iso)
u32 *prev_branch = NULL;
for (blk = 0; blk < recv->nblocks; blk++) {
u32 control;
/* the DMA descriptor */
struct dma_cmd *cmd = &recv->block[blk];
......@@ -1305,29 +1320,29 @@ static void ohci_iso_recv_program(struct hpsb_iso *iso)
unsigned long buf_offset = blk * recv->buf_stride;
if (recv->dma_mode == BUFFER_FILL_MODE) {
cmd->control = 2 << 28; /* INPUT_MORE */
control = 2 << 28; /* INPUT_MORE */
} else {
cmd->control = 3 << 28; /* INPUT_LAST */
control = 3 << 28; /* INPUT_LAST */
}
cmd->control |= 8 << 24; /* s = 1, update xferStatus and resCount */
control |= 8 << 24; /* s = 1, update xferStatus and resCount */
/* interrupt on last block, and at intervals */
if (blk == recv->nblocks-1 || (blk % recv->block_irq_interval) == 0) {
cmd->control |= 3 << 20; /* want interrupt */
control |= 3 << 20; /* want interrupt */
}
cmd->control |= 3 << 18; /* enable branch to address */
cmd->control |= recv->buf_stride;
control |= 3 << 18; /* enable branch to address */
control |= recv->buf_stride;
cmd->address = dma_region_offset_to_bus(&iso->data_buf, buf_offset);
cmd->control = cpu_to_le32(control);
cmd->address = cpu_to_le32(dma_region_offset_to_bus(&iso->data_buf, buf_offset));
cmd->branchAddress = 0; /* filled in on next loop */
cmd->status = recv->buf_stride;
cmd->status = cpu_to_le32(recv->buf_stride);
/* link the previous descriptor to this one */
if (prev_branch) {
*prev_branch = dma_prog_region_offset_to_bus(&recv->prog, prog_offset);
*prev_branch |= 1; /* set Z=1 */
*prev_branch = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog, prog_offset) | 1);
}
prev_branch = &cmd->branchAddress;
......@@ -1485,18 +1500,18 @@ static void ohci_iso_recv_release_block(struct ohci_iso_recv *recv, int block)
/* 'next' becomes the new end of the DMA chain,
so disable branch and enable interrupt */
next->branchAddress = 0;
next->control |= 3 << 20;
next->control |= cpu_to_le32(3 << 20);
/* link prev to next */
prev->branchAddress = dma_prog_region_offset_to_bus(&recv->prog,
prev->branchAddress = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog,
sizeof(struct dma_cmd) * next_i)
| 1; /* Z=1 */
| 1); /* Z=1 */
/* disable interrupt on previous DMA descriptor, except at intervals */
if((prev_i % recv->block_irq_interval) == 0) {
prev->control |= 3 << 20; /* enable interrupt */
prev->control |= cpu_to_le32(3 << 20); /* enable interrupt */
} else {
prev->control &= ~(3<<20); /* disable interrupt */
prev->control &= cpu_to_le32(~(3<<20)); /* disable interrupt */
}
wmb();
......@@ -1720,8 +1735,8 @@ static void ohci_iso_recv_packetperbuf_task(unsigned long data)
struct dma_cmd *il = ((struct dma_cmd*) recv->prog.kvirt) + iso->pkt_dma;
/* check the DMA descriptor for new writes to xferStatus */
u16 xferstatus = il->status >> 16;
u16 rescount = il->status & 0xFFFF;
u16 xferstatus = le32_to_cpu(il->status) >> 16;
u16 rescount = le32_to_cpu(il->status) & 0xFFFF;
unsigned char event = xferstatus & 0x1F;
......@@ -1903,7 +1918,7 @@ static void ohci_iso_xmit_task(unsigned long data)
struct iso_xmit_cmd *cmd = dma_region_i(&xmit->prog, struct iso_xmit_cmd, iso->pkt_dma);
/* check for new writes to xferStatus */
u16 xferstatus = cmd->output_last.status >> 16;
u16 xferstatus = le32_to_cpu(cmd->output_last.status) >> 16;
u8 event = xferstatus & 0x1F;
if(!event) {
......@@ -1919,7 +1934,7 @@ static void ohci_iso_xmit_task(unsigned long data)
wake = 1;
/* parse cycle */
cycle = cmd->output_last.status & 0x1FFF;
cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF;
/* tell the subsystem the packet has gone out */
hpsb_iso_packet_sent(iso, cycle, event != 0x11);
......@@ -1972,7 +1987,7 @@ static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info
/* set up the OUTPUT_MORE_IMMEDIATE descriptor */
memset(next, 0, sizeof(struct iso_xmit_cmd));
next->output_more_immediate.control = 0x02000008;
next->output_more_immediate.control = cpu_to_le32(0x02000008);
/* ISO packet header is embedded in the OUTPUT_MORE_IMMEDIATE */
......@@ -1990,28 +2005,28 @@ static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info
next->iso_hdr[7] = len >> 8;
/* set up the OUTPUT_LAST */
next->output_last.control = 1 << 28;
next->output_last.control |= 1 << 27; /* update timeStamp */
next->output_last.control |= 3 << 20; /* want interrupt */
next->output_last.control |= 3 << 18; /* enable branch */
next->output_last.control |= len;
next->output_last.control = cpu_to_le32(1 << 28);
next->output_last.control |= cpu_to_le32(1 << 27); /* update timeStamp */
next->output_last.control |= cpu_to_le32(3 << 20); /* want interrupt */
next->output_last.control |= cpu_to_le32(3 << 18); /* enable branch */
next->output_last.control |= cpu_to_le32(len);
/* payload bus address */
next->output_last.address = dma_region_offset_to_bus(&iso->data_buf, offset);
next->output_last.address = cpu_to_le32(dma_region_offset_to_bus(&iso->data_buf, offset));
/* leave branchAddress at zero for now */
/* re-write the previous DMA descriptor to chain to this one */
/* set prev branch address to point to next (Z=3) */
prev->output_last.branchAddress =
dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3;
prev->output_last.branchAddress = cpu_to_le32(
dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3);
/* disable interrupt, unless required by the IRQ interval */
if(prev_i % iso->irq_interval) {
prev->output_last.control &= ~(3 << 20); /* no interrupt */
prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */
} else {
prev->output_last.control |= 3 << 20; /* enable interrupt */
prev->output_last.control |= cpu_to_le32(3 << 20); /* enable interrupt */
}
wmb();
......@@ -3474,7 +3489,7 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
static struct pci_device_id ohci1394_pci_tbl[] __devinitdata = {
{
.class = PCI_CLASS_FIREWIRE_OHCI,
.class_mask = 0x00ffffff,
.class_mask = ~0,
.vendor = PCI_ANY_ID,
.device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID,
......
......@@ -238,7 +238,7 @@ static void remove_host(struct hpsb_host *host)
list_del(&hi->list);
host_count--;
/*
FIXME: addressranges should be removed
FIXME: address ranges should be removed
and fileinfo states should be initialized
(including setting generation to
internal-generation ...)
......@@ -281,8 +281,8 @@ static void host_reset(struct hpsb_host *host)
req->req.misc = (host->node_id << 16)
| host->node_count;
if (fi->protocol_version > 3) {
req->req.misc |= ((host->irm_id
& NODE_MASK) << 8);
req->req.misc |= (NODEID_TO_NODE(host->irm_id)
<< 8);
}
queue_complete_req(req);
......@@ -571,8 +571,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
req->req.misc = (fi->host->node_id << 16)
| fi->host->node_count;
if (fi->protocol_version > 3) {
req->req.misc |=
(fi->host->irm_id & NODE_MASK) << 8;
req->req.misc |= NODEID_TO_NODE(fi->host->irm_id) << 8;
}
} else {
req->req.error = RAW1394_ERROR_INVALID_ARG;
......
This diff is collapsed.
......@@ -22,15 +22,6 @@
#ifndef SBP2_H
#define SBP2_H
/* Some compatibility code */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#define SCSI_REGISTER_HOST(tmpl) scsi_register_module(MODULE_SCSI_HA, tmpl)
#define SCSI_UNREGISTER_HOST(tmpl) scsi_unregister_module(MODULE_SCSI_HA, tmpl)
#else
#define SCSI_REGISTER_HOST(tmpl) scsi_register_host(tmpl)
#define SCSI_UNREGISTER_HOST(tmpl) scsi_unregister_host(tmpl)
#endif
#define SBP2_DEVICE_NAME "sbp2"
/*
......@@ -442,8 +433,6 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i
static void sbp2_add_host(struct hpsb_host *host);
static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host);
static void sbp2_remove_host(struct hpsb_host *host);
int sbp2_init(void);
void sbp2_cleanup(void);
static int sbp2_probe(struct unit_directory *ud);
static void sbp2_disconnect(struct unit_directory *ud);
static void sbp2_update(struct unit_directory *ud);
......@@ -487,23 +476,4 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id);
static int sbp2_set_busy_timeout(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
/*
* Scsi interface related prototypes
*/
static int sbp2scsi_detect (Scsi_Host_Template *tpnt);
static const char *sbp2scsi_info (struct Scsi_Host *host);
void sbp2scsi_setup(char *str, int *ints);
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,44)
static int sbp2scsi_biosparam (struct scsi_device *sdev, struct block_device *dev, sector_t capacity, int geom[]);
#else
static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]);
#endif
static int sbp2scsi_abort (Scsi_Cmnd *SCpnt);
static int sbp2scsi_reset (Scsi_Cmnd *SCpnt);
static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
static void sbp2scsi_complete_all_commands(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id,
u32 status);
static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id,
u32 scsi_status, Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
#endif /* SBP2_H */
......@@ -43,6 +43,8 @@
#include <linux/vmalloc.h>
#include <linux/timex.h>
#include <linux/mm.h>
#include <linux/ioctl32.h>
#include <linux/compat.h>
#include "ieee1394.h"
#include "ieee1394_types.h"
......@@ -1338,8 +1340,133 @@ MODULE_DESCRIPTION("driver for digital video on OHCI board");
MODULE_SUPPORTED_DEVICE(VIDEO1394_DRIVER_NAME);
MODULE_LICENSE("GPL");
#ifdef CONFIG_COMPAT
#define VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER \
_IOW ('#', 0x12, struct video1394_wait32)
#define VIDEO1394_IOC32_LISTEN_WAIT_BUFFER \
_IOWR('#', 0x13, struct video1394_wait32)
#define VIDEO1394_IOC32_TALK_WAIT_BUFFER \
_IOW ('#', 0x17, struct video1394_wait32)
#define VIDEO1394_IOC32_LISTEN_POLL_BUFFER \
_IOWR('#', 0x18, struct video1394_wait32)
struct video1394_wait32 {
u32 channel;
u32 buffer;
struct compat_timeval filltime;
};
static int video1394_wr_wait32(unsigned int fd, unsigned int cmd, unsigned long arg,
struct file *file)
{
struct video1394_wait32 wait32;
struct video1394_wait wait;
mm_segment_t old_fs;
int ret;
if (file->f_op->ioctl != video1394_ioctl)
return -EFAULT;
if (copy_from_user(&wait32, (void *)arg, sizeof(wait32)))
return -EFAULT;
wait.channel = wait32.channel;
wait.buffer = wait32.buffer;
wait.filltime.tv_sec = (time_t)wait32.filltime.tv_sec;
wait.filltime.tv_usec = (suseconds_t)wait32.filltime.tv_usec;
old_fs = get_fs();
set_fs(KERNEL_DS);
if (cmd == VIDEO1394_IOC32_LISTEN_WAIT_BUFFER)
ret = video1394_ioctl(file->f_dentry->d_inode, file,
VIDEO1394_IOC_LISTEN_WAIT_BUFFER,
(unsigned long) &wait);
else
ret = video1394_ioctl(file->f_dentry->d_inode, file,
VIDEO1394_IOC_LISTEN_POLL_BUFFER,
(unsigned long) &wait);
set_fs(old_fs);
if (!ret) {
wait32.channel = wait.channel;
wait32.buffer = wait.buffer;
wait32.filltime.tv_sec = (int)wait.filltime.tv_sec;
wait32.filltime.tv_usec = (int)wait.filltime.tv_usec;
if (copy_to_user((struct video1394_wait32 *)arg, &wait32, sizeof(wait32)))
ret = -EFAULT;
}
return ret;
}
static int video1394_w_wait32(unsigned int fd, unsigned int cmd, unsigned long arg,
struct file *file)
{
struct video1394_wait32 wait32;
struct video1394_wait wait;
mm_segment_t old_fs;
int ret;
if (file->f_op->ioctl != video1394_ioctl)
return -EFAULT;
if (copy_from_user(&wait32, (void *)arg, sizeof(wait32)))
return -EFAULT;
wait.channel = wait32.channel;
wait.buffer = wait32.buffer;
wait.filltime.tv_sec = (time_t)wait32.filltime.tv_sec;
wait.filltime.tv_usec = (suseconds_t)wait32.filltime.tv_usec;
old_fs = get_fs();
set_fs(KERNEL_DS);
if (cmd == VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER)
ret = video1394_ioctl(file->f_dentry->d_inode, file,
VIDEO1394_IOC_LISTEN_QUEUE_BUFFER,
(unsigned long) &wait);
else
ret = video1394_ioctl(file->f_dentry->d_inode, file,
VIDEO1394_IOC_TALK_WAIT_BUFFER,
(unsigned long) &wait);
set_fs(old_fs);
return ret;
}
static int video1394_queue_buf32(unsigned int fd, unsigned int cmd, unsigned long arg,
struct file *file)
{
if (file->f_op->ioctl != video1394_ioctl)
return -EFAULT;
return -EFAULT;
return video1394_ioctl(file->f_dentry->d_inode, file,
VIDEO1394_IOC_TALK_QUEUE_BUFFER, arg);
}
#endif /* CONFIG_COMPAT */
static void __exit video1394_exit_module (void)
{
#ifdef CONFIG_COMPAT
int ret;
ret = unregister_ioctl32_conversion(VIDEO1394_IOC_LISTEN_CHANNEL);
ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_UNLISTEN_CHANNEL);
ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_TALK_CHANNEL);
ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_UNTALK_CHANNEL);
ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER);
ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_WAIT_BUFFER);
ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_TALK_QUEUE_BUFFER);
ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_TALK_WAIT_BUFFER);
ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_POLL_BUFFER);
if (ret)
PRINT_G(KERN_INFO, "Error unregistering ioctl32 translations");
#endif
hpsb_unregister_highlevel (hl_handle);
devfs_unregister(devfs_handle);
......@@ -1350,8 +1477,11 @@ static void __exit video1394_exit_module (void)
static int __init video1394_init_module (void)
{
if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394,
THIS_MODULE, &video1394_fops)) {
int ret;
ret = ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394,
THIS_MODULE, &video1394_fops);
if (ret) {
PRINT_G(KERN_ERR, "video1394: unable to get minor device block");
return -EIO;
}
......@@ -1366,9 +1496,32 @@ static int __init video1394_init_module (void)
return -ENOMEM;
}
#ifdef CONFIG_COMPAT
/* First the compatible ones */
ret = register_ioctl32_conversion(VIDEO1394_IOC_LISTEN_CHANNEL, NULL);
ret |= register_ioctl32_conversion(VIDEO1394_IOC_UNLISTEN_CHANNEL, NULL);
ret |= register_ioctl32_conversion(VIDEO1394_IOC_TALK_CHANNEL, NULL);
ret |= register_ioctl32_conversion(VIDEO1394_IOC_UNTALK_CHANNEL, NULL);
/* These need translation */
ret |= register_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER,
video1394_w_wait32);
ret |= register_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_WAIT_BUFFER,
video1394_wr_wait32);
ret |= register_ioctl32_conversion(VIDEO1394_IOC_TALK_QUEUE_BUFFER,
video1394_queue_buf32);
ret |= register_ioctl32_conversion(VIDEO1394_IOC32_TALK_WAIT_BUFFER,
video1394_w_wait32);
ret |= register_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_POLL_BUFFER,
video1394_wr_wait32);
if (ret)
PRINT_G(KERN_INFO, "Error registering ioctl32 translations");
#endif
PRINT_G(KERN_INFO, "Installed " VIDEO1394_DRIVER_NAME " module");
return 0;
}
module_init(video1394_init_module);
module_exit(video1394_exit_module);
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