{
struct ar_context *ctx = (struct ar_context *)data;
struct fw_ohci *ohci = ctx->ohci;
- u32 status;
- int length, speed, ack, timestamp, tcode;
+ struct fw_packet p;
+ u32 status, length, tcode;
/* FIXME: What to do about evt_* errors? */
length = le16_to_cpu(ctx->descriptor.req_count) -
le16_to_cpu(ctx->descriptor.res_count) - 4;
status = le32_to_cpu(ctx->buffer[length / 4]);
- ack = ((status >> 16) & 0x1f) - 16;
- speed = (status >> 21) & 0x7;
- timestamp = status & 0xffff;
- ctx->buffer[0] = le32_to_cpu(ctx->buffer[0]);
- ctx->buffer[1] = le32_to_cpu(ctx->buffer[1]);
- ctx->buffer[2] = le32_to_cpu(ctx->buffer[2]);
+ p.ack = ((status >> 16) & 0x1f) - 16;
+ p.speed = (status >> 21) & 0x7;
+ p.timestamp = status & 0xffff;
+ p.generation = ohci->request_generation;
+
+ p.header[0] = le32_to_cpu(ctx->buffer[0]);
+ p.header[1] = le32_to_cpu(ctx->buffer[1]);
+ p.header[2] = le32_to_cpu(ctx->buffer[2]);
+
+ tcode = (p.header[0] >> 4) & 0x0f;
+ switch (tcode) {
+ case TCODE_WRITE_QUADLET_REQUEST:
+ case TCODE_READ_QUADLET_RESPONSE:
+ p.header[3] = ctx->buffer[3];
+ p.header_length = 16;
+ break;
+
+ case TCODE_WRITE_BLOCK_REQUEST:
+ case TCODE_READ_BLOCK_REQUEST :
+ case TCODE_READ_BLOCK_RESPONSE:
+ case TCODE_LOCK_REQUEST:
+ case TCODE_LOCK_RESPONSE:
+ p.header[3] = le32_to_cpu(ctx->buffer[3]);
+ p.header_length = 16;
+ break;
+
+ case TCODE_WRITE_RESPONSE:
+ case TCODE_READ_QUADLET_REQUEST:
+ p.header_length = 12;
+ break;
+ }
- tcode = (ctx->buffer[0] >> 4) & 0x0f;
- if (TCODE_IS_BLOCK_PACKET(tcode))
- ctx->buffer[3] = le32_to_cpu(ctx->buffer[3]);
+ p.payload = (void *) ctx->buffer + p.header_length;
+ p.payload_length = length - p.header_length;
/* The OHCI bus reset handler synthesizes a phy packet with
* the new generation number when a bus reset happens (see
* we use the unique tlabel for finding the matching
* request. */
- if (ack + 16 == 0x09)
+ if (p.ack + 16 == 0x09)
ohci->request_generation = (ctx->buffer[2] >> 16) & 0xff;
else if (ctx == &ohci->ar_request_ctx)
- fw_core_handle_request(&ohci->card, speed, ack, timestamp,
- ohci->request_generation,
- length, ctx->buffer);
+ fw_core_handle_request(&ohci->card, &p);
else
- fw_core_handle_response(&ohci->card, speed, ack, timestamp,
- length, ctx->buffer);
+ fw_core_handle_response(&ohci->card, &p);
ctx->descriptor.data_address = cpu_to_le32(ctx->buffer_bus);
ctx->descriptor.req_count = cpu_to_le16(sizeof ctx->buffer);
struct fw_packet *p, *next;
list_for_each_entry_safe(p, next, list, link)
- p->callback(p, &ohci->card, p->status);
+ p->callback(p, &ohci->card, p->ack);
}
static void
complete_transmission(struct fw_packet *packet,
- int status, struct list_head *list)
+ int ack, struct list_head *list)
{
list_move_tail(&packet->link, list);
- packet->status = status;
+ packet->ack = ack;
}
/* This function prepares the first packet in the context queue for
static void
fw_fill_response(struct fw_packet *response,
- u32 *request, u32 *data, size_t length)
+ struct fw_packet *request, void *data)
{
int tcode, tlabel, extended_tcode, source, destination;
- tcode = header_get_tcode(request[0]);
- tlabel = header_get_tlabel(request[0]);
- source = header_get_destination(request[0]);
- destination = header_get_source(request[1]);
- extended_tcode = header_get_extended_tcode(request[3]);
+ tcode = header_get_tcode(request->header[0]);
+ tlabel = header_get_tlabel(request->header[0]);
+ source = header_get_destination(request->header[0]);
+ destination = header_get_source(request->header[1]);
+ extended_tcode = header_get_extended_tcode(request->header[3]);
response->header[0] =
header_retry(RETRY_1) |
case TCODE_LOCK_REQUEST:
response->header[0] |= header_tcode(tcode + 2);
response->header[3] =
- header_data_length(length) |
+ header_data_length(request->payload_length) |
header_extended_tcode(extended_tcode);
response->header_length = 16;
response->payload = data;
- response->payload_length = length;
+ response->payload_length = request->payload_length;
break;
default:
}
static struct fw_request *
-allocate_request(u32 *header, int ack,
- int speed, int timestamp, int generation)
+allocate_request(struct fw_packet *p)
{
struct fw_request *request;
u32 *data, length;
- int request_tcode;
+ int request_tcode, t;
- request_tcode = header_get_tcode(header[0]);
+ request_tcode = header_get_tcode(p->header[0]);
switch (request_tcode) {
case TCODE_WRITE_QUADLET_REQUEST:
- data = &header[3];
+ data = &p->header[3];
length = 4;
break;
case TCODE_WRITE_BLOCK_REQUEST:
case TCODE_LOCK_REQUEST:
- data = &header[4];
- length = header_get_data_length(header[3]);
+ data = p->payload;
+ length = header_get_data_length(p->header[3]);
break;
case TCODE_READ_QUADLET_REQUEST:
case TCODE_READ_BLOCK_REQUEST:
data = NULL;
- length = header_get_data_length(header[3]);
+ length = header_get_data_length(p->header[3]);
break;
default:
if (request == NULL)
return NULL;
- request->response.speed = speed;
- request->response.timestamp = timestamp;
- request->response.generation = generation;
+ t = (p->timestamp & 0x1fff) + 4000;
+ if (t >= 8000)
+ t = (p->timestamp & ~0x1fff) + 0x2000 + t - 8000;
+ else
+ t = (p->timestamp & ~0x1fff) + t;
+
+ request->response.speed = p->speed;
+ request->response.timestamp = t;
+ request->response.generation = p->generation;
request->response.callback = free_response_callback;
- request->ack = ack;
- request->length = length;
+ request->ack = p->ack;
+ request->length = p->payload_length;
if (data)
- memcpy(request->data, data, length);
+ memcpy(request->data, p->payload, p->payload_length);
- fw_fill_response(&request->response, header, request->data, length);
+ fw_fill_response(&request->response, p, request->data);
return request;
}
EXPORT_SYMBOL(fw_send_response);
void
-fw_core_handle_request(struct fw_card *card,
- int speed, int ack, int timestamp,
- int generation, u32 length, u32 *header)
+fw_core_handle_request(struct fw_card *card, struct fw_packet *p)
{
struct fw_address_handler *handler;
struct fw_request *request;
unsigned long long offset;
unsigned long flags;
- int tcode, destination, source, t;
+ int tcode, destination, source;
- if (length > 2048) {
+ if (p->payload_length > 2048) {
/* FIXME: send error response. */
return;
}
- if (ack != ACK_PENDING && ack != ACK_COMPLETE)
+ if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE)
return;
- t = (timestamp & 0x1fff) + 4000;
- if (t >= 8000)
- t = (timestamp & ~0x1fff) + 0x2000 + t - 8000;
- else
- t = (timestamp & ~0x1fff) + t;
-
- request = allocate_request(header, ack, speed, t, generation);
+ request = allocate_request(p);
if (request == NULL) {
/* FIXME: send statically allocated busy packet. */
return;
offset =
((unsigned long long)
- header_get_offset_high(header[1]) << 32) | header[2];
- tcode = header_get_tcode(header[0]);
- destination = header_get_destination(header[0]);
- source = header_get_source(header[0]);
+ header_get_offset_high(p->header[1]) << 32) | p->header[2];
+ tcode = header_get_tcode(p->header[0]);
+ destination = header_get_destination(p->header[0]);
+ source = header_get_source(p->header[0]);
spin_lock_irqsave(&address_handler_lock, flags);
handler = lookup_enclosing_address_handler(&address_handler_list,
else
handler->address_callback(card, request,
tcode, destination, source,
- generation, speed, offset,
+ p->generation, p->speed, offset,
request->data, request->length,
handler->callback_data);
}
EXPORT_SYMBOL(fw_core_handle_request);
void
-fw_core_handle_response(struct fw_card *card,
- int speed, int ack, int timestamp,
- u32 length, u32 *header)
+fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
{
struct fw_transaction *t;
unsigned long flags;
size_t data_length;
int tcode, tlabel, destination, source, rcode;
- tcode = header_get_tcode(header[0]);
- tlabel = header_get_tlabel(header[0]);
- destination = header_get_destination(header[0]);
- source = header_get_source(header[1]);
- rcode = header_get_rcode(header[1]);
+ tcode = header_get_tcode(p->header[0]);
+ tlabel = header_get_tlabel(p->header[0]);
+ destination = header_get_destination(p->header[0]);
+ source = header_get_source(p->header[1]);
+ rcode = header_get_rcode(p->header[1]);
spin_lock_irqsave(&card->lock, flags);
list_for_each_entry(t, &card->transaction_list, link) {
switch (tcode) {
case TCODE_READ_QUADLET_RESPONSE:
- data = (u32 *) &header[3];
+ data = (u32 *) &p->header[3];
data_length = 4;
break;
case TCODE_READ_BLOCK_RESPONSE:
case TCODE_LOCK_RESPONSE:
- data = &header[4];
- data_length = header_get_data_length(header[3]);
+ data = &p->header[4];
+ data_length = header_get_data_length(p->header[3]);
break;
default: