···66666767source "drivers/ieee1394/Kconfig"68686969+config FIREWIRE_NOSY7070+ tristate "Nosy - a FireWire traffic sniffer for PCILynx cards"7171+ depends on PCI7272+ help7373+ Nosy is an IEEE 1394 packet sniffer that is used for protocol7474+ analysis and in development of IEEE 1394 drivers, applications,7575+ or firmwares.7676+7777+ This driver lets you use a Texas Instruments PCILynx 1394 to PCI7878+ link layer controller TSB12LV21/A/B as a low-budget bus analyzer.7979+ PCILynx is a nowadays very rare IEEE 1394 controller which is8080+ not OHCI 1394 compliant.8181+8282+ The following cards are known to be based on PCILynx or PCILynx-2:8383+ IOI IOI-1394TT (PCI card), Unibrain Fireboard 400 PCI Lynx-28484+ (PCI card), Newer Technology FireWire 2 Go (CardBus card),8585+ Apple Power Mac G3 blue & white (onboard controller).8686+8787+ To compile this driver as a module, say M here: The module will be8888+ called nosy. Source code of a userspace interface to nosy, called8989+ nosy-dump, can be found in tools/firewire/ of the kernel sources.9090+9191+ If unsure, say N.9292+6993endmenu
···204204}205205EXPORT_SYMBOL(fw_core_remove_descriptor);206206207207+static int reset_bus(struct fw_card *card, bool short_reset)208208+{209209+ int reg = short_reset ? 5 : 1;210210+ int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET;211211+212212+ return card->driver->update_phy_reg(card, reg, 0, bit);213213+}214214+215215+void fw_schedule_bus_reset(struct fw_card *card, bool delayed, bool short_reset)216216+{217217+ /* We don't try hard to sort out requests of long vs. short resets. */218218+ card->br_short = short_reset;219219+220220+ /* Use an arbitrary short delay to combine multiple reset requests. */221221+ fw_card_get(card);222222+ if (!schedule_delayed_work(&card->br_work,223223+ delayed ? DIV_ROUND_UP(HZ, 100) : 0))224224+ fw_card_put(card);225225+}226226+EXPORT_SYMBOL(fw_schedule_bus_reset);227227+228228+static void br_work(struct work_struct *work)229229+{230230+ struct fw_card *card = container_of(work, struct fw_card, br_work.work);231231+232232+ /* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */233233+ if (card->reset_jiffies != 0 &&234234+ time_is_after_jiffies(card->reset_jiffies + 2 * HZ)) {235235+ if (!schedule_delayed_work(&card->br_work, 2 * HZ))236236+ fw_card_put(card);237237+ return;238238+ }239239+240240+ fw_send_phy_config(card, FW_PHY_CONFIG_NO_NODE_ID, card->generation,241241+ FW_PHY_CONFIG_CURRENT_GAP_COUNT);242242+ reset_bus(card, card->br_short);243243+ fw_card_put(card);244244+}245245+207246static void allocate_broadcast_channel(struct fw_card *card, int generation)208247{209248 int channel, bandwidth = 0;210249211211- fw_iso_resource_manage(card, generation, 1ULL << 31, &channel,212212- &bandwidth, true, card->bm_transaction_data);213213- if (channel == 31) {250250+ if (!card->broadcast_channel_allocated) {251251+ fw_iso_resource_manage(card, generation, 1ULL << 31,252252+ &channel, &bandwidth, true,253253+ card->bm_transaction_data);254254+ if (channel != 31) {255255+ fw_notify("failed to allocate broadcast channel\n");256256+ return;257257+ }214258 card->broadcast_channel_allocated = true;215215- device_for_each_child(card->device, (void *)(long)generation,216216- fw_device_set_broadcast_channel);217259 }260260+261261+ device_for_each_child(card->device, (void *)(long)generation,262262+ fw_device_set_broadcast_channel);218263}219264220265static const char gap_count_table[] = {···269224void fw_schedule_bm_work(struct fw_card *card, unsigned long delay)270225{271226 fw_card_get(card);272272- if (!schedule_delayed_work(&card->work, delay))227227+ if (!schedule_delayed_work(&card->bm_work, delay))273228 fw_card_put(card);274229}275230276276-static void fw_card_bm_work(struct work_struct *work)231231+static void bm_work(struct work_struct *work)277232{278278- struct fw_card *card = container_of(work, struct fw_card, work.work);233233+ struct fw_card *card = container_of(work, struct fw_card, bm_work.work);279234 struct fw_device *root_device, *irm_device;280235 struct fw_node *root_node;281281- unsigned long flags;282282- int root_id, new_root_id, irm_id, local_id;236236+ int root_id, new_root_id, irm_id, bm_id, local_id;283237 int gap_count, generation, grace, rcode;284238 bool do_reset = false;285239 bool root_device_is_running;286240 bool root_device_is_cmc;287241 bool irm_is_1394_1995_only;288242289289- spin_lock_irqsave(&card->lock, flags);243243+ spin_lock_irq(&card->lock);290244291245 if (card->local_node == NULL) {292292- spin_unlock_irqrestore(&card->lock, flags);246246+ spin_unlock_irq(&card->lock);293247 goto out_put_card;294248 }295249···311267312268 grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 8));313269314314- if (is_next_generation(generation, card->bm_generation) ||270270+ if ((is_next_generation(generation, card->bm_generation) &&271271+ !card->bm_abdicate) ||315272 (card->bm_generation != generation && grace)) {316273 /*317274 * This first step is to figure out who is IRM and···343298 card->bm_transaction_data[0] = cpu_to_be32(0x3f);344299 card->bm_transaction_data[1] = cpu_to_be32(local_id);345300346346- spin_unlock_irqrestore(&card->lock, flags);301301+ spin_unlock_irq(&card->lock);347302348303 rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,349304 irm_id, generation, SCODE_100,350305 CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,351351- card->bm_transaction_data,352352- sizeof(card->bm_transaction_data));306306+ card->bm_transaction_data, 8);353307354308 if (rcode == RCODE_GENERATION)355309 /* Another bus reset, BM work has been rescheduled. */356310 goto out;357311358358- if (rcode == RCODE_COMPLETE &&359359- card->bm_transaction_data[0] != cpu_to_be32(0x3f)) {312312+ bm_id = be32_to_cpu(card->bm_transaction_data[0]);360313314314+ spin_lock_irq(&card->lock);315315+ if (rcode == RCODE_COMPLETE && generation == card->generation)316316+ card->bm_node_id =317317+ bm_id == 0x3f ? local_id : 0xffc0 | bm_id;318318+ spin_unlock_irq(&card->lock);319319+320320+ if (rcode == RCODE_COMPLETE && bm_id != 0x3f) {361321 /* Somebody else is BM. Only act as IRM. */362322 if (local_id == irm_id)363323 allocate_broadcast_channel(card, generation);···370320 goto out;371321 }372322373373- spin_lock_irqsave(&card->lock, flags);323323+ if (rcode == RCODE_SEND_ERROR) {324324+ /*325325+ * We have been unable to send the lock request due to326326+ * some local problem. Let's try again later and hope327327+ * that the problem has gone away by then.328328+ */329329+ fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 8));330330+ goto out;331331+ }332332+333333+ spin_lock_irq(&card->lock);374334375335 if (rcode != RCODE_COMPLETE) {376336 /*···399339 * We weren't BM in the last generation, and the last400340 * bus reset is less than 125ms ago. Reschedule this job.401341 */402402- spin_unlock_irqrestore(&card->lock, flags);342342+ spin_unlock_irq(&card->lock);403343 fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 8));404344 goto out;405345 }···422362 * If we haven't probed this device yet, bail out now423363 * and let's try again once that's done.424364 */425425- spin_unlock_irqrestore(&card->lock, flags);365365+ spin_unlock_irq(&card->lock);426366 goto out;427367 } else if (root_device_is_cmc) {428368 /*429429- * FIXME: I suppose we should set the cmstr bit in the430430- * STATE_CLEAR register of this node, as described in431431- * 1394-1995, 8.4.2.6. Also, send out a force root432432- * packet for this node.369369+ * We will send out a force root packet for this370370+ * node as part of the gap count optimization.433371 */434372 new_root_id = root_id;435373 } else {···460402 (card->gap_count != gap_count || new_root_id != root_id))461403 do_reset = true;462404463463- spin_unlock_irqrestore(&card->lock, flags);405405+ spin_unlock_irq(&card->lock);464406465407 if (do_reset) {466408 fw_notify("phy config: card %d, new root=%x, gap_count=%d\n",467409 card->index, new_root_id, gap_count);468410 fw_send_phy_config(card, new_root_id, generation, gap_count);469469- fw_core_initiate_bus_reset(card, 1);411411+ reset_bus(card, true);470412 /* Will allocate broadcast channel after the reset. */471471- } else {472472- if (local_id == irm_id)473473- allocate_broadcast_channel(card, generation);413413+ goto out;474414 }415415+416416+ if (root_device_is_cmc) {417417+ /*418418+ * Make sure that the cycle master sends cycle start packets.419419+ */420420+ card->bm_transaction_data[0] = cpu_to_be32(CSR_STATE_BIT_CMSTR);421421+ rcode = fw_run_transaction(card, TCODE_WRITE_QUADLET_REQUEST,422422+ root_id, generation, SCODE_100,423423+ CSR_REGISTER_BASE + CSR_STATE_SET,424424+ card->bm_transaction_data, 4);425425+ if (rcode == RCODE_GENERATION)426426+ goto out;427427+ }428428+429429+ if (local_id == irm_id)430430+ allocate_broadcast_channel(card, generation);475431476432 out:477433 fw_node_put(root_node);···504432 card->device = device;505433 card->current_tlabel = 0;506434 card->tlabel_mask = 0;435435+ card->split_timeout_hi = 0;436436+ card->split_timeout_lo = 800 << 19;437437+ card->split_timeout_cycles = 800;438438+ card->split_timeout_jiffies = DIV_ROUND_UP(HZ, 10);507439 card->color = 0;508440 card->broadcast_channel = BROADCAST_CHANNEL_INITIAL;509441510442 kref_init(&card->kref);511443 init_completion(&card->done);512444 INIT_LIST_HEAD(&card->transaction_list);445445+ INIT_LIST_HEAD(&card->phy_receiver_list);513446 spin_lock_init(&card->lock);514447515448 card->local_node = NULL;516449517517- INIT_DELAYED_WORK(&card->work, fw_card_bm_work);450450+ INIT_DELAYED_WORK(&card->br_work, br_work);451451+ INIT_DELAYED_WORK(&card->bm_work, bm_work);518452}519453EXPORT_SYMBOL(fw_card_initialize);520454···546468}547469EXPORT_SYMBOL(fw_card_add);548470549549-550471/*551472 * The next few functions implement a dummy driver that is used once a card552473 * driver shuts down an fw_card. This allows the driver to cleanly unload,553474 * as all IO to the card will be handled (and failed) by the dummy driver554475 * instead of calling into the module. Only functions for iso context555476 * shutdown still need to be provided by the card driver.477477+ *478478+ * .read/write_csr() should never be called anymore after the dummy driver479479+ * was bound since they are only used within request handler context.480480+ * .set_config_rom() is never called since the card is taken out of card_list481481+ * before switching to the dummy driver.556482 */557483558558-static int dummy_enable(struct fw_card *card,559559- const __be32 *config_rom, size_t length)484484+static int dummy_read_phy_reg(struct fw_card *card, int address)560485{561561- BUG();562562- return -1;486486+ return -ENODEV;563487}564488565489static int dummy_update_phy_reg(struct fw_card *card, int address,···570490 return -ENODEV;571491}572492573573-static int dummy_set_config_rom(struct fw_card *card,574574- const __be32 *config_rom, size_t length)575575-{576576- /*577577- * We take the card out of card_list before setting the dummy578578- * driver, so this should never get called.579579- */580580- BUG();581581- return -1;582582-}583583-584493static void dummy_send_request(struct fw_card *card, struct fw_packet *packet)585494{586586- packet->callback(packet, card, -ENODEV);495495+ packet->callback(packet, card, RCODE_CANCELLED);587496}588497589498static void dummy_send_response(struct fw_card *card, struct fw_packet *packet)590499{591591- packet->callback(packet, card, -ENODEV);500500+ packet->callback(packet, card, RCODE_CANCELLED);592501}593502594503static int dummy_cancel_packet(struct fw_card *card, struct fw_packet *packet)···591522 return -ENODEV;592523}593524525525+static struct fw_iso_context *dummy_allocate_iso_context(struct fw_card *card,526526+ int type, int channel, size_t header_size)527527+{528528+ return ERR_PTR(-ENODEV);529529+}530530+531531+static int dummy_start_iso(struct fw_iso_context *ctx,532532+ s32 cycle, u32 sync, u32 tags)533533+{534534+ return -ENODEV;535535+}536536+537537+static int dummy_set_iso_channels(struct fw_iso_context *ctx, u64 *channels)538538+{539539+ return -ENODEV;540540+}541541+542542+static int dummy_queue_iso(struct fw_iso_context *ctx, struct fw_iso_packet *p,543543+ struct fw_iso_buffer *buffer, unsigned long payload)544544+{545545+ return -ENODEV;546546+}547547+594548static const struct fw_card_driver dummy_driver_template = {595595- .enable = dummy_enable,596596- .update_phy_reg = dummy_update_phy_reg,597597- .set_config_rom = dummy_set_config_rom,598598- .send_request = dummy_send_request,599599- .cancel_packet = dummy_cancel_packet,600600- .send_response = dummy_send_response,601601- .enable_phys_dma = dummy_enable_phys_dma,549549+ .read_phy_reg = dummy_read_phy_reg,550550+ .update_phy_reg = dummy_update_phy_reg,551551+ .send_request = dummy_send_request,552552+ .send_response = dummy_send_response,553553+ .cancel_packet = dummy_cancel_packet,554554+ .enable_phys_dma = dummy_enable_phys_dma,555555+ .allocate_iso_context = dummy_allocate_iso_context,556556+ .start_iso = dummy_start_iso,557557+ .set_iso_channels = dummy_set_iso_channels,558558+ .queue_iso = dummy_queue_iso,602559};603560604561void fw_card_release(struct kref *kref)···640545641546 card->driver->update_phy_reg(card, 4,642547 PHY_LINK_ACTIVE | PHY_CONTENDER, 0);643643- fw_core_initiate_bus_reset(card, 1);548548+ fw_schedule_bus_reset(card, false, true);644549645550 mutex_lock(&card_mutex);646551 list_del_init(&card->link);···660565 WARN_ON(!list_empty(&card->transaction_list));661566}662567EXPORT_SYMBOL(fw_core_remove_card);663663-664664-int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset)665665-{666666- int reg = short_reset ? 5 : 1;667667- int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET;668668-669669- return card->driver->update_phy_reg(card, reg, 0, bit);670670-}671671-EXPORT_SYMBOL(fw_core_initiate_bus_reset);
+327-82
drivers/firewire/core-cdev.c
···1818 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.1919 */20202121+#include <linux/bug.h>2122#include <linux/compat.h>2223#include <linux/delay.h>2324#include <linux/device.h>···3433#include <linux/module.h>3534#include <linux/mutex.h>3635#include <linux/poll.h>3737-#include <linux/sched.h>3636+#include <linux/sched.h> /* required for linux/wait.h */3837#include <linux/slab.h>3938#include <linux/spinlock.h>4039#include <linux/string.h>···4746#include <asm/system.h>48474948#include "core.h"4949+5050+/*5151+ * ABI version history is documented in linux/firewire-cdev.h.5252+ */5353+#define FW_CDEV_KERNEL_VERSION 45454+#define FW_CDEV_VERSION_EVENT_REQUEST2 45555+#define FW_CDEV_VERSION_ALLOCATE_REGION_END 450565157struct client {5258 u32 version;···7062 u64 iso_closure;7163 struct fw_iso_buffer buffer;7264 unsigned long vm_start;6565+6666+ struct list_head phy_receiver_link;6767+ u64 phy_receiver_closure;73687469 struct list_head link;7570 struct kref kref;···118107119108struct inbound_transaction_resource {120109 struct client_resource resource;110110+ struct fw_card *card;121111 struct fw_request *request;122112 void *data;123113 size_t length;···183171184172struct inbound_transaction_event {185173 struct event event;186186- struct fw_cdev_event_request request;174174+ union {175175+ struct fw_cdev_event_request request;176176+ struct fw_cdev_event_request2 request2;177177+ } req;187178};188179189180struct iso_interrupt_event {···194179 struct fw_cdev_event_iso_interrupt interrupt;195180};196181182182+struct iso_interrupt_mc_event {183183+ struct event event;184184+ struct fw_cdev_event_iso_interrupt_mc interrupt;185185+};186186+197187struct iso_resource_event {198188 struct event event;199189 struct fw_cdev_event_iso_resource iso_resource;190190+};191191+192192+struct outbound_phy_packet_event {193193+ struct event event;194194+ struct client *client;195195+ struct fw_packet p;196196+ struct fw_cdev_event_phy_packet phy_packet;197197+};198198+199199+struct inbound_phy_packet_event {200200+ struct event event;201201+ struct fw_cdev_event_phy_packet phy_packet;200202};201203202204static inline void __user *u64_to_uptr(__u64 value)···251219 idr_init(&client->resource_idr);252220 INIT_LIST_HEAD(&client->event_list);253221 init_waitqueue_head(&client->wait);222222+ INIT_LIST_HEAD(&client->phy_receiver_link);254223 kref_init(&client->kref);255224256225 file->private_data = client;···342309 event->generation = client->device->generation;343310 event->node_id = client->device->node_id;344311 event->local_node_id = card->local_node->node_id;345345- event->bm_node_id = 0; /* FIXME: We don't track the BM. */312312+ event->bm_node_id = card->bm_node_id;346313 event->irm_node_id = card->irm_node->node_id;347314 event->root_node_id = card->root_node->node_id;348315···373340374341 e = kzalloc(sizeof(*e), GFP_KERNEL);375342 if (e == NULL) {376376- fw_notify("Out of memory when allocating bus reset event\n");343343+ fw_notify("Out of memory when allocating event\n");377344 return;378345 }379346···419386 struct fw_cdev_allocate_iso_resource allocate_iso_resource;420387 struct fw_cdev_send_stream_packet send_stream_packet;421388 struct fw_cdev_get_cycle_timer2 get_cycle_timer2;389389+ struct fw_cdev_send_phy_packet send_phy_packet;390390+ struct fw_cdev_receive_phy_packets receive_phy_packets;391391+ struct fw_cdev_set_iso_channels set_iso_channels;422392};423393424394static int ioctl_get_info(struct client *client, union ioctl_arg *arg)···431395 unsigned long ret = 0;432396433397 client->version = a->version;434434- a->version = FW_CDEV_VERSION;398398+ a->version = FW_CDEV_KERNEL_VERSION;435399 a->card = client->device->card->index;436400437401 down_read(&fw_device_rwsem);···590554 (request->length > 4096 || request->length > 512 << speed))591555 return -EIO;592556557557+ if (request->tcode == TCODE_WRITE_QUADLET_REQUEST &&558558+ request->length < 4)559559+ return -EINVAL;560560+593561 e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL);594562 if (e == NULL)595563 return -ENOMEM;···666626 if (is_fcp_request(r->request))667627 kfree(r->data);668628 else669669- fw_send_response(client->device->card, r->request,670670- RCODE_CONFLICT_ERROR);629629+ fw_send_response(r->card, r->request, RCODE_CONFLICT_ERROR);630630+631631+ fw_card_put(r->card);671632 kfree(r);672633}673634674635static void handle_request(struct fw_card *card, struct fw_request *request,675636 int tcode, int destination, int source,676676- int generation, int speed,677677- unsigned long long offset,637637+ int generation, unsigned long long offset,678638 void *payload, size_t length, void *callback_data)679639{680640 struct address_handler_resource *handler = callback_data;681641 struct inbound_transaction_resource *r;682642 struct inbound_transaction_event *e;643643+ size_t event_size0;683644 void *fcp_frame = NULL;684645 int ret;685646647647+ /* card may be different from handler->client->device->card */648648+ fw_card_get(card);649649+686650 r = kmalloc(sizeof(*r), GFP_ATOMIC);687651 e = kmalloc(sizeof(*e), GFP_ATOMIC);688688- if (r == NULL || e == NULL)652652+ if (r == NULL || e == NULL) {653653+ fw_notify("Out of memory when allocating event\n");689654 goto failed;690690-655655+ }656656+ r->card = card;691657 r->request = request;692658 r->data = payload;693659 r->length = length;···715669 if (ret < 0)716670 goto failed;717671718718- e->request.type = FW_CDEV_EVENT_REQUEST;719719- e->request.tcode = tcode;720720- e->request.offset = offset;721721- e->request.length = length;722722- e->request.handle = r->resource.handle;723723- e->request.closure = handler->closure;672672+ if (handler->client->version < FW_CDEV_VERSION_EVENT_REQUEST2) {673673+ struct fw_cdev_event_request *req = &e->req.request;674674+675675+ if (tcode & 0x10)676676+ tcode = TCODE_LOCK_REQUEST;677677+678678+ req->type = FW_CDEV_EVENT_REQUEST;679679+ req->tcode = tcode;680680+ req->offset = offset;681681+ req->length = length;682682+ req->handle = r->resource.handle;683683+ req->closure = handler->closure;684684+ event_size0 = sizeof(*req);685685+ } else {686686+ struct fw_cdev_event_request2 *req = &e->req.request2;687687+688688+ req->type = FW_CDEV_EVENT_REQUEST2;689689+ req->tcode = tcode;690690+ req->offset = offset;691691+ req->source_node_id = source;692692+ req->destination_node_id = destination;693693+ req->card = card->index;694694+ req->generation = generation;695695+ req->length = length;696696+ req->handle = r->resource.handle;697697+ req->closure = handler->closure;698698+ event_size0 = sizeof(*req);699699+ }724700725701 queue_event(handler->client, &e->event,726726- &e->request, sizeof(e->request), r->data, length);702702+ &e->req, event_size0, r->data, length);727703 return;728704729705 failed:···755687756688 if (!is_fcp_request(request))757689 fw_send_response(card, request, RCODE_CONFLICT_ERROR);690690+691691+ fw_card_put(card);758692}759693760694static void release_address_handler(struct client *client,···781711 return -ENOMEM;782712783713 region.start = a->offset;784784- region.end = a->offset + a->length;714714+ if (client->version < FW_CDEV_VERSION_ALLOCATE_REGION_END)715715+ region.end = a->offset + a->length;716716+ else717717+ region.end = a->region_end;718718+785719 r->handler.length = a->length;786720 r->handler.address_callback = handle_request;787721 r->handler.callback_data = r;···797723 kfree(r);798724 return ret;799725 }726726+ a->offset = r->handler.offset;800727801728 r->resource.release = release_address_handler;802729 ret = add_client_resource(client, &r->resource, GFP_KERNEL);···832757 if (is_fcp_request(r->request))833758 goto out;834759835835- if (a->length < r->length)836836- r->length = a->length;837837- if (copy_from_user(r->data, u64_to_uptr(a->data), r->length)) {760760+ if (a->length != fw_get_response_length(r->request)) {761761+ ret = -EINVAL;762762+ kfree(r->request);763763+ goto out;764764+ }765765+ if (copy_from_user(r->data, u64_to_uptr(a->data), a->length)) {838766 ret = -EFAULT;839767 kfree(r->request);840768 goto out;841769 }842842- fw_send_response(client->device->card, r->request, a->rcode);770770+ fw_send_response(r->card, r->request, a->rcode);843771 out:772772+ fw_card_put(r->card);844773 kfree(r);845774846775 return ret;···852773853774static int ioctl_initiate_bus_reset(struct client *client, union ioctl_arg *arg)854775{855855- return fw_core_initiate_bus_reset(client->device->card,776776+ fw_schedule_bus_reset(client->device->card, true,856777 arg->initiate_bus_reset.type == FW_CDEV_SHORT_RESET);778778+ return 0;857779}858780859781static void release_descriptor(struct client *client,···925845 struct client *client = data;926846 struct iso_interrupt_event *e;927847928928- e = kzalloc(sizeof(*e) + header_length, GFP_ATOMIC);929929- if (e == NULL)848848+ e = kmalloc(sizeof(*e) + header_length, GFP_ATOMIC);849849+ if (e == NULL) {850850+ fw_notify("Out of memory when allocating event\n");930851 return;931931-852852+ }932853 e->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT;933854 e->interrupt.closure = client->iso_closure;934855 e->interrupt.cycle = cycle;···939858 sizeof(e->interrupt) + header_length, NULL, 0);940859}941860861861+static void iso_mc_callback(struct fw_iso_context *context,862862+ dma_addr_t completed, void *data)863863+{864864+ struct client *client = data;865865+ struct iso_interrupt_mc_event *e;866866+867867+ e = kmalloc(sizeof(*e), GFP_ATOMIC);868868+ if (e == NULL) {869869+ fw_notify("Out of memory when allocating event\n");870870+ return;871871+ }872872+ e->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL;873873+ e->interrupt.closure = client->iso_closure;874874+ e->interrupt.completed = fw_iso_buffer_lookup(&client->buffer,875875+ completed);876876+ queue_event(client, &e->event, &e->interrupt,877877+ sizeof(e->interrupt), NULL, 0);878878+}879879+942880static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg)943881{944882 struct fw_cdev_create_iso_context *a = &arg->create_iso_context;945883 struct fw_iso_context *context;884884+ fw_iso_callback_t cb;946885947947- /* We only support one context at this time. */948948- if (client->iso_context != NULL)949949- return -EBUSY;950950-951951- if (a->channel > 63)952952- return -EINVAL;886886+ BUILD_BUG_ON(FW_CDEV_ISO_CONTEXT_TRANSMIT != FW_ISO_CONTEXT_TRANSMIT ||887887+ FW_CDEV_ISO_CONTEXT_RECEIVE != FW_ISO_CONTEXT_RECEIVE ||888888+ FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL !=889889+ FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL);953890954891 switch (a->type) {955955- case FW_ISO_CONTEXT_RECEIVE:956956- if (a->header_size < 4 || (a->header_size & 3))892892+ case FW_ISO_CONTEXT_TRANSMIT:893893+ if (a->speed > SCODE_3200 || a->channel > 63)957894 return -EINVAL;895895+896896+ cb = iso_callback;958897 break;959898960960- case FW_ISO_CONTEXT_TRANSMIT:961961- if (a->speed > SCODE_3200)899899+ case FW_ISO_CONTEXT_RECEIVE:900900+ if (a->header_size < 4 || (a->header_size & 3) ||901901+ a->channel > 63)962902 return -EINVAL;903903+904904+ cb = iso_callback;905905+ break;906906+907907+ case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:908908+ cb = (fw_iso_callback_t)iso_mc_callback;963909 break;964910965911 default:···994886 }995887996888 context = fw_iso_context_create(client->device->card, a->type,997997- a->channel, a->speed, a->header_size,998998- iso_callback, client);889889+ a->channel, a->speed, a->header_size, cb, client);999890 if (IS_ERR(context))1000891 return PTR_ERR(context);1001892893893+ /* We only support one context at this time. */894894+ spin_lock_irq(&client->lock);895895+ if (client->iso_context != NULL) {896896+ spin_unlock_irq(&client->lock);897897+ fw_iso_context_destroy(context);898898+ return -EBUSY;899899+ }1002900 client->iso_closure = a->closure;1003901 client->iso_context = context;902902+ spin_unlock_irq(&client->lock);100490310051005- /* We only support one context at this time. */1006904 a->handle = 0;10079051008906 return 0;907907+}908908+909909+static int ioctl_set_iso_channels(struct client *client, union ioctl_arg *arg)910910+{911911+ struct fw_cdev_set_iso_channels *a = &arg->set_iso_channels;912912+ struct fw_iso_context *ctx = client->iso_context;913913+914914+ if (ctx == NULL || a->handle != 0)915915+ return -EINVAL;916916+917917+ return fw_iso_context_set_channels(ctx, &a->channels);1009918}10109191011920/* Macros for decoding the iso packet control header. */···1038913 struct fw_cdev_queue_iso *a = &arg->queue_iso;1039914 struct fw_cdev_iso_packet __user *p, *end, *next;1040915 struct fw_iso_context *ctx = client->iso_context;10411041- unsigned long payload, buffer_end, header_length;916916+ unsigned long payload, buffer_end, transmit_header_bytes = 0;1042917 u32 control;1043918 int count;1044919 struct {···1058933 * use the indirect payload, the iso buffer need not be mapped1059934 * and the a->data pointer is ignored.1060935 */10611061-1062936 payload = (unsigned long)a->data - client->vm_start;1063937 buffer_end = client->buffer.page_count << PAGE_SHIFT;1064938 if (a->data == 0 || client->buffer.pages == NULL ||···1066942 buffer_end = 0;1067943 }106894410691069- p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(a->packets);945945+ if (ctx->type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL && payload & 3)946946+ return -EINVAL;1070947948948+ p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(a->packets);1071949 if (!access_ok(VERIFY_READ, p, a->size))1072950 return -EFAULT;1073951···1085959 u.packet.sy = GET_SY(control);1086960 u.packet.header_length = GET_HEADER_LENGTH(control);108796110881088- if (ctx->type == FW_ISO_CONTEXT_TRANSMIT) {10891089- if (u.packet.header_length % 4 != 0)962962+ switch (ctx->type) {963963+ case FW_ISO_CONTEXT_TRANSMIT:964964+ if (u.packet.header_length & 3)1090965 return -EINVAL;10911091- header_length = u.packet.header_length;10921092- } else {10931093- /*10941094- * We require that header_length is a multiple of10951095- * the fixed header size, ctx->header_size.10961096- */10971097- if (ctx->header_size == 0) {10981098- if (u.packet.header_length > 0)10991099- return -EINVAL;11001100- } else if (u.packet.header_length == 0 ||11011101- u.packet.header_length % ctx->header_size != 0) {966966+ transmit_header_bytes = u.packet.header_length;967967+ break;968968+969969+ case FW_ISO_CONTEXT_RECEIVE:970970+ if (u.packet.header_length == 0 ||971971+ u.packet.header_length % ctx->header_size != 0)1102972 return -EINVAL;11031103- }11041104- header_length = 0;973973+ break;974974+975975+ case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:976976+ if (u.packet.payload_length == 0 ||977977+ u.packet.payload_length & 3)978978+ return -EINVAL;979979+ break;1105980 }11069811107982 next = (struct fw_cdev_iso_packet __user *)11081108- &p->header[header_length / 4];983983+ &p->header[transmit_header_bytes / 4];1109984 if (next > end)1110985 return -EINVAL;1111986 if (__copy_from_user11121112- (u.packet.header, p->header, header_length))987987+ (u.packet.header, p->header, transmit_header_bytes))1113988 return -EFAULT;1114989 if (u.packet.skip && ctx->type == FW_ISO_CONTEXT_TRANSMIT &&1115990 u.packet.header_length + u.packet.payload_length > 0)···11371010static int ioctl_start_iso(struct client *client, union ioctl_arg *arg)11381011{11391012 struct fw_cdev_start_iso *a = &arg->start_iso;10131013+10141014+ BUILD_BUG_ON(10151015+ FW_CDEV_ISO_CONTEXT_MATCH_TAG0 != FW_ISO_CONTEXT_MATCH_TAG0 ||10161016+ FW_CDEV_ISO_CONTEXT_MATCH_TAG1 != FW_ISO_CONTEXT_MATCH_TAG1 ||10171017+ FW_CDEV_ISO_CONTEXT_MATCH_TAG2 != FW_ISO_CONTEXT_MATCH_TAG2 ||10181018+ FW_CDEV_ISO_CONTEXT_MATCH_TAG3 != FW_ISO_CONTEXT_MATCH_TAG3 ||10191019+ FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS != FW_ISO_CONTEXT_MATCH_ALL_TAGS);1140102011411021 if (client->iso_context == NULL || a->handle != 0)11421022 return -EINVAL;···1176104211771043 local_irq_disable();1178104411791179- cycle_time = card->driver->get_cycle_time(card);10451045+ cycle_time = card->driver->read_csr(card, CSR_CYCLE_TIME);1180104611811047 switch (a->clk_id) {11821048 case CLOCK_REALTIME: getnstimeofday(&ts); break;···14571323 return init_request(client, &request, dest, a->speed);14581324}1459132513261326+static void outbound_phy_packet_callback(struct fw_packet *packet,13271327+ struct fw_card *card, int status)13281328+{13291329+ struct outbound_phy_packet_event *e =13301330+ container_of(packet, struct outbound_phy_packet_event, p);13311331+13321332+ switch (status) {13331333+ /* expected: */13341334+ case ACK_COMPLETE: e->phy_packet.rcode = RCODE_COMPLETE; break;13351335+ /* should never happen with PHY packets: */13361336+ case ACK_PENDING: e->phy_packet.rcode = RCODE_COMPLETE; break;13371337+ case ACK_BUSY_X:13381338+ case ACK_BUSY_A:13391339+ case ACK_BUSY_B: e->phy_packet.rcode = RCODE_BUSY; break;13401340+ case ACK_DATA_ERROR: e->phy_packet.rcode = RCODE_DATA_ERROR; break;13411341+ case ACK_TYPE_ERROR: e->phy_packet.rcode = RCODE_TYPE_ERROR; break;13421342+ /* stale generation; cancelled; on certain controllers: no ack */13431343+ default: e->phy_packet.rcode = status; break;13441344+ }13451345+ e->phy_packet.data[0] = packet->timestamp;13461346+13471347+ queue_event(e->client, &e->event, &e->phy_packet,13481348+ sizeof(e->phy_packet) + e->phy_packet.length, NULL, 0);13491349+ client_put(e->client);13501350+}13511351+13521352+static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg)13531353+{13541354+ struct fw_cdev_send_phy_packet *a = &arg->send_phy_packet;13551355+ struct fw_card *card = client->device->card;13561356+ struct outbound_phy_packet_event *e;13571357+13581358+ /* Access policy: Allow this ioctl only on local nodes' device files. */13591359+ if (!client->device->is_local)13601360+ return -ENOSYS;13611361+13621362+ e = kzalloc(sizeof(*e) + 4, GFP_KERNEL);13631363+ if (e == NULL)13641364+ return -ENOMEM;13651365+13661366+ client_get(client);13671367+ e->client = client;13681368+ e->p.speed = SCODE_100;13691369+ e->p.generation = a->generation;13701370+ e->p.header[0] = a->data[0];13711371+ e->p.header[1] = a->data[1];13721372+ e->p.header_length = 8;13731373+ e->p.callback = outbound_phy_packet_callback;13741374+ e->phy_packet.closure = a->closure;13751375+ e->phy_packet.type = FW_CDEV_EVENT_PHY_PACKET_SENT;13761376+ if (is_ping_packet(a->data))13771377+ e->phy_packet.length = 4;13781378+13791379+ card->driver->send_request(card, &e->p);13801380+13811381+ return 0;13821382+}13831383+13841384+static int ioctl_receive_phy_packets(struct client *client, union ioctl_arg *arg)13851385+{13861386+ struct fw_cdev_receive_phy_packets *a = &arg->receive_phy_packets;13871387+ struct fw_card *card = client->device->card;13881388+13891389+ /* Access policy: Allow this ioctl only on local nodes' device files. */13901390+ if (!client->device->is_local)13911391+ return -ENOSYS;13921392+13931393+ spin_lock_irq(&card->lock);13941394+13951395+ list_move_tail(&client->phy_receiver_link, &card->phy_receiver_list);13961396+ client->phy_receiver_closure = a->closure;13971397+13981398+ spin_unlock_irq(&card->lock);13991399+14001400+ return 0;14011401+}14021402+14031403+void fw_cdev_handle_phy_packet(struct fw_card *card, struct fw_packet *p)14041404+{14051405+ struct client *client;14061406+ struct inbound_phy_packet_event *e;14071407+ unsigned long flags;14081408+14091409+ spin_lock_irqsave(&card->lock, flags);14101410+14111411+ list_for_each_entry(client, &card->phy_receiver_list, phy_receiver_link) {14121412+ e = kmalloc(sizeof(*e) + 8, GFP_ATOMIC);14131413+ if (e == NULL) {14141414+ fw_notify("Out of memory when allocating event\n");14151415+ break;14161416+ }14171417+ e->phy_packet.closure = client->phy_receiver_closure;14181418+ e->phy_packet.type = FW_CDEV_EVENT_PHY_PACKET_RECEIVED;14191419+ e->phy_packet.rcode = RCODE_COMPLETE;14201420+ e->phy_packet.length = 8;14211421+ e->phy_packet.data[0] = p->header[1];14221422+ e->phy_packet.data[1] = p->header[2];14231423+ queue_event(client, &e->event,14241424+ &e->phy_packet, sizeof(e->phy_packet) + 8, NULL, 0);14251425+ }14261426+14271427+ spin_unlock_irqrestore(&card->lock, flags);14281428+}14291429+14601430static int (* const ioctl_handlers[])(struct client *, union ioctl_arg *) = {14611461- ioctl_get_info,14621462- ioctl_send_request,14631463- ioctl_allocate,14641464- ioctl_deallocate,14651465- ioctl_send_response,14661466- ioctl_initiate_bus_reset,14671467- ioctl_add_descriptor,14681468- ioctl_remove_descriptor,14691469- ioctl_create_iso_context,14701470- ioctl_queue_iso,14711471- ioctl_start_iso,14721472- ioctl_stop_iso,14731473- ioctl_get_cycle_timer,14741474- ioctl_allocate_iso_resource,14751475- ioctl_deallocate_iso_resource,14761476- ioctl_allocate_iso_resource_once,14771477- ioctl_deallocate_iso_resource_once,14781478- ioctl_get_speed,14791479- ioctl_send_broadcast_request,14801480- ioctl_send_stream_packet,14811481- ioctl_get_cycle_timer2,14311431+ [0x00] = ioctl_get_info,14321432+ [0x01] = ioctl_send_request,14331433+ [0x02] = ioctl_allocate,14341434+ [0x03] = ioctl_deallocate,14351435+ [0x04] = ioctl_send_response,14361436+ [0x05] = ioctl_initiate_bus_reset,14371437+ [0x06] = ioctl_add_descriptor,14381438+ [0x07] = ioctl_remove_descriptor,14391439+ [0x08] = ioctl_create_iso_context,14401440+ [0x09] = ioctl_queue_iso,14411441+ [0x0a] = ioctl_start_iso,14421442+ [0x0b] = ioctl_stop_iso,14431443+ [0x0c] = ioctl_get_cycle_timer,14441444+ [0x0d] = ioctl_allocate_iso_resource,14451445+ [0x0e] = ioctl_deallocate_iso_resource,14461446+ [0x0f] = ioctl_allocate_iso_resource_once,14471447+ [0x10] = ioctl_deallocate_iso_resource_once,14481448+ [0x11] = ioctl_get_speed,14491449+ [0x12] = ioctl_send_broadcast_request,14501450+ [0x13] = ioctl_send_stream_packet,14511451+ [0x14] = ioctl_get_cycle_timer2,14521452+ [0x15] = ioctl_send_phy_packet,14531453+ [0x16] = ioctl_receive_phy_packets,14541454+ [0x17] = ioctl_set_iso_channels,14821455};1483145614841457static int dispatch_ioctl(struct client *client,···16921451{16931452 struct client *client = file->private_data;16941453 struct event *event, *next_event;14541454+14551455+ spin_lock_irq(&client->device->card->lock);14561456+ list_del(&client->phy_receiver_link);14571457+ spin_unlock_irq(&client->device->card->lock);1695145816961459 mutex_lock(&client->device->client_list_mutex);16971460 list_del(&client->link);
+6-5
drivers/firewire/core-device.c
···107107}108108109109/**110110- * fw_csr_string - reads a string from the configuration ROM111111- * @directory: e.g. root directory or unit directory112112- * @key: the key of the preceding directory entry113113- * @buf: where to put the string114114- * @size: size of @buf, in bytes110110+ * fw_csr_string() - reads a string from the configuration ROM111111+ * @directory: e.g. root directory or unit directory112112+ * @key: the key of the preceding directory entry113113+ * @buf: where to put the string114114+ * @size: size of @buf, in bytes115115 *116116 * The string is taken from a minimal ASCII text descriptor leaf after117117 * the immediate entry with @key. The string is zero-terminated.···11361136 goto give_up;11371137 }1138113811391139+ fw_device_cdev_update(device);11391140 create_units(device);1140114111411142 /* Userspace may want to re-read attributes. */
+26-8
drivers/firewire/core-iso.c
···118118}119119EXPORT_SYMBOL(fw_iso_buffer_destroy);120120121121+/* Convert DMA address to offset into virtually contiguous buffer. */122122+size_t fw_iso_buffer_lookup(struct fw_iso_buffer *buffer, dma_addr_t completed)123123+{124124+ int i;125125+ dma_addr_t address;126126+ ssize_t offset;127127+128128+ for (i = 0; i < buffer->page_count; i++) {129129+ address = page_private(buffer->pages[i]);130130+ offset = (ssize_t)completed - (ssize_t)address;131131+ if (offset > 0 && offset <= PAGE_SIZE)132132+ return (i << PAGE_SHIFT) + offset;133133+ }134134+135135+ return 0;136136+}137137+121138struct fw_iso_context *fw_iso_context_create(struct fw_card *card,122139 int type, int channel, int speed, size_t header_size,123140 fw_iso_callback_t callback, void *callback_data)···151134 ctx->channel = channel;152135 ctx->speed = speed;153136 ctx->header_size = header_size;154154- ctx->callback = callback;137137+ ctx->callback.sc = callback;155138 ctx->callback_data = callback_data;156139157140 return ctx;···160143161144void fw_iso_context_destroy(struct fw_iso_context *ctx)162145{163163- struct fw_card *card = ctx->card;164164-165165- card->driver->free_iso_context(ctx);146146+ ctx->card->driver->free_iso_context(ctx);166147}167148EXPORT_SYMBOL(fw_iso_context_destroy);168149···171156}172157EXPORT_SYMBOL(fw_iso_context_start);173158159159+int fw_iso_context_set_channels(struct fw_iso_context *ctx, u64 *channels)160160+{161161+ return ctx->card->driver->set_iso_channels(ctx, channels);162162+}163163+174164int fw_iso_context_queue(struct fw_iso_context *ctx,175165 struct fw_iso_packet *packet,176166 struct fw_iso_buffer *buffer,177167 unsigned long payload)178168{179179- struct fw_card *card = ctx->card;180180-181181- return card->driver->queue_iso(ctx, packet, buffer, payload);169169+ return ctx->card->driver->queue_iso(ctx, packet, buffer, payload);182170}183171EXPORT_SYMBOL(fw_iso_context_queue);184172···297279}298280299281/**300300- * fw_iso_resource_manage - Allocate or deallocate a channel and/or bandwidth282282+ * fw_iso_resource_manage() - Allocate or deallocate a channel and/or bandwidth301283 *302284 * In parameters: card, generation, channels_mask, bandwidth, allocate303285 * Out parameters: channel, bandwidth
+9-13
drivers/firewire/core-topology.c
···174174 return list_entry(l, struct fw_node, link);175175}176176177177-/**178178- * build_tree - Build the tree representation of the topology179179- * @self_ids: array of self IDs to create the tree from180180- * @self_id_count: the length of the self_ids array181181- * @local_id: the node ID of the local node182182- *177177+/*183178 * This function builds the tree representation of the topology given184179 * by the self IDs from the latest bus reset. During the construction185180 * of the tree, the function checks that the self IDs are valid and···415420 }416421}417422418418-/**419419- * update_tree - compare the old topology tree for card with the new420420- * one specified by root. Queue the nodes and mark them as either421421- * found, lost or updated. Update the nodes in the card topology tree422422- * as we go.423423+/*424424+ * Compare the old topology tree for card with the new one specified by root.425425+ * Queue the nodes and mark them as either found, lost or updated.426426+ * Update the nodes in the card topology tree as we go.423427 */424428static void update_tree(struct fw_card *card, struct fw_node *root)425429{···518524}519525520526void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation,521521- int self_id_count, u32 *self_ids)527527+ int self_id_count, u32 *self_ids, bool bm_abdicate)522528{523529 struct fw_node *local_node;524530 unsigned long flags;···537543538544 spin_lock_irqsave(&card->lock, flags);539545540540- card->broadcast_channel_allocated = false;546546+ card->broadcast_channel_allocated = card->broadcast_channel_auto_allocated;541547 card->node_id = node_id;542548 /*543549 * Update node_id before generation to prevent anybody from using···546552 smp_wmb();547553 card->generation = generation;548554 card->reset_jiffies = jiffies;555555+ card->bm_node_id = 0xffff;556556+ card->bm_abdicate = bm_abdicate;549557 fw_schedule_bm_work(card, 0);550558551559 local_node = build_tree(card, self_ids, self_id_count);
+228-78
drivers/firewire/core-transaction.c
···246246 break;247247248248 default:249249- WARN(1, KERN_ERR "wrong tcode %d", tcode);249249+ WARN(1, "wrong tcode %d", tcode);250250 }251251 common:252252 packet->speed = speed;···273273}274274275275/**276276- * This function provides low-level access to the IEEE1394 transaction277277- * logic. Most C programs would use either fw_read(), fw_write() or278278- * fw_lock() instead - those function are convenience wrappers for279279- * this function. The fw_send_request() function is primarily280280- * provided as a flexible, one-stop entry point for languages bindings281281- * and protocol bindings.276276+ * fw_send_request() - submit a request packet for transmission277277+ * @card: interface to send the request at278278+ * @t: transaction instance to which the request belongs279279+ * @tcode: transaction code280280+ * @destination_id: destination node ID, consisting of bus_ID and phy_ID281281+ * @generation: bus generation in which request and response are valid282282+ * @speed: transmission speed283283+ * @offset: 48bit wide offset into destination's address space284284+ * @payload: data payload for the request subaction285285+ * @length: length of the payload, in bytes286286+ * @callback: function to be called when the transaction is completed287287+ * @callback_data: data to be passed to the transaction completion callback282288 *283283- * FIXME: Document this function further, in particular the possible284284- * values for rcode in the callback. In short, we map ACK_COMPLETE to285285- * RCODE_COMPLETE, internal errors set errno and set rcode to286286- * RCODE_SEND_ERROR (which is out of range for standard ieee1394287287- * rcodes). All other rcodes are forwarded unchanged. For all288288- * errors, payload is NULL, length is 0.289289+ * Submit a request packet into the asynchronous request transmission queue.290290+ * Can be called from atomic context. If you prefer a blocking API, use291291+ * fw_run_transaction() in a context that can sleep.289292 *290290- * Can not expect the callback to be called before the function291291- * returns, though this does happen in some cases (ACK_COMPLETE and292292- * errors).293293+ * In case of lock requests, specify one of the firewire-core specific %TCODE_294294+ * constants instead of %TCODE_LOCK_REQUEST in @tcode.293295 *294294- * The payload is only used for write requests and must not be freed295295- * until the callback has been called.296296+ * Make sure that the value in @destination_id is not older than the one in297297+ * @generation. Otherwise the request is in danger to be sent to a wrong node.296298 *297297- * @param card the card from which to send the request298298- * @param tcode the tcode for this transaction. Do not use299299- * TCODE_LOCK_REQUEST directly, instead use TCODE_LOCK_MASK_SWAP300300- * etc. to specify tcode and ext_tcode.301301- * @param node_id the destination node ID (bus ID and PHY ID concatenated)302302- * @param generation the generation for which node_id is valid303303- * @param speed the speed to use for sending the request304304- * @param offset the 48 bit offset on the destination node305305- * @param payload the data payload for the request subaction306306- * @param length the length in bytes of the data to read307307- * @param callback function to be called when the transaction is completed308308- * @param callback_data pointer to arbitrary data, which will be309309- * passed to the callback310310- *311311- * In case of asynchronous stream packets i.e. TCODE_STREAM_DATA, the caller299299+ * In case of asynchronous stream packets i.e. %TCODE_STREAM_DATA, the caller312300 * needs to synthesize @destination_id with fw_stream_packet_destination_id().301301+ * It will contain tag, channel, and sy data instead of a node ID then.302302+ *303303+ * The payload buffer at @data is going to be DMA-mapped except in case of304304+ * quadlet-sized payload or of local (loopback) requests. Hence make sure that305305+ * the buffer complies with the restrictions for DMA-mapped memory. The306306+ * @payload must not be freed before the @callback is called.307307+ *308308+ * In case of request types without payload, @data is NULL and @length is 0.309309+ *310310+ * After the transaction is completed successfully or unsuccessfully, the311311+ * @callback will be called. Among its parameters is the response code which312312+ * is either one of the rcodes per IEEE 1394 or, in case of internal errors,313313+ * the firewire-core specific %RCODE_SEND_ERROR. The other firewire-core314314+ * specific rcodes (%RCODE_CANCELLED, %RCODE_BUSY, %RCODE_GENERATION,315315+ * %RCODE_NO_ACK) denote transaction timeout, busy responder, stale request316316+ * generation, or missing ACK respectively.317317+ *318318+ * Note some timing corner cases: fw_send_request() may complete much earlier319319+ * than when the request packet actually hits the wire. On the other hand,320320+ * transaction completion and hence execution of @callback may happen even321321+ * before fw_send_request() returns.313322 */314323void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,315324 int destination_id, int generation, int speed,···348339 setup_timer(&t->split_timeout_timer,349340 split_transaction_timeout_callback, (unsigned long)t);350341 /* FIXME: start this timer later, relative to t->timestamp */351351- mod_timer(&t->split_timeout_timer, jiffies + DIV_ROUND_UP(HZ, 10));342342+ mod_timer(&t->split_timeout_timer,343343+ jiffies + card->split_timeout_jiffies);352344 t->callback = callback;353345 t->callback_data = callback_data;354346···384374}385375386376/**387387- * fw_run_transaction - send request and sleep until transaction is completed377377+ * fw_run_transaction() - send request and sleep until transaction is completed388378 *389389- * Returns the RCODE.379379+ * Returns the RCODE. See fw_send_request() for parameter documentation.380380+ * Unlike fw_send_request(), @data points to the payload of the request or/and381381+ * to the payload of the response.390382 */391383int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,392384 int generation, int speed, unsigned long long offset,···429417 int node_id, int generation, int gap_count)430418{431419 long timeout = DIV_ROUND_UP(HZ, 10);432432- u32 data = PHY_IDENTIFIER(PHY_PACKET_CONFIG) |433433- PHY_CONFIG_ROOT_ID(node_id) |434434- PHY_CONFIG_GAP_COUNT(gap_count);420420+ u32 data = PHY_IDENTIFIER(PHY_PACKET_CONFIG);421421+422422+ if (node_id != FW_PHY_CONFIG_NO_NODE_ID)423423+ data |= PHY_CONFIG_ROOT_ID(node_id);424424+425425+ if (gap_count == FW_PHY_CONFIG_CURRENT_GAP_COUNT) {426426+ gap_count = card->driver->read_phy_reg(card, 1);427427+ if (gap_count < 0)428428+ return;429429+430430+ gap_count &= 63;431431+ if (gap_count == 63)432432+ return;433433+ }434434+ data |= PHY_CONFIG_GAP_COUNT(gap_count);435435436436 mutex_lock(&phy_config_mutex);437437···518494}519495520496/**521521- * fw_core_add_address_handler - register for incoming requests522522- * @handler: callback523523- * @region: region in the IEEE 1212 node space address range497497+ * fw_core_add_address_handler() - register for incoming requests498498+ * @handler: callback499499+ * @region: region in the IEEE 1212 node space address range524500 *525501 * region->start, ->end, and handler->length have to be quadlet-aligned.526502 *···543519 int ret = -EBUSY;544520545521 if (region->start & 0xffff000000000003ULL ||546546- region->end & 0xffff000000000003ULL ||547522 region->start >= region->end ||523523+ region->end > 0x0001000000000000ULL ||548524 handler->length & 3 ||549525 handler->length == 0)550526 return -EINVAL;···575551EXPORT_SYMBOL(fw_core_add_address_handler);576552577553/**578578- * fw_core_remove_address_handler - unregister an address handler554554+ * fw_core_remove_address_handler() - unregister an address handler579555 */580556void fw_core_remove_address_handler(struct fw_address_handler *handler)581557{···602578603579 request = container_of(packet, struct fw_request, response);604580 kfree(request);581581+}582582+583583+int fw_get_response_length(struct fw_request *r)584584+{585585+ int tcode, ext_tcode, data_length;586586+587587+ tcode = HEADER_GET_TCODE(r->request_header[0]);588588+589589+ switch (tcode) {590590+ case TCODE_WRITE_QUADLET_REQUEST:591591+ case TCODE_WRITE_BLOCK_REQUEST:592592+ return 0;593593+594594+ case TCODE_READ_QUADLET_REQUEST:595595+ return 4;596596+597597+ case TCODE_READ_BLOCK_REQUEST:598598+ data_length = HEADER_GET_DATA_LENGTH(r->request_header[3]);599599+ return data_length;600600+601601+ case TCODE_LOCK_REQUEST:602602+ ext_tcode = HEADER_GET_EXTENDED_TCODE(r->request_header[3]);603603+ data_length = HEADER_GET_DATA_LENGTH(r->request_header[3]);604604+ switch (ext_tcode) {605605+ case EXTCODE_FETCH_ADD:606606+ case EXTCODE_LITTLE_ADD:607607+ return data_length;608608+ default:609609+ return data_length / 2;610610+ }611611+612612+ default:613613+ WARN(1, "wrong tcode %d", tcode);614614+ return 0;615615+ }605616}606617607618void fw_fill_response(struct fw_packet *response, u32 *request_header,···690631 break;691632692633 default:693693- WARN(1, KERN_ERR "wrong tcode %d", tcode);634634+ WARN(1, "wrong tcode %d", tcode);694635 }695636696637 response->payload_mapped = false;697638}698639EXPORT_SYMBOL(fw_fill_response);699640700700-static struct fw_request *allocate_request(struct fw_packet *p)641641+static u32 compute_split_timeout_timestamp(struct fw_card *card,642642+ u32 request_timestamp)643643+{644644+ unsigned int cycles;645645+ u32 timestamp;646646+647647+ cycles = card->split_timeout_cycles;648648+ cycles += request_timestamp & 0x1fff;649649+650650+ timestamp = request_timestamp & ~0x1fff;651651+ timestamp += (cycles / 8000) << 13;652652+ timestamp |= cycles % 8000;653653+654654+ return timestamp;655655+}656656+657657+static struct fw_request *allocate_request(struct fw_card *card,658658+ struct fw_packet *p)701659{702660 struct fw_request *request;703661 u32 *data, length;704704- int request_tcode, t;662662+ int request_tcode;705663706664 request_tcode = HEADER_GET_TCODE(p->header[0]);707665 switch (request_tcode) {···753677 if (request == NULL)754678 return NULL;755679756756- t = (p->timestamp & 0x1fff) + 4000;757757- if (t >= 8000)758758- t = (p->timestamp & ~0x1fff) + 0x2000 + t - 8000;759759- else760760- t = (p->timestamp & ~0x1fff) + t;761761-762680 request->response.speed = p->speed;763763- request->response.timestamp = t;681681+ request->response.timestamp =682682+ compute_split_timeout_timestamp(card, p->timestamp);764683 request->response.generation = p->generation;765684 request->response.ack = 0;766685 request->response.callback = free_response_callback;···784713785714 if (rcode == RCODE_COMPLETE)786715 fw_fill_response(&request->response, request->request_header,787787- rcode, request->data, request->length);716716+ rcode, request->data,717717+ fw_get_response_length(request));788718 else789719 fw_fill_response(&request->response, request->request_header,790720 rcode, NULL, 0);···803731 unsigned long flags;804732 int tcode, destination, source;805733806806- tcode = HEADER_GET_TCODE(p->header[0]);807734 destination = HEADER_GET_DESTINATION(p->header[0]);808735 source = HEADER_GET_SOURCE(p->header[1]);736736+ tcode = HEADER_GET_TCODE(p->header[0]);737737+ if (tcode == TCODE_LOCK_REQUEST)738738+ tcode = 0x10 + HEADER_GET_EXTENDED_TCODE(p->header[3]);809739810740 spin_lock_irqsave(&address_handler_lock, flags);811741 handler = lookup_enclosing_address_handler(&address_handler_list,···827753 else828754 handler->address_callback(card, request,829755 tcode, destination, source,830830- p->generation, p->speed, offset,756756+ p->generation, offset,831757 request->data, request->length,832758 handler->callback_data);833759}···865791 if (is_enclosing_handler(handler, offset, request->length))866792 handler->address_callback(card, NULL, tcode,867793 destination, source,868868- p->generation, p->speed,869869- offset, request->data,794794+ p->generation, offset,795795+ request->data,870796 request->length,871797 handler->callback_data);872798 }···883809 if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE)884810 return;885811886886- request = allocate_request(p);812812+ if (TCODE_IS_LINK_INTERNAL(HEADER_GET_TCODE(p->header[0]))) {813813+ fw_cdev_handle_phy_packet(card, p);814814+ return;815815+ }816816+817817+ request = allocate_request(card, p);887818 if (request == NULL) {888819 /* FIXME: send statically allocated busy packet. */889820 return;···911832 unsigned long flags;912833 u32 *data;913834 size_t data_length;914914- int tcode, tlabel, destination, source, rcode;835835+ int tcode, tlabel, source, rcode;915836916916- tcode = HEADER_GET_TCODE(p->header[0]);917917- tlabel = HEADER_GET_TLABEL(p->header[0]);918918- destination = HEADER_GET_DESTINATION(p->header[0]);919919- source = HEADER_GET_SOURCE(p->header[1]);920920- rcode = HEADER_GET_RCODE(p->header[1]);837837+ tcode = HEADER_GET_TCODE(p->header[0]);838838+ tlabel = HEADER_GET_TLABEL(p->header[0]);839839+ source = HEADER_GET_SOURCE(p->header[1]);840840+ rcode = HEADER_GET_RCODE(p->header[1]);921841922842 spin_lock_irqsave(&card->lock, flags);923843 list_for_each_entry(t, &card->transaction_list, link) {···981903982904static void handle_topology_map(struct fw_card *card, struct fw_request *request,983905 int tcode, int destination, int source, int generation,984984- int speed, unsigned long long offset,985985- void *payload, size_t length, void *callback_data)906906+ unsigned long long offset, void *payload, size_t length,907907+ void *callback_data)986908{987909 int start;988910···1011933 { .start = CSR_REGISTER_BASE,1012934 .end = CSR_REGISTER_BASE | CSR_CONFIG_ROM, };1013935936936+static void update_split_timeout(struct fw_card *card)937937+{938938+ unsigned int cycles;939939+940940+ cycles = card->split_timeout_hi * 8000 + (card->split_timeout_lo >> 19);941941+942942+ cycles = max(cycles, 800u); /* minimum as per the spec */943943+ cycles = min(cycles, 3u * 8000u); /* maximum OHCI timeout */944944+945945+ card->split_timeout_cycles = cycles;946946+ card->split_timeout_jiffies = DIV_ROUND_UP(cycles * HZ, 8000);947947+}948948+1014949static void handle_registers(struct fw_card *card, struct fw_request *request,1015950 int tcode, int destination, int source, int generation,10161016- int speed, unsigned long long offset,10171017- void *payload, size_t length, void *callback_data)951951+ unsigned long long offset, void *payload, size_t length,952952+ void *callback_data)1018953{1019954 int reg = offset & ~CSR_REGISTER_BASE;1020955 __be32 *data = payload;1021956 int rcode = RCODE_COMPLETE;957957+ unsigned long flags;10229581023959 switch (reg) {960960+ case CSR_PRIORITY_BUDGET:961961+ if (!card->priority_budget_implemented) {962962+ rcode = RCODE_ADDRESS_ERROR;963963+ break;964964+ }965965+ /* else fall through */966966+967967+ case CSR_NODE_IDS:968968+ /*969969+ * per IEEE 1394-2008 8.3.22.3, not IEEE 1394.1-2004 3.2.8970970+ * and 9.6, but interoperable with IEEE 1394.1-2004 bridges971971+ */972972+ /* fall through */973973+974974+ case CSR_STATE_CLEAR:975975+ case CSR_STATE_SET:1024976 case CSR_CYCLE_TIME:10251025- if (TCODE_IS_READ_REQUEST(tcode) && length == 4)10261026- *data = cpu_to_be32(card->driver->get_cycle_time(card));977977+ case CSR_BUS_TIME:978978+ case CSR_BUSY_TIMEOUT:979979+ if (tcode == TCODE_READ_QUADLET_REQUEST)980980+ *data = cpu_to_be32(card->driver->read_csr(card, reg));981981+ else if (tcode == TCODE_WRITE_QUADLET_REQUEST)982982+ card->driver->write_csr(card, reg, be32_to_cpu(*data));983983+ else984984+ rcode = RCODE_TYPE_ERROR;985985+ break;986986+987987+ case CSR_RESET_START:988988+ if (tcode == TCODE_WRITE_QUADLET_REQUEST)989989+ card->driver->write_csr(card, CSR_STATE_CLEAR,990990+ CSR_STATE_BIT_ABDICATE);991991+ else992992+ rcode = RCODE_TYPE_ERROR;993993+ break;994994+995995+ case CSR_SPLIT_TIMEOUT_HI:996996+ if (tcode == TCODE_READ_QUADLET_REQUEST) {997997+ *data = cpu_to_be32(card->split_timeout_hi);998998+ } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) {999999+ spin_lock_irqsave(&card->lock, flags);10001000+ card->split_timeout_hi = be32_to_cpu(*data) & 7;10011001+ update_split_timeout(card);10021002+ spin_unlock_irqrestore(&card->lock, flags);10031003+ } else {10041004+ rcode = RCODE_TYPE_ERROR;10051005+ }10061006+ break;10071007+10081008+ case CSR_SPLIT_TIMEOUT_LO:10091009+ if (tcode == TCODE_READ_QUADLET_REQUEST) {10101010+ *data = cpu_to_be32(card->split_timeout_lo);10111011+ } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) {10121012+ spin_lock_irqsave(&card->lock, flags);10131013+ card->split_timeout_lo =10141014+ be32_to_cpu(*data) & 0xfff80000;10151015+ update_split_timeout(card);10161016+ spin_unlock_irqrestore(&card->lock, flags);10171017+ } else {10181018+ rcode = RCODE_TYPE_ERROR;10191019+ }10201020+ break;10211021+10221022+ case CSR_MAINT_UTILITY:10231023+ if (tcode == TCODE_READ_QUADLET_REQUEST)10241024+ *data = card->maint_utility_register;10251025+ else if (tcode == TCODE_WRITE_QUADLET_REQUEST)10261026+ card->maint_utility_register = *data;10271027 else10281028 rcode = RCODE_TYPE_ERROR;10291029 break;···1130974 */1131975 BUG();1132976 break;11331133-11341134- case CSR_BUSY_TIMEOUT:11351135- /* FIXME: Implement this. */11361136-11371137- case CSR_BUS_TIME:11381138- /* Useless without initialization by the bus manager. */11399771140978 default:1141979 rcode = RCODE_ADDRESS_ERROR;
+21-3
drivers/firewire/core.h
···3838#define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31)3939#define BROADCAST_CHANNEL_VALID (1 << 30)40404141+#define CSR_STATE_BIT_CMSTR (1 << 8)4242+#define CSR_STATE_BIT_ABDICATE (1 << 10)4343+4144struct fw_card_driver {4245 /*4346 * Enable the given card with the given initial config rom.···5148 int (*enable)(struct fw_card *card,5249 const __be32 *config_rom, size_t length);53505151+ int (*read_phy_reg)(struct fw_card *card, int address);5452 int (*update_phy_reg)(struct fw_card *card, int address,5553 int clear_bits, int set_bits);5654···7975 int (*enable_phys_dma)(struct fw_card *card,8076 int node_id, int generation);81778282- u32 (*get_cycle_time)(struct fw_card *card);7878+ u32 (*read_csr)(struct fw_card *card, int csr_offset);7979+ void (*write_csr)(struct fw_card *card, int csr_offset, u32 value);83808481 struct fw_iso_context *8582 (*allocate_iso_context)(struct fw_card *card,···89849085 int (*start_iso)(struct fw_iso_context *ctx,9186 s32 cycle, u32 sync, u32 tags);8787+8888+ int (*set_iso_channels)(struct fw_iso_context *ctx, u64 *channels);92899390 int (*queue_iso)(struct fw_iso_context *ctx,9491 struct fw_iso_packet *packet,···10598int fw_card_add(struct fw_card *card,10699 u32 max_receive, u32 link_speed, u64 guid);107100void fw_core_remove_card(struct fw_card *card);108108-int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset);109101int fw_compute_block_crc(__be32 *block);102102+void fw_schedule_bus_reset(struct fw_card *card, bool delayed, bool short_reset);110103void fw_schedule_bm_work(struct fw_card *card, unsigned long delay);111104112105static inline struct fw_card *fw_card_get(struct fw_card *card)···130123131124void fw_device_cdev_update(struct fw_device *device);132125void fw_device_cdev_remove(struct fw_device *device);126126+void fw_cdev_handle_phy_packet(struct fw_card *card, struct fw_packet *p);133127134128135129/* -device */···200192}201193202194void fw_core_handle_bus_reset(struct fw_card *card, int node_id,203203- int generation, int self_id_count, u32 *self_ids);195195+ int generation, int self_id_count, u32 *self_ids, bool bm_abdicate);204196void fw_destroy_nodes(struct fw_card *card);205197206198/*···217209218210#define TCODE_IS_READ_REQUEST(tcode) (((tcode) & ~1) == 4)219211#define TCODE_IS_BLOCK_PACKET(tcode) (((tcode) & 1) != 0)212212+#define TCODE_IS_LINK_INTERNAL(tcode) ((tcode) == 0xe)220213#define TCODE_IS_REQUEST(tcode) (((tcode) & 2) == 0)221214#define TCODE_IS_RESPONSE(tcode) (((tcode) & 2) != 0)222215#define TCODE_HAS_REQUEST_DATA(tcode) (((tcode) & 12) != 4)···227218228219void fw_core_handle_request(struct fw_card *card, struct fw_packet *request);229220void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);221221+int fw_get_response_length(struct fw_request *request);230222void fw_fill_response(struct fw_packet *response, u32 *request_header,231223 int rcode, void *payload, size_t length);224224+225225+#define FW_PHY_CONFIG_NO_NODE_ID -1226226+#define FW_PHY_CONFIG_CURRENT_GAP_COUNT -1232227void fw_send_phy_config(struct fw_card *card,233228 int node_id, int generation, int gap_count);229229+230230+static inline bool is_ping_packet(u32 *data)231231+{232232+ return (data[0] & 0xc0ffffff) == 0 && ~data[0] == data[1];233233+}234234235235#endif /* _FIREWIRE_CORE_H */
+2-2
drivers/firewire/net.c
···806806807807static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r,808808 int tcode, int destination, int source, int generation,809809- int speed, unsigned long long offset, void *payload,810810- size_t length, void *callback_data)809809+ unsigned long long offset, void *payload, size_t length,810810+ void *callback_data)811811{812812 struct fwnet_device *dev = callback_data;813813 int rcode;
+25
drivers/firewire/nosy-user.h
···11+#ifndef __nosy_user_h22+#define __nosy_user_h33+44+#include <linux/ioctl.h>55+#include <linux/types.h>66+77+#define NOSY_IOC_GET_STATS _IOR('&', 0, struct nosy_stats)88+#define NOSY_IOC_START _IO('&', 1)99+#define NOSY_IOC_STOP _IO('&', 2)1010+#define NOSY_IOC_FILTER _IOW('&', 2, __u32)1111+1212+struct nosy_stats {1313+ __u32 total_packet_count;1414+ __u32 lost_packet_count;1515+};1616+1717+/*1818+ * Format of packets returned from the kernel driver:1919+ *2020+ * quadlet with timestamp (microseconds, CPU endian)2121+ * quadlet-padded packet data... (little endian)2222+ * quadlet with ack (little endian)2323+ */2424+2525+#endif /* __nosy_user_h */
+721
drivers/firewire/nosy.c
···11+/*22+ * nosy - Snoop mode driver for TI PCILynx 1394 controllers33+ * Copyright (C) 2002-2007 Kristian Høgsberg44+ *55+ * This program is free software; you can redistribute it and/or modify66+ * it under the terms of the GNU General Public License as published by77+ * the Free Software Foundation; either version 2 of the License, or88+ * (at your option) any later version.99+ *1010+ * This program is distributed in the hope that it will be useful,1111+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1212+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1313+ * GNU General Public License for more details.1414+ *1515+ * You should have received a copy of the GNU General Public License1616+ * along with this program; if not, write to the Free Software Foundation,1717+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.1818+ */1919+2020+#include <linux/device.h>2121+#include <linux/errno.h>2222+#include <linux/fs.h>2323+#include <linux/init.h>2424+#include <linux/interrupt.h>2525+#include <linux/io.h>2626+#include <linux/kernel.h>2727+#include <linux/kref.h>2828+#include <linux/miscdevice.h>2929+#include <linux/module.h>3030+#include <linux/mutex.h>3131+#include <linux/pci.h>3232+#include <linux/poll.h>3333+#include <linux/sched.h> /* required for linux/wait.h */3434+#include <linux/slab.h>3535+#include <linux/spinlock.h>3636+#include <linux/timex.h>3737+#include <linux/uaccess.h>3838+#include <linux/wait.h>3939+4040+#include <asm/atomic.h>4141+#include <asm/byteorder.h>4242+4343+#include "nosy.h"4444+#include "nosy-user.h"4545+4646+#define TCODE_PHY_PACKET 0x104747+#define PCI_DEVICE_ID_TI_PCILYNX 0x80004848+4949+static char driver_name[] = KBUILD_MODNAME;5050+5151+/* this is the physical layout of a PCL, its size is 128 bytes */5252+struct pcl {5353+ __le32 next;5454+ __le32 async_error_next;5555+ u32 user_data;5656+ __le32 pcl_status;5757+ __le32 remaining_transfer_count;5858+ __le32 next_data_buffer;5959+ struct {6060+ __le32 control;6161+ __le32 pointer;6262+ } buffer[13];6363+};6464+6565+struct packet {6666+ unsigned int length;6767+ char data[0];6868+};6969+7070+struct packet_buffer {7171+ char *data;7272+ size_t capacity;7373+ long total_packet_count, lost_packet_count;7474+ atomic_t size;7575+ struct packet *head, *tail;7676+ wait_queue_head_t wait;7777+};7878+7979+struct pcilynx {8080+ struct pci_dev *pci_device;8181+ __iomem char *registers;8282+8383+ struct pcl *rcv_start_pcl, *rcv_pcl;8484+ __le32 *rcv_buffer;8585+8686+ dma_addr_t rcv_start_pcl_bus, rcv_pcl_bus, rcv_buffer_bus;8787+8888+ spinlock_t client_list_lock;8989+ struct list_head client_list;9090+9191+ struct miscdevice misc;9292+ struct list_head link;9393+ struct kref kref;9494+};9595+9696+static inline struct pcilynx *9797+lynx_get(struct pcilynx *lynx)9898+{9999+ kref_get(&lynx->kref);100100+101101+ return lynx;102102+}103103+104104+static void105105+lynx_release(struct kref *kref)106106+{107107+ kfree(container_of(kref, struct pcilynx, kref));108108+}109109+110110+static inline void111111+lynx_put(struct pcilynx *lynx)112112+{113113+ kref_put(&lynx->kref, lynx_release);114114+}115115+116116+struct client {117117+ struct pcilynx *lynx;118118+ u32 tcode_mask;119119+ struct packet_buffer buffer;120120+ struct list_head link;121121+};122122+123123+static DEFINE_MUTEX(card_mutex);124124+static LIST_HEAD(card_list);125125+126126+static int127127+packet_buffer_init(struct packet_buffer *buffer, size_t capacity)128128+{129129+ buffer->data = kmalloc(capacity, GFP_KERNEL);130130+ if (buffer->data == NULL)131131+ return -ENOMEM;132132+ buffer->head = (struct packet *) buffer->data;133133+ buffer->tail = (struct packet *) buffer->data;134134+ buffer->capacity = capacity;135135+ buffer->lost_packet_count = 0;136136+ atomic_set(&buffer->size, 0);137137+ init_waitqueue_head(&buffer->wait);138138+139139+ return 0;140140+}141141+142142+static void143143+packet_buffer_destroy(struct packet_buffer *buffer)144144+{145145+ kfree(buffer->data);146146+}147147+148148+static int149149+packet_buffer_get(struct client *client, char __user *data, size_t user_length)150150+{151151+ struct packet_buffer *buffer = &client->buffer;152152+ size_t length;153153+ char *end;154154+155155+ if (wait_event_interruptible(buffer->wait,156156+ atomic_read(&buffer->size) > 0) ||157157+ list_empty(&client->lynx->link))158158+ return -ERESTARTSYS;159159+160160+ if (atomic_read(&buffer->size) == 0)161161+ return -ENODEV;162162+163163+ /* FIXME: Check length <= user_length. */164164+165165+ end = buffer->data + buffer->capacity;166166+ length = buffer->head->length;167167+168168+ if (&buffer->head->data[length] < end) {169169+ if (copy_to_user(data, buffer->head->data, length))170170+ return -EFAULT;171171+ buffer->head = (struct packet *) &buffer->head->data[length];172172+ } else {173173+ size_t split = end - buffer->head->data;174174+175175+ if (copy_to_user(data, buffer->head->data, split))176176+ return -EFAULT;177177+ if (copy_to_user(data + split, buffer->data, length - split))178178+ return -EFAULT;179179+ buffer->head = (struct packet *) &buffer->data[length - split];180180+ }181181+182182+ /*183183+ * Decrease buffer->size as the last thing, since this is what184184+ * keeps the interrupt from overwriting the packet we are185185+ * retrieving from the buffer.186186+ */187187+ atomic_sub(sizeof(struct packet) + length, &buffer->size);188188+189189+ return length;190190+}191191+192192+static void193193+packet_buffer_put(struct packet_buffer *buffer, void *data, size_t length)194194+{195195+ char *end;196196+197197+ buffer->total_packet_count++;198198+199199+ if (buffer->capacity <200200+ atomic_read(&buffer->size) + sizeof(struct packet) + length) {201201+ buffer->lost_packet_count++;202202+ return;203203+ }204204+205205+ end = buffer->data + buffer->capacity;206206+ buffer->tail->length = length;207207+208208+ if (&buffer->tail->data[length] < end) {209209+ memcpy(buffer->tail->data, data, length);210210+ buffer->tail = (struct packet *) &buffer->tail->data[length];211211+ } else {212212+ size_t split = end - buffer->tail->data;213213+214214+ memcpy(buffer->tail->data, data, split);215215+ memcpy(buffer->data, data + split, length - split);216216+ buffer->tail = (struct packet *) &buffer->data[length - split];217217+ }218218+219219+ /* Finally, adjust buffer size and wake up userspace reader. */220220+221221+ atomic_add(sizeof(struct packet) + length, &buffer->size);222222+ wake_up_interruptible(&buffer->wait);223223+}224224+225225+static inline void226226+reg_write(struct pcilynx *lynx, int offset, u32 data)227227+{228228+ writel(data, lynx->registers + offset);229229+}230230+231231+static inline u32232232+reg_read(struct pcilynx *lynx, int offset)233233+{234234+ return readl(lynx->registers + offset);235235+}236236+237237+static inline void238238+reg_set_bits(struct pcilynx *lynx, int offset, u32 mask)239239+{240240+ reg_write(lynx, offset, (reg_read(lynx, offset) | mask));241241+}242242+243243+/*244244+ * Maybe the pcl programs could be set up to just append data instead245245+ * of using a whole packet.246246+ */247247+static inline void248248+run_pcl(struct pcilynx *lynx, dma_addr_t pcl_bus,249249+ int dmachan)250250+{251251+ reg_write(lynx, DMA0_CURRENT_PCL + dmachan * 0x20, pcl_bus);252252+ reg_write(lynx, DMA0_CHAN_CTRL + dmachan * 0x20,253253+ DMA_CHAN_CTRL_ENABLE | DMA_CHAN_CTRL_LINK);254254+}255255+256256+static int257257+set_phy_reg(struct pcilynx *lynx, int addr, int val)258258+{259259+ if (addr > 15) {260260+ dev_err(&lynx->pci_device->dev,261261+ "PHY register address %d out of range\n", addr);262262+ return -1;263263+ }264264+ if (val > 0xff) {265265+ dev_err(&lynx->pci_device->dev,266266+ "PHY register value %d out of range\n", val);267267+ return -1;268268+ }269269+ reg_write(lynx, LINK_PHY, LINK_PHY_WRITE |270270+ LINK_PHY_ADDR(addr) | LINK_PHY_WDATA(val));271271+272272+ return 0;273273+}274274+275275+static int276276+nosy_open(struct inode *inode, struct file *file)277277+{278278+ int minor = iminor(inode);279279+ struct client *client;280280+ struct pcilynx *tmp, *lynx = NULL;281281+282282+ mutex_lock(&card_mutex);283283+ list_for_each_entry(tmp, &card_list, link)284284+ if (tmp->misc.minor == minor) {285285+ lynx = lynx_get(tmp);286286+ break;287287+ }288288+ mutex_unlock(&card_mutex);289289+ if (lynx == NULL)290290+ return -ENODEV;291291+292292+ client = kmalloc(sizeof *client, GFP_KERNEL);293293+ if (client == NULL)294294+ goto fail;295295+296296+ client->tcode_mask = ~0;297297+ client->lynx = lynx;298298+ INIT_LIST_HEAD(&client->link);299299+300300+ if (packet_buffer_init(&client->buffer, 128 * 1024) < 0)301301+ goto fail;302302+303303+ file->private_data = client;304304+305305+ return 0;306306+fail:307307+ kfree(client);308308+ lynx_put(lynx);309309+310310+ return -ENOMEM;311311+}312312+313313+static int314314+nosy_release(struct inode *inode, struct file *file)315315+{316316+ struct client *client = file->private_data;317317+ struct pcilynx *lynx = client->lynx;318318+319319+ spin_lock_irq(&lynx->client_list_lock);320320+ list_del_init(&client->link);321321+ spin_unlock_irq(&lynx->client_list_lock);322322+323323+ packet_buffer_destroy(&client->buffer);324324+ kfree(client);325325+ lynx_put(lynx);326326+327327+ return 0;328328+}329329+330330+static unsigned int331331+nosy_poll(struct file *file, poll_table *pt)332332+{333333+ struct client *client = file->private_data;334334+ unsigned int ret = 0;335335+336336+ poll_wait(file, &client->buffer.wait, pt);337337+338338+ if (atomic_read(&client->buffer.size) > 0)339339+ ret = POLLIN | POLLRDNORM;340340+341341+ if (list_empty(&client->lynx->link))342342+ ret |= POLLHUP;343343+344344+ return ret;345345+}346346+347347+static ssize_t348348+nosy_read(struct file *file, char __user *buffer, size_t count, loff_t *offset)349349+{350350+ struct client *client = file->private_data;351351+352352+ return packet_buffer_get(client, buffer, count);353353+}354354+355355+static long356356+nosy_ioctl(struct file *file, unsigned int cmd, unsigned long arg)357357+{358358+ struct client *client = file->private_data;359359+ spinlock_t *client_list_lock = &client->lynx->client_list_lock;360360+ struct nosy_stats stats;361361+362362+ switch (cmd) {363363+ case NOSY_IOC_GET_STATS:364364+ spin_lock_irq(client_list_lock);365365+ stats.total_packet_count = client->buffer.total_packet_count;366366+ stats.lost_packet_count = client->buffer.lost_packet_count;367367+ spin_unlock_irq(client_list_lock);368368+369369+ if (copy_to_user((void __user *) arg, &stats, sizeof stats))370370+ return -EFAULT;371371+ else372372+ return 0;373373+374374+ case NOSY_IOC_START:375375+ spin_lock_irq(client_list_lock);376376+ list_add_tail(&client->link, &client->lynx->client_list);377377+ spin_unlock_irq(client_list_lock);378378+379379+ return 0;380380+381381+ case NOSY_IOC_STOP:382382+ spin_lock_irq(client_list_lock);383383+ list_del_init(&client->link);384384+ spin_unlock_irq(client_list_lock);385385+386386+ return 0;387387+388388+ case NOSY_IOC_FILTER:389389+ spin_lock_irq(client_list_lock);390390+ client->tcode_mask = arg;391391+ spin_unlock_irq(client_list_lock);392392+393393+ return 0;394394+395395+ default:396396+ return -EINVAL;397397+ /* Flush buffer, configure filter. */398398+ }399399+}400400+401401+static const struct file_operations nosy_ops = {402402+ .owner = THIS_MODULE,403403+ .read = nosy_read,404404+ .unlocked_ioctl = nosy_ioctl,405405+ .poll = nosy_poll,406406+ .open = nosy_open,407407+ .release = nosy_release,408408+};409409+410410+#define PHY_PACKET_SIZE 12 /* 1 payload, 1 inverse, 1 ack = 3 quadlets */411411+412412+static void413413+packet_irq_handler(struct pcilynx *lynx)414414+{415415+ struct client *client;416416+ u32 tcode_mask, tcode;417417+ size_t length;418418+ struct timeval tv;419419+420420+ /* FIXME: Also report rcv_speed. */421421+422422+ length = __le32_to_cpu(lynx->rcv_pcl->pcl_status) & 0x00001fff;423423+ tcode = __le32_to_cpu(lynx->rcv_buffer[1]) >> 4 & 0xf;424424+425425+ do_gettimeofday(&tv);426426+ lynx->rcv_buffer[0] = (__force __le32)tv.tv_usec;427427+428428+ if (length == PHY_PACKET_SIZE)429429+ tcode_mask = 1 << TCODE_PHY_PACKET;430430+ else431431+ tcode_mask = 1 << tcode;432432+433433+ spin_lock(&lynx->client_list_lock);434434+435435+ list_for_each_entry(client, &lynx->client_list, link)436436+ if (client->tcode_mask & tcode_mask)437437+ packet_buffer_put(&client->buffer,438438+ lynx->rcv_buffer, length + 4);439439+440440+ spin_unlock(&lynx->client_list_lock);441441+}442442+443443+static void444444+bus_reset_irq_handler(struct pcilynx *lynx)445445+{446446+ struct client *client;447447+ struct timeval tv;448448+449449+ do_gettimeofday(&tv);450450+451451+ spin_lock(&lynx->client_list_lock);452452+453453+ list_for_each_entry(client, &lynx->client_list, link)454454+ packet_buffer_put(&client->buffer, &tv.tv_usec, 4);455455+456456+ spin_unlock(&lynx->client_list_lock);457457+}458458+459459+static irqreturn_t460460+irq_handler(int irq, void *device)461461+{462462+ struct pcilynx *lynx = device;463463+ u32 pci_int_status;464464+465465+ pci_int_status = reg_read(lynx, PCI_INT_STATUS);466466+467467+ if (pci_int_status == ~0)468468+ /* Card was ejected. */469469+ return IRQ_NONE;470470+471471+ if ((pci_int_status & PCI_INT_INT_PEND) == 0)472472+ /* Not our interrupt, bail out quickly. */473473+ return IRQ_NONE;474474+475475+ if ((pci_int_status & PCI_INT_P1394_INT) != 0) {476476+ u32 link_int_status;477477+478478+ link_int_status = reg_read(lynx, LINK_INT_STATUS);479479+ reg_write(lynx, LINK_INT_STATUS, link_int_status);480480+481481+ if ((link_int_status & LINK_INT_PHY_BUSRESET) > 0)482482+ bus_reset_irq_handler(lynx);483483+ }484484+485485+ /* Clear the PCI_INT_STATUS register only after clearing the486486+ * LINK_INT_STATUS register; otherwise the PCI_INT_P1394 will487487+ * be set again immediately. */488488+489489+ reg_write(lynx, PCI_INT_STATUS, pci_int_status);490490+491491+ if ((pci_int_status & PCI_INT_DMA0_HLT) > 0) {492492+ packet_irq_handler(lynx);493493+ run_pcl(lynx, lynx->rcv_start_pcl_bus, 0);494494+ }495495+496496+ return IRQ_HANDLED;497497+}498498+499499+static void500500+remove_card(struct pci_dev *dev)501501+{502502+ struct pcilynx *lynx = pci_get_drvdata(dev);503503+ struct client *client;504504+505505+ mutex_lock(&card_mutex);506506+ list_del_init(&lynx->link);507507+ misc_deregister(&lynx->misc);508508+ mutex_unlock(&card_mutex);509509+510510+ reg_write(lynx, PCI_INT_ENABLE, 0);511511+ free_irq(lynx->pci_device->irq, lynx);512512+513513+ spin_lock_irq(&lynx->client_list_lock);514514+ list_for_each_entry(client, &lynx->client_list, link)515515+ wake_up_interruptible(&client->buffer.wait);516516+ spin_unlock_irq(&lynx->client_list_lock);517517+518518+ pci_free_consistent(lynx->pci_device, sizeof(struct pcl),519519+ lynx->rcv_start_pcl, lynx->rcv_start_pcl_bus);520520+ pci_free_consistent(lynx->pci_device, sizeof(struct pcl),521521+ lynx->rcv_pcl, lynx->rcv_pcl_bus);522522+ pci_free_consistent(lynx->pci_device, PAGE_SIZE,523523+ lynx->rcv_buffer, lynx->rcv_buffer_bus);524524+525525+ iounmap(lynx->registers);526526+ pci_disable_device(dev);527527+ lynx_put(lynx);528528+}529529+530530+#define RCV_BUFFER_SIZE (16 * 1024)531531+532532+static int __devinit533533+add_card(struct pci_dev *dev, const struct pci_device_id *unused)534534+{535535+ struct pcilynx *lynx;536536+ u32 p, end;537537+ int ret, i;538538+539539+ if (pci_set_dma_mask(dev, 0xffffffff)) {540540+ dev_err(&dev->dev,541541+ "DMA address limits not supported for PCILynx hardware\n");542542+ return -ENXIO;543543+ }544544+ if (pci_enable_device(dev)) {545545+ dev_err(&dev->dev, "Failed to enable PCILynx hardware\n");546546+ return -ENXIO;547547+ }548548+ pci_set_master(dev);549549+550550+ lynx = kzalloc(sizeof *lynx, GFP_KERNEL);551551+ if (lynx == NULL) {552552+ dev_err(&dev->dev, "Failed to allocate control structure\n");553553+ ret = -ENOMEM;554554+ goto fail_disable;555555+ }556556+ lynx->pci_device = dev;557557+ pci_set_drvdata(dev, lynx);558558+559559+ spin_lock_init(&lynx->client_list_lock);560560+ INIT_LIST_HEAD(&lynx->client_list);561561+ kref_init(&lynx->kref);562562+563563+ lynx->registers = ioremap_nocache(pci_resource_start(dev, 0),564564+ PCILYNX_MAX_REGISTER);565565+566566+ lynx->rcv_start_pcl = pci_alloc_consistent(lynx->pci_device,567567+ sizeof(struct pcl), &lynx->rcv_start_pcl_bus);568568+ lynx->rcv_pcl = pci_alloc_consistent(lynx->pci_device,569569+ sizeof(struct pcl), &lynx->rcv_pcl_bus);570570+ lynx->rcv_buffer = pci_alloc_consistent(lynx->pci_device,571571+ RCV_BUFFER_SIZE, &lynx->rcv_buffer_bus);572572+ if (lynx->rcv_start_pcl == NULL ||573573+ lynx->rcv_pcl == NULL ||574574+ lynx->rcv_buffer == NULL) {575575+ dev_err(&dev->dev, "Failed to allocate receive buffer\n");576576+ ret = -ENOMEM;577577+ goto fail_deallocate;578578+ }579579+ lynx->rcv_start_pcl->next = cpu_to_le32(lynx->rcv_pcl_bus);580580+ lynx->rcv_pcl->next = cpu_to_le32(PCL_NEXT_INVALID);581581+ lynx->rcv_pcl->async_error_next = cpu_to_le32(PCL_NEXT_INVALID);582582+583583+ lynx->rcv_pcl->buffer[0].control =584584+ cpu_to_le32(PCL_CMD_RCV | PCL_BIGENDIAN | 2044);585585+ lynx->rcv_pcl->buffer[0].pointer =586586+ cpu_to_le32(lynx->rcv_buffer_bus + 4);587587+ p = lynx->rcv_buffer_bus + 2048;588588+ end = lynx->rcv_buffer_bus + RCV_BUFFER_SIZE;589589+ for (i = 1; p < end; i++, p += 2048) {590590+ lynx->rcv_pcl->buffer[i].control =591591+ cpu_to_le32(PCL_CMD_RCV | PCL_BIGENDIAN | 2048);592592+ lynx->rcv_pcl->buffer[i].pointer = cpu_to_le32(p);593593+ }594594+ lynx->rcv_pcl->buffer[i - 1].control |= cpu_to_le32(PCL_LAST_BUFF);595595+596596+ reg_set_bits(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET);597597+ /* Fix buggy cards with autoboot pin not tied low: */598598+ reg_write(lynx, DMA0_CHAN_CTRL, 0);599599+ reg_write(lynx, DMA_GLOBAL_REGISTER, 0x00 << 24);600600+601601+#if 0602602+ /* now, looking for PHY register set */603603+ if ((get_phy_reg(lynx, 2) & 0xe0) == 0xe0) {604604+ lynx->phyic.reg_1394a = 1;605605+ PRINT(KERN_INFO, lynx->id,606606+ "found 1394a conform PHY (using extended register set)");607607+ lynx->phyic.vendor = get_phy_vendorid(lynx);608608+ lynx->phyic.product = get_phy_productid(lynx);609609+ } else {610610+ lynx->phyic.reg_1394a = 0;611611+ PRINT(KERN_INFO, lynx->id, "found old 1394 PHY");612612+ }613613+#endif614614+615615+ /* Setup the general receive FIFO max size. */616616+ reg_write(lynx, FIFO_SIZES, 255);617617+618618+ reg_set_bits(lynx, PCI_INT_ENABLE, PCI_INT_DMA_ALL);619619+620620+ reg_write(lynx, LINK_INT_ENABLE,621621+ LINK_INT_PHY_TIME_OUT | LINK_INT_PHY_REG_RCVD |622622+ LINK_INT_PHY_BUSRESET | LINK_INT_IT_STUCK |623623+ LINK_INT_AT_STUCK | LINK_INT_SNTRJ |624624+ LINK_INT_TC_ERR | LINK_INT_GRF_OVER_FLOW |625625+ LINK_INT_ITF_UNDER_FLOW | LINK_INT_ATF_UNDER_FLOW);626626+627627+ /* Disable the L flag in self ID packets. */628628+ set_phy_reg(lynx, 4, 0);629629+630630+ /* Put this baby into snoop mode */631631+ reg_set_bits(lynx, LINK_CONTROL, LINK_CONTROL_SNOOP_ENABLE);632632+633633+ run_pcl(lynx, lynx->rcv_start_pcl_bus, 0);634634+635635+ if (request_irq(dev->irq, irq_handler, IRQF_SHARED,636636+ driver_name, lynx)) {637637+ dev_err(&dev->dev,638638+ "Failed to allocate shared interrupt %d\n", dev->irq);639639+ ret = -EIO;640640+ goto fail_deallocate;641641+ }642642+643643+ lynx->misc.parent = &dev->dev;644644+ lynx->misc.minor = MISC_DYNAMIC_MINOR;645645+ lynx->misc.name = "nosy";646646+ lynx->misc.fops = &nosy_ops;647647+648648+ mutex_lock(&card_mutex);649649+ ret = misc_register(&lynx->misc);650650+ if (ret) {651651+ dev_err(&dev->dev, "Failed to register misc char device\n");652652+ mutex_unlock(&card_mutex);653653+ goto fail_free_irq;654654+ }655655+ list_add_tail(&lynx->link, &card_list);656656+ mutex_unlock(&card_mutex);657657+658658+ dev_info(&dev->dev,659659+ "Initialized PCILynx IEEE1394 card, irq=%d\n", dev->irq);660660+661661+ return 0;662662+663663+fail_free_irq:664664+ reg_write(lynx, PCI_INT_ENABLE, 0);665665+ free_irq(lynx->pci_device->irq, lynx);666666+667667+fail_deallocate:668668+ if (lynx->rcv_start_pcl)669669+ pci_free_consistent(lynx->pci_device, sizeof(struct pcl),670670+ lynx->rcv_start_pcl, lynx->rcv_start_pcl_bus);671671+ if (lynx->rcv_pcl)672672+ pci_free_consistent(lynx->pci_device, sizeof(struct pcl),673673+ lynx->rcv_pcl, lynx->rcv_pcl_bus);674674+ if (lynx->rcv_buffer)675675+ pci_free_consistent(lynx->pci_device, PAGE_SIZE,676676+ lynx->rcv_buffer, lynx->rcv_buffer_bus);677677+ iounmap(lynx->registers);678678+ kfree(lynx);679679+680680+fail_disable:681681+ pci_disable_device(dev);682682+683683+ return ret;684684+}685685+686686+static struct pci_device_id pci_table[] __devinitdata = {687687+ {688688+ .vendor = PCI_VENDOR_ID_TI,689689+ .device = PCI_DEVICE_ID_TI_PCILYNX,690690+ .subvendor = PCI_ANY_ID,691691+ .subdevice = PCI_ANY_ID,692692+ },693693+ { } /* Terminating entry */694694+};695695+696696+static struct pci_driver lynx_pci_driver = {697697+ .name = driver_name,698698+ .id_table = pci_table,699699+ .probe = add_card,700700+ .remove = remove_card,701701+};702702+703703+MODULE_AUTHOR("Kristian Hoegsberg");704704+MODULE_DESCRIPTION("Snoop mode driver for TI pcilynx 1394 controllers");705705+MODULE_LICENSE("GPL");706706+MODULE_DEVICE_TABLE(pci, pci_table);707707+708708+static int __init nosy_init(void)709709+{710710+ return pci_register_driver(&lynx_pci_driver);711711+}712712+713713+static void __exit nosy_cleanup(void)714714+{715715+ pci_unregister_driver(&lynx_pci_driver);716716+717717+ pr_info("Unloaded %s\n", driver_name);718718+}719719+720720+module_init(nosy_init);721721+module_exit(nosy_cleanup);
···194194195195static void handle_fcp(struct fw_card *card, struct fw_request *request,196196 int tcode, int destination, int source, int generation,197197- int speed, unsigned long long offset,198198- void *payload, size_t length, void *callback_data)197197+ unsigned long long offset, void *payload, size_t length,198198+ void *callback_data)199199{200200 struct firedtv *f, *fdtv = NULL;201201 struct fw_device *device;
+405-92
include/linux/firewire-cdev.h
···3030#include <linux/types.h>3131#include <linux/firewire-constants.h>32323333-#define FW_CDEV_EVENT_BUS_RESET 0x003434-#define FW_CDEV_EVENT_RESPONSE 0x013535-#define FW_CDEV_EVENT_REQUEST 0x023636-#define FW_CDEV_EVENT_ISO_INTERRUPT 0x033737-#define FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED 0x043838-#define FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED 0x053333+#define FW_CDEV_EVENT_BUS_RESET 0x003434+#define FW_CDEV_EVENT_RESPONSE 0x013535+#define FW_CDEV_EVENT_REQUEST 0x023636+#define FW_CDEV_EVENT_ISO_INTERRUPT 0x033737+#define FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED 0x043838+#define FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED 0x053939+4040+/* available since kernel version 2.6.36 */4141+#define FW_CDEV_EVENT_REQUEST2 0x064242+#define FW_CDEV_EVENT_PHY_PACKET_SENT 0x074343+#define FW_CDEV_EVENT_PHY_PACKET_RECEIVED 0x084444+#define FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL 0x0939454046/**4147 * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types···7468 * This event is sent when the bus the device belongs to goes through a bus7569 * reset. It provides information about the new bus configuration, such as7670 * new node ID for this device, new root ID, and others.7171+ *7272+ * If @bm_node_id is 0xffff right after bus reset it can be reread by an7373+ * %FW_CDEV_IOC_GET_INFO ioctl after bus manager selection was finished.7474+ * Kernels with ABI version < 4 do not set @bm_node_id.7775 */7876struct fw_cdev_event_bus_reset {7977 __u64 closure;···92829383/**9484 * struct fw_cdev_event_response - Sent when a response packet was received9595- * @closure: See &fw_cdev_event_common;9696- * set by %FW_CDEV_IOC_SEND_REQUEST ioctl8585+ * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_SEND_REQUEST8686+ * or %FW_CDEV_IOC_SEND_BROADCAST_REQUEST8787+ * or %FW_CDEV_IOC_SEND_STREAM_PACKET ioctl9788 * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_RESPONSE9889 * @rcode: Response code returned by the remote node9990 * @length: Data length, i.e. the response's payload size in bytes···10493 * sent by %FW_CDEV_IOC_SEND_REQUEST ioctl. The payload data for responses10594 * carrying data (read and lock responses) follows immediately and can be10695 * accessed through the @data field.9696+ *9797+ * The event is also generated after conclusions of transactions that do not9898+ * involve response packets. This includes unified write transactions,9999+ * broadcast write transactions, and transmission of asynchronous stream100100+ * packets. @rcode indicates success or failure of such transmissions.107101 */108102struct fw_cdev_event_response {109103 __u64 closure;···119103};120104121105/**122122- * struct fw_cdev_event_request - Sent on incoming request to an address region106106+ * struct fw_cdev_event_request - Old version of &fw_cdev_event_request2123107 * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl124108 * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST109109+ * @tcode: See &fw_cdev_event_request2110110+ * @offset: See &fw_cdev_event_request2111111+ * @handle: See &fw_cdev_event_request2112112+ * @length: See &fw_cdev_event_request2113113+ * @data: See &fw_cdev_event_request2114114+ *115115+ * This event is sent instead of &fw_cdev_event_request2 if the kernel or116116+ * the client implements ABI version <= 3.117117+ *118118+ * Unlike &fw_cdev_event_request2, the sender identity cannot be established,119119+ * broadcast write requests cannot be distinguished from unicast writes, and120120+ * @tcode of lock requests is %TCODE_LOCK_REQUEST.121121+ *122122+ * Requests to the FCP_REQUEST or FCP_RESPONSE register are responded to as123123+ * with &fw_cdev_event_request2, except in kernel 2.6.32 and older which send124124+ * the response packet of the client's %FW_CDEV_IOC_SEND_RESPONSE ioctl.125125+ */126126+struct fw_cdev_event_request {127127+ __u64 closure;128128+ __u32 type;129129+ __u32 tcode;130130+ __u64 offset;131131+ __u32 handle;132132+ __u32 length;133133+ __u32 data[0];134134+};135135+136136+/**137137+ * struct fw_cdev_event_request2 - Sent on incoming request to an address region138138+ * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl139139+ * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST2125140 * @tcode: Transaction code of the incoming request126141 * @offset: The offset into the 48-bit per-node address space142142+ * @source_node_id: Sender node ID143143+ * @destination_node_id: Destination node ID144144+ * @card: The index of the card from which the request came145145+ * @generation: Bus generation in which the request is valid127146 * @handle: Reference to the kernel-side pending request128147 * @length: Data length, i.e. the request's payload size in bytes129148 * @data: Incoming data, if any···171120 *172121 * The payload data for requests carrying data (write and lock requests)173122 * follows immediately and can be accessed through the @data field.123123+ *124124+ * Unlike &fw_cdev_event_request, @tcode of lock requests is one of the125125+ * firewire-core specific %TCODE_LOCK_MASK_SWAP...%TCODE_LOCK_VENDOR_DEPENDENT,126126+ * i.e. encodes the extended transaction code.127127+ *128128+ * @card may differ from &fw_cdev_get_info.card because requests are received129129+ * from all cards of the Linux host. @source_node_id, @destination_node_id, and130130+ * @generation pertain to that card. Destination node ID and bus generation may131131+ * therefore differ from the corresponding fields of the last132132+ * &fw_cdev_event_bus_reset.133133+ *134134+ * @destination_node_id may also differ from the current node ID because of a135135+ * non-local bus ID part or in case of a broadcast write request. Note, a136136+ * client must call an %FW_CDEV_IOC_SEND_RESPONSE ioctl even in case of a137137+ * broadcast write request; the kernel will then release the kernel-side pending138138+ * request but will not actually send a response packet.139139+ *140140+ * In case of a write request to FCP_REQUEST or FCP_RESPONSE, the kernel already141141+ * sent a write response immediately after the request was received; in this142142+ * case the client must still call an %FW_CDEV_IOC_SEND_RESPONSE ioctl to143143+ * release the kernel-side pending request, though another response won't be144144+ * sent.145145+ *146146+ * If the client subsequently needs to initiate requests to the sender node of147147+ * an &fw_cdev_event_request2, it needs to use a device file with matching148148+ * card index, node ID, and generation for outbound requests.174149 */175175-struct fw_cdev_event_request {150150+struct fw_cdev_event_request2 {176151 __u64 closure;177152 __u32 type;178153 __u32 tcode;179154 __u64 offset;155155+ __u32 source_node_id;156156+ __u32 destination_node_id;157157+ __u32 card;158158+ __u32 generation;180159 __u32 handle;181160 __u32 length;182161 __u32 data[0];···222141 * @header: Stripped headers, if any223142 *224143 * This event is sent when the controller has completed an &fw_cdev_iso_packet225225- * with the %FW_CDEV_ISO_INTERRUPT bit set. In the receive case, the headers226226- * stripped of all packets up until and including the interrupt packet are227227- * returned in the @header field. The amount of header data per packet is as228228- * specified at iso context creation by &fw_cdev_create_iso_context.header_size.144144+ * with the %FW_CDEV_ISO_INTERRUPT bit set.229145 *230230- * In version 1 of this ABI, header data consisted of the 1394 isochronous231231- * packet header, followed by quadlets from the packet payload if232232- * &fw_cdev_create_iso_context.header_size > 4.146146+ * Isochronous transmit events (context type %FW_CDEV_ISO_CONTEXT_TRANSMIT):233147 *234234- * In version 2 of this ABI, header data consist of the 1394 isochronous235235- * packet header, followed by a timestamp quadlet if236236- * &fw_cdev_create_iso_context.header_size > 4, followed by quadlets from the237237- * packet payload if &fw_cdev_create_iso_context.header_size > 8.148148+ * In version 3 and some implementations of version 2 of the ABI, &header_length149149+ * is a multiple of 4 and &header contains timestamps of all packets up until150150+ * the interrupt packet. The format of the timestamps is as described below for151151+ * isochronous reception. In version 1 of the ABI, &header_length was 0.238152 *153153+ * Isochronous receive events (context type %FW_CDEV_ISO_CONTEXT_RECEIVE):154154+ *155155+ * The headers stripped of all packets up until and including the interrupt156156+ * packet are returned in the @header field. The amount of header data per157157+ * packet is as specified at iso context creation by158158+ * &fw_cdev_create_iso_context.header_size.159159+ *160160+ * Hence, _interrupt.header_length / _context.header_size is the number of161161+ * packets received in this interrupt event. The client can now iterate162162+ * through the mmap()'ed DMA buffer according to this number of packets and163163+ * to the buffer sizes as the client specified in &fw_cdev_queue_iso.164164+ *165165+ * Since version 2 of this ABI, the portion for each packet in _interrupt.header166166+ * consists of the 1394 isochronous packet header, followed by a timestamp167167+ * quadlet if &fw_cdev_create_iso_context.header_size > 4, followed by quadlets168168+ * from the packet payload if &fw_cdev_create_iso_context.header_size > 8.169169+ *170170+ * Format of 1394 iso packet header: 16 bits data_length, 2 bits tag, 6 bits171171+ * channel, 4 bits tcode, 4 bits sy, in big endian byte order.172172+ * data_length is the actual received size of the packet without the four173173+ * 1394 iso packet header bytes.174174+ *175175+ * Format of timestamp: 16 bits invalid, 3 bits cycleSeconds, 13 bits176176+ * cycleCount, in big endian byte order.177177+ *178178+ * In version 1 of the ABI, no timestamp quadlet was inserted; instead, payload179179+ * data followed directly after the 1394 is header if header_size > 4.239180 * Behaviour of ver. 1 of this ABI is no longer available since ABI ver. 2.240240- *241241- * Format of 1394 iso packet header: 16 bits len, 2 bits tag, 6 bits channel,242242- * 4 bits tcode, 4 bits sy, in big endian byte order. Format of timestamp:243243- * 16 bits invalid, 3 bits cycleSeconds, 13 bits cycleCount, in big endian byte244244- * order.245181 */246182struct fw_cdev_event_iso_interrupt {247183 __u64 closure;···266168 __u32 cycle;267169 __u32 header_length;268170 __u32 header[0];171171+};172172+173173+/**174174+ * struct fw_cdev_event_iso_interrupt_mc - An iso buffer chunk was completed175175+ * @closure: See &fw_cdev_event_common;176176+ * set by %FW_CDEV_CREATE_ISO_CONTEXT ioctl177177+ * @type: %FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL178178+ * @completed: Offset into the receive buffer; data before this offest is valid179179+ *180180+ * This event is sent in multichannel contexts (context type181181+ * %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL) for &fw_cdev_iso_packet buffer182182+ * chunks that have the %FW_CDEV_ISO_INTERRUPT bit set. Whether this happens183183+ * when a packet is completed and/or when a buffer chunk is completed depends184184+ * on the hardware implementation.185185+ *186186+ * The buffer is continuously filled with the following data, per packet:187187+ * - the 1394 iso packet header as described at &fw_cdev_event_iso_interrupt,188188+ * but in little endian byte order,189189+ * - packet payload (as many bytes as specified in the data_length field of190190+ * the 1394 iso packet header) in big endian byte order,191191+ * - 0...3 padding bytes as needed to align the following trailer quadlet,192192+ * - trailer quadlet, containing the reception timestamp as described at193193+ * &fw_cdev_event_iso_interrupt, but in little endian byte order.194194+ *195195+ * Hence the per-packet size is data_length (rounded up to a multiple of 4) + 8.196196+ * When processing the data, stop before a packet that would cross the197197+ * @completed offset.198198+ *199199+ * A packet near the end of a buffer chunk will typically spill over into the200200+ * next queued buffer chunk. It is the responsibility of the client to check201201+ * for this condition, assemble a broken-up packet from its parts, and not to202202+ * re-queue any buffer chunks in which as yet unread packet parts reside.203203+ */204204+struct fw_cdev_event_iso_interrupt_mc {205205+ __u64 closure;206206+ __u32 type;207207+ __u32 completed;269208};270209271210/**···335200};336201337202/**203203+ * struct fw_cdev_event_phy_packet - A PHY packet was transmitted or received204204+ * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_SEND_PHY_PACKET205205+ * or %FW_CDEV_IOC_RECEIVE_PHY_PACKETS ioctl206206+ * @type: %FW_CDEV_EVENT_PHY_PACKET_SENT or %..._RECEIVED207207+ * @rcode: %RCODE_..., indicates success or failure of transmission208208+ * @length: Data length in bytes209209+ * @data: Incoming data210210+ *211211+ * If @type is %FW_CDEV_EVENT_PHY_PACKET_SENT, @length is 0 and @data empty,212212+ * except in case of a ping packet: Then, @length is 4, and @data[0] is the213213+ * ping time in 49.152MHz clocks if @rcode is %RCODE_COMPLETE.214214+ *215215+ * If @type is %FW_CDEV_EVENT_PHY_PACKET_RECEIVED, @length is 8 and @data216216+ * consists of the two PHY packet quadlets, in host byte order.217217+ */218218+struct fw_cdev_event_phy_packet {219219+ __u64 closure;220220+ __u32 type;221221+ __u32 rcode;222222+ __u32 length;223223+ __u32 data[0];224224+};225225+226226+/**338227 * union fw_cdev_event - Convenience union of fw_cdev_event_ types339339- * @common: Valid for all types340340- * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET341341- * @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE342342- * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST343343- * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT344344- * @iso_resource: Valid if @common.type ==228228+ * @common: Valid for all types229229+ * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET230230+ * @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE231231+ * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST232232+ * @request2: Valid if @common.type == %FW_CDEV_EVENT_REQUEST2233233+ * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT234234+ * @iso_interrupt_mc: Valid if @common.type ==235235+ * %FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL236236+ * @iso_resource: Valid if @common.type ==345237 * %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or346238 * %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED239239+ * @phy_packet: Valid if @common.type ==240240+ * %FW_CDEV_EVENT_PHY_PACKET_SENT or241241+ * %FW_CDEV_EVENT_PHY_PACKET_RECEIVED347242 *348243 * Convenience union for userspace use. Events could be read(2) into an349244 * appropriately aligned char buffer and then cast to this union for further···388223 struct fw_cdev_event_bus_reset bus_reset;389224 struct fw_cdev_event_response response;390225 struct fw_cdev_event_request request;226226+ struct fw_cdev_event_request2 request2; /* added in 2.6.36 */391227 struct fw_cdev_event_iso_interrupt iso_interrupt;392392- struct fw_cdev_event_iso_resource iso_resource;228228+ struct fw_cdev_event_iso_interrupt_mc iso_interrupt_mc; /* added in 2.6.36 */229229+ struct fw_cdev_event_iso_resource iso_resource; /* added in 2.6.30 */230230+ struct fw_cdev_event_phy_packet phy_packet; /* added in 2.6.36 */393231};394232395233/* available since kernel version 2.6.22 */···424256/* available since kernel version 2.6.34 */425257#define FW_CDEV_IOC_GET_CYCLE_TIMER2 _IOWR('#', 0x14, struct fw_cdev_get_cycle_timer2)426258259259+/* available since kernel version 2.6.36 */260260+#define FW_CDEV_IOC_SEND_PHY_PACKET _IOWR('#', 0x15, struct fw_cdev_send_phy_packet)261261+#define FW_CDEV_IOC_RECEIVE_PHY_PACKETS _IOW('#', 0x16, struct fw_cdev_receive_phy_packets)262262+#define FW_CDEV_IOC_SET_ISO_CHANNELS _IOW('#', 0x17, struct fw_cdev_set_iso_channels)263263+427264/*428428- * FW_CDEV_VERSION History265265+ * ABI version history429266 * 1 (2.6.22) - initial version267267+ * (2.6.24) - added %FW_CDEV_IOC_GET_CYCLE_TIMER430268 * 2 (2.6.30) - changed &fw_cdev_event_iso_interrupt.header if431269 * &fw_cdev_create_iso_context.header_size is 8 or more270270+ * - added %FW_CDEV_IOC_*_ISO_RESOURCE*,271271+ * %FW_CDEV_IOC_GET_SPEED, %FW_CDEV_IOC_SEND_BROADCAST_REQUEST,272272+ * %FW_CDEV_IOC_SEND_STREAM_PACKET432273 * (2.6.32) - added time stamp to xmit &fw_cdev_event_iso_interrupt433274 * (2.6.33) - IR has always packet-per-buffer semantics now, not one of434275 * dual-buffer or packet-per-buffer depending on hardware276276+ * - shared use and auto-response for FCP registers435277 * 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable278278+ * - added %FW_CDEV_IOC_GET_CYCLE_TIMER2279279+ * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2, %FW_CDEV_EVENT_PHY_PACKET_*,280280+ * and &fw_cdev_allocate.region_end281281+ * - implemented &fw_cdev_event_bus_reset.bm_node_id282282+ * - added %FW_CDEV_IOC_SEND_PHY_PACKET, _RECEIVE_PHY_PACKETS283283+ * - added %FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL,284284+ * %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL, and285285+ * %FW_CDEV_IOC_SET_ISO_CHANNELS436286 */437437-#define FW_CDEV_VERSION 3287287+#define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */438288439289/**440290 * struct fw_cdev_get_info - General purpose information ioctl441441- * @version: The version field is just a running serial number.442442- * We never break backwards compatibility, but may add more443443- * structs and ioctls in later revisions.291291+ * @version: The version field is just a running serial number. Both an292292+ * input parameter (ABI version implemented by the client) and293293+ * output parameter (ABI version implemented by the kernel).294294+ * A client must not fill in an %FW_CDEV_VERSION defined from an295295+ * included kernel header file but the actual version for which296296+ * the client was implemented. This is necessary for forward297297+ * compatibility. We never break backwards compatibility, but298298+ * may add more structs, events, and ioctls in later revisions.444299 * @rom_length: If @rom is non-zero, at most rom_length bytes of configuration445300 * ROM will be copied into that user space address. In either446301 * case, @rom_length is updated with the actual length of the···530339};531340532341/**533533- * struct fw_cdev_allocate - Allocate a CSR address range342342+ * struct fw_cdev_allocate - Allocate a CSR in an address range534343 * @offset: Start offset of the address range535344 * @closure: To be passed back to userspace in request events536536- * @length: Length of the address range, in bytes345345+ * @length: Length of the CSR, in bytes537346 * @handle: Handle to the allocation, written by the kernel347347+ * @region_end: First address above the address range (added in ABI v4, 2.6.36)538348 *539349 * Allocate an address range in the 48-bit address space on the local node540350 * (the controller). This allows userspace to listen for requests with an541541- * offset within that address range. When the kernel receives a request542542- * within the range, an &fw_cdev_event_request event will be written back.543543- * The @closure field is passed back to userspace in the response event.351351+ * offset within that address range. Every time when the kernel receives a352352+ * request within the range, an &fw_cdev_event_request2 event will be emitted.353353+ * (If the kernel or the client implements ABI version <= 3, an354354+ * &fw_cdev_event_request will be generated instead.)355355+ *356356+ * The @closure field is passed back to userspace in these request events.544357 * The @handle field is an out parameter, returning a handle to the allocated545358 * range to be used for later deallocation of the range.546359 *547360 * The address range is allocated on all local nodes. The address allocation548548- * is exclusive except for the FCP command and response registers.361361+ * is exclusive except for the FCP command and response registers. If an362362+ * exclusive address region is already in use, the ioctl fails with errno set363363+ * to %EBUSY.364364+ *365365+ * If kernel and client implement ABI version >= 4, the kernel looks up a free366366+ * spot of size @length inside [@offset..@region_end) and, if found, writes367367+ * the start address of the new CSR back in @offset. I.e. @offset is an368368+ * in and out parameter. If this automatic placement of a CSR in a bigger369369+ * address range is not desired, the client simply needs to set @region_end370370+ * = @offset + @length.371371+ *372372+ * If the kernel or the client implements ABI version <= 3, @region_end is373373+ * ignored and effectively assumed to be @offset + @length.374374+ *375375+ * @region_end is only present in a kernel header >= 2.6.36. If necessary,376376+ * this can for example be tested by #ifdef FW_CDEV_EVENT_REQUEST2.549377 */550378struct fw_cdev_allocate {551379 __u64 offset;552380 __u64 closure;553381 __u32 length;554382 __u32 handle;383383+ __u64 region_end; /* available since kernel version 2.6.36 */555384};556385557386/**···593382 * Initiate a bus reset for the bus this device is on. The bus reset can be594383 * either the original (long) bus reset or the arbitrated (short) bus reset595384 * introduced in 1394a-2000.385385+ *386386+ * The ioctl returns immediately. A subsequent &fw_cdev_event_bus_reset387387+ * indicates when the reset actually happened. Since ABI v4, this may be388388+ * considerably later than the ioctl because the kernel ensures a grace period389389+ * between subsequent bus resets as per IEEE 1394 bus management specification.596390 */597391struct fw_cdev_initiate_bus_reset {598598- __u32 type; /* FW_CDEV_SHORT_RESET or FW_CDEV_LONG_RESET */392392+ __u32 type;599393};600394601395/**···624408 *625409 * @immediate, @key, and @data array elements are CPU-endian quadlets.626410 *627627- * If successful, the kernel adds the descriptor and writes back a handle to the628628- * kernel-side object to be used for later removal of the descriptor block and629629- * immediate key.411411+ * If successful, the kernel adds the descriptor and writes back a @handle to412412+ * the kernel-side object to be used for later removal of the descriptor block413413+ * and immediate key. The kernel will also generate a bus reset to signal the414414+ * change of the configuration ROM to other nodes.630415 *631416 * This ioctl affects the configuration ROMs of all local nodes.632417 * The ioctl only succeeds on device files which represent a local node.···646429 * descriptor was added647430 *648431 * Remove a descriptor block and accompanying immediate key from the local649649- * nodes' configuration ROMs.432432+ * nodes' configuration ROMs. The kernel will also generate a bus reset to433433+ * signal the change of the configuration ROM to other nodes.650434 */651435struct fw_cdev_remove_descriptor {652436 __u32 handle;653437};654438655655-#define FW_CDEV_ISO_CONTEXT_TRANSMIT 0656656-#define FW_CDEV_ISO_CONTEXT_RECEIVE 1439439+#define FW_CDEV_ISO_CONTEXT_TRANSMIT 0440440+#define FW_CDEV_ISO_CONTEXT_RECEIVE 1441441+#define FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL 2 /* added in 2.6.36 */657442658443/**659659- * struct fw_cdev_create_iso_context - Create a context for isochronous IO660660- * @type: %FW_CDEV_ISO_CONTEXT_TRANSMIT or %FW_CDEV_ISO_CONTEXT_RECEIVE661661- * @header_size: Header size to strip for receive contexts662662- * @channel: Channel to bind to663663- * @speed: Speed for transmit contexts664664- * @closure: To be returned in &fw_cdev_event_iso_interrupt444444+ * struct fw_cdev_create_iso_context - Create a context for isochronous I/O445445+ * @type: %FW_CDEV_ISO_CONTEXT_TRANSMIT or %FW_CDEV_ISO_CONTEXT_RECEIVE or446446+ * %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL447447+ * @header_size: Header size to strip in single-channel reception448448+ * @channel: Channel to bind to in single-channel reception or transmission449449+ * @speed: Transmission speed450450+ * @closure: To be returned in &fw_cdev_event_iso_interrupt or451451+ * &fw_cdev_event_iso_interrupt_multichannel665452 * @handle: Handle to context, written back by kernel666453 *667454 * Prior to sending or receiving isochronous I/O, a context must be created.668455 * The context records information about the transmit or receive configuration669456 * and typically maps to an underlying hardware resource. A context is set up670457 * for either sending or receiving. It is bound to a specific isochronous671671- * channel.458458+ * @channel.459459+ *460460+ * In case of multichannel reception, @header_size and @channel are ignored461461+ * and the channels are selected by %FW_CDEV_IOC_SET_ISO_CHANNELS.462462+ *463463+ * For %FW_CDEV_ISO_CONTEXT_RECEIVE contexts, @header_size must be at least 4464464+ * and must be a multiple of 4. It is ignored in other context types.465465+ *466466+ * @speed is ignored in receive context types.672467 *673468 * If a context was successfully created, the kernel writes back a handle to the674469 * context, which must be passed in for subsequent operations on that context.675470 *676676- * For receive contexts, @header_size must be at least 4 and must be a multiple677677- * of 4.678678- *679679- * Note that the effect of a @header_size > 4 depends on680680- * &fw_cdev_get_info.version, as documented at &fw_cdev_event_iso_interrupt.471471+ * Limitations:472472+ * No more than one iso context can be created per fd.473473+ * The total number of contexts that all userspace and kernelspace drivers can474474+ * create on a card at a time is a hardware limit, typically 4 or 8 contexts per475475+ * direction, and of them at most one multichannel receive context.681476 */682477struct fw_cdev_create_iso_context {683478 __u32 type;···697468 __u32 channel;698469 __u32 speed;699470 __u64 closure;471471+ __u32 handle;472472+};473473+474474+/**475475+ * struct fw_cdev_set_iso_channels - Select channels in multichannel reception476476+ * @channels: Bitmask of channels to listen to477477+ * @handle: Handle of the mutichannel receive context478478+ *479479+ * @channels is the bitwise or of 1ULL << n for each channel n to listen to.480480+ *481481+ * The ioctl fails with errno %EBUSY if there is already another receive context482482+ * on a channel in @channels. In that case, the bitmask of all unoccupied483483+ * channels is returned in @channels.484484+ */485485+struct fw_cdev_set_iso_channels {486486+ __u64 channels;700487 __u32 handle;701488};702489···726481727482/**728483 * struct fw_cdev_iso_packet - Isochronous packet729729- * @control: Contains the header length (8 uppermost bits), the sy field730730- * (4 bits), the tag field (2 bits), a sync flag (1 bit),731731- * a skip flag (1 bit), an interrupt flag (1 bit), and the484484+ * @control: Contains the header length (8 uppermost bits),485485+ * the sy field (4 bits), the tag field (2 bits), a sync flag486486+ * or a skip flag (1 bit), an interrupt flag (1 bit), and the732487 * payload length (16 lowermost bits)733733- * @header: Header and payload488488+ * @header: Header and payload in case of a transmit context.734489 *735490 * &struct fw_cdev_iso_packet is used to describe isochronous packet queues.736736- *737491 * Use the FW_CDEV_ISO_ macros to fill in @control.492492+ * The @header array is empty in case of receive contexts.738493 *739739- * For transmit packets, the header length must be a multiple of 4 and specifies740740- * the numbers of bytes in @header that will be prepended to the packet's741741- * payload; these bytes are copied into the kernel and will not be accessed742742- * after the ioctl has returned. The sy and tag fields are copied to the iso743743- * packet header (these fields are specified by IEEE 1394a and IEC 61883-1).744744- * The skip flag specifies that no packet is to be sent in a frame; when using745745- * this, all other fields except the interrupt flag must be zero.494494+ * Context type %FW_CDEV_ISO_CONTEXT_TRANSMIT:746495 *747747- * For receive packets, the header length must be a multiple of the context's748748- * header size; if the header length is larger than the context's header size,749749- * multiple packets are queued for this entry. The sy and tag fields are750750- * ignored. If the sync flag is set, the context drops all packets until751751- * a packet with a matching sy field is received (the sync value to wait for is752752- * specified in the &fw_cdev_start_iso structure). The payload length defines753753- * how many payload bytes can be received for one packet (in addition to payload754754- * quadlets that have been defined as headers and are stripped and returned in755755- * the &fw_cdev_event_iso_interrupt structure). If more bytes are received, the756756- * additional bytes are dropped. If less bytes are received, the remaining757757- * bytes in this part of the payload buffer will not be written to, not even by758758- * the next packet, i.e., packets received in consecutive frames will not759759- * necessarily be consecutive in memory. If an entry has queued multiple760760- * packets, the payload length is divided equally among them.496496+ * @control.HEADER_LENGTH must be a multiple of 4. It specifies the numbers of497497+ * bytes in @header that will be prepended to the packet's payload. These bytes498498+ * are copied into the kernel and will not be accessed after the ioctl has499499+ * returned.761500 *762762- * When a packet with the interrupt flag set has been completed, the501501+ * The @control.SY and TAG fields are copied to the iso packet header. These502502+ * fields are specified by IEEE 1394a and IEC 61883-1.503503+ *504504+ * The @control.SKIP flag specifies that no packet is to be sent in a frame.505505+ * When using this, all other fields except @control.INTERRUPT must be zero.506506+ *507507+ * When a packet with the @control.INTERRUPT flag set has been completed, an508508+ * &fw_cdev_event_iso_interrupt event will be sent.509509+ *510510+ * Context type %FW_CDEV_ISO_CONTEXT_RECEIVE:511511+ *512512+ * @control.HEADER_LENGTH must be a multiple of the context's header_size.513513+ * If the HEADER_LENGTH is larger than the context's header_size, multiple514514+ * packets are queued for this entry.515515+ *516516+ * The @control.SY and TAG fields are ignored.517517+ *518518+ * If the @control.SYNC flag is set, the context drops all packets until a519519+ * packet with a sy field is received which matches &fw_cdev_start_iso.sync.520520+ *521521+ * @control.PAYLOAD_LENGTH defines how many payload bytes can be received for522522+ * one packet (in addition to payload quadlets that have been defined as headers523523+ * and are stripped and returned in the &fw_cdev_event_iso_interrupt structure).524524+ * If more bytes are received, the additional bytes are dropped. If less bytes525525+ * are received, the remaining bytes in this part of the payload buffer will not526526+ * be written to, not even by the next packet. I.e., packets received in527527+ * consecutive frames will not necessarily be consecutive in memory. If an528528+ * entry has queued multiple packets, the PAYLOAD_LENGTH is divided equally529529+ * among them.530530+ *531531+ * When a packet with the @control.INTERRUPT flag set has been completed, an763532 * &fw_cdev_event_iso_interrupt event will be sent. An entry that has queued764533 * multiple receive packets is completed when its last packet is completed.534534+ *535535+ * Context type %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL:536536+ *537537+ * Here, &fw_cdev_iso_packet would be more aptly named _iso_buffer_chunk since538538+ * it specifies a chunk of the mmap()'ed buffer, while the number and alignment539539+ * of packets to be placed into the buffer chunk is not known beforehand.540540+ *541541+ * @control.PAYLOAD_LENGTH is the size of the buffer chunk and specifies room542542+ * for header, payload, padding, and trailer bytes of one or more packets.543543+ * It must be a multiple of 4.544544+ *545545+ * @control.HEADER_LENGTH, TAG and SY are ignored. SYNC is treated as described546546+ * for single-channel reception.547547+ *548548+ * When a buffer chunk with the @control.INTERRUPT flag set has been filled549549+ * entirely, an &fw_cdev_event_iso_interrupt_mc event will be sent.765550 */766551struct fw_cdev_iso_packet {767552 __u32 control;···800525801526/**802527 * struct fw_cdev_queue_iso - Queue isochronous packets for I/O803803- * @packets: Userspace pointer to packet data528528+ * @packets: Userspace pointer to an array of &fw_cdev_iso_packet804529 * @data: Pointer into mmap()'ed payload buffer805805- * @size: Size of packet data in bytes530530+ * @size: Size of the @packets array, in bytes806531 * @handle: Isochronous context handle807532 *808533 * Queue a number of isochronous packets for reception or transmission.···815540 * The kernel may or may not queue all packets, but will write back updated816541 * values of the @packets, @data and @size fields, so the ioctl can be817542 * resubmitted easily.543543+ *544544+ * In case of a multichannel receive context, @data must be quadlet-aligned545545+ * relative to the buffer start.818546 */819547struct fw_cdev_queue_iso {820548 __u64 packets;···974696 __u64 data;975697 __u32 generation;976698 __u32 speed;699699+};700700+701701+/**702702+ * struct fw_cdev_send_phy_packet - send a PHY packet703703+ * @closure: Passed back to userspace in the PHY-packet-sent event704704+ * @data: First and second quadlet of the PHY packet705705+ * @generation: The bus generation where packet is valid706706+ *707707+ * The %FW_CDEV_IOC_SEND_PHY_PACKET ioctl sends a PHY packet to all nodes708708+ * on the same card as this device. After transmission, an709709+ * %FW_CDEV_EVENT_PHY_PACKET_SENT event is generated.710710+ *711711+ * The payload @data[] shall be specified in host byte order. Usually,712712+ * @data[1] needs to be the bitwise inverse of @data[0]. VersaPHY packets713713+ * are an exception to this rule.714714+ *715715+ * The ioctl is only permitted on device files which represent a local node.716716+ */717717+struct fw_cdev_send_phy_packet {718718+ __u64 closure;719719+ __u32 data[2];720720+ __u32 generation;721721+};722722+723723+/**724724+ * struct fw_cdev_receive_phy_packets - start reception of PHY packets725725+ * @closure: Passed back to userspace in phy packet events726726+ *727727+ * This ioctl activates issuing of %FW_CDEV_EVENT_PHY_PACKET_RECEIVED due to728728+ * incoming PHY packets from any node on the same bus as the device.729729+ *730730+ * The ioctl is only permitted on device files which represent a local node.731731+ */732732+struct fw_cdev_receive_phy_packets {733733+ __u64 closure;977734};978735979736#endif /* _LINUX_FIREWIRE_CDEV_H */
+44-18
include/linux/firewire.h
···3232#define CSR_CYCLE_TIME 0x2003333#define CSR_BUS_TIME 0x2043434#define CSR_BUSY_TIMEOUT 0x2103535+#define CSR_PRIORITY_BUDGET 0x2183536#define CSR_BUS_MANAGER_ID 0x21c3637#define CSR_BANDWIDTH_AVAILABLE 0x2203738#define CSR_CHANNELS_AVAILABLE 0x2243839#define CSR_CHANNELS_AVAILABLE_HI 0x2243940#define CSR_CHANNELS_AVAILABLE_LO 0x2284141+#define CSR_MAINT_UTILITY 0x2304042#define CSR_BROADCAST_CHANNEL 0x2344143#define CSR_CONFIG_ROM 0x4004244#define CSR_CONFIG_ROM_END 0x800···9189 struct list_head transaction_list;9290 unsigned long reset_jiffies;93919292+ u32 split_timeout_hi;9393+ u32 split_timeout_lo;9494+ unsigned int split_timeout_cycles;9595+ unsigned int split_timeout_jiffies;9696+9497 unsigned long long guid;9598 unsigned max_receive;9699 int link_speed;···111104 bool beta_repeaters_present;112105113106 int index;114114-115107 struct list_head link;116108117117- /* Work struct for BM duties. */118118- struct delayed_work work;109109+ struct list_head phy_receiver_list;110110+111111+ struct delayed_work br_work; /* bus reset job */112112+ bool br_short;113113+114114+ struct delayed_work bm_work; /* bus manager job */119115 int bm_retries;120116 int bm_generation;121117 __be32 bm_transaction_data[2];118118+ int bm_node_id;119119+ bool bm_abdicate;120120+121121+ bool priority_budget_implemented; /* controller feature */122122+ bool broadcast_channel_auto_allocated; /* controller feature */122123123124 bool broadcast_channel_allocated;124125 u32 broadcast_channel;125126 __be32 topology_map[(CSR_TOPOLOGY_MAP_END - CSR_TOPOLOGY_MAP) / 4];127127+128128+ __be32 maint_utility_register;126129};127130128131struct fw_attribute_group {···269252typedef void (*fw_address_callback_t)(struct fw_card *card,270253 struct fw_request *request,271254 int tcode, int destination, int source,272272- int generation, int speed,255255+ int generation,273256 unsigned long long offset,274257 void *data, size_t length,275258 void *callback_data);···286269 u32 timestamp;287270288271 /*289289- * This callback is called when the packet transmission has290290- * completed; for successful transmission, the status code is291291- * the ack received from the destination, otherwise it's a292292- * negative errno: ENOMEM, ESTALE, ETIMEDOUT, ENODEV, EIO.272272+ * This callback is called when the packet transmission has completed.273273+ * For successful transmission, the status code is the ack received274274+ * from the destination. Otherwise it is one of the juju-specific275275+ * rcodes: RCODE_SEND_ERROR, _CANCELLED, _BUSY, _GENERATION, _NO_ACK.293276 * The callback can be called from tasklet context and thus294277 * must never block.295278 */···372355 * scatter-gather streaming (e.g. assembling video frame automatically).373356 */374357struct fw_iso_packet {375375- u16 payload_length; /* Length of indirect payload. */376376- u32 interrupt:1; /* Generate interrupt on this packet */377377- u32 skip:1; /* Set to not send packet at all. */378378- u32 tag:2;379379- u32 sy:4;380380- u32 header_length:8; /* Length of immediate header. */381381- u32 header[0];358358+ u16 payload_length; /* Length of indirect payload */359359+ u32 interrupt:1; /* Generate interrupt on this packet */360360+ u32 skip:1; /* tx: Set to not send packet at all */361361+ /* rx: Sync bit, wait for matching sy */362362+ u32 tag:2; /* tx: Tag in packet header */363363+ u32 sy:4; /* tx: Sy in packet header */364364+ u32 header_length:8; /* Length of immediate header */365365+ u32 header[0]; /* tx: Top of 1394 isoch. data_block */382366};383367384384-#define FW_ISO_CONTEXT_TRANSMIT 0385385-#define FW_ISO_CONTEXT_RECEIVE 1368368+#define FW_ISO_CONTEXT_TRANSMIT 0369369+#define FW_ISO_CONTEXT_RECEIVE 1370370+#define FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL 2386371387372#define FW_ISO_CONTEXT_MATCH_TAG0 1388373#define FW_ISO_CONTEXT_MATCH_TAG1 2···408389int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card,409390 int page_count, enum dma_data_direction direction);410391void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card);392392+size_t fw_iso_buffer_lookup(struct fw_iso_buffer *buffer, dma_addr_t completed);411393412394struct fw_iso_context;413395typedef void (*fw_iso_callback_t)(struct fw_iso_context *context,414396 u32 cycle, size_t header_length,415397 void *header, void *data);398398+typedef void (*fw_iso_mc_callback_t)(struct fw_iso_context *context,399399+ dma_addr_t completed, void *data);416400struct fw_iso_context {417401 struct fw_card *card;418402 int type;419403 int channel;420404 int speed;421405 size_t header_size;422422- fw_iso_callback_t callback;406406+ union {407407+ fw_iso_callback_t sc;408408+ fw_iso_mc_callback_t mc;409409+ } callback;423410 void *callback_data;424411};425412426413struct fw_iso_context *fw_iso_context_create(struct fw_card *card,427414 int type, int channel, int speed, size_t header_size,428415 fw_iso_callback_t callback, void *callback_data);416416+int fw_iso_context_set_channels(struct fw_iso_context *ctx, u64 *channels);429417int fw_iso_context_queue(struct fw_iso_context *ctx,430418 struct fw_iso_packet *packet,431419 struct fw_iso_buffer *buffer,