···6667source "drivers/ieee1394/Kconfig"6869+config FIREWIRE_NOSY70+ tristate "Nosy - a FireWire traffic sniffer for PCILynx cards"71+ depends on PCI72+ help73+ Nosy is an IEEE 1394 packet sniffer that is used for protocol74+ analysis and in development of IEEE 1394 drivers, applications,75+ or firmwares.76+77+ This driver lets you use a Texas Instruments PCILynx 1394 to PCI78+ link layer controller TSB12LV21/A/B as a low-budget bus analyzer.79+ PCILynx is a nowadays very rare IEEE 1394 controller which is80+ not OHCI 1394 compliant.81+82+ The following cards are known to be based on PCILynx or PCILynx-2:83+ IOI IOI-1394TT (PCI card), Unibrain Fireboard 400 PCI Lynx-284+ (PCI card), Newer Technology FireWire 2 Go (CardBus card),85+ Apple Power Mac G3 blue & white (onboard controller).86+87+ To compile this driver as a module, say M here: The module will be88+ called nosy. Source code of a userspace interface to nosy, called89+ nosy-dump, can be found in tools/firewire/ of the kernel sources.90+91+ If unsure, say N.92+93endmenu
···204}205EXPORT_SYMBOL(fw_core_remove_descriptor);206000000000000000000000000000000000000000207static void allocate_broadcast_channel(struct fw_card *card, int generation)208{209 int channel, bandwidth = 0;210211- fw_iso_resource_manage(card, generation, 1ULL << 31, &channel,212- &bandwidth, true, card->bm_transaction_data);213- if (channel == 31) {00000214 card->broadcast_channel_allocated = true;215- device_for_each_child(card->device, (void *)(long)generation,216- fw_device_set_broadcast_channel);217 }000218}219220static const char gap_count_table[] = {···269void fw_schedule_bm_work(struct fw_card *card, unsigned long delay)270{271 fw_card_get(card);272- if (!schedule_delayed_work(&card->work, delay))273 fw_card_put(card);274}275276-static void fw_card_bm_work(struct work_struct *work)277{278- struct fw_card *card = container_of(work, struct fw_card, work.work);279 struct fw_device *root_device, *irm_device;280 struct fw_node *root_node;281- unsigned long flags;282- int root_id, new_root_id, irm_id, local_id;283 int gap_count, generation, grace, rcode;284 bool do_reset = false;285 bool root_device_is_running;286 bool root_device_is_cmc;287 bool irm_is_1394_1995_only;288289- spin_lock_irqsave(&card->lock, flags);290291 if (card->local_node == NULL) {292- spin_unlock_irqrestore(&card->lock, flags);293 goto out_put_card;294 }295···311312 grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 8));313314- if (is_next_generation(generation, card->bm_generation) ||0315 (card->bm_generation != generation && grace)) {316 /*317 * This first step is to figure out who is IRM and···343 card->bm_transaction_data[0] = cpu_to_be32(0x3f);344 card->bm_transaction_data[1] = cpu_to_be32(local_id);345346- spin_unlock_irqrestore(&card->lock, flags);347348 rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,349 irm_id, generation, SCODE_100,350 CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,351- card->bm_transaction_data,352- sizeof(card->bm_transaction_data));353354 if (rcode == RCODE_GENERATION)355 /* Another bus reset, BM work has been rescheduled. */356 goto out;357358- if (rcode == RCODE_COMPLETE &&359- card->bm_transaction_data[0] != cpu_to_be32(0x3f)) {3600000000361 /* Somebody else is BM. Only act as IRM. */362 if (local_id == irm_id)363 allocate_broadcast_channel(card, generation);···370 goto out;371 }372373- spin_lock_irqsave(&card->lock, flags);0000000000374375 if (rcode != RCODE_COMPLETE) {376 /*···399 * We weren't BM in the last generation, and the last400 * bus reset is less than 125ms ago. Reschedule this job.401 */402- spin_unlock_irqrestore(&card->lock, flags);403 fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 8));404 goto out;405 }···422 * If we haven't probed this device yet, bail out now423 * and let's try again once that's done.424 */425- spin_unlock_irqrestore(&card->lock, flags);426 goto out;427 } else if (root_device_is_cmc) {428 /*429- * FIXME: I suppose we should set the cmstr bit in the430- * STATE_CLEAR register of this node, as described in431- * 1394-1995, 8.4.2.6. Also, send out a force root432- * packet for this node.433 */434 new_root_id = root_id;435 } else {···460 (card->gap_count != gap_count || new_root_id != root_id))461 do_reset = true;462463- spin_unlock_irqrestore(&card->lock, flags);464465 if (do_reset) {466 fw_notify("phy config: card %d, new root=%x, gap_count=%d\n",467 card->index, new_root_id, gap_count);468 fw_send_phy_config(card, new_root_id, generation, gap_count);469- fw_core_initiate_bus_reset(card, 1);470 /* Will allocate broadcast channel after the reset. */471- } else {472- if (local_id == irm_id)473- allocate_broadcast_channel(card, generation);474 }0000000000000000475476 out:477 fw_node_put(root_node);···504 card->device = device;505 card->current_tlabel = 0;506 card->tlabel_mask = 0;0000507 card->color = 0;508 card->broadcast_channel = BROADCAST_CHANNEL_INITIAL;509510 kref_init(&card->kref);511 init_completion(&card->done);512 INIT_LIST_HEAD(&card->transaction_list);0513 spin_lock_init(&card->lock);514515 card->local_node = NULL;516517- INIT_DELAYED_WORK(&card->work, fw_card_bm_work);0518}519EXPORT_SYMBOL(fw_card_initialize);520···546}547EXPORT_SYMBOL(fw_card_add);548549-550/*551 * The next few functions implement a dummy driver that is used once a card552 * driver shuts down an fw_card. This allows the driver to cleanly unload,553 * as all IO to the card will be handled (and failed) by the dummy driver554 * instead of calling into the module. Only functions for iso context555 * shutdown still need to be provided by the card driver.00000556 */557558-static int dummy_enable(struct fw_card *card,559- const __be32 *config_rom, size_t length)560{561- BUG();562- return -1;563}564565static int dummy_update_phy_reg(struct fw_card *card, int address,···570 return -ENODEV;571}572573-static int dummy_set_config_rom(struct fw_card *card,574- const __be32 *config_rom, size_t length)575-{576- /*577- * We take the card out of card_list before setting the dummy578- * driver, so this should never get called.579- */580- BUG();581- return -1;582-}583-584static void dummy_send_request(struct fw_card *card, struct fw_packet *packet)585{586- packet->callback(packet, card, -ENODEV);587}588589static void dummy_send_response(struct fw_card *card, struct fw_packet *packet)590{591- packet->callback(packet, card, -ENODEV);592}593594static int dummy_cancel_packet(struct fw_card *card, struct fw_packet *packet)···591 return -ENODEV;592}59300000000000000000000000594static const struct fw_card_driver dummy_driver_template = {595- .enable = dummy_enable,596- .update_phy_reg = dummy_update_phy_reg,597- .set_config_rom = dummy_set_config_rom,598- .send_request = dummy_send_request,599- .cancel_packet = dummy_cancel_packet,600- .send_response = dummy_send_response,601- .enable_phys_dma = dummy_enable_phys_dma,000602};603604void fw_card_release(struct kref *kref)···640641 card->driver->update_phy_reg(card, 4,642 PHY_LINK_ACTIVE | PHY_CONTENDER, 0);643- fw_core_initiate_bus_reset(card, 1);644645 mutex_lock(&card_mutex);646 list_del_init(&card->link);···660 WARN_ON(!list_empty(&card->transaction_list));661}662EXPORT_SYMBOL(fw_core_remove_card);663-664-int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset)665-{666- int reg = short_reset ? 5 : 1;667- int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET;668-669- return card->driver->update_phy_reg(card, reg, 0, bit);670-}671-EXPORT_SYMBOL(fw_core_initiate_bus_reset);
···204}205EXPORT_SYMBOL(fw_core_remove_descriptor);206207+static int reset_bus(struct fw_card *card, bool short_reset)208+{209+ int reg = short_reset ? 5 : 1;210+ int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET;211+212+ return card->driver->update_phy_reg(card, reg, 0, bit);213+}214+215+void fw_schedule_bus_reset(struct fw_card *card, bool delayed, bool short_reset)216+{217+ /* We don't try hard to sort out requests of long vs. short resets. */218+ card->br_short = short_reset;219+220+ /* Use an arbitrary short delay to combine multiple reset requests. */221+ fw_card_get(card);222+ if (!schedule_delayed_work(&card->br_work,223+ delayed ? DIV_ROUND_UP(HZ, 100) : 0))224+ fw_card_put(card);225+}226+EXPORT_SYMBOL(fw_schedule_bus_reset);227+228+static void br_work(struct work_struct *work)229+{230+ struct fw_card *card = container_of(work, struct fw_card, br_work.work);231+232+ /* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */233+ if (card->reset_jiffies != 0 &&234+ time_is_after_jiffies(card->reset_jiffies + 2 * HZ)) {235+ if (!schedule_delayed_work(&card->br_work, 2 * HZ))236+ fw_card_put(card);237+ return;238+ }239+240+ fw_send_phy_config(card, FW_PHY_CONFIG_NO_NODE_ID, card->generation,241+ FW_PHY_CONFIG_CURRENT_GAP_COUNT);242+ reset_bus(card, card->br_short);243+ fw_card_put(card);244+}245+246static void allocate_broadcast_channel(struct fw_card *card, int generation)247{248 int channel, bandwidth = 0;249250+ if (!card->broadcast_channel_allocated) {251+ fw_iso_resource_manage(card, generation, 1ULL << 31,252+ &channel, &bandwidth, true,253+ card->bm_transaction_data);254+ if (channel != 31) {255+ fw_notify("failed to allocate broadcast channel\n");256+ return;257+ }258 card->broadcast_channel_allocated = true;00259 }260+261+ device_for_each_child(card->device, (void *)(long)generation,262+ fw_device_set_broadcast_channel);263}264265static const char gap_count_table[] = {···224void fw_schedule_bm_work(struct fw_card *card, unsigned long delay)225{226 fw_card_get(card);227+ if (!schedule_delayed_work(&card->bm_work, delay))228 fw_card_put(card);229}230231+static void bm_work(struct work_struct *work)232{233+ struct fw_card *card = container_of(work, struct fw_card, bm_work.work);234 struct fw_device *root_device, *irm_device;235 struct fw_node *root_node;236+ int root_id, new_root_id, irm_id, bm_id, local_id;0237 int gap_count, generation, grace, rcode;238 bool do_reset = false;239 bool root_device_is_running;240 bool root_device_is_cmc;241 bool irm_is_1394_1995_only;242243+ spin_lock_irq(&card->lock);244245 if (card->local_node == NULL) {246+ spin_unlock_irq(&card->lock);247 goto out_put_card;248 }249···267268 grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 8));269270+ if ((is_next_generation(generation, card->bm_generation) &&271+ !card->bm_abdicate) ||272 (card->bm_generation != generation && grace)) {273 /*274 * This first step is to figure out who is IRM and···298 card->bm_transaction_data[0] = cpu_to_be32(0x3f);299 card->bm_transaction_data[1] = cpu_to_be32(local_id);300301+ spin_unlock_irq(&card->lock);302303 rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,304 irm_id, generation, SCODE_100,305 CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,306+ card->bm_transaction_data, 8);0307308 if (rcode == RCODE_GENERATION)309 /* Another bus reset, BM work has been rescheduled. */310 goto out;311312+ bm_id = be32_to_cpu(card->bm_transaction_data[0]);0313314+ spin_lock_irq(&card->lock);315+ if (rcode == RCODE_COMPLETE && generation == card->generation)316+ card->bm_node_id =317+ bm_id == 0x3f ? local_id : 0xffc0 | bm_id;318+ spin_unlock_irq(&card->lock);319+320+ if (rcode == RCODE_COMPLETE && bm_id != 0x3f) {321 /* Somebody else is BM. Only act as IRM. */322 if (local_id == irm_id)323 allocate_broadcast_channel(card, generation);···320 goto out;321 }322323+ if (rcode == RCODE_SEND_ERROR) {324+ /*325+ * We have been unable to send the lock request due to326+ * some local problem. Let's try again later and hope327+ * that the problem has gone away by then.328+ */329+ fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 8));330+ goto out;331+ }332+333+ spin_lock_irq(&card->lock);334335 if (rcode != RCODE_COMPLETE) {336 /*···339 * We weren't BM in the last generation, and the last340 * bus reset is less than 125ms ago. Reschedule this job.341 */342+ spin_unlock_irq(&card->lock);343 fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 8));344 goto out;345 }···362 * If we haven't probed this device yet, bail out now363 * and let's try again once that's done.364 */365+ spin_unlock_irq(&card->lock);366 goto out;367 } else if (root_device_is_cmc) {368 /*369+ * We will send out a force root packet for this370+ * node as part of the gap count optimization.00371 */372 new_root_id = root_id;373 } else {···402 (card->gap_count != gap_count || new_root_id != root_id))403 do_reset = true;404405+ spin_unlock_irq(&card->lock);406407 if (do_reset) {408 fw_notify("phy config: card %d, new root=%x, gap_count=%d\n",409 card->index, new_root_id, gap_count);410 fw_send_phy_config(card, new_root_id, generation, gap_count);411+ reset_bus(card, true);412 /* Will allocate broadcast channel after the reset. */413+ goto out;00414 }415+416+ if (root_device_is_cmc) {417+ /*418+ * Make sure that the cycle master sends cycle start packets.419+ */420+ card->bm_transaction_data[0] = cpu_to_be32(CSR_STATE_BIT_CMSTR);421+ rcode = fw_run_transaction(card, TCODE_WRITE_QUADLET_REQUEST,422+ root_id, generation, SCODE_100,423+ CSR_REGISTER_BASE + CSR_STATE_SET,424+ card->bm_transaction_data, 4);425+ if (rcode == RCODE_GENERATION)426+ goto out;427+ }428+429+ if (local_id == irm_id)430+ allocate_broadcast_channel(card, generation);431432 out:433 fw_node_put(root_node);···432 card->device = device;433 card->current_tlabel = 0;434 card->tlabel_mask = 0;435+ card->split_timeout_hi = 0;436+ card->split_timeout_lo = 800 << 19;437+ card->split_timeout_cycles = 800;438+ card->split_timeout_jiffies = DIV_ROUND_UP(HZ, 10);439 card->color = 0;440 card->broadcast_channel = BROADCAST_CHANNEL_INITIAL;441442 kref_init(&card->kref);443 init_completion(&card->done);444 INIT_LIST_HEAD(&card->transaction_list);445+ INIT_LIST_HEAD(&card->phy_receiver_list);446 spin_lock_init(&card->lock);447448 card->local_node = NULL;449450+ INIT_DELAYED_WORK(&card->br_work, br_work);451+ INIT_DELAYED_WORK(&card->bm_work, bm_work);452}453EXPORT_SYMBOL(fw_card_initialize);454···468}469EXPORT_SYMBOL(fw_card_add);4700471/*472 * The next few functions implement a dummy driver that is used once a card473 * driver shuts down an fw_card. This allows the driver to cleanly unload,474 * as all IO to the card will be handled (and failed) by the dummy driver475 * instead of calling into the module. Only functions for iso context476 * shutdown still need to be provided by the card driver.477+ *478+ * .read/write_csr() should never be called anymore after the dummy driver479+ * was bound since they are only used within request handler context.480+ * .set_config_rom() is never called since the card is taken out of card_list481+ * before switching to the dummy driver.482 */483484+static int dummy_read_phy_reg(struct fw_card *card, int address)0485{486+ return -ENODEV;0487}488489static int dummy_update_phy_reg(struct fw_card *card, int address,···490 return -ENODEV;491}49200000000000493static void dummy_send_request(struct fw_card *card, struct fw_packet *packet)494{495+ packet->callback(packet, card, RCODE_CANCELLED);496}497498static void dummy_send_response(struct fw_card *card, struct fw_packet *packet)499{500+ packet->callback(packet, card, RCODE_CANCELLED);501}502503static int dummy_cancel_packet(struct fw_card *card, struct fw_packet *packet)···522 return -ENODEV;523}524525+static struct fw_iso_context *dummy_allocate_iso_context(struct fw_card *card,526+ int type, int channel, size_t header_size)527+{528+ return ERR_PTR(-ENODEV);529+}530+531+static int dummy_start_iso(struct fw_iso_context *ctx,532+ s32 cycle, u32 sync, u32 tags)533+{534+ return -ENODEV;535+}536+537+static int dummy_set_iso_channels(struct fw_iso_context *ctx, u64 *channels)538+{539+ return -ENODEV;540+}541+542+static int dummy_queue_iso(struct fw_iso_context *ctx, struct fw_iso_packet *p,543+ struct fw_iso_buffer *buffer, unsigned long payload)544+{545+ return -ENODEV;546+}547+548static const struct fw_card_driver dummy_driver_template = {549+ .read_phy_reg = dummy_read_phy_reg,550+ .update_phy_reg = dummy_update_phy_reg,551+ .send_request = dummy_send_request,552+ .send_response = dummy_send_response,553+ .cancel_packet = dummy_cancel_packet,554+ .enable_phys_dma = dummy_enable_phys_dma,555+ .allocate_iso_context = dummy_allocate_iso_context,556+ .start_iso = dummy_start_iso,557+ .set_iso_channels = dummy_set_iso_channels,558+ .queue_iso = dummy_queue_iso,559};560561void fw_card_release(struct kref *kref)···545546 card->driver->update_phy_reg(card, 4,547 PHY_LINK_ACTIVE | PHY_CONTENDER, 0);548+ fw_schedule_bus_reset(card, false, true);549550 mutex_lock(&card_mutex);551 list_del_init(&card->link);···565 WARN_ON(!list_empty(&card->transaction_list));566}567EXPORT_SYMBOL(fw_core_remove_card);000000000
+327-82
drivers/firewire/core-cdev.c
···18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.19 */20021#include <linux/compat.h>22#include <linux/delay.h>23#include <linux/device.h>···34#include <linux/module.h>35#include <linux/mutex.h>36#include <linux/poll.h>37-#include <linux/sched.h>38#include <linux/slab.h>39#include <linux/spinlock.h>40#include <linux/string.h>···47#include <asm/system.h>4849#include "core.h"00000005051struct client {52 u32 version;···70 u64 iso_closure;71 struct fw_iso_buffer buffer;72 unsigned long vm_start;0007374 struct list_head link;75 struct kref kref;···118119struct inbound_transaction_resource {120 struct client_resource resource;0121 struct fw_request *request;122 void *data;123 size_t length;···183184struct inbound_transaction_event {185 struct event event;186- struct fw_cdev_event_request request;000187};188189struct iso_interrupt_event {···194 struct fw_cdev_event_iso_interrupt interrupt;195};19600000197struct iso_resource_event {198 struct event event;199 struct fw_cdev_event_iso_resource iso_resource;000000000000200};201202static inline void __user *u64_to_uptr(__u64 value)···251 idr_init(&client->resource_idr);252 INIT_LIST_HEAD(&client->event_list);253 init_waitqueue_head(&client->wait);0254 kref_init(&client->kref);255256 file->private_data = client;···342 event->generation = client->device->generation;343 event->node_id = client->device->node_id;344 event->local_node_id = card->local_node->node_id;345- event->bm_node_id = 0; /* FIXME: We don't track the BM. */346 event->irm_node_id = card->irm_node->node_id;347 event->root_node_id = card->root_node->node_id;348···373374 e = kzalloc(sizeof(*e), GFP_KERNEL);375 if (e == NULL) {376- fw_notify("Out of memory when allocating bus reset event\n");377 return;378 }379···419 struct fw_cdev_allocate_iso_resource allocate_iso_resource;420 struct fw_cdev_send_stream_packet send_stream_packet;421 struct fw_cdev_get_cycle_timer2 get_cycle_timer2;000422};423424static int ioctl_get_info(struct client *client, union ioctl_arg *arg)···431 unsigned long ret = 0;432433 client->version = a->version;434- a->version = FW_CDEV_VERSION;435 a->card = client->device->card->index;436437 down_read(&fw_device_rwsem);···590 (request->length > 4096 || request->length > 512 << speed))591 return -EIO;5920000593 e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL);594 if (e == NULL)595 return -ENOMEM;···666 if (is_fcp_request(r->request))667 kfree(r->data);668 else669- fw_send_response(client->device->card, r->request,670- RCODE_CONFLICT_ERROR);0671 kfree(r);672}673674static void handle_request(struct fw_card *card, struct fw_request *request,675 int tcode, int destination, int source,676- int generation, int speed,677- unsigned long long offset,678 void *payload, size_t length, void *callback_data)679{680 struct address_handler_resource *handler = callback_data;681 struct inbound_transaction_resource *r;682 struct inbound_transaction_event *e;0683 void *fcp_frame = NULL;684 int ret;685000686 r = kmalloc(sizeof(*r), GFP_ATOMIC);687 e = kmalloc(sizeof(*e), GFP_ATOMIC);688- if (r == NULL || e == NULL)0689 goto failed;690-0691 r->request = request;692 r->data = payload;693 r->length = length;···715 if (ret < 0)716 goto failed;717718- e->request.type = FW_CDEV_EVENT_REQUEST;719- e->request.tcode = tcode;720- e->request.offset = offset;721- e->request.length = length;722- e->request.handle = r->resource.handle;723- e->request.closure = handler->closure;0000000000000000000000724725 queue_event(handler->client, &e->event,726- &e->request, sizeof(e->request), r->data, length);727 return;728729 failed:···755756 if (!is_fcp_request(request))757 fw_send_response(card, request, RCODE_CONFLICT_ERROR);00758}759760static void release_address_handler(struct client *client,···781 return -ENOMEM;782783 region.start = a->offset;784- region.end = a->offset + a->length;0000785 r->handler.length = a->length;786 r->handler.address_callback = handle_request;787 r->handler.callback_data = r;···797 kfree(r);798 return ret;799 }0800801 r->resource.release = release_address_handler;802 ret = add_client_resource(client, &r->resource, GFP_KERNEL);···832 if (is_fcp_request(r->request))833 goto out;834835- if (a->length < r->length)836- r->length = a->length;837- if (copy_from_user(r->data, u64_to_uptr(a->data), r->length)) {000838 ret = -EFAULT;839 kfree(r->request);840 goto out;841 }842- fw_send_response(client->device->card, r->request, a->rcode);843 out:0844 kfree(r);845846 return ret;···852853static int ioctl_initiate_bus_reset(struct client *client, union ioctl_arg *arg)854{855- return fw_core_initiate_bus_reset(client->device->card,856 arg->initiate_bus_reset.type == FW_CDEV_SHORT_RESET);0857}858859static void release_descriptor(struct client *client,···925 struct client *client = data;926 struct iso_interrupt_event *e;927928- e = kzalloc(sizeof(*e) + header_length, GFP_ATOMIC);929- if (e == NULL)0930 return;931-932 e->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT;933 e->interrupt.closure = client->iso_closure;934 e->interrupt.cycle = cycle;···939 sizeof(e->interrupt) + header_length, NULL, 0);940}9410000000000000000000942static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg)943{944 struct fw_cdev_create_iso_context *a = &arg->create_iso_context;945 struct fw_iso_context *context;0946947- /* We only support one context at this time. */948- if (client->iso_context != NULL)949- return -EBUSY;950-951- if (a->channel > 63)952- return -EINVAL;953954 switch (a->type) {955- case FW_ISO_CONTEXT_RECEIVE:956- if (a->header_size < 4 || (a->header_size & 3))957 return -EINVAL;00958 break;959960- case FW_ISO_CONTEXT_TRANSMIT:961- if (a->speed > SCODE_3200)0962 return -EINVAL;000000963 break;964965 default:···994 }995996 context = fw_iso_context_create(client->device->card, a->type,997- a->channel, a->speed, a->header_size,998- iso_callback, client);999 if (IS_ERR(context))1000 return PTR_ERR(context);100100000001002 client->iso_closure = a->closure;1003 client->iso_context = context;010041005- /* We only support one context at this time. */1006 a->handle = 0;10071008 return 0;000000000001009}10101011/* Macros for decoding the iso packet control header. */···1038 struct fw_cdev_queue_iso *a = &arg->queue_iso;1039 struct fw_cdev_iso_packet __user *p, *end, *next;1040 struct fw_iso_context *ctx = client->iso_context;1041- unsigned long payload, buffer_end, header_length;1042 u32 control;1043 int count;1044 struct {···1058 * use the indirect payload, the iso buffer need not be mapped1059 * and the a->data pointer is ignored.1060 */1061-1062 payload = (unsigned long)a->data - client->vm_start;1063 buffer_end = client->buffer.page_count << PAGE_SHIFT;1064 if (a->data == 0 || client->buffer.pages == NULL ||···1066 buffer_end = 0;1067 }10681069- p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(a->packets);0107001071 if (!access_ok(VERIFY_READ, p, a->size))1072 return -EFAULT;1073···1085 u.packet.sy = GET_SY(control);1086 u.packet.header_length = GET_HEADER_LENGTH(control);10871088- if (ctx->type == FW_ISO_CONTEXT_TRANSMIT) {1089- if (u.packet.header_length % 4 != 0)01090 return -EINVAL;1091- header_length = u.packet.header_length;1092- } else {1093- /*1094- * We require that header_length is a multiple of1095- * the fixed header size, ctx->header_size.1096- */1097- if (ctx->header_size == 0) {1098- if (u.packet.header_length > 0)1099- return -EINVAL;1100- } else if (u.packet.header_length == 0 ||1101- u.packet.header_length % ctx->header_size != 0) {1102 return -EINVAL;1103- }1104- header_length = 0;000001105 }11061107 next = (struct fw_cdev_iso_packet __user *)1108- &p->header[header_length / 4];1109 if (next > end)1110 return -EINVAL;1111 if (__copy_from_user1112- (u.packet.header, p->header, header_length))1113 return -EFAULT;1114 if (u.packet.skip && ctx->type == FW_ISO_CONTEXT_TRANSMIT &&1115 u.packet.header_length + u.packet.payload_length > 0)···1137static int ioctl_start_iso(struct client *client, union ioctl_arg *arg)1138{1139 struct fw_cdev_start_iso *a = &arg->start_iso;000000011401141 if (client->iso_context == NULL || a->handle != 0)1142 return -EINVAL;···11761177 local_irq_disable();11781179- cycle_time = card->driver->get_cycle_time(card);11801181 switch (a->clk_id) {1182 case CLOCK_REALTIME: getnstimeofday(&ts); break;···1457 return init_request(client, &request, dest, a->speed);1458}1459000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001460static int (* const ioctl_handlers[])(struct client *, union ioctl_arg *) = {1461- ioctl_get_info,1462- ioctl_send_request,1463- ioctl_allocate,1464- ioctl_deallocate,1465- ioctl_send_response,1466- ioctl_initiate_bus_reset,1467- ioctl_add_descriptor,1468- ioctl_remove_descriptor,1469- ioctl_create_iso_context,1470- ioctl_queue_iso,1471- ioctl_start_iso,1472- ioctl_stop_iso,1473- ioctl_get_cycle_timer,1474- ioctl_allocate_iso_resource,1475- ioctl_deallocate_iso_resource,1476- ioctl_allocate_iso_resource_once,1477- ioctl_deallocate_iso_resource_once,1478- ioctl_get_speed,1479- ioctl_send_broadcast_request,1480- ioctl_send_stream_packet,1481- ioctl_get_cycle_timer2,0001482};14831484static int dispatch_ioctl(struct client *client,···1692{1693 struct client *client = file->private_data;1694 struct event *event, *next_event;000016951696 mutex_lock(&client->device->client_list_mutex);1697 list_del(&client->link);
···18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.19 */2021+#include <linux/bug.h>22#include <linux/compat.h>23#include <linux/delay.h>24#include <linux/device.h>···33#include <linux/module.h>34#include <linux/mutex.h>35#include <linux/poll.h>36+#include <linux/sched.h> /* required for linux/wait.h */37#include <linux/slab.h>38#include <linux/spinlock.h>39#include <linux/string.h>···46#include <asm/system.h>4748#include "core.h"49+50+/*51+ * ABI version history is documented in linux/firewire-cdev.h.52+ */53+#define FW_CDEV_KERNEL_VERSION 454+#define FW_CDEV_VERSION_EVENT_REQUEST2 455+#define FW_CDEV_VERSION_ALLOCATE_REGION_END 45657struct client {58 u32 version;···62 u64 iso_closure;63 struct fw_iso_buffer buffer;64 unsigned long vm_start;65+66+ struct list_head phy_receiver_link;67+ u64 phy_receiver_closure;6869 struct list_head link;70 struct kref kref;···107108struct inbound_transaction_resource {109 struct client_resource resource;110+ struct fw_card *card;111 struct fw_request *request;112 void *data;113 size_t length;···171172struct inbound_transaction_event {173 struct event event;174+ union {175+ struct fw_cdev_event_request request;176+ struct fw_cdev_event_request2 request2;177+ } req;178};179180struct iso_interrupt_event {···179 struct fw_cdev_event_iso_interrupt interrupt;180};181182+struct iso_interrupt_mc_event {183+ struct event event;184+ struct fw_cdev_event_iso_interrupt_mc interrupt;185+};186+187struct iso_resource_event {188 struct event event;189 struct fw_cdev_event_iso_resource iso_resource;190+};191+192+struct outbound_phy_packet_event {193+ struct event event;194+ struct client *client;195+ struct fw_packet p;196+ struct fw_cdev_event_phy_packet phy_packet;197+};198+199+struct inbound_phy_packet_event {200+ struct event event;201+ struct fw_cdev_event_phy_packet phy_packet;202};203204static inline void __user *u64_to_uptr(__u64 value)···219 idr_init(&client->resource_idr);220 INIT_LIST_HEAD(&client->event_list);221 init_waitqueue_head(&client->wait);222+ INIT_LIST_HEAD(&client->phy_receiver_link);223 kref_init(&client->kref);224225 file->private_data = client;···309 event->generation = client->device->generation;310 event->node_id = client->device->node_id;311 event->local_node_id = card->local_node->node_id;312+ event->bm_node_id = card->bm_node_id;313 event->irm_node_id = card->irm_node->node_id;314 event->root_node_id = card->root_node->node_id;315···340341 e = kzalloc(sizeof(*e), GFP_KERNEL);342 if (e == NULL) {343+ fw_notify("Out of memory when allocating event\n");344 return;345 }346···386 struct fw_cdev_allocate_iso_resource allocate_iso_resource;387 struct fw_cdev_send_stream_packet send_stream_packet;388 struct fw_cdev_get_cycle_timer2 get_cycle_timer2;389+ struct fw_cdev_send_phy_packet send_phy_packet;390+ struct fw_cdev_receive_phy_packets receive_phy_packets;391+ struct fw_cdev_set_iso_channels set_iso_channels;392};393394static int ioctl_get_info(struct client *client, union ioctl_arg *arg)···395 unsigned long ret = 0;396397 client->version = a->version;398+ a->version = FW_CDEV_KERNEL_VERSION;399 a->card = client->device->card->index;400401 down_read(&fw_device_rwsem);···554 (request->length > 4096 || request->length > 512 << speed))555 return -EIO;556557+ if (request->tcode == TCODE_WRITE_QUADLET_REQUEST &&558+ request->length < 4)559+ return -EINVAL;560+561 e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL);562 if (e == NULL)563 return -ENOMEM;···626 if (is_fcp_request(r->request))627 kfree(r->data);628 else629+ fw_send_response(r->card, r->request, RCODE_CONFLICT_ERROR);630+631+ fw_card_put(r->card);632 kfree(r);633}634635static void handle_request(struct fw_card *card, struct fw_request *request,636 int tcode, int destination, int source,637+ int generation, unsigned long long offset,0638 void *payload, size_t length, void *callback_data)639{640 struct address_handler_resource *handler = callback_data;641 struct inbound_transaction_resource *r;642 struct inbound_transaction_event *e;643+ size_t event_size0;644 void *fcp_frame = NULL;645 int ret;646647+ /* card may be different from handler->client->device->card */648+ fw_card_get(card);649+650 r = kmalloc(sizeof(*r), GFP_ATOMIC);651 e = kmalloc(sizeof(*e), GFP_ATOMIC);652+ if (r == NULL || e == NULL) {653+ fw_notify("Out of memory when allocating event\n");654 goto failed;655+ }656+ r->card = card;657 r->request = request;658 r->data = payload;659 r->length = length;···669 if (ret < 0)670 goto failed;671672+ if (handler->client->version < FW_CDEV_VERSION_EVENT_REQUEST2) {673+ struct fw_cdev_event_request *req = &e->req.request;674+675+ if (tcode & 0x10)676+ tcode = TCODE_LOCK_REQUEST;677+678+ req->type = FW_CDEV_EVENT_REQUEST;679+ req->tcode = tcode;680+ req->offset = offset;681+ req->length = length;682+ req->handle = r->resource.handle;683+ req->closure = handler->closure;684+ event_size0 = sizeof(*req);685+ } else {686+ struct fw_cdev_event_request2 *req = &e->req.request2;687+688+ req->type = FW_CDEV_EVENT_REQUEST2;689+ req->tcode = tcode;690+ req->offset = offset;691+ req->source_node_id = source;692+ req->destination_node_id = destination;693+ req->card = card->index;694+ req->generation = generation;695+ req->length = length;696+ req->handle = r->resource.handle;697+ req->closure = handler->closure;698+ event_size0 = sizeof(*req);699+ }700701 queue_event(handler->client, &e->event,702+ &e->req, event_size0, r->data, length);703 return;704705 failed:···687688 if (!is_fcp_request(request))689 fw_send_response(card, request, RCODE_CONFLICT_ERROR);690+691+ fw_card_put(card);692}693694static void release_address_handler(struct client *client,···711 return -ENOMEM;712713 region.start = a->offset;714+ if (client->version < FW_CDEV_VERSION_ALLOCATE_REGION_END)715+ region.end = a->offset + a->length;716+ else717+ region.end = a->region_end;718+719 r->handler.length = a->length;720 r->handler.address_callback = handle_request;721 r->handler.callback_data = r;···723 kfree(r);724 return ret;725 }726+ a->offset = r->handler.offset;727728 r->resource.release = release_address_handler;729 ret = add_client_resource(client, &r->resource, GFP_KERNEL);···757 if (is_fcp_request(r->request))758 goto out;759760+ if (a->length != fw_get_response_length(r->request)) {761+ ret = -EINVAL;762+ kfree(r->request);763+ goto out;764+ }765+ if (copy_from_user(r->data, u64_to_uptr(a->data), a->length)) {766 ret = -EFAULT;767 kfree(r->request);768 goto out;769 }770+ fw_send_response(r->card, r->request, a->rcode);771 out:772+ fw_card_put(r->card);773 kfree(r);774775 return ret;···773774static int ioctl_initiate_bus_reset(struct client *client, union ioctl_arg *arg)775{776+ fw_schedule_bus_reset(client->device->card, true,777 arg->initiate_bus_reset.type == FW_CDEV_SHORT_RESET);778+ return 0;779}780781static void release_descriptor(struct client *client,···845 struct client *client = data;846 struct iso_interrupt_event *e;847848+ e = kmalloc(sizeof(*e) + header_length, GFP_ATOMIC);849+ if (e == NULL) {850+ fw_notify("Out of memory when allocating event\n");851 return;852+ }853 e->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT;854 e->interrupt.closure = client->iso_closure;855 e->interrupt.cycle = cycle;···858 sizeof(e->interrupt) + header_length, NULL, 0);859}860861+static void iso_mc_callback(struct fw_iso_context *context,862+ dma_addr_t completed, void *data)863+{864+ struct client *client = data;865+ struct iso_interrupt_mc_event *e;866+867+ e = kmalloc(sizeof(*e), GFP_ATOMIC);868+ if (e == NULL) {869+ fw_notify("Out of memory when allocating event\n");870+ return;871+ }872+ e->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL;873+ e->interrupt.closure = client->iso_closure;874+ e->interrupt.completed = fw_iso_buffer_lookup(&client->buffer,875+ completed);876+ queue_event(client, &e->event, &e->interrupt,877+ sizeof(e->interrupt), NULL, 0);878+}879+880static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg)881{882 struct fw_cdev_create_iso_context *a = &arg->create_iso_context;883 struct fw_iso_context *context;884+ fw_iso_callback_t cb;885886+ BUILD_BUG_ON(FW_CDEV_ISO_CONTEXT_TRANSMIT != FW_ISO_CONTEXT_TRANSMIT ||887+ FW_CDEV_ISO_CONTEXT_RECEIVE != FW_ISO_CONTEXT_RECEIVE ||888+ FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL !=889+ FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL);00890891 switch (a->type) {892+ case FW_ISO_CONTEXT_TRANSMIT:893+ if (a->speed > SCODE_3200 || a->channel > 63)894 return -EINVAL;895+896+ cb = iso_callback;897 break;898899+ case FW_ISO_CONTEXT_RECEIVE:900+ if (a->header_size < 4 || (a->header_size & 3) ||901+ a->channel > 63)902 return -EINVAL;903+904+ cb = iso_callback;905+ break;906+907+ case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:908+ cb = (fw_iso_callback_t)iso_mc_callback;909 break;910911 default:···886 }887888 context = fw_iso_context_create(client->device->card, a->type,889+ a->channel, a->speed, a->header_size, cb, client);0890 if (IS_ERR(context))891 return PTR_ERR(context);892893+ /* We only support one context at this time. */894+ spin_lock_irq(&client->lock);895+ if (client->iso_context != NULL) {896+ spin_unlock_irq(&client->lock);897+ fw_iso_context_destroy(context);898+ return -EBUSY;899+ }900 client->iso_closure = a->closure;901 client->iso_context = context;902+ spin_unlock_irq(&client->lock);9030904 a->handle = 0;905906 return 0;907+}908+909+static int ioctl_set_iso_channels(struct client *client, union ioctl_arg *arg)910+{911+ struct fw_cdev_set_iso_channels *a = &arg->set_iso_channels;912+ struct fw_iso_context *ctx = client->iso_context;913+914+ if (ctx == NULL || a->handle != 0)915+ return -EINVAL;916+917+ return fw_iso_context_set_channels(ctx, &a->channels);918}919920/* Macros for decoding the iso packet control header. */···913 struct fw_cdev_queue_iso *a = &arg->queue_iso;914 struct fw_cdev_iso_packet __user *p, *end, *next;915 struct fw_iso_context *ctx = client->iso_context;916+ unsigned long payload, buffer_end, transmit_header_bytes = 0;917 u32 control;918 int count;919 struct {···933 * use the indirect payload, the iso buffer need not be mapped934 * and the a->data pointer is ignored.935 */0936 payload = (unsigned long)a->data - client->vm_start;937 buffer_end = client->buffer.page_count << PAGE_SHIFT;938 if (a->data == 0 || client->buffer.pages == NULL ||···942 buffer_end = 0;943 }944945+ if (ctx->type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL && payload & 3)946+ return -EINVAL;947948+ p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(a->packets);949 if (!access_ok(VERIFY_READ, p, a->size))950 return -EFAULT;951···959 u.packet.sy = GET_SY(control);960 u.packet.header_length = GET_HEADER_LENGTH(control);961962+ switch (ctx->type) {963+ case FW_ISO_CONTEXT_TRANSMIT:964+ if (u.packet.header_length & 3)965 return -EINVAL;966+ transmit_header_bytes = u.packet.header_length;967+ break;968+969+ case FW_ISO_CONTEXT_RECEIVE:970+ if (u.packet.header_length == 0 ||971+ u.packet.header_length % ctx->header_size != 0)00000972 return -EINVAL;973+ break;974+975+ case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:976+ if (u.packet.payload_length == 0 ||977+ u.packet.payload_length & 3)978+ return -EINVAL;979+ break;980 }981982 next = (struct fw_cdev_iso_packet __user *)983+ &p->header[transmit_header_bytes / 4];984 if (next > end)985 return -EINVAL;986 if (__copy_from_user987+ (u.packet.header, p->header, transmit_header_bytes))988 return -EFAULT;989 if (u.packet.skip && ctx->type == FW_ISO_CONTEXT_TRANSMIT &&990 u.packet.header_length + u.packet.payload_length > 0)···1010static int ioctl_start_iso(struct client *client, union ioctl_arg *arg)1011{1012 struct fw_cdev_start_iso *a = &arg->start_iso;1013+1014+ BUILD_BUG_ON(1015+ FW_CDEV_ISO_CONTEXT_MATCH_TAG0 != FW_ISO_CONTEXT_MATCH_TAG0 ||1016+ FW_CDEV_ISO_CONTEXT_MATCH_TAG1 != FW_ISO_CONTEXT_MATCH_TAG1 ||1017+ FW_CDEV_ISO_CONTEXT_MATCH_TAG2 != FW_ISO_CONTEXT_MATCH_TAG2 ||1018+ FW_CDEV_ISO_CONTEXT_MATCH_TAG3 != FW_ISO_CONTEXT_MATCH_TAG3 ||1019+ FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS != FW_ISO_CONTEXT_MATCH_ALL_TAGS);10201021 if (client->iso_context == NULL || a->handle != 0)1022 return -EINVAL;···10421043 local_irq_disable();10441045+ cycle_time = card->driver->read_csr(card, CSR_CYCLE_TIME);10461047 switch (a->clk_id) {1048 case CLOCK_REALTIME: getnstimeofday(&ts); break;···1323 return init_request(client, &request, dest, a->speed);1324}13251326+static void outbound_phy_packet_callback(struct fw_packet *packet,1327+ struct fw_card *card, int status)1328+{1329+ struct outbound_phy_packet_event *e =1330+ container_of(packet, struct outbound_phy_packet_event, p);1331+1332+ switch (status) {1333+ /* expected: */1334+ case ACK_COMPLETE: e->phy_packet.rcode = RCODE_COMPLETE; break;1335+ /* should never happen with PHY packets: */1336+ case ACK_PENDING: e->phy_packet.rcode = RCODE_COMPLETE; break;1337+ case ACK_BUSY_X:1338+ case ACK_BUSY_A:1339+ case ACK_BUSY_B: e->phy_packet.rcode = RCODE_BUSY; break;1340+ case ACK_DATA_ERROR: e->phy_packet.rcode = RCODE_DATA_ERROR; break;1341+ case ACK_TYPE_ERROR: e->phy_packet.rcode = RCODE_TYPE_ERROR; break;1342+ /* stale generation; cancelled; on certain controllers: no ack */1343+ default: e->phy_packet.rcode = status; break;1344+ }1345+ e->phy_packet.data[0] = packet->timestamp;1346+1347+ queue_event(e->client, &e->event, &e->phy_packet,1348+ sizeof(e->phy_packet) + e->phy_packet.length, NULL, 0);1349+ client_put(e->client);1350+}1351+1352+static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg)1353+{1354+ struct fw_cdev_send_phy_packet *a = &arg->send_phy_packet;1355+ struct fw_card *card = client->device->card;1356+ struct outbound_phy_packet_event *e;1357+1358+ /* Access policy: Allow this ioctl only on local nodes' device files. */1359+ if (!client->device->is_local)1360+ return -ENOSYS;1361+1362+ e = kzalloc(sizeof(*e) + 4, GFP_KERNEL);1363+ if (e == NULL)1364+ return -ENOMEM;1365+1366+ client_get(client);1367+ e->client = client;1368+ e->p.speed = SCODE_100;1369+ e->p.generation = a->generation;1370+ e->p.header[0] = a->data[0];1371+ e->p.header[1] = a->data[1];1372+ e->p.header_length = 8;1373+ e->p.callback = outbound_phy_packet_callback;1374+ e->phy_packet.closure = a->closure;1375+ e->phy_packet.type = FW_CDEV_EVENT_PHY_PACKET_SENT;1376+ if (is_ping_packet(a->data))1377+ e->phy_packet.length = 4;1378+1379+ card->driver->send_request(card, &e->p);1380+1381+ return 0;1382+}1383+1384+static int ioctl_receive_phy_packets(struct client *client, union ioctl_arg *arg)1385+{1386+ struct fw_cdev_receive_phy_packets *a = &arg->receive_phy_packets;1387+ struct fw_card *card = client->device->card;1388+1389+ /* Access policy: Allow this ioctl only on local nodes' device files. */1390+ if (!client->device->is_local)1391+ return -ENOSYS;1392+1393+ spin_lock_irq(&card->lock);1394+1395+ list_move_tail(&client->phy_receiver_link, &card->phy_receiver_list);1396+ client->phy_receiver_closure = a->closure;1397+1398+ spin_unlock_irq(&card->lock);1399+1400+ return 0;1401+}1402+1403+void fw_cdev_handle_phy_packet(struct fw_card *card, struct fw_packet *p)1404+{1405+ struct client *client;1406+ struct inbound_phy_packet_event *e;1407+ unsigned long flags;1408+1409+ spin_lock_irqsave(&card->lock, flags);1410+1411+ list_for_each_entry(client, &card->phy_receiver_list, phy_receiver_link) {1412+ e = kmalloc(sizeof(*e) + 8, GFP_ATOMIC);1413+ if (e == NULL) {1414+ fw_notify("Out of memory when allocating event\n");1415+ break;1416+ }1417+ e->phy_packet.closure = client->phy_receiver_closure;1418+ e->phy_packet.type = FW_CDEV_EVENT_PHY_PACKET_RECEIVED;1419+ e->phy_packet.rcode = RCODE_COMPLETE;1420+ e->phy_packet.length = 8;1421+ e->phy_packet.data[0] = p->header[1];1422+ e->phy_packet.data[1] = p->header[2];1423+ queue_event(client, &e->event,1424+ &e->phy_packet, sizeof(e->phy_packet) + 8, NULL, 0);1425+ }1426+1427+ spin_unlock_irqrestore(&card->lock, flags);1428+}1429+1430static int (* const ioctl_handlers[])(struct client *, union ioctl_arg *) = {1431+ [0x00] = ioctl_get_info,1432+ [0x01] = ioctl_send_request,1433+ [0x02] = ioctl_allocate,1434+ [0x03] = ioctl_deallocate,1435+ [0x04] = ioctl_send_response,1436+ [0x05] = ioctl_initiate_bus_reset,1437+ [0x06] = ioctl_add_descriptor,1438+ [0x07] = ioctl_remove_descriptor,1439+ [0x08] = ioctl_create_iso_context,1440+ [0x09] = ioctl_queue_iso,1441+ [0x0a] = ioctl_start_iso,1442+ [0x0b] = ioctl_stop_iso,1443+ [0x0c] = ioctl_get_cycle_timer,1444+ [0x0d] = ioctl_allocate_iso_resource,1445+ [0x0e] = ioctl_deallocate_iso_resource,1446+ [0x0f] = ioctl_allocate_iso_resource_once,1447+ [0x10] = ioctl_deallocate_iso_resource_once,1448+ [0x11] = ioctl_get_speed,1449+ [0x12] = ioctl_send_broadcast_request,1450+ [0x13] = ioctl_send_stream_packet,1451+ [0x14] = ioctl_get_cycle_timer2,1452+ [0x15] = ioctl_send_phy_packet,1453+ [0x16] = ioctl_receive_phy_packets,1454+ [0x17] = ioctl_set_iso_channels,1455};14561457static int dispatch_ioctl(struct client *client,···1451{1452 struct client *client = file->private_data;1453 struct event *event, *next_event;1454+1455+ spin_lock_irq(&client->device->card->lock);1456+ list_del(&client->phy_receiver_link);1457+ spin_unlock_irq(&client->device->card->lock);14581459 mutex_lock(&client->device->client_list_mutex);1460 list_del(&client->link);
+6-5
drivers/firewire/core-device.c
···107}108109/**110- * fw_csr_string - reads a string from the configuration ROM111- * @directory: e.g. root directory or unit directory112- * @key: the key of the preceding directory entry113- * @buf: where to put the string114- * @size: size of @buf, in bytes115 *116 * The string is taken from a minimal ASCII text descriptor leaf after117 * the immediate entry with @key. The string is zero-terminated.···1136 goto give_up;1137 }113801139 create_units(device);11401141 /* Userspace may want to re-read attributes. */
···107}108109/**110+ * fw_csr_string() - reads a string from the configuration ROM111+ * @directory: e.g. root directory or unit directory112+ * @key: the key of the preceding directory entry113+ * @buf: where to put the string114+ * @size: size of @buf, in bytes115 *116 * The string is taken from a minimal ASCII text descriptor leaf after117 * the immediate entry with @key. The string is zero-terminated.···1136 goto give_up;1137 }11381139+ fw_device_cdev_update(device);1140 create_units(device);11411142 /* Userspace may want to re-read attributes. */
···118}119EXPORT_SYMBOL(fw_iso_buffer_destroy);120121+/* Convert DMA address to offset into virtually contiguous buffer. */122+size_t fw_iso_buffer_lookup(struct fw_iso_buffer *buffer, dma_addr_t completed)123+{124+ int i;125+ dma_addr_t address;126+ ssize_t offset;127+128+ for (i = 0; i < buffer->page_count; i++) {129+ address = page_private(buffer->pages[i]);130+ offset = (ssize_t)completed - (ssize_t)address;131+ if (offset > 0 && offset <= PAGE_SIZE)132+ return (i << PAGE_SHIFT) + offset;133+ }134+135+ return 0;136+}137+138struct fw_iso_context *fw_iso_context_create(struct fw_card *card,139 int type, int channel, int speed, size_t header_size,140 fw_iso_callback_t callback, void *callback_data)···134 ctx->channel = channel;135 ctx->speed = speed;136 ctx->header_size = header_size;137+ ctx->callback.sc = callback;138 ctx->callback_data = callback_data;139140 return ctx;···143144void fw_iso_context_destroy(struct fw_iso_context *ctx)145{146+ ctx->card->driver->free_iso_context(ctx);00147}148EXPORT_SYMBOL(fw_iso_context_destroy);149···156}157EXPORT_SYMBOL(fw_iso_context_start);158159+int fw_iso_context_set_channels(struct fw_iso_context *ctx, u64 *channels)160+{161+ return ctx->card->driver->set_iso_channels(ctx, channels);162+}163+164int fw_iso_context_queue(struct fw_iso_context *ctx,165 struct fw_iso_packet *packet,166 struct fw_iso_buffer *buffer,167 unsigned long payload)168{169+ return ctx->card->driver->queue_iso(ctx, packet, buffer, payload);00170}171EXPORT_SYMBOL(fw_iso_context_queue);172···279}280281/**282+ * fw_iso_resource_manage() - Allocate or deallocate a channel and/or bandwidth283 *284 * In parameters: card, generation, channels_mask, bandwidth, allocate285 * Out parameters: channel, bandwidth
+9-13
drivers/firewire/core-topology.c
···174 return list_entry(l, struct fw_node, link);175}176177-/**178- * build_tree - Build the tree representation of the topology179- * @self_ids: array of self IDs to create the tree from180- * @self_id_count: the length of the self_ids array181- * @local_id: the node ID of the local node182- *183 * This function builds the tree representation of the topology given184 * by the self IDs from the latest bus reset. During the construction185 * of the tree, the function checks that the self IDs are valid and···415 }416}417418-/**419- * update_tree - compare the old topology tree for card with the new420- * one specified by root. Queue the nodes and mark them as either421- * found, lost or updated. Update the nodes in the card topology tree422- * as we go.423 */424static void update_tree(struct fw_card *card, struct fw_node *root)425{···518}519520void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation,521- int self_id_count, u32 *self_ids)522{523 struct fw_node *local_node;524 unsigned long flags;···537538 spin_lock_irqsave(&card->lock, flags);539540- card->broadcast_channel_allocated = false;541 card->node_id = node_id;542 /*543 * Update node_id before generation to prevent anybody from using···546 smp_wmb();547 card->generation = generation;548 card->reset_jiffies = jiffies;00549 fw_schedule_bm_work(card, 0);550551 local_node = build_tree(card, self_ids, self_id_count);
···174 return list_entry(l, struct fw_node, link);175}176177+/*00000178 * This function builds the tree representation of the topology given179 * by the self IDs from the latest bus reset. During the construction180 * of the tree, the function checks that the self IDs are valid and···420 }421}422423+/*424+ * Compare the old topology tree for card with the new one specified by root.425+ * Queue the nodes and mark them as either found, lost or updated.426+ * Update the nodes in the card topology tree as we go.0427 */428static void update_tree(struct fw_card *card, struct fw_node *root)429{···524}525526void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation,527+ int self_id_count, u32 *self_ids, bool bm_abdicate)528{529 struct fw_node *local_node;530 unsigned long flags;···543544 spin_lock_irqsave(&card->lock, flags);545546+ card->broadcast_channel_allocated = card->broadcast_channel_auto_allocated;547 card->node_id = node_id;548 /*549 * Update node_id before generation to prevent anybody from using···552 smp_wmb();553 card->generation = generation;554 card->reset_jiffies = jiffies;555+ card->bm_node_id = 0xffff;556+ card->bm_abdicate = bm_abdicate;557 fw_schedule_bm_work(card, 0);558559 local_node = build_tree(card, self_ids, self_id_count);
+228-78
drivers/firewire/core-transaction.c
···246 break;247248 default:249- WARN(1, KERN_ERR "wrong tcode %d", tcode);250 }251 common:252 packet->speed = speed;···273}274275/**276- * This function provides low-level access to the IEEE1394 transaction277- * logic. Most C programs would use either fw_read(), fw_write() or278- * fw_lock() instead - those function are convenience wrappers for279- * this function. The fw_send_request() function is primarily280- * provided as a flexible, one-stop entry point for languages bindings281- * and protocol bindings.000000282 *283- * FIXME: Document this function further, in particular the possible284- * values for rcode in the callback. In short, we map ACK_COMPLETE to285- * RCODE_COMPLETE, internal errors set errno and set rcode to286- * RCODE_SEND_ERROR (which is out of range for standard ieee1394287- * rcodes). All other rcodes are forwarded unchanged. For all288- * errors, payload is NULL, length is 0.289 *290- * Can not expect the callback to be called before the function291- * returns, though this does happen in some cases (ACK_COMPLETE and292- * errors).293 *294- * The payload is only used for write requests and must not be freed295- * until the callback has been called.296 *297- * @param card the card from which to send the request298- * @param tcode the tcode for this transaction. Do not use299- * TCODE_LOCK_REQUEST directly, instead use TCODE_LOCK_MASK_SWAP300- * etc. to specify tcode and ext_tcode.301- * @param node_id the destination node ID (bus ID and PHY ID concatenated)302- * @param generation the generation for which node_id is valid303- * @param speed the speed to use for sending the request304- * @param offset the 48 bit offset on the destination node305- * @param payload the data payload for the request subaction306- * @param length the length in bytes of the data to read307- * @param callback function to be called when the transaction is completed308- * @param callback_data pointer to arbitrary data, which will be309- * passed to the callback310- *311- * In case of asynchronous stream packets i.e. TCODE_STREAM_DATA, the caller312 * needs to synthesize @destination_id with fw_stream_packet_destination_id().000000000000000000000313 */314void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,315 int destination_id, int generation, int speed,···348 setup_timer(&t->split_timeout_timer,349 split_transaction_timeout_callback, (unsigned long)t);350 /* FIXME: start this timer later, relative to t->timestamp */351- mod_timer(&t->split_timeout_timer, jiffies + DIV_ROUND_UP(HZ, 10));0352 t->callback = callback;353 t->callback_data = callback_data;354···384}385386/**387- * fw_run_transaction - send request and sleep until transaction is completed388 *389- * Returns the RCODE.00390 */391int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,392 int generation, int speed, unsigned long long offset,···429 int node_id, int generation, int gap_count)430{431 long timeout = DIV_ROUND_UP(HZ, 10);432- u32 data = PHY_IDENTIFIER(PHY_PACKET_CONFIG) |433- PHY_CONFIG_ROOT_ID(node_id) |434- PHY_CONFIG_GAP_COUNT(gap_count);000000000000435436 mutex_lock(&phy_config_mutex);437···518}519520/**521- * fw_core_add_address_handler - register for incoming requests522- * @handler: callback523- * @region: region in the IEEE 1212 node space address range524 *525 * region->start, ->end, and handler->length have to be quadlet-aligned.526 *···543 int ret = -EBUSY;544545 if (region->start & 0xffff000000000003ULL ||546- region->end & 0xffff000000000003ULL ||547 region->start >= region->end ||0548 handler->length & 3 ||549 handler->length == 0)550 return -EINVAL;···575EXPORT_SYMBOL(fw_core_add_address_handler);576577/**578- * fw_core_remove_address_handler - unregister an address handler579 */580void fw_core_remove_address_handler(struct fw_address_handler *handler)581{···602603 request = container_of(packet, struct fw_request, response);604 kfree(request);00000000000000000000000000000000000605}606607void fw_fill_response(struct fw_packet *response, u32 *request_header,···690 break;691692 default:693- WARN(1, KERN_ERR "wrong tcode %d", tcode);694 }695696 response->payload_mapped = false;697}698EXPORT_SYMBOL(fw_fill_response);699700-static struct fw_request *allocate_request(struct fw_packet *p)00000000000000000701{702 struct fw_request *request;703 u32 *data, length;704- int request_tcode, t;705706 request_tcode = HEADER_GET_TCODE(p->header[0]);707 switch (request_tcode) {···753 if (request == NULL)754 return NULL;755756- t = (p->timestamp & 0x1fff) + 4000;757- if (t >= 8000)758- t = (p->timestamp & ~0x1fff) + 0x2000 + t - 8000;759- else760- t = (p->timestamp & ~0x1fff) + t;761-762 request->response.speed = p->speed;763- request->response.timestamp = t;0764 request->response.generation = p->generation;765 request->response.ack = 0;766 request->response.callback = free_response_callback;···784785 if (rcode == RCODE_COMPLETE)786 fw_fill_response(&request->response, request->request_header,787- rcode, request->data, request->length);0788 else789 fw_fill_response(&request->response, request->request_header,790 rcode, NULL, 0);···803 unsigned long flags;804 int tcode, destination, source;805806- tcode = HEADER_GET_TCODE(p->header[0]);807 destination = HEADER_GET_DESTINATION(p->header[0]);808 source = HEADER_GET_SOURCE(p->header[1]);000809810 spin_lock_irqsave(&address_handler_lock, flags);811 handler = lookup_enclosing_address_handler(&address_handler_list,···827 else828 handler->address_callback(card, request,829 tcode, destination, source,830- p->generation, p->speed, offset,831 request->data, request->length,832 handler->callback_data);833}···865 if (is_enclosing_handler(handler, offset, request->length))866 handler->address_callback(card, NULL, tcode,867 destination, source,868- p->generation, p->speed,869- offset, request->data,870 request->length,871 handler->callback_data);872 }···883 if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE)884 return;885886- request = allocate_request(p);00000887 if (request == NULL) {888 /* FIXME: send statically allocated busy packet. */889 return;···911 unsigned long flags;912 u32 *data;913 size_t data_length;914- int tcode, tlabel, destination, source, rcode;915916- tcode = HEADER_GET_TCODE(p->header[0]);917- tlabel = HEADER_GET_TLABEL(p->header[0]);918- destination = HEADER_GET_DESTINATION(p->header[0]);919- source = HEADER_GET_SOURCE(p->header[1]);920- rcode = HEADER_GET_RCODE(p->header[1]);921922 spin_lock_irqsave(&card->lock, flags);923 list_for_each_entry(t, &card->transaction_list, link) {···981982static void handle_topology_map(struct fw_card *card, struct fw_request *request,983 int tcode, int destination, int source, int generation,984- int speed, unsigned long long offset,985- void *payload, size_t length, void *callback_data)986{987 int start;988···1011 { .start = CSR_REGISTER_BASE,1012 .end = CSR_REGISTER_BASE | CSR_CONFIG_ROM, };101300000000000001014static void handle_registers(struct fw_card *card, struct fw_request *request,1015 int tcode, int destination, int source, int generation,1016- int speed, unsigned long long offset,1017- void *payload, size_t length, void *callback_data)1018{1019 int reg = offset & ~CSR_REGISTER_BASE;1020 __be32 *data = payload;1021 int rcode = RCODE_COMPLETE;010221023 switch (reg) {00000000000000001024 case CSR_CYCLE_TIME:1025- if (TCODE_IS_READ_REQUEST(tcode) && length == 4)1026- *data = cpu_to_be32(card->driver->get_cycle_time(card));0000000000000000000000000000000000000000000000001027 else1028 rcode = RCODE_TYPE_ERROR;1029 break;···1130 */1131 BUG();1132 break;1133-1134- case CSR_BUSY_TIMEOUT:1135- /* FIXME: Implement this. */1136-1137- case CSR_BUS_TIME:1138- /* Useless without initialization by the bus manager. */11391140 default:1141 rcode = RCODE_ADDRESS_ERROR;
···246 break;247248 default:249+ WARN(1, "wrong tcode %d", tcode);250 }251 common:252 packet->speed = speed;···273}274275/**276+ * fw_send_request() - submit a request packet for transmission277+ * @card: interface to send the request at278+ * @t: transaction instance to which the request belongs279+ * @tcode: transaction code280+ * @destination_id: destination node ID, consisting of bus_ID and phy_ID281+ * @generation: bus generation in which request and response are valid282+ * @speed: transmission speed283+ * @offset: 48bit wide offset into destination's address space284+ * @payload: data payload for the request subaction285+ * @length: length of the payload, in bytes286+ * @callback: function to be called when the transaction is completed287+ * @callback_data: data to be passed to the transaction completion callback288 *289+ * Submit a request packet into the asynchronous request transmission queue.290+ * Can be called from atomic context. If you prefer a blocking API, use291+ * fw_run_transaction() in a context that can sleep.000292 *293+ * In case of lock requests, specify one of the firewire-core specific %TCODE_294+ * constants instead of %TCODE_LOCK_REQUEST in @tcode.0295 *296+ * Make sure that the value in @destination_id is not older than the one in297+ * @generation. Otherwise the request is in danger to be sent to a wrong node.298 *299+ * In case of asynchronous stream packets i.e. %TCODE_STREAM_DATA, the caller00000000000000300 * needs to synthesize @destination_id with fw_stream_packet_destination_id().301+ * It will contain tag, channel, and sy data instead of a node ID then.302+ *303+ * The payload buffer at @data is going to be DMA-mapped except in case of304+ * quadlet-sized payload or of local (loopback) requests. Hence make sure that305+ * the buffer complies with the restrictions for DMA-mapped memory. The306+ * @payload must not be freed before the @callback is called.307+ *308+ * In case of request types without payload, @data is NULL and @length is 0.309+ *310+ * After the transaction is completed successfully or unsuccessfully, the311+ * @callback will be called. Among its parameters is the response code which312+ * is either one of the rcodes per IEEE 1394 or, in case of internal errors,313+ * the firewire-core specific %RCODE_SEND_ERROR. The other firewire-core314+ * specific rcodes (%RCODE_CANCELLED, %RCODE_BUSY, %RCODE_GENERATION,315+ * %RCODE_NO_ACK) denote transaction timeout, busy responder, stale request316+ * generation, or missing ACK respectively.317+ *318+ * Note some timing corner cases: fw_send_request() may complete much earlier319+ * than when the request packet actually hits the wire. On the other hand,320+ * transaction completion and hence execution of @callback may happen even321+ * before fw_send_request() returns.322 */323void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,324 int destination_id, int generation, int speed,···339 setup_timer(&t->split_timeout_timer,340 split_transaction_timeout_callback, (unsigned long)t);341 /* FIXME: start this timer later, relative to t->timestamp */342+ mod_timer(&t->split_timeout_timer,343+ jiffies + card->split_timeout_jiffies);344 t->callback = callback;345 t->callback_data = callback_data;346···374}375376/**377+ * fw_run_transaction() - send request and sleep until transaction is completed378 *379+ * Returns the RCODE. See fw_send_request() for parameter documentation.380+ * Unlike fw_send_request(), @data points to the payload of the request or/and381+ * to the payload of the response.382 */383int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,384 int generation, int speed, unsigned long long offset,···417 int node_id, int generation, int gap_count)418{419 long timeout = DIV_ROUND_UP(HZ, 10);420+ u32 data = PHY_IDENTIFIER(PHY_PACKET_CONFIG);421+422+ if (node_id != FW_PHY_CONFIG_NO_NODE_ID)423+ data |= PHY_CONFIG_ROOT_ID(node_id);424+425+ if (gap_count == FW_PHY_CONFIG_CURRENT_GAP_COUNT) {426+ gap_count = card->driver->read_phy_reg(card, 1);427+ if (gap_count < 0)428+ return;429+430+ gap_count &= 63;431+ if (gap_count == 63)432+ return;433+ }434+ data |= PHY_CONFIG_GAP_COUNT(gap_count);435436 mutex_lock(&phy_config_mutex);437···494}495496/**497+ * fw_core_add_address_handler() - register for incoming requests498+ * @handler: callback499+ * @region: region in the IEEE 1212 node space address range500 *501 * region->start, ->end, and handler->length have to be quadlet-aligned.502 *···519 int ret = -EBUSY;520521 if (region->start & 0xffff000000000003ULL ||0522 region->start >= region->end ||523+ region->end > 0x0001000000000000ULL ||524 handler->length & 3 ||525 handler->length == 0)526 return -EINVAL;···551EXPORT_SYMBOL(fw_core_add_address_handler);552553/**554+ * fw_core_remove_address_handler() - unregister an address handler555 */556void fw_core_remove_address_handler(struct fw_address_handler *handler)557{···578579 request = container_of(packet, struct fw_request, response);580 kfree(request);581+}582+583+int fw_get_response_length(struct fw_request *r)584+{585+ int tcode, ext_tcode, data_length;586+587+ tcode = HEADER_GET_TCODE(r->request_header[0]);588+589+ switch (tcode) {590+ case TCODE_WRITE_QUADLET_REQUEST:591+ case TCODE_WRITE_BLOCK_REQUEST:592+ return 0;593+594+ case TCODE_READ_QUADLET_REQUEST:595+ return 4;596+597+ case TCODE_READ_BLOCK_REQUEST:598+ data_length = HEADER_GET_DATA_LENGTH(r->request_header[3]);599+ return data_length;600+601+ case TCODE_LOCK_REQUEST:602+ ext_tcode = HEADER_GET_EXTENDED_TCODE(r->request_header[3]);603+ data_length = HEADER_GET_DATA_LENGTH(r->request_header[3]);604+ switch (ext_tcode) {605+ case EXTCODE_FETCH_ADD:606+ case EXTCODE_LITTLE_ADD:607+ return data_length;608+ default:609+ return data_length / 2;610+ }611+612+ default:613+ WARN(1, "wrong tcode %d", tcode);614+ return 0;615+ }616}617618void fw_fill_response(struct fw_packet *response, u32 *request_header,···631 break;632633 default:634+ WARN(1, "wrong tcode %d", tcode);635 }636637 response->payload_mapped = false;638}639EXPORT_SYMBOL(fw_fill_response);640641+static u32 compute_split_timeout_timestamp(struct fw_card *card,642+ u32 request_timestamp)643+{644+ unsigned int cycles;645+ u32 timestamp;646+647+ cycles = card->split_timeout_cycles;648+ cycles += request_timestamp & 0x1fff;649+650+ timestamp = request_timestamp & ~0x1fff;651+ timestamp += (cycles / 8000) << 13;652+ timestamp |= cycles % 8000;653+654+ return timestamp;655+}656+657+static struct fw_request *allocate_request(struct fw_card *card,658+ struct fw_packet *p)659{660 struct fw_request *request;661 u32 *data, length;662+ int request_tcode;663664 request_tcode = HEADER_GET_TCODE(p->header[0]);665 switch (request_tcode) {···677 if (request == NULL)678 return NULL;679000000680 request->response.speed = p->speed;681+ request->response.timestamp =682+ compute_split_timeout_timestamp(card, p->timestamp);683 request->response.generation = p->generation;684 request->response.ack = 0;685 request->response.callback = free_response_callback;···713714 if (rcode == RCODE_COMPLETE)715 fw_fill_response(&request->response, request->request_header,716+ rcode, request->data,717+ fw_get_response_length(request));718 else719 fw_fill_response(&request->response, request->request_header,720 rcode, NULL, 0);···731 unsigned long flags;732 int tcode, destination, source;7330734 destination = HEADER_GET_DESTINATION(p->header[0]);735 source = HEADER_GET_SOURCE(p->header[1]);736+ tcode = HEADER_GET_TCODE(p->header[0]);737+ if (tcode == TCODE_LOCK_REQUEST)738+ tcode = 0x10 + HEADER_GET_EXTENDED_TCODE(p->header[3]);739740 spin_lock_irqsave(&address_handler_lock, flags);741 handler = lookup_enclosing_address_handler(&address_handler_list,···753 else754 handler->address_callback(card, request,755 tcode, destination, source,756+ p->generation, offset,757 request->data, request->length,758 handler->callback_data);759}···791 if (is_enclosing_handler(handler, offset, request->length))792 handler->address_callback(card, NULL, tcode,793 destination, source,794+ p->generation, offset,795+ request->data,796 request->length,797 handler->callback_data);798 }···809 if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE)810 return;811812+ if (TCODE_IS_LINK_INTERNAL(HEADER_GET_TCODE(p->header[0]))) {813+ fw_cdev_handle_phy_packet(card, p);814+ return;815+ }816+817+ request = allocate_request(card, p);818 if (request == NULL) {819 /* FIXME: send statically allocated busy packet. */820 return;···832 unsigned long flags;833 u32 *data;834 size_t data_length;835+ int tcode, tlabel, source, rcode;836837+ tcode = HEADER_GET_TCODE(p->header[0]);838+ tlabel = HEADER_GET_TLABEL(p->header[0]);839+ source = HEADER_GET_SOURCE(p->header[1]);840+ rcode = HEADER_GET_RCODE(p->header[1]);0841842 spin_lock_irqsave(&card->lock, flags);843 list_for_each_entry(t, &card->transaction_list, link) {···903904static void handle_topology_map(struct fw_card *card, struct fw_request *request,905 int tcode, int destination, int source, int generation,906+ unsigned long long offset, void *payload, size_t length,907+ void *callback_data)908{909 int start;910···933 { .start = CSR_REGISTER_BASE,934 .end = CSR_REGISTER_BASE | CSR_CONFIG_ROM, };935936+static void update_split_timeout(struct fw_card *card)937+{938+ unsigned int cycles;939+940+ cycles = card->split_timeout_hi * 8000 + (card->split_timeout_lo >> 19);941+942+ cycles = max(cycles, 800u); /* minimum as per the spec */943+ cycles = min(cycles, 3u * 8000u); /* maximum OHCI timeout */944+945+ card->split_timeout_cycles = cycles;946+ card->split_timeout_jiffies = DIV_ROUND_UP(cycles * HZ, 8000);947+}948+949static void handle_registers(struct fw_card *card, struct fw_request *request,950 int tcode, int destination, int source, int generation,951+ unsigned long long offset, void *payload, size_t length,952+ void *callback_data)953{954 int reg = offset & ~CSR_REGISTER_BASE;955 __be32 *data = payload;956 int rcode = RCODE_COMPLETE;957+ unsigned long flags;958959 switch (reg) {960+ case CSR_PRIORITY_BUDGET:961+ if (!card->priority_budget_implemented) {962+ rcode = RCODE_ADDRESS_ERROR;963+ break;964+ }965+ /* else fall through */966+967+ case CSR_NODE_IDS:968+ /*969+ * per IEEE 1394-2008 8.3.22.3, not IEEE 1394.1-2004 3.2.8970+ * and 9.6, but interoperable with IEEE 1394.1-2004 bridges971+ */972+ /* fall through */973+974+ case CSR_STATE_CLEAR:975+ case CSR_STATE_SET:976 case CSR_CYCLE_TIME:977+ case CSR_BUS_TIME:978+ case CSR_BUSY_TIMEOUT:979+ if (tcode == TCODE_READ_QUADLET_REQUEST)980+ *data = cpu_to_be32(card->driver->read_csr(card, reg));981+ else if (tcode == TCODE_WRITE_QUADLET_REQUEST)982+ card->driver->write_csr(card, reg, be32_to_cpu(*data));983+ else984+ rcode = RCODE_TYPE_ERROR;985+ break;986+987+ case CSR_RESET_START:988+ if (tcode == TCODE_WRITE_QUADLET_REQUEST)989+ card->driver->write_csr(card, CSR_STATE_CLEAR,990+ CSR_STATE_BIT_ABDICATE);991+ else992+ rcode = RCODE_TYPE_ERROR;993+ break;994+995+ case CSR_SPLIT_TIMEOUT_HI:996+ if (tcode == TCODE_READ_QUADLET_REQUEST) {997+ *data = cpu_to_be32(card->split_timeout_hi);998+ } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) {999+ spin_lock_irqsave(&card->lock, flags);1000+ card->split_timeout_hi = be32_to_cpu(*data) & 7;1001+ update_split_timeout(card);1002+ spin_unlock_irqrestore(&card->lock, flags);1003+ } else {1004+ rcode = RCODE_TYPE_ERROR;1005+ }1006+ break;1007+1008+ case CSR_SPLIT_TIMEOUT_LO:1009+ if (tcode == TCODE_READ_QUADLET_REQUEST) {1010+ *data = cpu_to_be32(card->split_timeout_lo);1011+ } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) {1012+ spin_lock_irqsave(&card->lock, flags);1013+ card->split_timeout_lo =1014+ be32_to_cpu(*data) & 0xfff80000;1015+ update_split_timeout(card);1016+ spin_unlock_irqrestore(&card->lock, flags);1017+ } else {1018+ rcode = RCODE_TYPE_ERROR;1019+ }1020+ break;1021+1022+ case CSR_MAINT_UTILITY:1023+ if (tcode == TCODE_READ_QUADLET_REQUEST)1024+ *data = card->maint_utility_register;1025+ else if (tcode == TCODE_WRITE_QUADLET_REQUEST)1026+ card->maint_utility_register = *data;1027 else1028 rcode = RCODE_TYPE_ERROR;1029 break;···974 */975 BUG();976 break;000000977978 default:979 rcode = RCODE_ADDRESS_ERROR;
+21-3
drivers/firewire/core.h
···38#define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31)39#define BROADCAST_CHANNEL_VALID (1 << 30)4000041struct fw_card_driver {42 /*43 * Enable the given card with the given initial config rom.···51 int (*enable)(struct fw_card *card,52 const __be32 *config_rom, size_t length);53054 int (*update_phy_reg)(struct fw_card *card, int address,55 int clear_bits, int set_bits);56···79 int (*enable_phys_dma)(struct fw_card *card,80 int node_id, int generation);8182- u32 (*get_cycle_time)(struct fw_card *card);08384 struct fw_iso_context *85 (*allocate_iso_context)(struct fw_card *card,···8990 int (*start_iso)(struct fw_iso_context *ctx,91 s32 cycle, u32 sync, u32 tags);009293 int (*queue_iso)(struct fw_iso_context *ctx,94 struct fw_iso_packet *packet,···105int fw_card_add(struct fw_card *card,106 u32 max_receive, u32 link_speed, u64 guid);107void fw_core_remove_card(struct fw_card *card);108-int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset);109int fw_compute_block_crc(__be32 *block);0110void fw_schedule_bm_work(struct fw_card *card, unsigned long delay);111112static inline struct fw_card *fw_card_get(struct fw_card *card)···130131void fw_device_cdev_update(struct fw_device *device);132void fw_device_cdev_remove(struct fw_device *device);0133134135/* -device */···200}201202void fw_core_handle_bus_reset(struct fw_card *card, int node_id,203- int generation, int self_id_count, u32 *self_ids);204void fw_destroy_nodes(struct fw_card *card);205206/*···217218#define TCODE_IS_READ_REQUEST(tcode) (((tcode) & ~1) == 4)219#define TCODE_IS_BLOCK_PACKET(tcode) (((tcode) & 1) != 0)0220#define TCODE_IS_REQUEST(tcode) (((tcode) & 2) == 0)221#define TCODE_IS_RESPONSE(tcode) (((tcode) & 2) != 0)222#define TCODE_HAS_REQUEST_DATA(tcode) (((tcode) & 12) != 4)···227228void fw_core_handle_request(struct fw_card *card, struct fw_packet *request);229void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);0230void fw_fill_response(struct fw_packet *response, u32 *request_header,231 int rcode, void *payload, size_t length);000232void fw_send_phy_config(struct fw_card *card,233 int node_id, int generation, int gap_count);00000234235#endif /* _FIREWIRE_CORE_H */
···38#define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31)39#define BROADCAST_CHANNEL_VALID (1 << 30)4041+#define CSR_STATE_BIT_CMSTR (1 << 8)42+#define CSR_STATE_BIT_ABDICATE (1 << 10)43+44struct fw_card_driver {45 /*46 * Enable the given card with the given initial config rom.···48 int (*enable)(struct fw_card *card,49 const __be32 *config_rom, size_t length);5051+ int (*read_phy_reg)(struct fw_card *card, int address);52 int (*update_phy_reg)(struct fw_card *card, int address,53 int clear_bits, int set_bits);54···75 int (*enable_phys_dma)(struct fw_card *card,76 int node_id, int generation);7778+ u32 (*read_csr)(struct fw_card *card, int csr_offset);79+ void (*write_csr)(struct fw_card *card, int csr_offset, u32 value);8081 struct fw_iso_context *82 (*allocate_iso_context)(struct fw_card *card,···8485 int (*start_iso)(struct fw_iso_context *ctx,86 s32 cycle, u32 sync, u32 tags);87+88+ int (*set_iso_channels)(struct fw_iso_context *ctx, u64 *channels);8990 int (*queue_iso)(struct fw_iso_context *ctx,91 struct fw_iso_packet *packet,···98int fw_card_add(struct fw_card *card,99 u32 max_receive, u32 link_speed, u64 guid);100void fw_core_remove_card(struct fw_card *card);0101int fw_compute_block_crc(__be32 *block);102+void fw_schedule_bus_reset(struct fw_card *card, bool delayed, bool short_reset);103void fw_schedule_bm_work(struct fw_card *card, unsigned long delay);104105static inline struct fw_card *fw_card_get(struct fw_card *card)···123124void fw_device_cdev_update(struct fw_device *device);125void fw_device_cdev_remove(struct fw_device *device);126+void fw_cdev_handle_phy_packet(struct fw_card *card, struct fw_packet *p);127128129/* -device */···192}193194void fw_core_handle_bus_reset(struct fw_card *card, int node_id,195+ int generation, int self_id_count, u32 *self_ids, bool bm_abdicate);196void fw_destroy_nodes(struct fw_card *card);197198/*···209210#define TCODE_IS_READ_REQUEST(tcode) (((tcode) & ~1) == 4)211#define TCODE_IS_BLOCK_PACKET(tcode) (((tcode) & 1) != 0)212+#define TCODE_IS_LINK_INTERNAL(tcode) ((tcode) == 0xe)213#define TCODE_IS_REQUEST(tcode) (((tcode) & 2) == 0)214#define TCODE_IS_RESPONSE(tcode) (((tcode) & 2) != 0)215#define TCODE_HAS_REQUEST_DATA(tcode) (((tcode) & 12) != 4)···218219void fw_core_handle_request(struct fw_card *card, struct fw_packet *request);220void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);221+int fw_get_response_length(struct fw_request *request);222void fw_fill_response(struct fw_packet *response, u32 *request_header,223 int rcode, void *payload, size_t length);224+225+#define FW_PHY_CONFIG_NO_NODE_ID -1226+#define FW_PHY_CONFIG_CURRENT_GAP_COUNT -1227void fw_send_phy_config(struct fw_card *card,228 int node_id, int generation, int gap_count);229+230+static inline bool is_ping_packet(u32 *data)231+{232+ return (data[0] & 0xc0ffffff) == 0 && ~data[0] == data[1];233+}234235#endif /* _FIREWIRE_CORE_H */
+2-2
drivers/firewire/net.c
···806807static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r,808 int tcode, int destination, int source, int generation,809- int speed, unsigned long long offset, void *payload,810- size_t length, void *callback_data)811{812 struct fwnet_device *dev = callback_data;813 int rcode;
···806807static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r,808 int tcode, int destination, int source, int generation,809+ unsigned long long offset, void *payload, size_t length,810+ void *callback_data)811{812 struct fwnet_device *dev = callback_data;813 int rcode;
+25
drivers/firewire/nosy-user.h
···0000000000000000000000000
···1+#ifndef __nosy_user_h2+#define __nosy_user_h3+4+#include <linux/ioctl.h>5+#include <linux/types.h>6+7+#define NOSY_IOC_GET_STATS _IOR('&', 0, struct nosy_stats)8+#define NOSY_IOC_START _IO('&', 1)9+#define NOSY_IOC_STOP _IO('&', 2)10+#define NOSY_IOC_FILTER _IOW('&', 2, __u32)11+12+struct nosy_stats {13+ __u32 total_packet_count;14+ __u32 lost_packet_count;15+};16+17+/*18+ * Format of packets returned from the kernel driver:19+ *20+ * quadlet with timestamp (microseconds, CPU endian)21+ * quadlet-padded packet data... (little endian)22+ * quadlet with ack (little endian)23+ */24+25+#endif /* __nosy_user_h */
···172173static inline struct video_card* file_to_video_card(struct file *file)174{175- return (struct video_card*) file->private_data;176}177178/*** FRAME METHODS *********************************************************/···610 } else {611612 u32 transmit_sec, transmit_cyc;613- u32 ts_cyc, ts_off;614615 /* DMA is stopped, so this is the very first frame */616 video->active_frame = this_frame;···636 transmit_sec += transmit_cyc/8000;637 transmit_cyc %= 8000;638639- ts_off = ct_off;640 ts_cyc = transmit_cyc + 3;641 ts_cyc %= 8000;642···1783 struct video_card *video = NULL;17841785 if (file->private_data) {1786- video = (struct video_card*) file->private_data;17871788 } else {1789 /* look up the card by ID */···20032004 int sof=0; /* start-of-frame flag */2005 struct frame *f;2006- u16 packet_length, packet_time;2007 int i, dbc=0;2008 struct DMA_descriptor_block *block = NULL;2009 u16 xferstatus;···2023 sizeof(struct packet));20242025 packet_length = le16_to_cpu(p->data_length);2026- packet_time = le16_to_cpu(p->timestamp);2027-2028- irq_printk("received packet %02d, timestamp=%04x, length=%04x, sof=%02x%02x\n", video->current_packet,2029- packet_time, packet_length,2030- p->data[0], p->data[1]);20312032 /* get the descriptor based on packet_buffer cursor */2033 f = video->frames[video->current_packet / MAX_PACKETS];···23142315static void dv1394_host_reset(struct hpsb_host *host)2316{2317- struct ti_ohci *ohci;2318 struct video_card *video = NULL, *tmp_vid;2319 unsigned long flags;23202321 /* We only work with the OHCI-1394 driver */2322 if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))2323 return;2324-2325- ohci = (struct ti_ohci *)host->hostdata;2326-23272328 /* find the corresponding video_cards */2329 spin_lock_irqsave(&dv1394_cards_lock, flags);
···172173static inline struct video_card* file_to_video_card(struct file *file)174{175+ return file->private_data;176}177178/*** FRAME METHODS *********************************************************/···610 } else {611612 u32 transmit_sec, transmit_cyc;613+ u32 ts_cyc;614615 /* DMA is stopped, so this is the very first frame */616 video->active_frame = this_frame;···636 transmit_sec += transmit_cyc/8000;637 transmit_cyc %= 8000;6380639 ts_cyc = transmit_cyc + 3;640 ts_cyc %= 8000;641···1784 struct video_card *video = NULL;17851786 if (file->private_data) {1787+ video = file->private_data;17881789 } else {1790 /* look up the card by ID */···20042005 int sof=0; /* start-of-frame flag */2006 struct frame *f;2007+ u16 packet_length;2008 int i, dbc=0;2009 struct DMA_descriptor_block *block = NULL;2010 u16 xferstatus;···2024 sizeof(struct packet));20252026 packet_length = le16_to_cpu(p->data_length);0000020272028 /* get the descriptor based on packet_buffer cursor */2029 f = video->frames[video->current_packet / MAX_PACKETS];···23202321static void dv1394_host_reset(struct hpsb_host *host)2322{02323 struct video_card *video = NULL, *tmp_vid;2324 unsigned long flags;23252326 /* We only work with the OHCI-1394 driver */2327 if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))2328 return;00023292330 /* find the corresponding video_cards */2331 spin_lock_irqsave(&dv1394_cards_lock, flags);
···720static long video1394_ioctl(struct file *file,721 unsigned int cmd, unsigned long arg)722{723+ struct file_ctx *ctx = file->private_data;724 struct ti_ohci *ohci = ctx->ohci;725 unsigned long flags;726 void __user *argp = (void __user *)arg;···1045 if (get_user(qv, &p->packet_sizes))1046 return -EFAULT;10471048+ psizes = memdup_user(qv, buf_size);1049+ if (IS_ERR(psizes))1050+ return PTR_ERR(psizes);000001051 }10521053 spin_lock_irqsave(&d->lock,flags);···11771178static int video1394_mmap(struct file *file, struct vm_area_struct *vma)1179{1180+ struct file_ctx *ctx = file->private_data;11811182 if (ctx->current_ctx == NULL) {1183 PRINT(KERN_ERR, ctx->ohci->host->id,···12441245static int video1394_release(struct inode *inode, struct file *file)1246{1247+ struct file_ctx *ctx = file->private_data;1248 struct ti_ohci *ohci = ctx->ohci;1249 struct list_head *lh, *next;1250 u64 mask;
+2-2
drivers/media/dvb/firewire/firedtv-fw.c
···194195static void handle_fcp(struct fw_card *card, struct fw_request *request,196 int tcode, int destination, int source, int generation,197- int speed, unsigned long long offset,198- void *payload, size_t length, void *callback_data)199{200 struct firedtv *f, *fdtv = NULL;201 struct fw_device *device;
···194195static void handle_fcp(struct fw_card *card, struct fw_request *request,196 int tcode, int destination, int source, int generation,197+ unsigned long long offset, void *payload, size_t length,198+ void *callback_data)199{200 struct firedtv *f, *fdtv = NULL;201 struct fw_device *device;
+405-92
include/linux/firewire-cdev.h
···30#include <linux/types.h>31#include <linux/firewire-constants.h>3233-#define FW_CDEV_EVENT_BUS_RESET 0x0034-#define FW_CDEV_EVENT_RESPONSE 0x0135-#define FW_CDEV_EVENT_REQUEST 0x0236-#define FW_CDEV_EVENT_ISO_INTERRUPT 0x0337-#define FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED 0x0438-#define FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED 0x050000003940/**41 * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types···74 * This event is sent when the bus the device belongs to goes through a bus75 * reset. It provides information about the new bus configuration, such as76 * new node ID for this device, new root ID, and others.000077 */78struct fw_cdev_event_bus_reset {79 __u64 closure;···9293/**94 * struct fw_cdev_event_response - Sent when a response packet was received95- * @closure: See &fw_cdev_event_common;96- * set by %FW_CDEV_IOC_SEND_REQUEST ioctl097 * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_RESPONSE98 * @rcode: Response code returned by the remote node99 * @length: Data length, i.e. the response's payload size in bytes···104 * sent by %FW_CDEV_IOC_SEND_REQUEST ioctl. The payload data for responses105 * carrying data (read and lock responses) follows immediately and can be106 * accessed through the @data field.00000107 */108struct fw_cdev_event_response {109 __u64 closure;···119};120121/**122- * struct fw_cdev_event_request - Sent on incoming request to an address region123 * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl124 * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST0000000000000000000000000000000125 * @tcode: Transaction code of the incoming request126 * @offset: The offset into the 48-bit per-node address space0000127 * @handle: Reference to the kernel-side pending request128 * @length: Data length, i.e. the request's payload size in bytes129 * @data: Incoming data, if any···171 *172 * The payload data for requests carrying data (write and lock requests)173 * follows immediately and can be accessed through the @data field.00000000000000000000000000174 */175-struct fw_cdev_event_request {176 __u64 closure;177 __u32 type;178 __u32 tcode;179 __u64 offset;0000180 __u32 handle;181 __u32 length;182 __u32 data[0];···222 * @header: Stripped headers, if any223 *224 * This event is sent when the controller has completed an &fw_cdev_iso_packet225- * with the %FW_CDEV_ISO_INTERRUPT bit set. In the receive case, the headers226- * stripped of all packets up until and including the interrupt packet are227- * returned in the @header field. The amount of header data per packet is as228- * specified at iso context creation by &fw_cdev_create_iso_context.header_size.229 *230- * In version 1 of this ABI, header data consisted of the 1394 isochronous231- * packet header, followed by quadlets from the packet payload if232- * &fw_cdev_create_iso_context.header_size > 4.233 *234- * In version 2 of this ABI, header data consist of the 1394 isochronous235- * packet header, followed by a timestamp quadlet if236- * &fw_cdev_create_iso_context.header_size > 4, followed by quadlets from the237- * packet payload if &fw_cdev_create_iso_context.header_size > 8.238 *000000000000000000000000000239 * Behaviour of ver. 1 of this ABI is no longer available since ABI ver. 2.240- *241- * Format of 1394 iso packet header: 16 bits len, 2 bits tag, 6 bits channel,242- * 4 bits tcode, 4 bits sy, in big endian byte order. Format of timestamp:243- * 16 bits invalid, 3 bits cycleSeconds, 13 bits cycleCount, in big endian byte244- * order.245 */246struct fw_cdev_event_iso_interrupt {247 __u64 closure;···266 __u32 cycle;267 __u32 header_length;268 __u32 header[0];0000000000000000000000000000000000000269};270271/**···335};336337/**000000000000000000000000338 * union fw_cdev_event - Convenience union of fw_cdev_event_ types339- * @common: Valid for all types340- * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET341- * @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE342- * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST343- * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT344- * @iso_resource: Valid if @common.type ==000345 * %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or346 * %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED000347 *348 * Convenience union for userspace use. Events could be read(2) into an349 * appropriately aligned char buffer and then cast to this union for further···388 struct fw_cdev_event_bus_reset bus_reset;389 struct fw_cdev_event_response response;390 struct fw_cdev_event_request request;0391 struct fw_cdev_event_iso_interrupt iso_interrupt;392- struct fw_cdev_event_iso_resource iso_resource;00393};394395/* available since kernel version 2.6.22 */···424/* available since kernel version 2.6.34 */425#define FW_CDEV_IOC_GET_CYCLE_TIMER2 _IOWR('#', 0x14, struct fw_cdev_get_cycle_timer2)42600000427/*428- * FW_CDEV_VERSION History429 * 1 (2.6.22) - initial version0430 * 2 (2.6.30) - changed &fw_cdev_event_iso_interrupt.header if431 * &fw_cdev_create_iso_context.header_size is 8 or more000432 * (2.6.32) - added time stamp to xmit &fw_cdev_event_iso_interrupt433 * (2.6.33) - IR has always packet-per-buffer semantics now, not one of434 * dual-buffer or packet-per-buffer depending on hardware0435 * 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable00000000436 */437-#define FW_CDEV_VERSION 3438439/**440 * struct fw_cdev_get_info - General purpose information ioctl441- * @version: The version field is just a running serial number.442- * We never break backwards compatibility, but may add more443- * structs and ioctls in later revisions.00000444 * @rom_length: If @rom is non-zero, at most rom_length bytes of configuration445 * ROM will be copied into that user space address. In either446 * case, @rom_length is updated with the actual length of the···530};531532/**533- * struct fw_cdev_allocate - Allocate a CSR address range534 * @offset: Start offset of the address range535 * @closure: To be passed back to userspace in request events536- * @length: Length of the address range, in bytes537 * @handle: Handle to the allocation, written by the kernel0538 *539 * Allocate an address range in the 48-bit address space on the local node540 * (the controller). This allows userspace to listen for requests with an541- * offset within that address range. When the kernel receives a request542- * within the range, an &fw_cdev_event_request event will be written back.543- * The @closure field is passed back to userspace in the response event.000544 * The @handle field is an out parameter, returning a handle to the allocated545 * range to be used for later deallocation of the range.546 *547 * The address range is allocated on all local nodes. The address allocation548- * is exclusive except for the FCP command and response registers.000000000000000549 */550struct fw_cdev_allocate {551 __u64 offset;552 __u64 closure;553 __u32 length;554 __u32 handle;0555};556557/**···593 * Initiate a bus reset for the bus this device is on. The bus reset can be594 * either the original (long) bus reset or the arbitrated (short) bus reset595 * introduced in 1394a-2000.00000596 */597struct fw_cdev_initiate_bus_reset {598- __u32 type; /* FW_CDEV_SHORT_RESET or FW_CDEV_LONG_RESET */599};600601/**···624 *625 * @immediate, @key, and @data array elements are CPU-endian quadlets.626 *627- * If successful, the kernel adds the descriptor and writes back a handle to the628- * kernel-side object to be used for later removal of the descriptor block and629- * immediate key.0630 *631 * This ioctl affects the configuration ROMs of all local nodes.632 * The ioctl only succeeds on device files which represent a local node.···646 * descriptor was added647 *648 * Remove a descriptor block and accompanying immediate key from the local649- * nodes' configuration ROMs.0650 */651struct fw_cdev_remove_descriptor {652 __u32 handle;653};654655-#define FW_CDEV_ISO_CONTEXT_TRANSMIT 0656-#define FW_CDEV_ISO_CONTEXT_RECEIVE 10657658/**659- * struct fw_cdev_create_iso_context - Create a context for isochronous IO660- * @type: %FW_CDEV_ISO_CONTEXT_TRANSMIT or %FW_CDEV_ISO_CONTEXT_RECEIVE661- * @header_size: Header size to strip for receive contexts662- * @channel: Channel to bind to663- * @speed: Speed for transmit contexts664- * @closure: To be returned in &fw_cdev_event_iso_interrupt00665 * @handle: Handle to context, written back by kernel666 *667 * Prior to sending or receiving isochronous I/O, a context must be created.668 * The context records information about the transmit or receive configuration669 * and typically maps to an underlying hardware resource. A context is set up670 * for either sending or receiving. It is bound to a specific isochronous671- * channel.00000000672 *673 * If a context was successfully created, the kernel writes back a handle to the674 * context, which must be passed in for subsequent operations on that context.675 *676- * For receive contexts, @header_size must be at least 4 and must be a multiple677- * of 4.678- *679- * Note that the effect of a @header_size > 4 depends on680- * &fw_cdev_get_info.version, as documented at &fw_cdev_event_iso_interrupt.681 */682struct fw_cdev_create_iso_context {683 __u32 type;···697 __u32 channel;698 __u32 speed;699 __u64 closure;0000000000000000700 __u32 handle;701};702···726727/**728 * struct fw_cdev_iso_packet - Isochronous packet729- * @control: Contains the header length (8 uppermost bits), the sy field730- * (4 bits), the tag field (2 bits), a sync flag (1 bit),731- * a skip flag (1 bit), an interrupt flag (1 bit), and the732 * payload length (16 lowermost bits)733- * @header: Header and payload734 *735 * &struct fw_cdev_iso_packet is used to describe isochronous packet queues.736- *737 * Use the FW_CDEV_ISO_ macros to fill in @control.0738 *739- * For transmit packets, the header length must be a multiple of 4 and specifies740- * the numbers of bytes in @header that will be prepended to the packet's741- * payload; these bytes are copied into the kernel and will not be accessed742- * after the ioctl has returned. The sy and tag fields are copied to the iso743- * packet header (these fields are specified by IEEE 1394a and IEC 61883-1).744- * The skip flag specifies that no packet is to be sent in a frame; when using745- * this, all other fields except the interrupt flag must be zero.746 *747- * For receive packets, the header length must be a multiple of the context's748- * header size; if the header length is larger than the context's header size,749- * multiple packets are queued for this entry. The sy and tag fields are750- * ignored. If the sync flag is set, the context drops all packets until751- * a packet with a matching sy field is received (the sync value to wait for is752- * specified in the &fw_cdev_start_iso structure). The payload length defines753- * how many payload bytes can be received for one packet (in addition to payload754- * quadlets that have been defined as headers and are stripped and returned in755- * the &fw_cdev_event_iso_interrupt structure). If more bytes are received, the756- * additional bytes are dropped. If less bytes are received, the remaining757- * bytes in this part of the payload buffer will not be written to, not even by758- * the next packet, i.e., packets received in consecutive frames will not759- * necessarily be consecutive in memory. If an entry has queued multiple760- * packets, the payload length is divided equally among them.761 *762- * When a packet with the interrupt flag set has been completed, the000000000000000000000000000000763 * &fw_cdev_event_iso_interrupt event will be sent. An entry that has queued764 * multiple receive packets is completed when its last packet is completed.0000000000000000765 */766struct fw_cdev_iso_packet {767 __u32 control;···800801/**802 * struct fw_cdev_queue_iso - Queue isochronous packets for I/O803- * @packets: Userspace pointer to packet data804 * @data: Pointer into mmap()'ed payload buffer805- * @size: Size of packet data in bytes806 * @handle: Isochronous context handle807 *808 * Queue a number of isochronous packets for reception or transmission.···815 * The kernel may or may not queue all packets, but will write back updated816 * values of the @packets, @data and @size fields, so the ioctl can be817 * resubmitted easily.000818 */819struct fw_cdev_queue_iso {820 __u64 packets;···974 __u64 data;975 __u32 generation;976 __u32 speed;00000000000000000000000000000000000977};978979#endif /* _LINUX_FIREWIRE_CDEV_H */
···30#include <linux/types.h>31#include <linux/firewire-constants.h>3233+#define FW_CDEV_EVENT_BUS_RESET 0x0034+#define FW_CDEV_EVENT_RESPONSE 0x0135+#define FW_CDEV_EVENT_REQUEST 0x0236+#define FW_CDEV_EVENT_ISO_INTERRUPT 0x0337+#define FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED 0x0438+#define FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED 0x0539+40+/* available since kernel version 2.6.36 */41+#define FW_CDEV_EVENT_REQUEST2 0x0642+#define FW_CDEV_EVENT_PHY_PACKET_SENT 0x0743+#define FW_CDEV_EVENT_PHY_PACKET_RECEIVED 0x0844+#define FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL 0x094546/**47 * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types···68 * This event is sent when the bus the device belongs to goes through a bus69 * reset. It provides information about the new bus configuration, such as70 * new node ID for this device, new root ID, and others.71+ *72+ * If @bm_node_id is 0xffff right after bus reset it can be reread by an73+ * %FW_CDEV_IOC_GET_INFO ioctl after bus manager selection was finished.74+ * Kernels with ABI version < 4 do not set @bm_node_id.75 */76struct fw_cdev_event_bus_reset {77 __u64 closure;···8283/**84 * struct fw_cdev_event_response - Sent when a response packet was received85+ * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_SEND_REQUEST86+ * or %FW_CDEV_IOC_SEND_BROADCAST_REQUEST87+ * or %FW_CDEV_IOC_SEND_STREAM_PACKET ioctl88 * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_RESPONSE89 * @rcode: Response code returned by the remote node90 * @length: Data length, i.e. the response's payload size in bytes···93 * sent by %FW_CDEV_IOC_SEND_REQUEST ioctl. The payload data for responses94 * carrying data (read and lock responses) follows immediately and can be95 * accessed through the @data field.96+ *97+ * The event is also generated after conclusions of transactions that do not98+ * involve response packets. This includes unified write transactions,99+ * broadcast write transactions, and transmission of asynchronous stream100+ * packets. @rcode indicates success or failure of such transmissions.101 */102struct fw_cdev_event_response {103 __u64 closure;···103};104105/**106+ * struct fw_cdev_event_request - Old version of &fw_cdev_event_request2107 * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl108 * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST109+ * @tcode: See &fw_cdev_event_request2110+ * @offset: See &fw_cdev_event_request2111+ * @handle: See &fw_cdev_event_request2112+ * @length: See &fw_cdev_event_request2113+ * @data: See &fw_cdev_event_request2114+ *115+ * This event is sent instead of &fw_cdev_event_request2 if the kernel or116+ * the client implements ABI version <= 3.117+ *118+ * Unlike &fw_cdev_event_request2, the sender identity cannot be established,119+ * broadcast write requests cannot be distinguished from unicast writes, and120+ * @tcode of lock requests is %TCODE_LOCK_REQUEST.121+ *122+ * Requests to the FCP_REQUEST or FCP_RESPONSE register are responded to as123+ * with &fw_cdev_event_request2, except in kernel 2.6.32 and older which send124+ * the response packet of the client's %FW_CDEV_IOC_SEND_RESPONSE ioctl.125+ */126+struct fw_cdev_event_request {127+ __u64 closure;128+ __u32 type;129+ __u32 tcode;130+ __u64 offset;131+ __u32 handle;132+ __u32 length;133+ __u32 data[0];134+};135+136+/**137+ * struct fw_cdev_event_request2 - Sent on incoming request to an address region138+ * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl139+ * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST2140 * @tcode: Transaction code of the incoming request141 * @offset: The offset into the 48-bit per-node address space142+ * @source_node_id: Sender node ID143+ * @destination_node_id: Destination node ID144+ * @card: The index of the card from which the request came145+ * @generation: Bus generation in which the request is valid146 * @handle: Reference to the kernel-side pending request147 * @length: Data length, i.e. the request's payload size in bytes148 * @data: Incoming data, if any···120 *121 * The payload data for requests carrying data (write and lock requests)122 * follows immediately and can be accessed through the @data field.123+ *124+ * Unlike &fw_cdev_event_request, @tcode of lock requests is one of the125+ * firewire-core specific %TCODE_LOCK_MASK_SWAP...%TCODE_LOCK_VENDOR_DEPENDENT,126+ * i.e. encodes the extended transaction code.127+ *128+ * @card may differ from &fw_cdev_get_info.card because requests are received129+ * from all cards of the Linux host. @source_node_id, @destination_node_id, and130+ * @generation pertain to that card. Destination node ID and bus generation may131+ * therefore differ from the corresponding fields of the last132+ * &fw_cdev_event_bus_reset.133+ *134+ * @destination_node_id may also differ from the current node ID because of a135+ * non-local bus ID part or in case of a broadcast write request. Note, a136+ * client must call an %FW_CDEV_IOC_SEND_RESPONSE ioctl even in case of a137+ * broadcast write request; the kernel will then release the kernel-side pending138+ * request but will not actually send a response packet.139+ *140+ * In case of a write request to FCP_REQUEST or FCP_RESPONSE, the kernel already141+ * sent a write response immediately after the request was received; in this142+ * case the client must still call an %FW_CDEV_IOC_SEND_RESPONSE ioctl to143+ * release the kernel-side pending request, though another response won't be144+ * sent.145+ *146+ * If the client subsequently needs to initiate requests to the sender node of147+ * an &fw_cdev_event_request2, it needs to use a device file with matching148+ * card index, node ID, and generation for outbound requests.149 */150+struct fw_cdev_event_request2 {151 __u64 closure;152 __u32 type;153 __u32 tcode;154 __u64 offset;155+ __u32 source_node_id;156+ __u32 destination_node_id;157+ __u32 card;158+ __u32 generation;159 __u32 handle;160 __u32 length;161 __u32 data[0];···141 * @header: Stripped headers, if any142 *143 * This event is sent when the controller has completed an &fw_cdev_iso_packet144+ * with the %FW_CDEV_ISO_INTERRUPT bit set.000145 *146+ * Isochronous transmit events (context type %FW_CDEV_ISO_CONTEXT_TRANSMIT):00147 *148+ * In version 3 and some implementations of version 2 of the ABI, &header_length149+ * is a multiple of 4 and &header contains timestamps of all packets up until150+ * the interrupt packet. The format of the timestamps is as described below for151+ * isochronous reception. In version 1 of the ABI, &header_length was 0.152 *153+ * Isochronous receive events (context type %FW_CDEV_ISO_CONTEXT_RECEIVE):154+ *155+ * The headers stripped of all packets up until and including the interrupt156+ * packet are returned in the @header field. The amount of header data per157+ * packet is as specified at iso context creation by158+ * &fw_cdev_create_iso_context.header_size.159+ *160+ * Hence, _interrupt.header_length / _context.header_size is the number of161+ * packets received in this interrupt event. The client can now iterate162+ * through the mmap()'ed DMA buffer according to this number of packets and163+ * to the buffer sizes as the client specified in &fw_cdev_queue_iso.164+ *165+ * Since version 2 of this ABI, the portion for each packet in _interrupt.header166+ * consists of the 1394 isochronous packet header, followed by a timestamp167+ * quadlet if &fw_cdev_create_iso_context.header_size > 4, followed by quadlets168+ * from the packet payload if &fw_cdev_create_iso_context.header_size > 8.169+ *170+ * Format of 1394 iso packet header: 16 bits data_length, 2 bits tag, 6 bits171+ * channel, 4 bits tcode, 4 bits sy, in big endian byte order.172+ * data_length is the actual received size of the packet without the four173+ * 1394 iso packet header bytes.174+ *175+ * Format of timestamp: 16 bits invalid, 3 bits cycleSeconds, 13 bits176+ * cycleCount, in big endian byte order.177+ *178+ * In version 1 of the ABI, no timestamp quadlet was inserted; instead, payload179+ * data followed directly after the 1394 is header if header_size > 4.180 * Behaviour of ver. 1 of this ABI is no longer available since ABI ver. 2.00000181 */182struct fw_cdev_event_iso_interrupt {183 __u64 closure;···168 __u32 cycle;169 __u32 header_length;170 __u32 header[0];171+};172+173+/**174+ * struct fw_cdev_event_iso_interrupt_mc - An iso buffer chunk was completed175+ * @closure: See &fw_cdev_event_common;176+ * set by %FW_CDEV_CREATE_ISO_CONTEXT ioctl177+ * @type: %FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL178+ * @completed: Offset into the receive buffer; data before this offest is valid179+ *180+ * This event is sent in multichannel contexts (context type181+ * %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL) for &fw_cdev_iso_packet buffer182+ * chunks that have the %FW_CDEV_ISO_INTERRUPT bit set. Whether this happens183+ * when a packet is completed and/or when a buffer chunk is completed depends184+ * on the hardware implementation.185+ *186+ * The buffer is continuously filled with the following data, per packet:187+ * - the 1394 iso packet header as described at &fw_cdev_event_iso_interrupt,188+ * but in little endian byte order,189+ * - packet payload (as many bytes as specified in the data_length field of190+ * the 1394 iso packet header) in big endian byte order,191+ * - 0...3 padding bytes as needed to align the following trailer quadlet,192+ * - trailer quadlet, containing the reception timestamp as described at193+ * &fw_cdev_event_iso_interrupt, but in little endian byte order.194+ *195+ * Hence the per-packet size is data_length (rounded up to a multiple of 4) + 8.196+ * When processing the data, stop before a packet that would cross the197+ * @completed offset.198+ *199+ * A packet near the end of a buffer chunk will typically spill over into the200+ * next queued buffer chunk. It is the responsibility of the client to check201+ * for this condition, assemble a broken-up packet from its parts, and not to202+ * re-queue any buffer chunks in which as yet unread packet parts reside.203+ */204+struct fw_cdev_event_iso_interrupt_mc {205+ __u64 closure;206+ __u32 type;207+ __u32 completed;208};209210/**···200};201202/**203+ * struct fw_cdev_event_phy_packet - A PHY packet was transmitted or received204+ * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_SEND_PHY_PACKET205+ * or %FW_CDEV_IOC_RECEIVE_PHY_PACKETS ioctl206+ * @type: %FW_CDEV_EVENT_PHY_PACKET_SENT or %..._RECEIVED207+ * @rcode: %RCODE_..., indicates success or failure of transmission208+ * @length: Data length in bytes209+ * @data: Incoming data210+ *211+ * If @type is %FW_CDEV_EVENT_PHY_PACKET_SENT, @length is 0 and @data empty,212+ * except in case of a ping packet: Then, @length is 4, and @data[0] is the213+ * ping time in 49.152MHz clocks if @rcode is %RCODE_COMPLETE.214+ *215+ * If @type is %FW_CDEV_EVENT_PHY_PACKET_RECEIVED, @length is 8 and @data216+ * consists of the two PHY packet quadlets, in host byte order.217+ */218+struct fw_cdev_event_phy_packet {219+ __u64 closure;220+ __u32 type;221+ __u32 rcode;222+ __u32 length;223+ __u32 data[0];224+};225+226+/**227 * union fw_cdev_event - Convenience union of fw_cdev_event_ types228+ * @common: Valid for all types229+ * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET230+ * @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE231+ * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST232+ * @request2: Valid if @common.type == %FW_CDEV_EVENT_REQUEST2233+ * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT234+ * @iso_interrupt_mc: Valid if @common.type ==235+ * %FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL236+ * @iso_resource: Valid if @common.type ==237 * %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or238 * %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED239+ * @phy_packet: Valid if @common.type ==240+ * %FW_CDEV_EVENT_PHY_PACKET_SENT or241+ * %FW_CDEV_EVENT_PHY_PACKET_RECEIVED242 *243 * Convenience union for userspace use. Events could be read(2) into an244 * appropriately aligned char buffer and then cast to this union for further···223 struct fw_cdev_event_bus_reset bus_reset;224 struct fw_cdev_event_response response;225 struct fw_cdev_event_request request;226+ struct fw_cdev_event_request2 request2; /* added in 2.6.36 */227 struct fw_cdev_event_iso_interrupt iso_interrupt;228+ struct fw_cdev_event_iso_interrupt_mc iso_interrupt_mc; /* added in 2.6.36 */229+ struct fw_cdev_event_iso_resource iso_resource; /* added in 2.6.30 */230+ struct fw_cdev_event_phy_packet phy_packet; /* added in 2.6.36 */231};232233/* available since kernel version 2.6.22 */···256/* available since kernel version 2.6.34 */257#define FW_CDEV_IOC_GET_CYCLE_TIMER2 _IOWR('#', 0x14, struct fw_cdev_get_cycle_timer2)258259+/* available since kernel version 2.6.36 */260+#define FW_CDEV_IOC_SEND_PHY_PACKET _IOWR('#', 0x15, struct fw_cdev_send_phy_packet)261+#define FW_CDEV_IOC_RECEIVE_PHY_PACKETS _IOW('#', 0x16, struct fw_cdev_receive_phy_packets)262+#define FW_CDEV_IOC_SET_ISO_CHANNELS _IOW('#', 0x17, struct fw_cdev_set_iso_channels)263+264/*265+ * ABI version history266 * 1 (2.6.22) - initial version267+ * (2.6.24) - added %FW_CDEV_IOC_GET_CYCLE_TIMER268 * 2 (2.6.30) - changed &fw_cdev_event_iso_interrupt.header if269 * &fw_cdev_create_iso_context.header_size is 8 or more270+ * - added %FW_CDEV_IOC_*_ISO_RESOURCE*,271+ * %FW_CDEV_IOC_GET_SPEED, %FW_CDEV_IOC_SEND_BROADCAST_REQUEST,272+ * %FW_CDEV_IOC_SEND_STREAM_PACKET273 * (2.6.32) - added time stamp to xmit &fw_cdev_event_iso_interrupt274 * (2.6.33) - IR has always packet-per-buffer semantics now, not one of275 * dual-buffer or packet-per-buffer depending on hardware276+ * - shared use and auto-response for FCP registers277 * 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable278+ * - added %FW_CDEV_IOC_GET_CYCLE_TIMER2279+ * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2, %FW_CDEV_EVENT_PHY_PACKET_*,280+ * and &fw_cdev_allocate.region_end281+ * - implemented &fw_cdev_event_bus_reset.bm_node_id282+ * - added %FW_CDEV_IOC_SEND_PHY_PACKET, _RECEIVE_PHY_PACKETS283+ * - added %FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL,284+ * %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL, and285+ * %FW_CDEV_IOC_SET_ISO_CHANNELS286 */287+#define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */288289/**290 * struct fw_cdev_get_info - General purpose information ioctl291+ * @version: The version field is just a running serial number. Both an292+ * input parameter (ABI version implemented by the client) and293+ * output parameter (ABI version implemented by the kernel).294+ * A client must not fill in an %FW_CDEV_VERSION defined from an295+ * included kernel header file but the actual version for which296+ * the client was implemented. This is necessary for forward297+ * compatibility. We never break backwards compatibility, but298+ * may add more structs, events, and ioctls in later revisions.299 * @rom_length: If @rom is non-zero, at most rom_length bytes of configuration300 * ROM will be copied into that user space address. In either301 * case, @rom_length is updated with the actual length of the···339};340341/**342+ * struct fw_cdev_allocate - Allocate a CSR in an address range343 * @offset: Start offset of the address range344 * @closure: To be passed back to userspace in request events345+ * @length: Length of the CSR, in bytes346 * @handle: Handle to the allocation, written by the kernel347+ * @region_end: First address above the address range (added in ABI v4, 2.6.36)348 *349 * Allocate an address range in the 48-bit address space on the local node350 * (the controller). This allows userspace to listen for requests with an351+ * offset within that address range. Every time when the kernel receives a352+ * request within the range, an &fw_cdev_event_request2 event will be emitted.353+ * (If the kernel or the client implements ABI version <= 3, an354+ * &fw_cdev_event_request will be generated instead.)355+ *356+ * The @closure field is passed back to userspace in these request events.357 * The @handle field is an out parameter, returning a handle to the allocated358 * range to be used for later deallocation of the range.359 *360 * The address range is allocated on all local nodes. The address allocation361+ * is exclusive except for the FCP command and response registers. If an362+ * exclusive address region is already in use, the ioctl fails with errno set363+ * to %EBUSY.364+ *365+ * If kernel and client implement ABI version >= 4, the kernel looks up a free366+ * spot of size @length inside [@offset..@region_end) and, if found, writes367+ * the start address of the new CSR back in @offset. I.e. @offset is an368+ * in and out parameter. If this automatic placement of a CSR in a bigger369+ * address range is not desired, the client simply needs to set @region_end370+ * = @offset + @length.371+ *372+ * If the kernel or the client implements ABI version <= 3, @region_end is373+ * ignored and effectively assumed to be @offset + @length.374+ *375+ * @region_end is only present in a kernel header >= 2.6.36. If necessary,376+ * this can for example be tested by #ifdef FW_CDEV_EVENT_REQUEST2.377 */378struct fw_cdev_allocate {379 __u64 offset;380 __u64 closure;381 __u32 length;382 __u32 handle;383+ __u64 region_end; /* available since kernel version 2.6.36 */384};385386/**···382 * Initiate a bus reset for the bus this device is on. The bus reset can be383 * either the original (long) bus reset or the arbitrated (short) bus reset384 * introduced in 1394a-2000.385+ *386+ * The ioctl returns immediately. A subsequent &fw_cdev_event_bus_reset387+ * indicates when the reset actually happened. Since ABI v4, this may be388+ * considerably later than the ioctl because the kernel ensures a grace period389+ * between subsequent bus resets as per IEEE 1394 bus management specification.390 */391struct fw_cdev_initiate_bus_reset {392+ __u32 type;393};394395/**···408 *409 * @immediate, @key, and @data array elements are CPU-endian quadlets.410 *411+ * If successful, the kernel adds the descriptor and writes back a @handle to412+ * the kernel-side object to be used for later removal of the descriptor block413+ * and immediate key. The kernel will also generate a bus reset to signal the414+ * change of the configuration ROM to other nodes.415 *416 * This ioctl affects the configuration ROMs of all local nodes.417 * The ioctl only succeeds on device files which represent a local node.···429 * descriptor was added430 *431 * Remove a descriptor block and accompanying immediate key from the local432+ * nodes' configuration ROMs. The kernel will also generate a bus reset to433+ * signal the change of the configuration ROM to other nodes.434 */435struct fw_cdev_remove_descriptor {436 __u32 handle;437};438439+#define FW_CDEV_ISO_CONTEXT_TRANSMIT 0440+#define FW_CDEV_ISO_CONTEXT_RECEIVE 1441+#define FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL 2 /* added in 2.6.36 */442443/**444+ * struct fw_cdev_create_iso_context - Create a context for isochronous I/O445+ * @type: %FW_CDEV_ISO_CONTEXT_TRANSMIT or %FW_CDEV_ISO_CONTEXT_RECEIVE or446+ * %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL447+ * @header_size: Header size to strip in single-channel reception448+ * @channel: Channel to bind to in single-channel reception or transmission449+ * @speed: Transmission speed450+ * @closure: To be returned in &fw_cdev_event_iso_interrupt or451+ * &fw_cdev_event_iso_interrupt_multichannel452 * @handle: Handle to context, written back by kernel453 *454 * Prior to sending or receiving isochronous I/O, a context must be created.455 * The context records information about the transmit or receive configuration456 * and typically maps to an underlying hardware resource. A context is set up457 * for either sending or receiving. It is bound to a specific isochronous458+ * @channel.459+ *460+ * In case of multichannel reception, @header_size and @channel are ignored461+ * and the channels are selected by %FW_CDEV_IOC_SET_ISO_CHANNELS.462+ *463+ * For %FW_CDEV_ISO_CONTEXT_RECEIVE contexts, @header_size must be at least 4464+ * and must be a multiple of 4. It is ignored in other context types.465+ *466+ * @speed is ignored in receive context types.467 *468 * If a context was successfully created, the kernel writes back a handle to the469 * context, which must be passed in for subsequent operations on that context.470 *471+ * Limitations:472+ * No more than one iso context can be created per fd.473+ * The total number of contexts that all userspace and kernelspace drivers can474+ * create on a card at a time is a hardware limit, typically 4 or 8 contexts per475+ * direction, and of them at most one multichannel receive context.476 */477struct fw_cdev_create_iso_context {478 __u32 type;···468 __u32 channel;469 __u32 speed;470 __u64 closure;471+ __u32 handle;472+};473+474+/**475+ * struct fw_cdev_set_iso_channels - Select channels in multichannel reception476+ * @channels: Bitmask of channels to listen to477+ * @handle: Handle of the mutichannel receive context478+ *479+ * @channels is the bitwise or of 1ULL << n for each channel n to listen to.480+ *481+ * The ioctl fails with errno %EBUSY if there is already another receive context482+ * on a channel in @channels. In that case, the bitmask of all unoccupied483+ * channels is returned in @channels.484+ */485+struct fw_cdev_set_iso_channels {486+ __u64 channels;487 __u32 handle;488};489···481482/**483 * struct fw_cdev_iso_packet - Isochronous packet484+ * @control: Contains the header length (8 uppermost bits),485+ * the sy field (4 bits), the tag field (2 bits), a sync flag486+ * or a skip flag (1 bit), an interrupt flag (1 bit), and the487 * payload length (16 lowermost bits)488+ * @header: Header and payload in case of a transmit context.489 *490 * &struct fw_cdev_iso_packet is used to describe isochronous packet queues.0491 * Use the FW_CDEV_ISO_ macros to fill in @control.492+ * The @header array is empty in case of receive contexts.493 *494+ * Context type %FW_CDEV_ISO_CONTEXT_TRANSMIT:000000495 *496+ * @control.HEADER_LENGTH must be a multiple of 4. It specifies the numbers of497+ * bytes in @header that will be prepended to the packet's payload. These bytes498+ * are copied into the kernel and will not be accessed after the ioctl has499+ * returned.0000000000500 *501+ * The @control.SY and TAG fields are copied to the iso packet header. These502+ * fields are specified by IEEE 1394a and IEC 61883-1.503+ *504+ * The @control.SKIP flag specifies that no packet is to be sent in a frame.505+ * When using this, all other fields except @control.INTERRUPT must be zero.506+ *507+ * When a packet with the @control.INTERRUPT flag set has been completed, an508+ * &fw_cdev_event_iso_interrupt event will be sent.509+ *510+ * Context type %FW_CDEV_ISO_CONTEXT_RECEIVE:511+ *512+ * @control.HEADER_LENGTH must be a multiple of the context's header_size.513+ * If the HEADER_LENGTH is larger than the context's header_size, multiple514+ * packets are queued for this entry.515+ *516+ * The @control.SY and TAG fields are ignored.517+ *518+ * If the @control.SYNC flag is set, the context drops all packets until a519+ * packet with a sy field is received which matches &fw_cdev_start_iso.sync.520+ *521+ * @control.PAYLOAD_LENGTH defines how many payload bytes can be received for522+ * one packet (in addition to payload quadlets that have been defined as headers523+ * and are stripped and returned in the &fw_cdev_event_iso_interrupt structure).524+ * If more bytes are received, the additional bytes are dropped. If less bytes525+ * are received, the remaining bytes in this part of the payload buffer will not526+ * be written to, not even by the next packet. I.e., packets received in527+ * consecutive frames will not necessarily be consecutive in memory. If an528+ * entry has queued multiple packets, the PAYLOAD_LENGTH is divided equally529+ * among them.530+ *531+ * When a packet with the @control.INTERRUPT flag set has been completed, an532 * &fw_cdev_event_iso_interrupt event will be sent. An entry that has queued533 * multiple receive packets is completed when its last packet is completed.534+ *535+ * Context type %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL:536+ *537+ * Here, &fw_cdev_iso_packet would be more aptly named _iso_buffer_chunk since538+ * it specifies a chunk of the mmap()'ed buffer, while the number and alignment539+ * of packets to be placed into the buffer chunk is not known beforehand.540+ *541+ * @control.PAYLOAD_LENGTH is the size of the buffer chunk and specifies room542+ * for header, payload, padding, and trailer bytes of one or more packets.543+ * It must be a multiple of 4.544+ *545+ * @control.HEADER_LENGTH, TAG and SY are ignored. SYNC is treated as described546+ * for single-channel reception.547+ *548+ * When a buffer chunk with the @control.INTERRUPT flag set has been filled549+ * entirely, an &fw_cdev_event_iso_interrupt_mc event will be sent.550 */551struct fw_cdev_iso_packet {552 __u32 control;···525526/**527 * struct fw_cdev_queue_iso - Queue isochronous packets for I/O528+ * @packets: Userspace pointer to an array of &fw_cdev_iso_packet529 * @data: Pointer into mmap()'ed payload buffer530+ * @size: Size of the @packets array, in bytes531 * @handle: Isochronous context handle532 *533 * Queue a number of isochronous packets for reception or transmission.···540 * The kernel may or may not queue all packets, but will write back updated541 * values of the @packets, @data and @size fields, so the ioctl can be542 * resubmitted easily.543+ *544+ * In case of a multichannel receive context, @data must be quadlet-aligned545+ * relative to the buffer start.546 */547struct fw_cdev_queue_iso {548 __u64 packets;···696 __u64 data;697 __u32 generation;698 __u32 speed;699+};700+701+/**702+ * struct fw_cdev_send_phy_packet - send a PHY packet703+ * @closure: Passed back to userspace in the PHY-packet-sent event704+ * @data: First and second quadlet of the PHY packet705+ * @generation: The bus generation where packet is valid706+ *707+ * The %FW_CDEV_IOC_SEND_PHY_PACKET ioctl sends a PHY packet to all nodes708+ * on the same card as this device. After transmission, an709+ * %FW_CDEV_EVENT_PHY_PACKET_SENT event is generated.710+ *711+ * The payload @data[] shall be specified in host byte order. Usually,712+ * @data[1] needs to be the bitwise inverse of @data[0]. VersaPHY packets713+ * are an exception to this rule.714+ *715+ * The ioctl is only permitted on device files which represent a local node.716+ */717+struct fw_cdev_send_phy_packet {718+ __u64 closure;719+ __u32 data[2];720+ __u32 generation;721+};722+723+/**724+ * struct fw_cdev_receive_phy_packets - start reception of PHY packets725+ * @closure: Passed back to userspace in phy packet events726+ *727+ * This ioctl activates issuing of %FW_CDEV_EVENT_PHY_PACKET_RECEIVED due to728+ * incoming PHY packets from any node on the same bus as the device.729+ *730+ * The ioctl is only permitted on device files which represent a local node.731+ */732+struct fw_cdev_receive_phy_packets {733+ __u64 closure;734};735736#endif /* _LINUX_FIREWIRE_CDEV_H */
+44-18
include/linux/firewire.h
···32#define CSR_CYCLE_TIME 0x20033#define CSR_BUS_TIME 0x20434#define CSR_BUSY_TIMEOUT 0x210035#define CSR_BUS_MANAGER_ID 0x21c36#define CSR_BANDWIDTH_AVAILABLE 0x22037#define CSR_CHANNELS_AVAILABLE 0x22438#define CSR_CHANNELS_AVAILABLE_HI 0x22439#define CSR_CHANNELS_AVAILABLE_LO 0x228040#define CSR_BROADCAST_CHANNEL 0x23441#define CSR_CONFIG_ROM 0x40042#define CSR_CONFIG_ROM_END 0x800···91 struct list_head transaction_list;92 unsigned long reset_jiffies;930000094 unsigned long long guid;95 unsigned max_receive;96 int link_speed;···111 bool beta_repeaters_present;112113 int index;114-115 struct list_head link;116117- /* Work struct for BM duties. */118- struct delayed_work work;0000119 int bm_retries;120 int bm_generation;121 __be32 bm_transaction_data[2];00000122123 bool broadcast_channel_allocated;124 u32 broadcast_channel;125 __be32 topology_map[(CSR_TOPOLOGY_MAP_END - CSR_TOPOLOGY_MAP) / 4];00126};127128struct fw_attribute_group {···269typedef void (*fw_address_callback_t)(struct fw_card *card,270 struct fw_request *request,271 int tcode, int destination, int source,272- int generation, int speed,273 unsigned long long offset,274 void *data, size_t length,275 void *callback_data);···286 u32 timestamp;287288 /*289- * This callback is called when the packet transmission has290- * completed; for successful transmission, the status code is291- * the ack received from the destination, otherwise it's a292- * negative errno: ENOMEM, ESTALE, ETIMEDOUT, ENODEV, EIO.293 * The callback can be called from tasklet context and thus294 * must never block.295 */···372 * scatter-gather streaming (e.g. assembling video frame automatically).373 */374struct fw_iso_packet {375- u16 payload_length; /* Length of indirect payload. */376- u32 interrupt:1; /* Generate interrupt on this packet */377- u32 skip:1; /* Set to not send packet at all. */378- u32 tag:2;379- u32 sy:4;380- u32 header_length:8; /* Length of immediate header. */381- u32 header[0];0382};383384-#define FW_ISO_CONTEXT_TRANSMIT 0385-#define FW_ISO_CONTEXT_RECEIVE 10386387#define FW_ISO_CONTEXT_MATCH_TAG0 1388#define FW_ISO_CONTEXT_MATCH_TAG1 2···408int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card,409 int page_count, enum dma_data_direction direction);410void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card);0411412struct fw_iso_context;413typedef void (*fw_iso_callback_t)(struct fw_iso_context *context,414 u32 cycle, size_t header_length,415 void *header, void *data);00416struct fw_iso_context {417 struct fw_card *card;418 int type;419 int channel;420 int speed;421 size_t header_size;422- fw_iso_callback_t callback;000423 void *callback_data;424};425426struct fw_iso_context *fw_iso_context_create(struct fw_card *card,427 int type, int channel, int speed, size_t header_size,428 fw_iso_callback_t callback, void *callback_data);0429int fw_iso_context_queue(struct fw_iso_context *ctx,430 struct fw_iso_packet *packet,431 struct fw_iso_buffer *buffer,
···32#define CSR_CYCLE_TIME 0x20033#define CSR_BUS_TIME 0x20434#define CSR_BUSY_TIMEOUT 0x21035+#define CSR_PRIORITY_BUDGET 0x21836#define CSR_BUS_MANAGER_ID 0x21c37#define CSR_BANDWIDTH_AVAILABLE 0x22038#define CSR_CHANNELS_AVAILABLE 0x22439#define CSR_CHANNELS_AVAILABLE_HI 0x22440#define CSR_CHANNELS_AVAILABLE_LO 0x22841+#define CSR_MAINT_UTILITY 0x23042#define CSR_BROADCAST_CHANNEL 0x23443#define CSR_CONFIG_ROM 0x40044#define CSR_CONFIG_ROM_END 0x800···89 struct list_head transaction_list;90 unsigned long reset_jiffies;9192+ u32 split_timeout_hi;93+ u32 split_timeout_lo;94+ unsigned int split_timeout_cycles;95+ unsigned int split_timeout_jiffies;96+97 unsigned long long guid;98 unsigned max_receive;99 int link_speed;···104 bool beta_repeaters_present;105106 int index;0107 struct list_head link;108109+ struct list_head phy_receiver_list;110+111+ struct delayed_work br_work; /* bus reset job */112+ bool br_short;113+114+ struct delayed_work bm_work; /* bus manager job */115 int bm_retries;116 int bm_generation;117 __be32 bm_transaction_data[2];118+ int bm_node_id;119+ bool bm_abdicate;120+121+ bool priority_budget_implemented; /* controller feature */122+ bool broadcast_channel_auto_allocated; /* controller feature */123124 bool broadcast_channel_allocated;125 u32 broadcast_channel;126 __be32 topology_map[(CSR_TOPOLOGY_MAP_END - CSR_TOPOLOGY_MAP) / 4];127+128+ __be32 maint_utility_register;129};130131struct fw_attribute_group {···252typedef void (*fw_address_callback_t)(struct fw_card *card,253 struct fw_request *request,254 int tcode, int destination, int source,255+ int generation,256 unsigned long long offset,257 void *data, size_t length,258 void *callback_data);···269 u32 timestamp;270271 /*272+ * This callback is called when the packet transmission has completed.273+ * For successful transmission, the status code is the ack received274+ * from the destination. Otherwise it is one of the juju-specific275+ * rcodes: RCODE_SEND_ERROR, _CANCELLED, _BUSY, _GENERATION, _NO_ACK.276 * The callback can be called from tasklet context and thus277 * must never block.278 */···355 * scatter-gather streaming (e.g. assembling video frame automatically).356 */357struct fw_iso_packet {358+ u16 payload_length; /* Length of indirect payload */359+ u32 interrupt:1; /* Generate interrupt on this packet */360+ u32 skip:1; /* tx: Set to not send packet at all */361+ /* rx: Sync bit, wait for matching sy */362+ u32 tag:2; /* tx: Tag in packet header */363+ u32 sy:4; /* tx: Sy in packet header */364+ u32 header_length:8; /* Length of immediate header */365+ u32 header[0]; /* tx: Top of 1394 isoch. data_block */366};367368+#define FW_ISO_CONTEXT_TRANSMIT 0369+#define FW_ISO_CONTEXT_RECEIVE 1370+#define FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL 2371372#define FW_ISO_CONTEXT_MATCH_TAG0 1373#define FW_ISO_CONTEXT_MATCH_TAG1 2···389int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card,390 int page_count, enum dma_data_direction direction);391void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card);392+size_t fw_iso_buffer_lookup(struct fw_iso_buffer *buffer, dma_addr_t completed);393394struct fw_iso_context;395typedef void (*fw_iso_callback_t)(struct fw_iso_context *context,396 u32 cycle, size_t header_length,397 void *header, void *data);398+typedef void (*fw_iso_mc_callback_t)(struct fw_iso_context *context,399+ dma_addr_t completed, void *data);400struct fw_iso_context {401 struct fw_card *card;402 int type;403 int channel;404 int speed;405 size_t header_size;406+ union {407+ fw_iso_callback_t sc;408+ fw_iso_mc_callback_t mc;409+ } callback;410 void *callback_data;411};412413struct fw_iso_context *fw_iso_context_create(struct fw_card *card,414 int type, int channel, int speed, size_t header_size,415 fw_iso_callback_t callback, void *callback_data);416+int fw_iso_context_set_channels(struct fw_iso_context *ctx, u64 *channels);417int fw_iso_context_queue(struct fw_iso_context *ctx,418 struct fw_iso_packet *packet,419 struct fw_iso_buffer *buffer,