Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 206846
b: refs/heads/master
c: 850bb6f
h: refs/heads/master
v: v3
  • Loading branch information
Stefan Richter committed Jul 23, 2010
1 parent ee42056 commit a646dcf
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b9dc61cf404165fb77e80c853e9fec9af258f9ce
refs/heads/master: 850bb6f23b93c04ce1e4509a87fa607dc17d97c1
64 changes: 64 additions & 0 deletions trunk/drivers/firewire/core-cdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,13 @@ struct iso_resource_event {
struct fw_cdev_event_iso_resource iso_resource;
};

struct outbound_phy_packet_event {
struct event event;
struct client *client;
struct fw_packet p;
struct fw_cdev_event_phy_packet phy_packet;
};

static inline void __user *u64_to_uptr(__u64 value)
{
return (void __user *)(unsigned long)value;
Expand Down Expand Up @@ -396,6 +403,7 @@ union ioctl_arg {
struct fw_cdev_allocate_iso_resource allocate_iso_resource;
struct fw_cdev_send_stream_packet send_stream_packet;
struct fw_cdev_get_cycle_timer2 get_cycle_timer2;
struct fw_cdev_send_phy_packet send_phy_packet;
};

static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
Expand Down Expand Up @@ -1384,6 +1392,61 @@ static int ioctl_send_stream_packet(struct client *client, union ioctl_arg *arg)
return init_request(client, &request, dest, a->speed);
}

static void outbound_phy_packet_callback(struct fw_packet *packet,
struct fw_card *card, int status)
{
struct outbound_phy_packet_event *e =
container_of(packet, struct outbound_phy_packet_event, p);

switch (status) {
/* expected: */
case ACK_COMPLETE: e->phy_packet.rcode = RCODE_COMPLETE; break;
/* should never happen with PHY packets: */
case ACK_PENDING: e->phy_packet.rcode = RCODE_COMPLETE; break;
case ACK_BUSY_X:
case ACK_BUSY_A:
case ACK_BUSY_B: e->phy_packet.rcode = RCODE_BUSY; break;
case ACK_DATA_ERROR: e->phy_packet.rcode = RCODE_DATA_ERROR; break;
case ACK_TYPE_ERROR: e->phy_packet.rcode = RCODE_TYPE_ERROR; break;
/* stale generation; cancelled; on certain controllers: no ack */
default: e->phy_packet.rcode = status; break;
}

queue_event(e->client, &e->event,
&e->phy_packet, sizeof(e->phy_packet), NULL, 0);
client_put(e->client);
}

static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg)
{
struct fw_cdev_send_phy_packet *a = &arg->send_phy_packet;
struct fw_card *card = client->device->card;
struct outbound_phy_packet_event *e;

/* Access policy: Allow this ioctl only on local nodes' device files. */
if (!client->device->is_local)
return -ENOSYS;

e = kzalloc(sizeof(*e), GFP_KERNEL);
if (e == NULL)
return -ENOMEM;

client_get(client);
e->client = client;
e->p.speed = SCODE_100;
e->p.generation = a->generation;
e->p.header[0] = a->data[0];
e->p.header[1] = a->data[1];
e->p.header_length = 8;
e->p.callback = outbound_phy_packet_callback;
e->phy_packet.closure = a->closure;
e->phy_packet.type = FW_CDEV_EVENT_PHY_PACKET_SENT;

card->driver->send_request(card, &e->p);

return 0;
}

static int (* const ioctl_handlers[])(struct client *, union ioctl_arg *) = {
[0x00] = ioctl_get_info,
[0x01] = ioctl_send_request,
Expand All @@ -1406,6 +1469,7 @@ static int (* const ioctl_handlers[])(struct client *, union ioctl_arg *) = {
[0x12] = ioctl_send_broadcast_request,
[0x13] = ioctl_send_stream_packet,
[0x14] = ioctl_get_cycle_timer2,
[0x15] = ioctl_send_phy_packet,
};

static int dispatch_ioctl(struct client *client,
Expand Down
44 changes: 43 additions & 1 deletion trunk/include/linux/firewire-cdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

/* available since kernel version 2.6.36 */
#define FW_CDEV_EVENT_REQUEST2 0x06
#define FW_CDEV_EVENT_PHY_PACKET_SENT 0x07

/**
* struct fw_cdev_event_common - Common part of all fw_cdev_event_ types
Expand Down Expand Up @@ -283,6 +284,19 @@ struct fw_cdev_event_iso_resource {
__s32 bandwidth;
};

/**
* struct fw_cdev_event_phy_packet - A PHY packet was transmitted
* @closure: See &fw_cdev_event_common;
* set by %FW_CDEV_IOC_SEND_PHY_PACKET ioctl
* @type: %FW_CDEV_EVENT_PHY_PACKET_SENT
* @rcode: %RCODE_..., indicates success or failure of transmission
*/
struct fw_cdev_event_phy_packet {
__u64 closure;
__u32 type;
__u32 rcode;
};

/**
* union fw_cdev_event - Convenience union of fw_cdev_event_ types
* @common: Valid for all types
Expand All @@ -294,6 +308,7 @@ struct fw_cdev_event_iso_resource {
* @iso_resource: Valid if @common.type ==
* %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or
* %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED
* @phy_packet: Valid if @common.type == %FW_CDEV_EVENT_PHY_PACKET_SENT
*
* Convenience union for userspace use. Events could be read(2) into an
* appropriately aligned char buffer and then cast to this union for further
Expand All @@ -311,6 +326,7 @@ union fw_cdev_event {
struct fw_cdev_event_request2 request2; /* added in 2.6.36 */
struct fw_cdev_event_iso_interrupt iso_interrupt;
struct fw_cdev_event_iso_resource iso_resource; /* added in 2.6.30 */
struct fw_cdev_event_phy_packet phy_packet; /* added in 2.6.36 */
};

/* available since kernel version 2.6.22 */
Expand Down Expand Up @@ -342,6 +358,9 @@ union fw_cdev_event {
/* available since kernel version 2.6.34 */
#define FW_CDEV_IOC_GET_CYCLE_TIMER2 _IOWR('#', 0x14, struct fw_cdev_get_cycle_timer2)

/* available since kernel version 2.6.36 */
#define FW_CDEV_IOC_SEND_PHY_PACKET _IOWR('#', 0x15, struct fw_cdev_send_phy_packet)

/*
* ABI version history
* 1 (2.6.22) - initial version
Expand All @@ -357,8 +376,9 @@ union fw_cdev_event {
* - shared use and auto-response for FCP registers
* 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable
* - added %FW_CDEV_IOC_GET_CYCLE_TIMER2
* 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2
* 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2, %FW_CDEV_EVENT_PHY_PACKET_SENT
* - implemented &fw_cdev_event_bus_reset.bm_node_id
* - added %FW_CDEV_IOC_SEND_PHY_PACKET
*/
#define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */

Expand Down Expand Up @@ -808,4 +828,26 @@ struct fw_cdev_send_stream_packet {
__u32 speed;
};

/**
* struct fw_cdev_send_phy_packet - send a PHY packet
* @closure: Passed back to userspace in the PHY-packet-sent event
* @data: First and second quadlet of the PHY packet
* @generation: The bus generation where packet is valid
*
* The %FW_CDEV_IOC_SEND_PHY_PACKET ioctl sends a PHY packet to all nodes
* on the same card as this device. After transmission, an
* %FW_CDEV_EVENT_PHY_PACKET_SENT event is generated.
*
* The payload @data[] shall be specified in host byte order. Usually,
* @data[1] needs to be the bitwise inverse of @data[0]. VersaPHY packets
* are an exception to this rule.
*
* The ioctl is only permitted on device files which represent a local node.
*/
struct fw_cdev_send_phy_packet {
__u64 closure;
__u32 data[2];
__u32 generation;
};

#endif /* _LINUX_FIREWIRE_CDEV_H */

0 comments on commit a646dcf

Please sign in to comment.