187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter/* 287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter * FireDTV driver -- firewire I/O backend 387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter */ 487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#include <linux/device.h> 687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#include <linux/errno.h> 787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#include <linux/firewire.h> 887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#include <linux/firewire-constants.h> 987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#include <linux/kernel.h> 1087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#include <linux/list.h> 11a8aeb7836edac3e0cce1286eefbca793c54cbad0Stefan Richter#include <linux/mm.h> 1292374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter#include <linux/mod_devicetable.h> 1392374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter#include <linux/module.h> 1492374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter#include <linux/mutex.h> 1587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#include <linux/slab.h> 1687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#include <linux/spinlock.h> 1792374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter#include <linux/string.h> 1887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#include <linux/types.h> 1992374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter#include <linux/wait.h> 2092374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter#include <linux/workqueue.h> 2187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 2287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#include <asm/page.h> 2387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 2487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#include <dvb_demux.h> 2587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 2687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#include "firedtv.h" 2787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 2887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richterstatic LIST_HEAD(node_list); 2987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richterstatic DEFINE_SPINLOCK(node_list_lock); 3087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 3187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richterstatic inline struct fw_device *device_of(struct firedtv *fdtv) 3287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter{ 3387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter return fw_device(fdtv->device->parent); 3487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter} 3587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 3687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richterstatic int node_req(struct firedtv *fdtv, u64 addr, void *data, size_t len, 3787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter int tcode) 3887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter{ 3987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter struct fw_device *device = device_of(fdtv); 4087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter int rcode, generation = device->generation; 4187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 4287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter smp_rmb(); /* node_id vs. generation */ 4387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 4487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter rcode = fw_run_transaction(device->card, tcode, device->node_id, 4587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter generation, device->max_speed, addr, data, len); 4687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 4787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter return rcode != RCODE_COMPLETE ? -EIO : 0; 4887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter} 4987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 5092374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richterint fdtv_lock(struct firedtv *fdtv, u64 addr, void *data) 5187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter{ 5287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter return node_req(fdtv, addr, data, 8, TCODE_LOCK_COMPARE_SWAP); 5387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter} 5487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 5592374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richterint fdtv_read(struct firedtv *fdtv, u64 addr, void *data) 5687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter{ 575375659a3df319700d97d911e44926fb43354839Stefan Richter return node_req(fdtv, addr, data, 4, TCODE_READ_QUADLET_REQUEST); 5887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter} 5987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 6092374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richterint fdtv_write(struct firedtv *fdtv, u64 addr, void *data, size_t len) 6187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter{ 6287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter return node_req(fdtv, addr, data, len, TCODE_WRITE_BLOCK_REQUEST); 6387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter} 6487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 6587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#define ISO_HEADER_SIZE 4 6687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#define CIP_HEADER_SIZE 8 6787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#define MPEG2_TS_HEADER_SIZE 4 6887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#define MPEG2_TS_SOURCE_PACKET_SIZE (4 + 188) 6987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 7087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#define MAX_PACKET_SIZE 1024 /* 776, rounded up to 2^n */ 7187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#define PACKETS_PER_PAGE (PAGE_SIZE / MAX_PACKET_SIZE) 7287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#define N_PACKETS 64 /* buffer size */ 7387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#define N_PAGES DIV_ROUND_UP(N_PACKETS, PACKETS_PER_PAGE) 7487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter#define IRQ_INTERVAL 16 7587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 7692374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richterstruct fdtv_ir_context { 7787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter struct fw_iso_context *context; 7887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter struct fw_iso_buffer buffer; 7987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter int interrupt_packet; 8087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter int current_packet; 81a8aeb7836edac3e0cce1286eefbca793c54cbad0Stefan Richter char *pages[N_PAGES]; 8287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter}; 8387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 8492374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richterstatic int queue_iso(struct fdtv_ir_context *ctx, int index) 8587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter{ 8687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter struct fw_iso_packet p; 8787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 8887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter p.payload_length = MAX_PACKET_SIZE; 89b1d33f4b0ae319ca79b6bafd6e815cbe0dcd7c14Stefan Richter p.interrupt = !(++ctx->interrupt_packet & (IRQ_INTERVAL - 1)); 9087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter p.skip = 0; 9187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter p.header_length = ISO_HEADER_SIZE; 9287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 93b1d33f4b0ae319ca79b6bafd6e815cbe0dcd7c14Stefan Richter return fw_iso_context_queue(ctx->context, &p, &ctx->buffer, 94b1d33f4b0ae319ca79b6bafd6e815cbe0dcd7c14Stefan Richter index * MAX_PACKET_SIZE); 9587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter} 9687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 9787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richterstatic void handle_iso(struct fw_iso_context *context, u32 cycle, 9887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter size_t header_length, void *header, void *data) 9987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter{ 10087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter struct firedtv *fdtv = data; 10192374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter struct fdtv_ir_context *ctx = fdtv->ir_context; 10287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter __be32 *h, *h_end; 103a8aeb7836edac3e0cce1286eefbca793c54cbad0Stefan Richter int length, err, i = ctx->current_packet; 10487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter char *p, *p_end; 10587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 10687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter for (h = header, h_end = h + header_length / 4; h < h_end; h++) { 10787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter length = be32_to_cpup(h) >> 16; 10887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter if (unlikely(length > MAX_PACKET_SIZE)) { 10987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter dev_err(fdtv->device, "length = %d\n", length); 11087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter length = MAX_PACKET_SIZE; 11187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter } 11287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 113a8aeb7836edac3e0cce1286eefbca793c54cbad0Stefan Richter p = ctx->pages[i / PACKETS_PER_PAGE] 114a8aeb7836edac3e0cce1286eefbca793c54cbad0Stefan Richter + (i % PACKETS_PER_PAGE) * MAX_PACKET_SIZE; 11587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter p_end = p + length; 11687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 11787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter for (p += CIP_HEADER_SIZE + MPEG2_TS_HEADER_SIZE; p < p_end; 11887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter p += MPEG2_TS_SOURCE_PACKET_SIZE) 11987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter dvb_dmx_swfilter_packets(&fdtv->demux, p, 1); 12087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 12187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter err = queue_iso(ctx, i); 12287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter if (unlikely(err)) 12387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter dev_err(fdtv->device, "requeue failed\n"); 12487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 12587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter i = (i + 1) & (N_PACKETS - 1); 12687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter } 12713882a82ee1646336c3996c93b4a560a55d2a419Clemens Ladisch fw_iso_context_queue_flush(ctx->context); 12887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter ctx->current_packet = i; 12987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter} 13087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 13192374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richterint fdtv_start_iso(struct firedtv *fdtv) 13287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter{ 13392374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter struct fdtv_ir_context *ctx; 13487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter struct fw_device *device = device_of(fdtv); 135a8aeb7836edac3e0cce1286eefbca793c54cbad0Stefan Richter int i, err; 13687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 13787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); 13887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter if (!ctx) 13987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter return -ENOMEM; 14087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 14187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter ctx->context = fw_iso_context_create(device->card, 14287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter FW_ISO_CONTEXT_RECEIVE, fdtv->isochannel, 14387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter device->max_speed, ISO_HEADER_SIZE, handle_iso, fdtv); 14487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter if (IS_ERR(ctx->context)) { 14587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter err = PTR_ERR(ctx->context); 14687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter goto fail_free; 14787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter } 14887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 14987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter err = fw_iso_buffer_init(&ctx->buffer, device->card, 15087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter N_PAGES, DMA_FROM_DEVICE); 15187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter if (err) 15287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter goto fail_context_destroy; 15387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 154b1d33f4b0ae319ca79b6bafd6e815cbe0dcd7c14Stefan Richter ctx->interrupt_packet = 0; 15587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter ctx->current_packet = 0; 15687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 157a8aeb7836edac3e0cce1286eefbca793c54cbad0Stefan Richter for (i = 0; i < N_PAGES; i++) 158a8aeb7836edac3e0cce1286eefbca793c54cbad0Stefan Richter ctx->pages[i] = page_address(ctx->buffer.pages[i]); 15987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 16087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter for (i = 0; i < N_PACKETS; i++) { 16187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter err = queue_iso(ctx, i); 16287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter if (err) 16387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter goto fail; 16487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter } 16587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 16687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter err = fw_iso_context_start(ctx->context, -1, 0, 16787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter FW_ISO_CONTEXT_MATCH_ALL_TAGS); 16887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter if (err) 16987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter goto fail; 17087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 17192374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter fdtv->ir_context = ctx; 17287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 17387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter return 0; 17487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richterfail: 17587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter fw_iso_buffer_destroy(&ctx->buffer, device->card); 17687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richterfail_context_destroy: 17787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter fw_iso_context_destroy(ctx->context); 17887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richterfail_free: 17987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter kfree(ctx); 18087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 18187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter return err; 18287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter} 18387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 18492374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richtervoid fdtv_stop_iso(struct firedtv *fdtv) 18587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter{ 18692374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter struct fdtv_ir_context *ctx = fdtv->ir_context; 18787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 18887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter fw_iso_context_stop(ctx->context); 18987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter fw_iso_buffer_destroy(&ctx->buffer, device_of(fdtv)->card); 19087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter fw_iso_context_destroy(ctx->context); 19187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter kfree(ctx); 19287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter} 19387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 19487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richterstatic void handle_fcp(struct fw_card *card, struct fw_request *request, 19587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter int tcode, int destination, int source, int generation, 19633e553fe2b4a983ef34a57ab1440d8d33397bb12Stefan Richter unsigned long long offset, void *payload, size_t length, 19733e553fe2b4a983ef34a57ab1440d8d33397bb12Stefan Richter void *callback_data) 19887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter{ 19987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter struct firedtv *f, *fdtv = NULL; 20087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter struct fw_device *device; 20187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter unsigned long flags; 20287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter int su; 20387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 204db5d247ae811f49185a71e703b65acad845e4b18Clemens Ladisch if (length < 2 || (((u8 *)payload)[0] & 0xf0) != 0) 20587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter return; 20687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 20787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter su = ((u8 *)payload)[1] & 0x7; 20887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 20987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter spin_lock_irqsave(&node_list_lock, flags); 21087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter list_for_each_entry(f, &node_list, list) { 21187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter device = device_of(f); 21287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter if (device->generation != generation) 21387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter continue; 21487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 21587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter smp_rmb(); /* node_id vs. generation */ 21687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 21787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter if (device->card == card && 21887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter device->node_id == source && 21987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter (f->subunit == su || (f->subunit == 0 && su == 0x7))) { 22087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter fdtv = f; 22187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter break; 22287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter } 22387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter } 22487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter spin_unlock_irqrestore(&node_list_lock, flags); 22587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 226db5d247ae811f49185a71e703b65acad845e4b18Clemens Ladisch if (fdtv) 22787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter avc_recv(fdtv, payload, length); 22887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter} 22987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 23087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richterstatic struct fw_address_handler fcp_handler = { 23187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter .length = CSR_FCP_END - CSR_FCP_RESPONSE, 23287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter .address_callback = handle_fcp, 23387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter}; 23487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 23587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richterstatic const struct fw_address_region fcp_region = { 23687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter .start = CSR_REGISTER_BASE + CSR_FCP_RESPONSE, 23787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter .end = CSR_REGISTER_BASE + CSR_FCP_END, 23887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter}; 23987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 24092374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richterstatic const char * const model_names[] = { 24192374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter [FIREDTV_UNKNOWN] = "unknown type", 24292374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter [FIREDTV_DVB_S] = "FireDTV S/CI", 24392374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter [FIREDTV_DVB_C] = "FireDTV C/CI", 24492374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter [FIREDTV_DVB_T] = "FireDTV T/CI", 24592374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter [FIREDTV_DVB_S2] = "FireDTV S2 ", 24692374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter}; 24792374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter 24887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter/* Adjust the template string if models with longer names appear. */ 2491f8fef7b3388b5a976e80839679b5bae581a1091Clemens Ladisch#define MAX_MODEL_NAME_LEN sizeof("FireDTV ????") 25087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 25194a87157cde95d38b9cdf1116e4f0fd93f6d25dfStefan Richterstatic int node_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) 25287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter{ 25387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter struct firedtv *fdtv; 2541f8fef7b3388b5a976e80839679b5bae581a1091Clemens Ladisch char name[MAX_MODEL_NAME_LEN]; 25592374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter int name_len, i, err; 25687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 25792374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL); 25887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter if (!fdtv) 25987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter return -ENOMEM; 26087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 26194a87157cde95d38b9cdf1116e4f0fd93f6d25dfStefan Richter dev_set_drvdata(&unit->device, fdtv); 26294a87157cde95d38b9cdf1116e4f0fd93f6d25dfStefan Richter fdtv->device = &unit->device; 26392374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter fdtv->isochannel = -1; 26492374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter fdtv->voltage = 0xff; 26592374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter fdtv->tone = 0xff; 26692374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter 26792374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter mutex_init(&fdtv->avc_mutex); 26892374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter init_waitqueue_head(&fdtv->avc_wait); 26992374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter mutex_init(&fdtv->demux_mutex); 27092374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work); 27192374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter 27294a87157cde95d38b9cdf1116e4f0fd93f6d25dfStefan Richter name_len = fw_csr_string(unit->directory, CSR_MODEL, 27392374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter name, sizeof(name)); 27492374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter for (i = ARRAY_SIZE(model_names); --i; ) 27592374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter if (strlen(model_names[i]) <= name_len && 27692374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter strncmp(name, model_names[i], name_len) == 0) 27792374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter break; 27892374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter fdtv->type = i; 27992374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter 28094a87157cde95d38b9cdf1116e4f0fd93f6d25dfStefan Richter err = fdtv_register_rc(fdtv, &unit->device); 28187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter if (err) 28287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter goto fail_free; 28387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 28487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter spin_lock_irq(&node_list_lock); 28587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter list_add_tail(&fdtv->list, &node_list); 28687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter spin_unlock_irq(&node_list_lock); 28787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 28887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter err = avc_identify_subunit(fdtv); 28987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter if (err) 29087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter goto fail; 29187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 29292374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter err = fdtv_dvb_register(fdtv, model_names[fdtv->type]); 29387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter if (err) 29487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter goto fail; 29587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 29687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter avc_register_remote_control(fdtv); 29787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 29887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter return 0; 29987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richterfail: 30087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter spin_lock_irq(&node_list_lock); 30187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter list_del(&fdtv->list); 30287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter spin_unlock_irq(&node_list_lock); 30387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter fdtv_unregister_rc(fdtv); 30487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richterfail_free: 30587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter kfree(fdtv); 30687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 30787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter return err; 30887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter} 30987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 31094a87157cde95d38b9cdf1116e4f0fd93f6d25dfStefan Richterstatic void node_remove(struct fw_unit *unit) 31187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter{ 31294a87157cde95d38b9cdf1116e4f0fd93f6d25dfStefan Richter struct firedtv *fdtv = dev_get_drvdata(&unit->device); 31387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 31487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter fdtv_dvb_unregister(fdtv); 31587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 31687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter spin_lock_irq(&node_list_lock); 31787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter list_del(&fdtv->list); 31887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter spin_unlock_irq(&node_list_lock); 31987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 32087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter fdtv_unregister_rc(fdtv); 32187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 32287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter kfree(fdtv); 32387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter} 32487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 32587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richterstatic void node_update(struct fw_unit *unit) 32687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter{ 32787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter struct firedtv *fdtv = dev_get_drvdata(&unit->device); 32887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 32987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter if (fdtv->isochannel >= 0) 33087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter cmp_establish_pp_connection(fdtv, fdtv->subunit, 33187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter fdtv->isochannel); 33287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter} 33387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 33492374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter#define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \ 33592374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION) 33692374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter 33792374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter#define DIGITAL_EVERYWHERE_OUI 0x001287 33892374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter#define AVC_UNIT_SPEC_ID_ENTRY 0x00a02d 33992374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter#define AVC_SW_VERSION_ENTRY 0x010001 34092374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter 34192374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richterstatic const struct ieee1394_device_id fdtv_id_table[] = { 34292374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter { 34392374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter /* FloppyDTV S/CI and FloppyDTV S2 */ 34492374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .match_flags = MATCH_FLAGS, 34592374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .vendor_id = DIGITAL_EVERYWHERE_OUI, 34692374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .model_id = 0x000024, 34792374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, 34892374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .version = AVC_SW_VERSION_ENTRY, 34992374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter }, { 35092374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter /* FloppyDTV T/CI */ 35192374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .match_flags = MATCH_FLAGS, 35292374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .vendor_id = DIGITAL_EVERYWHERE_OUI, 35392374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .model_id = 0x000025, 35492374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, 35592374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .version = AVC_SW_VERSION_ENTRY, 35692374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter }, { 35792374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter /* FloppyDTV C/CI */ 35892374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .match_flags = MATCH_FLAGS, 35992374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .vendor_id = DIGITAL_EVERYWHERE_OUI, 36092374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .model_id = 0x000026, 36192374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, 36292374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .version = AVC_SW_VERSION_ENTRY, 36392374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter }, { 36492374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter /* FireDTV S/CI and FloppyDTV S2 */ 36592374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .match_flags = MATCH_FLAGS, 36692374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .vendor_id = DIGITAL_EVERYWHERE_OUI, 36792374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .model_id = 0x000034, 36892374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, 36992374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .version = AVC_SW_VERSION_ENTRY, 37092374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter }, { 37192374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter /* FireDTV T/CI */ 37292374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .match_flags = MATCH_FLAGS, 37392374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .vendor_id = DIGITAL_EVERYWHERE_OUI, 37492374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .model_id = 0x000035, 37592374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, 37692374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .version = AVC_SW_VERSION_ENTRY, 37792374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter }, { 37892374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter /* FireDTV C/CI */ 37992374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .match_flags = MATCH_FLAGS, 38092374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .vendor_id = DIGITAL_EVERYWHERE_OUI, 38192374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .model_id = 0x000036, 38292374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, 38392374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter .version = AVC_SW_VERSION_ENTRY, 38492374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter }, {} 38592374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter}; 38692374e886c7518387e6816dedfe60fc7bdfa8fddStefan RichterMODULE_DEVICE_TABLE(ieee1394, fdtv_id_table); 38792374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter 38887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richterstatic struct fw_driver fdtv_driver = { 38987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter .driver = { 39087918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter .owner = THIS_MODULE, 39187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter .name = "firedtv", 39287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter .bus = &fw_bus_type, 39387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter }, 39494a87157cde95d38b9cdf1116e4f0fd93f6d25dfStefan Richter .probe = node_probe, 39587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter .update = node_update, 39694a87157cde95d38b9cdf1116e4f0fd93f6d25dfStefan Richter .remove = node_remove, 39787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter .id_table = fdtv_id_table, 39887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter}; 39987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 40092374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richterstatic int __init fdtv_init(void) 40187918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter{ 40287918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter int ret; 40387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 40487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter ret = fw_core_add_address_handler(&fcp_handler, &fcp_region); 40587918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter if (ret < 0) 40687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter return ret; 40787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 40892374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter ret = driver_register(&fdtv_driver.driver); 40992374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter if (ret < 0) 41092374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter fw_core_remove_address_handler(&fcp_handler); 41192374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter 41292374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter return ret; 41387918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter} 41487918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter 41592374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richterstatic void __exit fdtv_exit(void) 41687918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter{ 41787918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter driver_unregister(&fdtv_driver.driver); 41887918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter fw_core_remove_address_handler(&fcp_handler); 41987918334792a4d8a73b0511466b77bd6aa055db3Stefan Richter} 42092374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter 42192374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richtermodule_init(fdtv_init); 42292374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richtermodule_exit(fdtv_exit); 42392374e886c7518387e6816dedfe60fc7bdfa8fddStefan Richter 42492374e886c7518387e6816dedfe60fc7bdfa8fddStefan RichterMODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>"); 42592374e886c7518387e6816dedfe60fc7bdfa8fddStefan RichterMODULE_AUTHOR("Ben Backx <ben@bbackx.com>"); 42692374e886c7518387e6816dedfe60fc7bdfa8fddStefan RichterMODULE_DESCRIPTION("FireDTV DVB Driver"); 42792374e886c7518387e6816dedfe60fc7bdfa8fddStefan RichterMODULE_LICENSE("GPL"); 42892374e886c7518387e6816dedfe60fc7bdfa8fddStefan RichterMODULE_SUPPORTED_DEVICE("FireDTV DVB"); 429