struct tasklet_struct tasklet;
};
-struct at_context {
- struct fw_ohci *ohci;
- dma_addr_t descriptor_bus;
- dma_addr_t buffer_bus;
- struct fw_packet *current_packet;
-
- struct list_head list;
-
- struct {
- struct descriptor more;
- __le32 header[4];
- struct descriptor last;
- } d;
-
- u32 regs;
-
- struct tasklet_struct tasklet;
-};
-
#define it_header_sy(v) ((v) << 0)
#define it_header_tcode(v) ((v) << 4)
#define it_header_channel(v) ((v) << 8)
int node_id;
int generation;
int request_generation;
+ u32 bus_seconds;
/* Spinlock for accessing fw_ohci data. Never call out of
* this driver with this lock held. */
struct ar_context ar_request_ctx;
struct ar_context ar_response_ctx;
- struct at_context at_request_ctx;
- struct at_context at_response_ctx;
+ struct context at_request_ctx;
+ struct context at_response_ctx;
u32 it_context_mask;
struct iso_context *it_context_list;
#define SELF_ID_BUF_SIZE 0x800
#define OHCI_TCODE_PHY_PACKET 0x0e
#define OHCI_VERSION_1_1 0x010010
+#define ISO_BUFFER_SIZE (64 * 1024)
+#define AT_BUFFER_SIZE 4096
static char ohci_driver_name[] = KBUILD_MODNAME;
}
}
-static void
-do_packet_callbacks(struct fw_ohci *ohci, struct list_head *list)
-{
- struct fw_packet *p, *next;
-
- list_for_each_entry_safe(p, next, list, link)
- p->callback(p, &ohci->card, p->ack);
-}
-
-static void
-complete_transmission(struct fw_packet *packet,
- int ack, struct list_head *list)
-{
- list_move_tail(&packet->link, list);
- packet->ack = ack;
-}
+struct driver_data {
+ struct fw_packet *packet;
+};
-/* This function prepares the first packet in the context queue for
- * transmission. Must always be called with the ochi->lock held to
- * ensure proper generation handling and locking around packet queue
- * manipulation. */
-static void
-at_context_setup_packet(struct at_context *ctx, struct list_head *list)
+/* This function apppends a packet to the DMA queue for transmission.
+ * Must always be called with the ochi->lock held to ensure proper
+ * generation handling and locking around packet queue manipulation. */
+static int
+at_context_queue_packet(struct context *ctx, struct fw_packet *packet)
{
- struct fw_packet *packet;
struct fw_ohci *ohci = ctx->ohci;
+ dma_addr_t d_bus, payload_bus;
+ struct driver_data *driver_data;
+ struct descriptor *d, *last;
+ __le32 *header;
int z, tcode;
+ u32 reg;
- packet = fw_packet(ctx->list.next);
-
- memset(&ctx->d, 0, sizeof ctx->d);
- if (packet->payload_length > 0) {
- packet->payload_bus = dma_map_single(ohci->card.device,
- packet->payload,
- packet->payload_length,
- DMA_TO_DEVICE);
- if (dma_mapping_error(packet->payload_bus)) {
- complete_transmission(packet, RCODE_SEND_ERROR, list);
- return;
- }
-
- ctx->d.more.control =
- cpu_to_le16(descriptor_output_more |
- descriptor_key_immediate);
- ctx->d.more.req_count = cpu_to_le16(packet->header_length);
- ctx->d.more.res_count = cpu_to_le16(packet->timestamp);
- ctx->d.last.control =
- cpu_to_le16(descriptor_output_last |
- descriptor_irq_always |
- descriptor_branch_always);
- ctx->d.last.req_count = cpu_to_le16(packet->payload_length);
- ctx->d.last.data_address = cpu_to_le32(packet->payload_bus);
- z = 3;
- } else {
- ctx->d.more.control =
- cpu_to_le16(descriptor_output_last |
- descriptor_key_immediate |
- descriptor_irq_always |
- descriptor_branch_always);
- ctx->d.more.req_count = cpu_to_le16(packet->header_length);
- ctx->d.more.res_count = cpu_to_le16(packet->timestamp);
- z = 2;
+ d = context_get_descriptors(ctx, 4, &d_bus);
+ if (d == NULL) {
+ packet->ack = RCODE_SEND_ERROR;
+ return -1;
}
+ d[0].control = cpu_to_le16(descriptor_key_immediate);
+ d[0].res_count = cpu_to_le16(packet->timestamp);
+
/* The DMA format for asyncronous link packets is different
* from the IEEE1394 layout, so shift the fields around
* accordingly. If header_length is 8, it's a PHY packet, to
* which we need to prepend an extra quadlet. */
+
+ header = (__le32 *) &d[1];
if (packet->header_length > 8) {
- ctx->d.header[0] = cpu_to_le32((packet->header[0] & 0xffff) |
- (packet->speed << 16));
- ctx->d.header[1] = cpu_to_le32((packet->header[1] & 0xffff) |
- (packet->header[0] & 0xffff0000));
- ctx->d.header[2] = cpu_to_le32(packet->header[2]);
+ header[0] = cpu_to_le32((packet->header[0] & 0xffff) |
+ (packet->speed << 16));
+ header[1] = cpu_to_le32((packet->header[1] & 0xffff) |
+ (packet->header[0] & 0xffff0000));
+ header[2] = cpu_to_le32(packet->header[2]);
tcode = (packet->header[0] >> 4) & 0x0f;
if (TCODE_IS_BLOCK_PACKET(tcode))
- ctx->d.header[3] = cpu_to_le32(packet->header[3]);
+ header[3] = cpu_to_le32(packet->header[3]);
else
- ctx->d.header[3] = packet->header[3];
+ header[3] = (__force __le32) packet->header[3];
+
+ d[0].req_count = cpu_to_le16(packet->header_length);
} else {
- ctx->d.header[0] =
- cpu_to_le32((OHCI1394_phy_tcode << 4) |
- (packet->speed << 16));
- ctx->d.header[1] = cpu_to_le32(packet->header[0]);
- ctx->d.header[2] = cpu_to_le32(packet->header[1]);
- ctx->d.more.req_count = cpu_to_le16(12);
+ header[0] = cpu_to_le32((OHCI1394_phy_tcode << 4) |
+ (packet->speed << 16));
+ header[1] = cpu_to_le32(packet->header[0]);
+ header[2] = cpu_to_le32(packet->header[1]);
+ d[0].req_count = cpu_to_le16(12);
}
- /* FIXME: Document how the locking works. */
- if (ohci->generation == packet->generation) {
- reg_write(ctx->ohci, command_ptr(ctx->regs),
- ctx->descriptor_bus | z);
- reg_write(ctx->ohci, control_set(ctx->regs),
- CONTEXT_RUN | CONTEXT_WAKE);
- ctx->current_packet = packet;
+ driver_data = (struct driver_data *) &d[3];
+ driver_data->packet = packet;
+
+ if (packet->payload_length > 0) {
+ payload_bus =
+ dma_map_single(ohci->card.device, packet->payload,
+ packet->payload_length, DMA_TO_DEVICE);
+ if (dma_mapping_error(payload_bus)) {
+ packet->ack = RCODE_SEND_ERROR;
+ return -1;
+ }
+
+ d[2].req_count = cpu_to_le16(packet->payload_length);
+ d[2].data_address = cpu_to_le32(payload_bus);
+ last = &d[2];
+ z = 3;
} else {
- /* We dont return error codes from this function; all
- * transmission errors are reported through the
- * callback. */
- complete_transmission(packet, RCODE_GENERATION, list);
+ last = &d[0];
+ z = 2;
}
-}
-static void at_context_stop(struct at_context *ctx)
-{
- u32 reg;
+ last->control |= cpu_to_le16(descriptor_output_last |
+ descriptor_irq_always |
+ descriptor_branch_always);
- reg_write(ctx->ohci, control_clear(ctx->regs), CONTEXT_RUN);
+ /* FIXME: Document how the locking works. */
+ if (ohci->generation != packet->generation) {
+ packet->ack = RCODE_GENERATION;
+ return -1;
+ }
+
+ context_append(ctx, d, z, 4 - z);
+ /* If the context isn't already running, start it up. */
reg = reg_read(ctx->ohci, control_set(ctx->regs));
- if (reg & CONTEXT_ACTIVE)
- fw_notify("Tried to stop context, but it is still active "
- "(0x%08x).\n", reg);
+ if ((reg & CONTEXT_ACTIVE) == 0)
+ context_run(ctx, 0);
+
+ return 0;
}
-static void at_context_tasklet(unsigned long data)
+static int handle_at_packet(struct context *context,
+ struct descriptor *d,
+ struct descriptor *last)
{
- struct at_context *ctx = (struct at_context *)data;
- struct fw_ohci *ohci = ctx->ohci;
+ struct driver_data *driver_data;
struct fw_packet *packet;
- LIST_HEAD(list);
- unsigned long flags;
+ struct fw_ohci *ohci = context->ohci;
+ dma_addr_t payload_bus;
int evt;
- spin_lock_irqsave(&ohci->lock, flags);
-
- packet = fw_packet(ctx->list.next);
-
- at_context_stop(ctx);
+ if (last->transfer_status == 0)
+ /* This descriptor isn't done yet, stop iteration. */
+ return 0;
- /* If the head of the list isn't the packet that just got
- * transmitted, the packet got cancelled before we finished
- * transmitting it. */
- if (ctx->current_packet != packet)
- goto skip_to_next;
+ driver_data = (struct driver_data *) &d[3];
+ packet = driver_data->packet;
+ if (packet == NULL)
+ /* This packet was cancelled, just continue. */
+ return 1;
- if (packet->payload_length > 0) {
- dma_unmap_single(ohci->card.device, packet->payload_bus,
+ payload_bus = le32_to_cpu(last->data_address);
+ if (payload_bus != 0)
+ dma_unmap_single(ohci->card.device, payload_bus,
packet->payload_length, DMA_TO_DEVICE);
- evt = le16_to_cpu(ctx->d.last.transfer_status) & 0x1f;
- packet->timestamp = le16_to_cpu(ctx->d.last.res_count);
- }
- else {
- evt = le16_to_cpu(ctx->d.more.transfer_status) & 0x1f;
- packet->timestamp = le16_to_cpu(ctx->d.more.res_count);
- }
- if (evt < 16) {
- switch (evt) {
- case OHCI1394_evt_timeout:
- /* Async response transmit timed out. */
- complete_transmission(packet, RCODE_CANCELLED, &list);
- break;
-
- case OHCI1394_evt_flushed:
- /* The packet was flushed should give same
- * error as when we try to use a stale
- * generation count. */
- complete_transmission(packet,
- RCODE_GENERATION, &list);
- break;
+ evt = le16_to_cpu(last->transfer_status) & 0x1f;
+ packet->timestamp = le16_to_cpu(last->res_count);
- case OHCI1394_evt_missing_ack:
- /* Using a valid (current) generation count,
- * but the node is not on the bus or not
- * sending acks. */
- complete_transmission(packet, RCODE_NO_ACK, &list);
- break;
-
- default:
- complete_transmission(packet, RCODE_SEND_ERROR, &list);
- break;
- }
- } else
- complete_transmission(packet, evt - 16, &list);
-
- skip_to_next:
- /* If more packets are queued, set up the next one. */
- if (!list_empty(&ctx->list))
- at_context_setup_packet(ctx, &list);
-
- spin_unlock_irqrestore(&ohci->lock, flags);
+ switch (evt) {
+ case OHCI1394_evt_timeout:
+ /* Async response transmit timed out. */
+ packet->ack = RCODE_CANCELLED;
+ break;
- do_packet_callbacks(ohci, &list);
-}
+ case OHCI1394_evt_flushed:
+ /* The packet was flushed should give same error as
+ * when we try to use a stale generation count. */
+ packet->ack = RCODE_GENERATION;
+ break;
-static int
-at_context_init(struct at_context *ctx, struct fw_ohci *ohci, u32 regs)
-{
- INIT_LIST_HEAD(&ctx->list);
+ case OHCI1394_evt_missing_ack:
+ /* Using a valid (current) generation count, but the
+ * node is not on the bus or not sending acks. */
+ packet->ack = RCODE_NO_ACK;
+ break;
- ctx->descriptor_bus =
- dma_map_single(ohci->card.device, &ctx->d,
- sizeof ctx->d, DMA_TO_DEVICE);
- if (dma_mapping_error(ctx->descriptor_bus))
- return -ENOMEM;
+ case ACK_COMPLETE + 0x10:
+ case ACK_PENDING + 0x10:
+ case ACK_BUSY_X + 0x10:
+ case ACK_BUSY_A + 0x10:
+ case ACK_BUSY_B + 0x10:
+ case ACK_DATA_ERROR + 0x10:
+ case ACK_TYPE_ERROR + 0x10:
+ packet->ack = evt - 0x10;
+ break;
- ctx->regs = regs;
- ctx->ohci = ohci;
+ default:
+ packet->ack = RCODE_SEND_ERROR;
+ break;
+ }
- tasklet_init(&ctx->tasklet, at_context_tasklet, (unsigned long)ctx);
+ packet->callback(packet, &ohci->card, packet->ack);
- return 0;
+ return 1;
}
#define header_get_destination(q) (((q) >> 16) & 0xffff)
}
static void
-handle_local_request(struct at_context *ctx, struct fw_packet *packet)
+handle_local_request(struct context *ctx, struct fw_packet *packet)
{
u64 offset;
u32 csr;
- packet->ack = ACK_PENDING;
- packet->callback(packet, &ctx->ohci->card, packet->ack);
+ if (ctx == &ctx->ohci->at_request_ctx) {
+ packet->ack = ACK_PENDING;
+ packet->callback(packet, &ctx->ohci->card, packet->ack);
+ }
offset =
((unsigned long long)
fw_core_handle_response(&ctx->ohci->card, packet);
break;
}
+
+ if (ctx == &ctx->ohci->at_response_ctx) {
+ packet->ack = ACK_COMPLETE;
+ packet->callback(packet, &ctx->ohci->card, packet->ack);
+ }
}
static void
-at_context_transmit(struct at_context *ctx, struct fw_packet *packet)
+at_context_transmit(struct context *ctx, struct fw_packet *packet)
{
- LIST_HEAD(list);
unsigned long flags;
+ int retval;
spin_lock_irqsave(&ctx->ohci->lock, flags);
return;
}
- list_add_tail(&packet->link, &ctx->list);
- if (ctx->list.next == &packet->link)
- at_context_setup_packet(ctx, &list);
-
+ retval = at_context_queue_packet(ctx, packet);
spin_unlock_irqrestore(&ctx->ohci->lock, flags);
- do_packet_callbacks(ctx->ohci, &list);
+ if (retval < 0)
+ packet->callback(packet, &ctx->ohci->card, packet->ack);
+
}
static void bus_reset_tasklet(unsigned long data)
spin_lock_irqsave(&ohci->lock, flags);
ohci->generation = generation;
- at_context_stop(&ohci->at_request_ctx);
- at_context_stop(&ohci->at_response_ctx);
+ context_stop(&ohci->at_request_ctx);
+ context_stop(&ohci->at_response_ctx);
reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
/* This next bit is unrelated to the AT context stuff but we
static irqreturn_t irq_handler(int irq, void *data)
{
struct fw_ohci *ohci = data;
- u32 event, iso_event;
+ u32 event, iso_event, cycle_time;
int i;
event = reg_read(ohci, OHCI1394_IntEventClear);
iso_event &= ~(1 << i);
}
+ if (event & OHCI1394_cycle64Seconds) {
+ cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
+ if ((cycle_time & 0x80000000) == 0)
+ ohci->bus_seconds++;
+ }
+
return IRQ_HANDLED;
}
static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
{
struct fw_ohci *ohci = fw_ohci(card);
- LIST_HEAD(list);
- unsigned long flags;
+ struct context *ctx = &ohci->at_request_ctx;
+ struct driver_data *driver_data = packet->driver_data;
+ int retval = -ENOENT;
- spin_lock_irqsave(&ohci->lock, flags);
+ tasklet_disable(&ctx->tasklet);
- if (packet->ack == 0) {
- fw_notify("cancelling packet %p (header[0]=%08x)\n",
- packet, packet->header[0]);
+ if (packet->ack != 0)
+ goto out;
- complete_transmission(packet, RCODE_CANCELLED, &list);
- }
+ driver_data->packet = NULL;
+ packet->ack = RCODE_CANCELLED;
+ packet->callback(packet, &ohci->card, packet->ack);
+ retval = 0;
- spin_unlock_irqrestore(&ohci->lock, flags);
-
- do_packet_callbacks(ohci, &list);
+ out:
+ tasklet_enable(&ctx->tasklet);
- /* Return success if we actually cancelled something. */
- return list_empty(&list) ? -ENOENT : 0;
+ return retval;
}
static int
return retval;
}
-static int handle_ir_bufferfill_packet(struct context *context,
- struct descriptor *d,
- struct descriptor *last)
+static u64
+ohci_get_bus_time(struct fw_card *card)
{
- struct iso_context *ctx =
- container_of(context, struct iso_context, context);
+ struct fw_ohci *ohci = fw_ohci(card);
+ u32 cycle_time;
+ u64 bus_time;
- if (d->res_count > 0)
- return 0;
+ cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
+ bus_time = ((u64) ohci->bus_seconds << 32) | cycle_time;
- if (le16_to_cpu(last->control) & descriptor_irq_always)
- ctx->base.callback(&ctx->base,
- le16_to_cpu(last->res_count),
- 0, NULL, ctx->base.callback_data);
-
- return 1;
+ return bus_time;
}
static int handle_ir_dualbuffer_packet(struct context *context,
struct iso_context *ctx =
container_of(context, struct iso_context, context);
struct db_descriptor *db = (struct db_descriptor *) d;
+ __le32 *ir_header;
size_t header_length;
+ void *p, *end;
+ int i;
if (db->first_res_count > 0 && db->second_res_count > 0)
/* This descriptor isn't done yet, stop iteration. */
return 0;
- header_length = db->first_req_count - db->first_res_count;
- if (ctx->header_length + header_length <= PAGE_SIZE)
- memcpy(ctx->header + ctx->header_length, db + 1, header_length);
- ctx->header_length += header_length;
+ header_length = le16_to_cpu(db->first_req_count) -
+ le16_to_cpu(db->first_res_count);
+
+ i = ctx->header_length;
+ p = db + 1;
+ end = p + header_length;
+ while (p < end && i + ctx->base.header_size <= PAGE_SIZE) {
+ memcpy(ctx->header + i, p + 4, ctx->base.header_size);
+ i += ctx->base.header_size;
+ p += ctx->base.header_size + 4;
+ }
+
+ ctx->header_length = i;
if (le16_to_cpu(db->control) & descriptor_irq_always) {
- ctx->base.callback(&ctx->base, 0,
+ ir_header = (__le32 *) (db + 1);
+ ctx->base.callback(&ctx->base,
+ le32_to_cpu(ir_header[0]) & 0xffff,
ctx->header_length, ctx->header,
ctx->base.callback_data);
ctx->header_length = 0;
return 1;
}
-#define ISO_BUFFER_SIZE (64 * 1024)
-
static int handle_it_packet(struct context *context,
struct descriptor *d,
struct descriptor *last)
} else {
mask = &ohci->ir_context_mask;
list = ohci->ir_context_list;
- if (header_size > 0)
- callback = handle_ir_dualbuffer_packet;
- else
- callback = handle_ir_bufferfill_packet;
+ callback = handle_ir_dualbuffer_packet;
}
+ /* FIXME: We need a fallback for pre 1.1 OHCI. */
if (callback == handle_ir_dualbuffer_packet &&
ohci->version < OHCI_VERSION_1_1)
return ERR_PTR(-EINVAL);
{
struct iso_context *ctx = container_of(base, struct iso_context, base);
struct fw_ohci *ohci = ctx->context.ohci;
- u32 cycle_match = 0, mode;
+ u32 cycle_match = 0;
int index;
if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) {
} else {
index = ctx - ohci->ir_context_list;
- if (ctx->base.header_size > 0)
- mode = IR_CONTEXT_DUAL_BUFFER_MODE;
- else
- mode = IR_CONTEXT_BUFFER_FILL;
reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 1 << index);
reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index);
reg_write(ohci, context_match(ctx->context.regs),
(ctx->base.tags << 28) |
(ctx->base.sync << 8) | ctx->base.channel);
- context_run(&ctx->context, mode);
+ context_run(&ctx->context,
+ IR_CONTEXT_DUAL_BUFFER_MODE |
+ IR_CONTEXT_ISOCH_HEADER);
}
return 0;
return 0;
}
-static int
-setup_wait_descriptor(struct context *ctx)
-{
- struct descriptor *d;
- dma_addr_t d_bus;
-
- d = context_get_descriptors(ctx, 1, &d_bus);
- if (d == NULL)
- return -ENOMEM;
-
- d->control = cpu_to_le16(descriptor_input_more |
- descriptor_status |
- descriptor_branch_always |
- descriptor_wait);
-
- context_append(ctx, d, 1, 0);
-
- return 0;
-}
-
static int
ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
struct fw_iso_packet *packet,
struct fw_iso_packet *p;
dma_addr_t d_bus, page_bus;
u32 z, header_z, length, rest;
- int page, offset;
+ int page, offset, packet_count, header_size;
/* FIXME: Cycle lost behavior should be configurable: lose
* packet, retransmit or terminate.. */
- if (packet->skip && setup_wait_descriptor(&ctx->context) < 0)
- return -ENOMEM;
+ if (packet->skip) {
+ d = context_get_descriptors(&ctx->context, 2, &d_bus);
+ if (d == NULL)
+ return -ENOMEM;
+
+ db = (struct db_descriptor *) d;
+ db->control = cpu_to_le16(descriptor_status |
+ descriptor_branch_always |
+ descriptor_wait);
+ db->first_size = cpu_to_le16(ctx->base.header_size + 4);
+ context_append(&ctx->context, d, 2, 0);
+ }
p = packet;
z = 2;
+ /* The OHCI controller puts the status word in the header
+ * buffer too, so we need 4 extra bytes per packet. */
+ packet_count = p->header_length / ctx->base.header_size;
+ header_size = packet_count * (ctx->base.header_size + 4);
+
/* Get header size in number of descriptors. */
- header_z = DIV_ROUND_UP(p->header_length, sizeof *d);
+ header_z = DIV_ROUND_UP(header_size, sizeof *d);
page = payload >> PAGE_SHIFT;
offset = payload & ~PAGE_MASK;
rest = p->payload_length;
/* FIXME: OHCI 1.0 doesn't support dual buffer receive */
- /* FIXME: handle descriptor_wait */
/* FIXME: make packet-per-buffer/dual-buffer a context option */
while (rest > 0) {
d = context_get_descriptors(&ctx->context,
db = (struct db_descriptor *) d;
db->control = cpu_to_le16(descriptor_status |
descriptor_branch_always);
- db->first_size = cpu_to_le16(ctx->base.header_size);
- db->first_req_count = cpu_to_le16(p->header_length);
+ db->first_size = cpu_to_le16(ctx->base.header_size + 4);
+ db->first_req_count = cpu_to_le16(header_size);
db->first_res_count = db->first_req_count;
db->first_buffer = cpu_to_le32(d_bus + sizeof *db);
return 0;
}
-static int
-ohci_queue_iso_receive_bufferfill(struct fw_iso_context *base,
- struct fw_iso_packet *packet,
- struct fw_iso_buffer *buffer,
- unsigned long payload)
-{
- struct iso_context *ctx = container_of(base, struct iso_context, base);
- struct descriptor *d = NULL;
- dma_addr_t d_bus, page_bus;
- u32 length, rest;
- int page, offset;
-
- page = payload >> PAGE_SHIFT;
- offset = payload & ~PAGE_MASK;
- rest = packet->payload_length;
-
- if (packet->skip && setup_wait_descriptor(&ctx->context) < 0)
- return -ENOMEM;
-
- while (rest > 0) {
- d = context_get_descriptors(&ctx->context, 1, &d_bus);
- if (d == NULL)
- return -ENOMEM;
-
- d->control = cpu_to_le16(descriptor_input_more |
- descriptor_status |
- descriptor_branch_always);
-
- if (offset + rest < PAGE_SIZE)
- length = rest;
- else
- length = PAGE_SIZE - offset;
-
- page_bus = page_private(buffer->pages[page]);
- d->data_address = cpu_to_le32(page_bus + offset);
- d->req_count = cpu_to_le16(length);
- d->res_count = cpu_to_le16(length);
-
- if (packet->interrupt && length == rest)
- d->control |= cpu_to_le16(descriptor_irq_always);
-
- context_append(&ctx->context, d, 1, 0);
-
- offset = (offset + length) & ~PAGE_MASK;
- rest -= length;
- page++;
- }
-
- return 0;
-}
-
static int
ohci_queue_iso(struct fw_iso_context *base,
struct fw_iso_packet *packet,
if (base->type == FW_ISO_CONTEXT_TRANSMIT)
return ohci_queue_iso_transmit(base, packet, buffer, payload);
- else if (base->header_size == 0)
- return ohci_queue_iso_receive_bufferfill(base, packet,
- buffer, payload);
else if (ctx->context.ohci->version >= OHCI_VERSION_1_1)
return ohci_queue_iso_receive_dualbuffer(base, packet,
buffer, payload);
.send_response = ohci_send_response,
.cancel_packet = ohci_cancel_packet,
.enable_phys_dma = ohci_enable_phys_dma,
+ .get_bus_time = ohci_get_bus_time,
.allocate_iso_context = ohci_allocate_iso_context,
.free_iso_context = ohci_free_iso_context,
ar_context_init(&ohci->ar_response_ctx, ohci,
OHCI1394_AsRspRcvContextControlSet);
- at_context_init(&ohci->at_request_ctx, ohci,
- OHCI1394_AsReqTrContextControlSet);
+ context_init(&ohci->at_request_ctx, ohci, AT_BUFFER_SIZE,
+ OHCI1394_AsReqTrContextControlSet, handle_at_packet);
- at_context_init(&ohci->at_response_ctx, ohci,
- OHCI1394_AsRspTrContextControlSet);
+ context_init(&ohci->at_response_ctx, ohci, AT_BUFFER_SIZE,
+ OHCI1394_AsRspTrContextControlSet, handle_at_packet);
reg_write(ohci, OHCI1394_ATRetries,
OHCI1394_MAX_AT_REQ_RETRIES |
OHCI1394_RQPkt | OHCI1394_RSPkt |
OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
OHCI1394_isochRx | OHCI1394_isochTx |
- OHCI1394_masterIntEnable);
+ OHCI1394_masterIntEnable |
+ OHCI1394_cycle64Seconds);
bus_options = reg_read(ohci, OHCI1394_BusOptions);
max_receive = (bus_options >> 12) & 0xf;