📄 ieee1394_transactions.c
字号:
return NULL;
packet = hpsb_alloc_packet(length);
if (!packet)
return NULL;
if (length % 4) { /* zero padding bytes */
packet->data[length >> 2] = 0;
}
packet->host = host;
packet->node_id = node;
if (hpsb_get_tlabel(packet)) {
hpsb_free_packet(packet);
return NULL;
}
if (length == 4) {
fill_async_writequad(packet, addr, buffer ? *buffer : 0);
} else {
fill_async_writeblock(packet, addr, length);
if (buffer)
memcpy(packet->data, buffer, length);
}
return packet;
}
struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 * buffer,
int length, int channel, int tag,
int sync)
{
struct hpsb_packet *packet;
if (length == 0)
return NULL;
packet = hpsb_alloc_packet(length);
if (!packet)
return NULL;
if (length % 4) { /* zero padding bytes */
packet->data[length >> 2] = 0;
}
packet->host = host;
/* Because it is too difficult to determine all PHY speeds and link
* speeds here, we use S100... */
packet->speed_code = IEEE1394_SPEED_100;
/* ...and prevent hpsb_send_packet() from overriding it. */
packet->node_id = LOCAL_BUS | ALL_NODES;
if (hpsb_get_tlabel(packet)) {
hpsb_free_packet(packet);
return NULL;
}
fill_async_stream_packet(packet, length, channel, tag, sync);
if (buffer)
memcpy(packet->data, buffer, length);
return packet;
}
struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
u64 addr, int extcode,
quadlet_t * data, quadlet_t arg)
{
struct hpsb_packet *p;
u32 length;
p = hpsb_alloc_packet(8);
if (!p)
return NULL;
p->host = host;
p->node_id = node;
if (hpsb_get_tlabel(p)) {
hpsb_free_packet(p);
return NULL;
}
switch (extcode) {
case EXTCODE_FETCH_ADD:
case EXTCODE_LITTLE_ADD:
length = 4;
if (data)
p->data[0] = *data;
break;
default:
length = 8;
if (data) {
p->data[0] = arg;
p->data[1] = *data;
}
break;
}
fill_async_lock(p, addr, extcode, length);
return p;
}
struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host,
nodeid_t node, u64 addr, int extcode,
octlet_t * data, octlet_t arg)
{
struct hpsb_packet *p;
u32 length;
p = hpsb_alloc_packet(16);
if (!p)
return NULL;
p->host = host;
p->node_id = node;
if (hpsb_get_tlabel(p)) {
hpsb_free_packet(p);
return NULL;
}
switch (extcode) {
case EXTCODE_FETCH_ADD:
case EXTCODE_LITTLE_ADD:
length = 8;
if (data) {
p->data[0] = *data >> 32;
p->data[1] = *data & 0xffffffff;
}
break;
default:
length = 16;
if (data) {
p->data[0] = arg >> 32;
p->data[1] = arg & 0xffffffff;
p->data[2] = *data >> 32;
p->data[3] = *data & 0xffffffff;
}
break;
}
fill_async_lock(p, addr, extcode, length);
return p;
}
struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data)
{
struct hpsb_packet *p;
p = hpsb_alloc_packet(0);
if (!p)
return NULL;
p->host = host;
fill_phy_packet(p, data);
return p;
}
/*
* FIXME - these functions should probably read from / write to user space to
* avoid in kernel buffers for user space callers
*/
/**
* hpsb_read - generic read function
*
* Recognizes the local node ID and act accordingly. Automatically uses a
* quadlet read request if @length == 4 and and a block read request otherwise.
* It does not yet support lengths that are not a multiple of 4.
*
* You must explicitly specifiy the @generation for which the node ID is valid,
* to avoid sending packets to the wrong nodes when we race with a bus reset.
*/
int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, quadlet_t * buffer, size_t length)
{
struct hpsb_packet *packet;
int retval = 0;
if (length == 0)
return -EINVAL;
BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
packet = hpsb_make_readpacket(host, node, addr, length);
if (!packet) {
return -ENOMEM;
}
packet->generation = generation;
retval = hpsb_send_packet_and_wait(packet);
if (retval < 0)
goto hpsb_read_fail;
retval = hpsb_packet_success(packet);
if (retval == 0) {
if (length == 4) {
*buffer = packet->header[3];
} else {
memcpy(buffer, packet->data, length);
}
}
hpsb_read_fail:
hpsb_free_tlabel(packet);
hpsb_free_packet(packet);
return retval;
}
/**
* hpsb_write - generic write function
*
* Recognizes the local node ID and act accordingly. Automatically uses a
* quadlet write request if @length == 4 and and a block write request
* otherwise. It does not yet support lengths that are not a multiple of 4.
*
* You must explicitly specifiy the @generation for which the node ID is valid,
* to avoid sending packets to the wrong nodes when we race with a bus reset.
*/
int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, quadlet_t * buffer, size_t length)
{
struct hpsb_packet *packet;
int retval;
if (length == 0)
return -EINVAL;
BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
packet = hpsb_make_writepacket(host, node, addr, buffer, length);
if (!packet)
return -ENOMEM;
packet->generation = generation;
retval = hpsb_send_packet_and_wait(packet);
if (retval < 0)
goto hpsb_write_fail;
retval = hpsb_packet_success(packet);
hpsb_write_fail:
hpsb_free_tlabel(packet);
hpsb_free_packet(packet);
return retval;
}
#if 0
int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, int extcode, quadlet_t * data, quadlet_t arg)
{
struct hpsb_packet *packet;
int retval = 0;
BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg);
if (!packet)
return -ENOMEM;
packet->generation = generation;
retval = hpsb_send_packet_and_wait(packet);
if (retval < 0)
goto hpsb_lock_fail;
retval = hpsb_packet_success(packet);
if (retval == 0) {
*data = packet->data[0];
}
hpsb_lock_fail:
hpsb_free_tlabel(packet);
hpsb_free_packet(packet);
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)
{
struct hpsb_packet *packet;
int retval = 0;
u16 specifier_id_hi = (specifier_id & 0x00ffff00) >> 8;
u8 specifier_id_lo = specifier_id & 0xff;
HPSB_VERBOSE("Send GASP: channel = %d, length = %Zd", channel, length);
length += 8;
packet = hpsb_make_streampacket(host, NULL, length, channel, 3, 0);
if (!packet)
return -ENOMEM;
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 - 8);
packet->generation = generation;
packet->no_waiter = 1;
retval = hpsb_send_packet(packet);
if (retval < 0)
hpsb_free_packet(packet);
return retval;
}
#endif /* 0 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -