1/* 2 * FireDTV driver -- ieee1394 I/O backend 3 * 4 * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> 5 * Copyright (C) 2007-2008 Ben Backx <ben@bbackx.com> 6 * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 */ 13 14#include <linux/device.h> 15#include <linux/errno.h> 16#include <linux/kernel.h> 17#include <linux/list.h> 18#include <linux/slab.h> 19#include <linux/spinlock.h> 20#include <linux/types.h> 21 22#include <dma.h> 23#include <csr1212.h> 24#include <highlevel.h> 25#include <hosts.h> 26#include <ieee1394.h> 27#include <iso.h> 28#include <nodemgr.h> 29 30#include <dvb_demux.h> 31 32#include "firedtv.h" 33 34static LIST_HEAD(node_list); 35static DEFINE_SPINLOCK(node_list_lock); 36 37#define CIP_HEADER_SIZE 8 38#define MPEG2_TS_HEADER_SIZE 4 39#define MPEG2_TS_SOURCE_PACKET_SIZE (4 + 188) 40 41static void rawiso_activity_cb(struct hpsb_iso *iso) 42{ 43 struct firedtv *f, *fdtv = NULL; 44 unsigned int i, num, packet; 45 unsigned char *buf; 46 unsigned long flags; 47 int count; 48 49 spin_lock_irqsave(&node_list_lock, flags); 50 list_for_each_entry(f, &node_list, list) 51 if (f->backend_data == iso) { 52 fdtv = f; 53 break; 54 } 55 spin_unlock_irqrestore(&node_list_lock, flags); 56 57 packet = iso->first_packet; 58 num = hpsb_iso_n_ready(iso); 59 60 if (!fdtv) { 61 pr_err("received at unknown iso channel\n"); 62 goto out; 63 } 64 65 for (i = 0; i < num; i++, packet = (packet + 1) % iso->buf_packets) { 66 buf = dma_region_i(&iso->data_buf, unsigned char, 67 iso->infos[packet].offset + CIP_HEADER_SIZE); 68 count = (iso->infos[packet].len - CIP_HEADER_SIZE) / 69 MPEG2_TS_SOURCE_PACKET_SIZE; 70 71 /* ignore empty packet */ 72 if (iso->infos[packet].len <= CIP_HEADER_SIZE) 73 continue; 74 75 while (count--) { 76 if (buf[MPEG2_TS_HEADER_SIZE] == 0x47) 77 dvb_dmx_swfilter_packets(&fdtv->demux, 78 &buf[MPEG2_TS_HEADER_SIZE], 1); 79 else 80 dev_err(fdtv->device, 81 "skipping invalid packet\n"); 82 buf += MPEG2_TS_SOURCE_PACKET_SIZE; 83 } 84 } 85out: 86 hpsb_iso_recv_release_packets(iso, num); 87} 88 89static inline struct node_entry *node_of(struct firedtv *fdtv) 90{ 91 return container_of(fdtv->device, struct unit_directory, device)->ne; 92} 93 94static int node_lock(struct firedtv *fdtv, u64 addr, void *data) 95{ 96 quadlet_t *d = data; 97 int ret; 98 99 ret = hpsb_node_lock(node_of(fdtv), addr, 100 EXTCODE_COMPARE_SWAP, &d[1], d[0]); 101 d[0] = d[1]; 102 103 return ret; 104} 105 106static int node_read(struct firedtv *fdtv, u64 addr, void *data) 107{ 108 return hpsb_node_read(node_of(fdtv), addr, data, 4); 109} 110 111static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len) 112{ 113 return hpsb_node_write(node_of(fdtv), addr, data, len); 114} 115 116#define FDTV_ISO_BUFFER_PACKETS 256 117#define FDTV_ISO_BUFFER_SIZE (FDTV_ISO_BUFFER_PACKETS * 200) 118 119static int start_iso(struct firedtv *fdtv) 120{ 121 struct hpsb_iso *iso_handle; 122 int ret; 123 124 iso_handle = hpsb_iso_recv_init(node_of(fdtv)->host, 125 FDTV_ISO_BUFFER_SIZE, FDTV_ISO_BUFFER_PACKETS, 126 fdtv->isochannel, HPSB_ISO_DMA_DEFAULT, 127 -1, /* stat.config.irq_interval */ 128 rawiso_activity_cb); 129 if (iso_handle == NULL) { 130 dev_err(fdtv->device, "cannot initialize iso receive\n"); 131 return -ENOMEM; 132 } 133 fdtv->backend_data = iso_handle; 134 135 ret = hpsb_iso_recv_start(iso_handle, -1, -1, 0); 136 if (ret != 0) { 137 dev_err(fdtv->device, "cannot start iso receive\n"); 138 hpsb_iso_shutdown(iso_handle); 139 fdtv->backend_data = NULL; 140 } 141 return ret; 142} 143 144static void stop_iso(struct firedtv *fdtv) 145{ 146 struct hpsb_iso *iso_handle = fdtv->backend_data; 147 148 if (iso_handle != NULL) { 149 hpsb_iso_stop(iso_handle); 150 hpsb_iso_shutdown(iso_handle); 151 } 152 fdtv->backend_data = NULL; 153} 154 155static const struct firedtv_backend fdtv_1394_backend = { 156 .lock = node_lock, 157 .read = node_read, 158 .write = node_write, 159 .start_iso = start_iso, 160 .stop_iso = stop_iso, 161}; 162 163static void fcp_request(struct hpsb_host *host, int nodeid, int direction, 164 int cts, u8 *data, size_t length) 165{ 166 struct firedtv *f, *fdtv = NULL; 167 unsigned long flags; 168 int su; 169 170 if (length == 0 || (data[0] & 0xf0) != 0) 171 return; 172 173 su = data[1] & 0x7; 174 175 spin_lock_irqsave(&node_list_lock, flags); 176 list_for_each_entry(f, &node_list, list) 177 if (node_of(f)->host == host && 178 node_of(f)->nodeid == nodeid && 179 (f->subunit == su || (f->subunit == 0 && su == 0x7))) { 180 fdtv = f; 181 break; 182 } 183 spin_unlock_irqrestore(&node_list_lock, flags); 184 185 if (fdtv) 186 avc_recv(fdtv, data, length); 187} 188 189static int node_probe(struct device *dev) 190{ 191 struct unit_directory *ud = 192 container_of(dev, struct unit_directory, device); 193 struct firedtv *fdtv; 194 int kv_len, err; 195 void *kv_str; 196 197 if (ud->model_name_kv) { 198 kv_len = (ud->model_name_kv->value.leaf.len - 2) * 4; 199 kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv); 200 } else { 201 kv_len = 0; 202 kv_str = NULL; 203 } 204 fdtv = fdtv_alloc(dev, &fdtv_1394_backend, kv_str, kv_len); 205 if (!fdtv) 206 return -ENOMEM; 207 208 err = fdtv_register_rc(fdtv, dev->parent->parent); 209 if (err) 210 goto fail_free; 211 212 spin_lock_irq(&node_list_lock); 213 list_add_tail(&fdtv->list, &node_list); 214 spin_unlock_irq(&node_list_lock); 215 216 err = avc_identify_subunit(fdtv); 217 if (err) 218 goto fail; 219 220 err = fdtv_dvb_register(fdtv); 221 if (err) 222 goto fail; 223 224 avc_register_remote_control(fdtv); 225 226 return 0; 227fail: 228 spin_lock_irq(&node_list_lock); 229 list_del(&fdtv->list); 230 spin_unlock_irq(&node_list_lock); 231 fdtv_unregister_rc(fdtv); 232fail_free: 233 kfree(fdtv); 234 235 return err; 236} 237 238static int node_remove(struct device *dev) 239{ 240 struct firedtv *fdtv = dev_get_drvdata(dev); 241 242 fdtv_dvb_unregister(fdtv); 243 244 spin_lock_irq(&node_list_lock); 245 list_del(&fdtv->list); 246 spin_unlock_irq(&node_list_lock); 247 248 fdtv_unregister_rc(fdtv); 249 kfree(fdtv); 250 251 return 0; 252} 253 254static int node_update(struct unit_directory *ud) 255{ 256 struct firedtv *fdtv = dev_get_drvdata(&ud->device); 257 258 if (fdtv->isochannel >= 0) 259 cmp_establish_pp_connection(fdtv, fdtv->subunit, 260 fdtv->isochannel); 261 return 0; 262} 263 264static struct hpsb_protocol_driver fdtv_driver = { 265 .name = "firedtv", 266 .id_table = fdtv_id_table, 267 .update = node_update, 268 .driver = { 269 .probe = node_probe, 270 .remove = node_remove, 271 }, 272}; 273 274static struct hpsb_highlevel fdtv_highlevel = { 275 .name = "firedtv", 276 .fcp_request = fcp_request, 277}; 278 279int __init fdtv_1394_init(void) 280{ 281 int ret; 282 283 hpsb_register_highlevel(&fdtv_highlevel); 284 ret = hpsb_register_protocol(&fdtv_driver); 285 if (ret) { 286 printk(KERN_ERR "firedtv: failed to register protocol\n"); 287 hpsb_unregister_highlevel(&fdtv_highlevel); 288 } 289 return ret; 290} 291 292void __exit fdtv_1394_exit(void) 293{ 294 hpsb_unregister_protocol(&fdtv_driver); 295 hpsb_unregister_highlevel(&fdtv_highlevel); 296} 297