ia64/linux-2.6.18-xen.hg

annotate drivers/ieee1394/video1394.c @ 893:f994bfe9b93b

linux/blktap2: reduce TLB flush scope

c/s 885 added very coarse TLB flushing. Since these flushes always
follow single page updates, single page flushes (when available) are
sufficient.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 04 10:32:57 2009 +0100 (2009-06-04)
parents 831230e53067
children
rev   line source
ian@0 1 /*
ian@0 2 * video1394.c - video driver for OHCI 1394 boards
ian@0 3 * Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
ian@0 4 * Peter Schlaile <udbz@rz.uni-karlsruhe.de>
ian@0 5 *
ian@0 6 * This program is free software; you can redistribute it and/or modify
ian@0 7 * it under the terms of the GNU General Public License as published by
ian@0 8 * the Free Software Foundation; either version 2 of the License, or
ian@0 9 * (at your option) any later version.
ian@0 10 *
ian@0 11 * This program is distributed in the hope that it will be useful,
ian@0 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ian@0 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ian@0 14 * GNU General Public License for more details.
ian@0 15 *
ian@0 16 * You should have received a copy of the GNU General Public License
ian@0 17 * along with this program; if not, write to the Free Software Foundation,
ian@0 18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
ian@0 19 *
ian@0 20 * NOTES:
ian@0 21 *
ian@0 22 * ioctl return codes:
ian@0 23 * EFAULT is only for invalid address for the argp
ian@0 24 * EINVAL for out of range values
ian@0 25 * EBUSY when trying to use an already used resource
ian@0 26 * ESRCH when trying to free/stop a not used resource
ian@0 27 * EAGAIN for resource allocation failure that could perhaps succeed later
ian@0 28 * ENOTTY for unsupported ioctl request
ian@0 29 *
ian@0 30 */
ian@0 31 #include <linux/kernel.h>
ian@0 32 #include <linux/list.h>
ian@0 33 #include <linux/slab.h>
ian@0 34 #include <linux/interrupt.h>
ian@0 35 #include <linux/wait.h>
ian@0 36 #include <linux/errno.h>
ian@0 37 #include <linux/module.h>
ian@0 38 #include <linux/init.h>
ian@0 39 #include <linux/pci.h>
ian@0 40 #include <linux/fs.h>
ian@0 41 #include <linux/poll.h>
ian@0 42 #include <linux/smp_lock.h>
ian@0 43 #include <linux/delay.h>
ian@0 44 #include <linux/bitops.h>
ian@0 45 #include <linux/types.h>
ian@0 46 #include <linux/vmalloc.h>
ian@0 47 #include <linux/timex.h>
ian@0 48 #include <linux/mm.h>
ian@0 49 #include <linux/compat.h>
ian@0 50 #include <linux/cdev.h>
ian@0 51
ian@0 52 #include "ieee1394.h"
ian@0 53 #include "ieee1394_types.h"
ian@0 54 #include "hosts.h"
ian@0 55 #include "ieee1394_core.h"
ian@0 56 #include "highlevel.h"
ian@0 57 #include "video1394.h"
ian@0 58 #include "nodemgr.h"
ian@0 59 #include "dma.h"
ian@0 60
ian@0 61 #include "ohci1394.h"
ian@0 62
ian@0 63 #define ISO_CHANNELS 64
ian@0 64
ian@0 65 struct it_dma_prg {
ian@0 66 struct dma_cmd begin;
ian@0 67 quadlet_t data[4];
ian@0 68 struct dma_cmd end;
ian@0 69 quadlet_t pad[4]; /* FIXME: quick hack for memory alignment */
ian@0 70 };
ian@0 71
ian@0 72 struct dma_iso_ctx {
ian@0 73 struct ti_ohci *ohci;
ian@0 74 int type; /* OHCI_ISO_TRANSMIT or OHCI_ISO_RECEIVE */
ian@0 75 struct ohci1394_iso_tasklet iso_tasklet;
ian@0 76 int channel;
ian@0 77 int ctx;
ian@0 78 int last_buffer;
ian@0 79 int * next_buffer; /* For ISO Transmit of video packets
ian@0 80 to write the correct SYT field
ian@0 81 into the next block */
ian@0 82 unsigned int num_desc;
ian@0 83 unsigned int buf_size;
ian@0 84 unsigned int frame_size;
ian@0 85 unsigned int packet_size;
ian@0 86 unsigned int left_size;
ian@0 87 unsigned int nb_cmd;
ian@0 88
ian@0 89 struct dma_region dma;
ian@0 90
ian@0 91 struct dma_prog_region *prg_reg;
ian@0 92
ian@0 93 struct dma_cmd **ir_prg;
ian@0 94 struct it_dma_prg **it_prg;
ian@0 95
ian@0 96 unsigned int *buffer_status;
ian@0 97 unsigned int *buffer_prg_assignment;
ian@0 98 struct timeval *buffer_time; /* time when the buffer was received */
ian@0 99 unsigned int *last_used_cmd; /* For ISO Transmit with
ian@0 100 variable sized packets only ! */
ian@0 101 int ctrlClear;
ian@0 102 int ctrlSet;
ian@0 103 int cmdPtr;
ian@0 104 int ctxMatch;
ian@0 105 wait_queue_head_t waitq;
ian@0 106 spinlock_t lock;
ian@0 107 unsigned int syt_offset;
ian@0 108 int flags;
ian@0 109
ian@0 110 struct list_head link;
ian@0 111 };
ian@0 112
ian@0 113
ian@0 114 struct file_ctx {
ian@0 115 struct ti_ohci *ohci;
ian@0 116 struct list_head context_list;
ian@0 117 struct dma_iso_ctx *current_ctx;
ian@0 118 };
ian@0 119
ian@0 120 #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
ian@0 121 #define VIDEO1394_DEBUG
ian@0 122 #endif
ian@0 123
ian@0 124 #ifdef DBGMSG
ian@0 125 #undef DBGMSG
ian@0 126 #endif
ian@0 127
ian@0 128 #ifdef VIDEO1394_DEBUG
ian@0 129 #define DBGMSG(card, fmt, args...) \
ian@0 130 printk(KERN_INFO "video1394_%d: " fmt "\n" , card , ## args)
ian@0 131 #else
ian@0 132 #define DBGMSG(card, fmt, args...)
ian@0 133 #endif
ian@0 134
ian@0 135 /* print general (card independent) information */
ian@0 136 #define PRINT_G(level, fmt, args...) \
ian@0 137 printk(level "video1394: " fmt "\n" , ## args)
ian@0 138
ian@0 139 /* print card specific information */
ian@0 140 #define PRINT(level, card, fmt, args...) \
ian@0 141 printk(level "video1394_%d: " fmt "\n" , card , ## args)
ian@0 142
ian@0 143 static void wakeup_dma_ir_ctx(unsigned long l);
ian@0 144 static void wakeup_dma_it_ctx(unsigned long l);
ian@0 145
ian@0 146 static struct hpsb_highlevel video1394_highlevel;
ian@0 147
ian@0 148 static int free_dma_iso_ctx(struct dma_iso_ctx *d)
ian@0 149 {
ian@0 150 int i;
ian@0 151
ian@0 152 DBGMSG(d->ohci->host->id, "Freeing dma_iso_ctx %d", d->ctx);
ian@0 153
ian@0 154 ohci1394_stop_context(d->ohci, d->ctrlClear, NULL);
ian@0 155 if (d->iso_tasklet.link.next != NULL)
ian@0 156 ohci1394_unregister_iso_tasklet(d->ohci, &d->iso_tasklet);
ian@0 157
ian@0 158 dma_region_free(&d->dma);
ian@0 159
ian@0 160 if (d->prg_reg) {
ian@0 161 for (i = 0; i < d->num_desc; i++)
ian@0 162 dma_prog_region_free(&d->prg_reg[i]);
ian@0 163 kfree(d->prg_reg);
ian@0 164 }
ian@0 165
ian@0 166 kfree(d->ir_prg);
ian@0 167 kfree(d->it_prg);
ian@0 168 kfree(d->buffer_status);
ian@0 169 kfree(d->buffer_prg_assignment);
ian@0 170 kfree(d->buffer_time);
ian@0 171 kfree(d->last_used_cmd);
ian@0 172 kfree(d->next_buffer);
ian@0 173 list_del(&d->link);
ian@0 174 kfree(d);
ian@0 175
ian@0 176 return 0;
ian@0 177 }
ian@0 178
ian@0 179 static struct dma_iso_ctx *
ian@0 180 alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
ian@0 181 int buf_size, int channel, unsigned int packet_size)
ian@0 182 {
ian@0 183 struct dma_iso_ctx *d;
ian@0 184 int i;
ian@0 185
ian@0 186 d = kzalloc(sizeof(*d), GFP_KERNEL);
ian@0 187 if (!d) {
ian@0 188 PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma_iso_ctx");
ian@0 189 return NULL;
ian@0 190 }
ian@0 191
ian@0 192 d->ohci = ohci;
ian@0 193 d->type = type;
ian@0 194 d->channel = channel;
ian@0 195 d->num_desc = num_desc;
ian@0 196 d->frame_size = buf_size;
ian@0 197 d->buf_size = PAGE_ALIGN(buf_size);
ian@0 198 d->last_buffer = -1;
ian@0 199 INIT_LIST_HEAD(&d->link);
ian@0 200 init_waitqueue_head(&d->waitq);
ian@0 201
ian@0 202 /* Init the regions for easy cleanup */
ian@0 203 dma_region_init(&d->dma);
ian@0 204
ian@0 205 if (dma_region_alloc(&d->dma, (d->num_desc - 1) * d->buf_size, ohci->dev,
ian@0 206 PCI_DMA_BIDIRECTIONAL)) {
ian@0 207 PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma buffer");
ian@0 208 free_dma_iso_ctx(d);
ian@0 209 return NULL;
ian@0 210 }
ian@0 211
ian@0 212 if (type == OHCI_ISO_RECEIVE)
ian@0 213 ohci1394_init_iso_tasklet(&d->iso_tasklet, type,
ian@0 214 wakeup_dma_ir_ctx,
ian@0 215 (unsigned long) d);
ian@0 216 else
ian@0 217 ohci1394_init_iso_tasklet(&d->iso_tasklet, type,
ian@0 218 wakeup_dma_it_ctx,
ian@0 219 (unsigned long) d);
ian@0 220
ian@0 221 if (ohci1394_register_iso_tasklet(ohci, &d->iso_tasklet) < 0) {
ian@0 222 PRINT(KERN_ERR, ohci->host->id, "no free iso %s contexts",
ian@0 223 type == OHCI_ISO_RECEIVE ? "receive" : "transmit");
ian@0 224 free_dma_iso_ctx(d);
ian@0 225 return NULL;
ian@0 226 }
ian@0 227 d->ctx = d->iso_tasklet.context;
ian@0 228
ian@0 229 d->prg_reg = kmalloc(d->num_desc * sizeof(*d->prg_reg), GFP_KERNEL);
ian@0 230 if (!d->prg_reg) {
ian@0 231 PRINT(KERN_ERR, ohci->host->id, "Failed to allocate ir prg regs");
ian@0 232 free_dma_iso_ctx(d);
ian@0 233 return NULL;
ian@0 234 }
ian@0 235 /* Makes for easier cleanup */
ian@0 236 for (i = 0; i < d->num_desc; i++)
ian@0 237 dma_prog_region_init(&d->prg_reg[i]);
ian@0 238
ian@0 239 if (type == OHCI_ISO_RECEIVE) {
ian@0 240 d->ctrlSet = OHCI1394_IsoRcvContextControlSet+32*d->ctx;
ian@0 241 d->ctrlClear = OHCI1394_IsoRcvContextControlClear+32*d->ctx;
ian@0 242 d->cmdPtr = OHCI1394_IsoRcvCommandPtr+32*d->ctx;
ian@0 243 d->ctxMatch = OHCI1394_IsoRcvContextMatch+32*d->ctx;
ian@0 244
ian@0 245 d->ir_prg = kzalloc(d->num_desc * sizeof(*d->ir_prg),
ian@0 246 GFP_KERNEL);
ian@0 247
ian@0 248 if (!d->ir_prg) {
ian@0 249 PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma ir prg");
ian@0 250 free_dma_iso_ctx(d);
ian@0 251 return NULL;
ian@0 252 }
ian@0 253
ian@0 254 d->nb_cmd = d->buf_size / PAGE_SIZE + 1;
ian@0 255 d->left_size = (d->frame_size % PAGE_SIZE) ?
ian@0 256 d->frame_size % PAGE_SIZE : PAGE_SIZE;
ian@0 257
ian@0 258 for (i = 0;i < d->num_desc; i++) {
ian@0 259 if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd *
ian@0 260 sizeof(struct dma_cmd), ohci->dev)) {
ian@0 261 PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma ir prg");
ian@0 262 free_dma_iso_ctx(d);
ian@0 263 return NULL;
ian@0 264 }
ian@0 265 d->ir_prg[i] = (struct dma_cmd *)d->prg_reg[i].kvirt;
ian@0 266 }
ian@0 267
ian@0 268 } else { /* OHCI_ISO_TRANSMIT */
ian@0 269 d->ctrlSet = OHCI1394_IsoXmitContextControlSet+16*d->ctx;
ian@0 270 d->ctrlClear = OHCI1394_IsoXmitContextControlClear+16*d->ctx;
ian@0 271 d->cmdPtr = OHCI1394_IsoXmitCommandPtr+16*d->ctx;
ian@0 272
ian@0 273 d->it_prg = kzalloc(d->num_desc * sizeof(*d->it_prg),
ian@0 274 GFP_KERNEL);
ian@0 275
ian@0 276 if (!d->it_prg) {
ian@0 277 PRINT(KERN_ERR, ohci->host->id,
ian@0 278 "Failed to allocate dma it prg");
ian@0 279 free_dma_iso_ctx(d);
ian@0 280 return NULL;
ian@0 281 }
ian@0 282
ian@0 283 d->packet_size = packet_size;
ian@0 284
ian@0 285 if (PAGE_SIZE % packet_size || packet_size>4096) {
ian@0 286 PRINT(KERN_ERR, ohci->host->id,
ian@0 287 "Packet size %d (page_size: %ld) "
ian@0 288 "not yet supported\n",
ian@0 289 packet_size, PAGE_SIZE);
ian@0 290 free_dma_iso_ctx(d);
ian@0 291 return NULL;
ian@0 292 }
ian@0 293
ian@0 294 d->nb_cmd = d->frame_size / d->packet_size;
ian@0 295 if (d->frame_size % d->packet_size) {
ian@0 296 d->nb_cmd++;
ian@0 297 d->left_size = d->frame_size % d->packet_size;
ian@0 298 } else
ian@0 299 d->left_size = d->packet_size;
ian@0 300
ian@0 301 for (i = 0; i < d->num_desc; i++) {
ian@0 302 if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd *
ian@0 303 sizeof(struct it_dma_prg), ohci->dev)) {
ian@0 304 PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma it prg");
ian@0 305 free_dma_iso_ctx(d);
ian@0 306 return NULL;
ian@0 307 }
ian@0 308 d->it_prg[i] = (struct it_dma_prg *)d->prg_reg[i].kvirt;
ian@0 309 }
ian@0 310 }
ian@0 311
ian@0 312 d->buffer_status =
ian@0 313 kzalloc(d->num_desc * sizeof(*d->buffer_status), GFP_KERNEL);
ian@0 314 d->buffer_prg_assignment =
ian@0 315 kzalloc(d->num_desc * sizeof(*d->buffer_prg_assignment), GFP_KERNEL);
ian@0 316 d->buffer_time =
ian@0 317 kzalloc(d->num_desc * sizeof(*d->buffer_time), GFP_KERNEL);
ian@0 318 d->last_used_cmd =
ian@0 319 kzalloc(d->num_desc * sizeof(*d->last_used_cmd), GFP_KERNEL);
ian@0 320 d->next_buffer =
ian@0 321 kzalloc(d->num_desc * sizeof(*d->next_buffer), GFP_KERNEL);
ian@0 322
ian@0 323 if (!d->buffer_status || !d->buffer_prg_assignment || !d->buffer_time ||
ian@0 324 !d->last_used_cmd || !d->next_buffer) {
ian@0 325 PRINT(KERN_ERR, ohci->host->id,
ian@0 326 "Failed to allocate dma_iso_ctx member");
ian@0 327 free_dma_iso_ctx(d);
ian@0 328 return NULL;
ian@0 329 }
ian@0 330
ian@0 331 spin_lock_init(&d->lock);
ian@0 332
ian@0 333 DBGMSG(ohci->host->id, "Iso %s DMA: %d buffers "
ian@0 334 "of size %d allocated for a frame size %d, each with %d prgs",
ian@0 335 (type == OHCI_ISO_RECEIVE) ? "receive" : "transmit",
ian@0 336 d->num_desc - 1, d->buf_size, d->frame_size, d->nb_cmd);
ian@0 337
ian@0 338 return d;
ian@0 339 }
ian@0 340
ian@0 341 static void reset_ir_status(struct dma_iso_ctx *d, int n)
ian@0 342 {
ian@0 343 int i;
ian@0 344 d->ir_prg[n][0].status = cpu_to_le32(4);
ian@0 345 d->ir_prg[n][1].status = cpu_to_le32(PAGE_SIZE-4);
ian@0 346 for (i = 2; i < d->nb_cmd - 1; i++)
ian@0 347 d->ir_prg[n][i].status = cpu_to_le32(PAGE_SIZE);
ian@0 348 d->ir_prg[n][i].status = cpu_to_le32(d->left_size);
ian@0 349 }
ian@0 350
ian@0 351 static void reprogram_dma_ir_prg(struct dma_iso_ctx *d, int n, int buffer, int flags)
ian@0 352 {
ian@0 353 struct dma_cmd *ir_prg = d->ir_prg[n];
ian@0 354 unsigned long buf = (unsigned long)d->dma.kvirt + buffer * d->buf_size;
ian@0 355 int i;
ian@0 356
ian@0 357 d->buffer_prg_assignment[n] = buffer;
ian@0 358
ian@0 359 ir_prg[0].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, buf -
ian@0 360 (unsigned long)d->dma.kvirt));
ian@0 361 ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
ian@0 362 (buf + 4) - (unsigned long)d->dma.kvirt));
ian@0 363
ian@0 364 for (i=2;i<d->nb_cmd-1;i++) {
ian@0 365 ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
ian@0 366 (buf+(i-1)*PAGE_SIZE) -
ian@0 367 (unsigned long)d->dma.kvirt));
ian@0 368 }
ian@0 369
ian@0 370 ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
ian@0 371 DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size);
ian@0 372 ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
ian@0 373 (buf+(i-1)*PAGE_SIZE) - (unsigned long)d->dma.kvirt));
ian@0 374 }
ian@0 375
ian@0 376 static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n, int flags)
ian@0 377 {
ian@0 378 struct dma_cmd *ir_prg = d->ir_prg[n];
ian@0 379 struct dma_prog_region *ir_reg = &d->prg_reg[n];
ian@0 380 unsigned long buf = (unsigned long)d->dma.kvirt;
ian@0 381 int i;
ian@0 382
ian@0 383 /* the first descriptor will read only 4 bytes */
ian@0 384 ir_prg[0].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
ian@0 385 DMA_CTL_BRANCH | 4);
ian@0 386
ian@0 387 /* set the sync flag */
ian@0 388 if (flags & VIDEO1394_SYNC_FRAMES)
ian@0 389 ir_prg[0].control |= cpu_to_le32(DMA_CTL_WAIT);
ian@0 390
ian@0 391 ir_prg[0].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, buf -
ian@0 392 (unsigned long)d->dma.kvirt));
ian@0 393 ir_prg[0].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
ian@0 394 1 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
ian@0 395
ian@0 396 /* If there is *not* only one DMA page per frame (hence, d->nb_cmd==2) */
ian@0 397 if (d->nb_cmd > 2) {
ian@0 398 /* The second descriptor will read PAGE_SIZE-4 bytes */
ian@0 399 ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
ian@0 400 DMA_CTL_BRANCH | (PAGE_SIZE-4));
ian@0 401 ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf + 4) -
ian@0 402 (unsigned long)d->dma.kvirt));
ian@0 403 ir_prg[1].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
ian@0 404 2 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
ian@0 405
ian@0 406 for (i = 2; i < d->nb_cmd - 1; i++) {
ian@0 407 ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
ian@0 408 DMA_CTL_BRANCH | PAGE_SIZE);
ian@0 409 ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
ian@0 410 (buf+(i-1)*PAGE_SIZE) -
ian@0 411 (unsigned long)d->dma.kvirt));
ian@0 412
ian@0 413 ir_prg[i].branchAddress =
ian@0 414 cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
ian@0 415 (i + 1) * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
ian@0 416 }
ian@0 417
ian@0 418 /* The last descriptor will generate an interrupt */
ian@0 419 ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
ian@0 420 DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size);
ian@0 421 ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
ian@0 422 (buf+(i-1)*PAGE_SIZE) -
ian@0 423 (unsigned long)d->dma.kvirt));
ian@0 424 } else {
ian@0 425 /* Only one DMA page is used. Read d->left_size immediately and */
ian@0 426 /* generate an interrupt as this is also the last page. */
ian@0 427 ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
ian@0 428 DMA_CTL_IRQ | DMA_CTL_BRANCH | (d->left_size-4));
ian@0 429 ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
ian@0 430 (buf + 4) - (unsigned long)d->dma.kvirt));
ian@0 431 }
ian@0 432 }
ian@0 433
ian@0 434 static void initialize_dma_ir_ctx(struct dma_iso_ctx *d, int tag, int flags)
ian@0 435 {
ian@0 436 struct ti_ohci *ohci = (struct ti_ohci *)d->ohci;
ian@0 437 int i;
ian@0 438
ian@0 439 d->flags = flags;
ian@0 440
ian@0 441 ohci1394_stop_context(ohci, d->ctrlClear, NULL);
ian@0 442
ian@0 443 for (i=0;i<d->num_desc;i++) {
ian@0 444 initialize_dma_ir_prg(d, i, flags);
ian@0 445 reset_ir_status(d, i);
ian@0 446 }
ian@0 447
ian@0 448 /* reset the ctrl register */
ian@0 449 reg_write(ohci, d->ctrlClear, 0xf0000000);
ian@0 450
ian@0 451 /* Set bufferFill */
ian@0 452 reg_write(ohci, d->ctrlSet, 0x80000000);
ian@0 453
ian@0 454 /* Set isoch header */
ian@0 455 if (flags & VIDEO1394_INCLUDE_ISO_HEADERS)
ian@0 456 reg_write(ohci, d->ctrlSet, 0x40000000);
ian@0 457
ian@0 458 /* Set the context match register to match on all tags,
ian@0 459 sync for sync tag, and listen to d->channel */
ian@0 460 reg_write(ohci, d->ctxMatch, 0xf0000000|((tag&0xf)<<8)|d->channel);
ian@0 461
ian@0 462 /* Set up isoRecvIntMask to generate interrupts */
ian@0 463 reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1<<d->ctx);
ian@0 464 }
ian@0 465
ian@0 466 /* find which context is listening to this channel */
ian@0 467 static struct dma_iso_ctx *
ian@0 468 find_ctx(struct list_head *list, int type, int channel)
ian@0 469 {
ian@0 470 struct dma_iso_ctx *ctx;
ian@0 471
ian@0 472 list_for_each_entry(ctx, list, link) {
ian@0 473 if (ctx->type == type && ctx->channel == channel)
ian@0 474 return ctx;
ian@0 475 }
ian@0 476
ian@0 477 return NULL;
ian@0 478 }
ian@0 479
ian@0 480 static void wakeup_dma_ir_ctx(unsigned long l)
ian@0 481 {
ian@0 482 struct dma_iso_ctx *d = (struct dma_iso_ctx *) l;
ian@0 483 int i;
ian@0 484
ian@0 485 spin_lock(&d->lock);
ian@0 486
ian@0 487 for (i = 0; i < d->num_desc; i++) {
ian@0 488 if (d->ir_prg[i][d->nb_cmd-1].status & cpu_to_le32(0xFFFF0000)) {
ian@0 489 reset_ir_status(d, i);
ian@0 490 d->buffer_status[d->buffer_prg_assignment[i]] = VIDEO1394_BUFFER_READY;
ian@0 491 do_gettimeofday(&d->buffer_time[d->buffer_prg_assignment[i]]);
ian@0 492 }
ian@0 493 }
ian@0 494
ian@0 495 spin_unlock(&d->lock);
ian@0 496
ian@0 497 if (waitqueue_active(&d->waitq))
ian@0 498 wake_up_interruptible(&d->waitq);
ian@0 499 }
ian@0 500
ian@0 501 static inline void put_timestamp(struct ti_ohci *ohci, struct dma_iso_ctx * d,
ian@0 502 int n)
ian@0 503 {
ian@0 504 unsigned char* buf = d->dma.kvirt + n * d->buf_size;
ian@0 505 u32 cycleTimer;
ian@0 506 u32 timeStamp;
ian@0 507
ian@0 508 if (n == -1) {
ian@0 509 return;
ian@0 510 }
ian@0 511
ian@0 512 cycleTimer = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
ian@0 513
ian@0 514 timeStamp = ((cycleTimer & 0x0fff) + d->syt_offset); /* 11059 = 450 us */
ian@0 515 timeStamp = (timeStamp % 3072 + ((timeStamp / 3072) << 12)
ian@0 516 + (cycleTimer & 0xf000)) & 0xffff;
ian@0 517
ian@0 518 buf[6] = timeStamp >> 8;
ian@0 519 buf[7] = timeStamp & 0xff;
ian@0 520
ian@0 521 /* if first packet is empty packet, then put timestamp into the next full one too */
ian@0 522 if ( (le32_to_cpu(d->it_prg[n][0].data[1]) >>16) == 0x008) {
ian@0 523 buf += d->packet_size;
ian@0 524 buf[6] = timeStamp >> 8;
ian@0 525 buf[7] = timeStamp & 0xff;
ian@0 526 }
ian@0 527
ian@0 528 /* do the next buffer frame too in case of irq latency */
ian@0 529 n = d->next_buffer[n];
ian@0 530 if (n == -1) {
ian@0 531 return;
ian@0 532 }
ian@0 533 buf = d->dma.kvirt + n * d->buf_size;
ian@0 534
ian@0 535 timeStamp += (d->last_used_cmd[n] << 12) & 0xffff;
ian@0 536
ian@0 537 buf[6] = timeStamp >> 8;
ian@0 538 buf[7] = timeStamp & 0xff;
ian@0 539
ian@0 540 /* if first packet is empty packet, then put timestamp into the next full one too */
ian@0 541 if ( (le32_to_cpu(d->it_prg[n][0].data[1]) >>16) == 0x008) {
ian@0 542 buf += d->packet_size;
ian@0 543 buf[6] = timeStamp >> 8;
ian@0 544 buf[7] = timeStamp & 0xff;
ian@0 545 }
ian@0 546
ian@0 547 #if 0
ian@0 548 printk("curr: %d, next: %d, cycleTimer: %08x timeStamp: %08x\n",
ian@0 549 curr, n, cycleTimer, timeStamp);
ian@0 550 #endif
ian@0 551 }
ian@0 552
ian@0 553 static void wakeup_dma_it_ctx(unsigned long l)
ian@0 554 {
ian@0 555 struct dma_iso_ctx *d = (struct dma_iso_ctx *) l;
ian@0 556 struct ti_ohci *ohci = d->ohci;
ian@0 557 int i;
ian@0 558
ian@0 559 spin_lock(&d->lock);
ian@0 560
ian@0 561 for (i = 0; i < d->num_desc; i++) {
ian@0 562 if (d->it_prg[i][d->last_used_cmd[i]].end.status &
ian@0 563 cpu_to_le32(0xFFFF0000)) {
ian@0 564 int next = d->next_buffer[i];
ian@0 565 put_timestamp(ohci, d, next);
ian@0 566 d->it_prg[i][d->last_used_cmd[i]].end.status = 0;
ian@0 567 d->buffer_status[d->buffer_prg_assignment[i]] = VIDEO1394_BUFFER_READY;
ian@0 568 }
ian@0 569 }
ian@0 570
ian@0 571 spin_unlock(&d->lock);
ian@0 572
ian@0 573 if (waitqueue_active(&d->waitq))
ian@0 574 wake_up_interruptible(&d->waitq);
ian@0 575 }
ian@0 576
ian@0 577 static void reprogram_dma_it_prg(struct dma_iso_ctx *d, int n, int buffer)
ian@0 578 {
ian@0 579 struct it_dma_prg *it_prg = d->it_prg[n];
ian@0 580 unsigned long buf = (unsigned long)d->dma.kvirt + buffer * d->buf_size;
ian@0 581 int i;
ian@0 582
ian@0 583 d->buffer_prg_assignment[n] = buffer;
ian@0 584 for (i=0;i<d->nb_cmd;i++) {
ian@0 585 it_prg[i].end.address =
ian@0 586 cpu_to_le32(dma_region_offset_to_bus(&d->dma,
ian@0 587 (buf+i*d->packet_size) - (unsigned long)d->dma.kvirt));
ian@0 588 }
ian@0 589 }
ian@0 590
ian@0 591 static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag)
ian@0 592 {
ian@0 593 struct it_dma_prg *it_prg = d->it_prg[n];
ian@0 594 struct dma_prog_region *it_reg = &d->prg_reg[n];
ian@0 595 unsigned long buf = (unsigned long)d->dma.kvirt;
ian@0 596 int i;
ian@0 597 d->last_used_cmd[n] = d->nb_cmd - 1;
ian@0 598 for (i=0;i<d->nb_cmd;i++) {
ian@0 599
ian@0 600 it_prg[i].begin.control = cpu_to_le32(DMA_CTL_OUTPUT_MORE |
ian@0 601 DMA_CTL_IMMEDIATE | 8) ;
ian@0 602 it_prg[i].begin.address = 0;
ian@0 603
ian@0 604 it_prg[i].begin.status = 0;
ian@0 605
ian@0 606 it_prg[i].data[0] = cpu_to_le32(
ian@0 607 (IEEE1394_SPEED_100 << 16)
ian@0 608 | (/* tag */ 1 << 14)
ian@0 609 | (d->channel << 8)
ian@0 610 | (TCODE_ISO_DATA << 4));
ian@0 611 if (i==0) it_prg[i].data[0] |= cpu_to_le32(sync_tag);
ian@0 612 it_prg[i].data[1] = cpu_to_le32(d->packet_size << 16);
ian@0 613 it_prg[i].data[2] = 0;
ian@0 614 it_prg[i].data[3] = 0;
ian@0 615
ian@0 616 it_prg[i].end.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST |
ian@0 617 DMA_CTL_BRANCH);
ian@0 618 it_prg[i].end.address =
ian@0 619 cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf+i*d->packet_size) -
ian@0 620 (unsigned long)d->dma.kvirt));
ian@0 621
ian@0 622 if (i<d->nb_cmd-1) {
ian@0 623 it_prg[i].end.control |= cpu_to_le32(d->packet_size);
ian@0 624 it_prg[i].begin.branchAddress =
ian@0 625 cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
ian@0 626 sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
ian@0 627 it_prg[i].end.branchAddress =
ian@0 628 cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
ian@0 629 sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
ian@0 630 } else {
ian@0 631 /* the last prg generates an interrupt */
ian@0 632 it_prg[i].end.control |= cpu_to_le32(DMA_CTL_UPDATE |
ian@0 633 DMA_CTL_IRQ | d->left_size);
ian@0 634 /* the last prg doesn't branch */
ian@0 635 it_prg[i].begin.branchAddress = 0;
ian@0 636 it_prg[i].end.branchAddress = 0;
ian@0 637 }
ian@0 638 it_prg[i].end.status = 0;
ian@0 639 }
ian@0 640 }
ian@0 641
ian@0 642 static void initialize_dma_it_prg_var_packet_queue(
ian@0 643 struct dma_iso_ctx *d, int n, unsigned int * packet_sizes,
ian@0 644 struct ti_ohci *ohci)
ian@0 645 {
ian@0 646 struct it_dma_prg *it_prg = d->it_prg[n];
ian@0 647 struct dma_prog_region *it_reg = &d->prg_reg[n];
ian@0 648 int i;
ian@0 649
ian@0 650 #if 0
ian@0 651 if (n != -1) {
ian@0 652 put_timestamp(ohci, d, n);
ian@0 653 }
ian@0 654 #endif
ian@0 655 d->last_used_cmd[n] = d->nb_cmd - 1;
ian@0 656
ian@0 657 for (i = 0; i < d->nb_cmd; i++) {
ian@0 658 unsigned int size;
ian@0 659 if (packet_sizes[i] > d->packet_size) {
ian@0 660 size = d->packet_size;
ian@0 661 } else {
ian@0 662 size = packet_sizes[i];
ian@0 663 }
ian@0 664 it_prg[i].data[1] = cpu_to_le32(size << 16);
ian@0 665 it_prg[i].end.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH);
ian@0 666
ian@0 667 if (i < d->nb_cmd-1 && packet_sizes[i+1] != 0) {
ian@0 668 it_prg[i].end.control |= cpu_to_le32(size);
ian@0 669 it_prg[i].begin.branchAddress =
ian@0 670 cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
ian@0 671 sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
ian@0 672 it_prg[i].end.branchAddress =
ian@0 673 cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
ian@0 674 sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
ian@0 675 } else {
ian@0 676 /* the last prg generates an interrupt */
ian@0 677 it_prg[i].end.control |= cpu_to_le32(DMA_CTL_UPDATE |
ian@0 678 DMA_CTL_IRQ | size);
ian@0 679 /* the last prg doesn't branch */
ian@0 680 it_prg[i].begin.branchAddress = 0;
ian@0 681 it_prg[i].end.branchAddress = 0;
ian@0 682 d->last_used_cmd[n] = i;
ian@0 683 break;
ian@0 684 }
ian@0 685 }
ian@0 686 }
ian@0 687
ian@0 688 static void initialize_dma_it_ctx(struct dma_iso_ctx *d, int sync_tag,
ian@0 689 unsigned int syt_offset, int flags)
ian@0 690 {
ian@0 691 struct ti_ohci *ohci = (struct ti_ohci *)d->ohci;
ian@0 692 int i;
ian@0 693
ian@0 694 d->flags = flags;
ian@0 695 d->syt_offset = (syt_offset == 0 ? 11000 : syt_offset);
ian@0 696
ian@0 697 ohci1394_stop_context(ohci, d->ctrlClear, NULL);
ian@0 698
ian@0 699 for (i=0;i<d->num_desc;i++)
ian@0 700 initialize_dma_it_prg(d, i, sync_tag);
ian@0 701
ian@0 702 /* Set up isoRecvIntMask to generate interrupts */
ian@0 703 reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1<<d->ctx);
ian@0 704 }
ian@0 705
ian@0 706 static inline unsigned video1394_buffer_state(struct dma_iso_ctx *d,
ian@0 707 unsigned int buffer)
ian@0 708 {
ian@0 709 unsigned long flags;
ian@0 710 unsigned int ret;
ian@0 711 spin_lock_irqsave(&d->lock, flags);
ian@0 712 ret = d->buffer_status[buffer];
ian@0 713 spin_unlock_irqrestore(&d->lock, flags);
ian@0 714 return ret;
ian@0 715 }
ian@0 716
ian@0 717 static int __video1394_ioctl(struct file *file,
ian@0 718 unsigned int cmd, unsigned long arg)
ian@0 719 {
ian@0 720 struct file_ctx *ctx = (struct file_ctx *)file->private_data;
ian@0 721 struct ti_ohci *ohci = ctx->ohci;
ian@0 722 unsigned long flags;
ian@0 723 void __user *argp = (void __user *)arg;
ian@0 724
ian@0 725 switch(cmd)
ian@0 726 {
ian@0 727 case VIDEO1394_IOC_LISTEN_CHANNEL:
ian@0 728 case VIDEO1394_IOC_TALK_CHANNEL:
ian@0 729 {
ian@0 730 struct video1394_mmap v;
ian@0 731 u64 mask;
ian@0 732 struct dma_iso_ctx *d;
ian@0 733 int i;
ian@0 734
ian@0 735 if (copy_from_user(&v, argp, sizeof(v)))
ian@0 736 return -EFAULT;
ian@0 737
ian@0 738 /* if channel < 0, find lowest available one */
ian@0 739 if (v.channel < 0) {
ian@0 740 mask = (u64)0x1;
ian@0 741 for (i=0; ; i++) {
ian@0 742 if (i == ISO_CHANNELS) {
ian@0 743 PRINT(KERN_ERR, ohci->host->id,
ian@0 744 "No free channel found");
ian@0 745 return -EAGAIN;
ian@0 746 }
ian@0 747 if (!(ohci->ISO_channel_usage & mask)) {
ian@0 748 v.channel = i;
ian@0 749 PRINT(KERN_INFO, ohci->host->id, "Found free channel %d", i);
ian@0 750 break;
ian@0 751 }
ian@0 752 mask = mask << 1;
ian@0 753 }
ian@0 754 } else if (v.channel >= ISO_CHANNELS) {
ian@0 755 PRINT(KERN_ERR, ohci->host->id,
ian@0 756 "Iso channel %d out of bounds", v.channel);
ian@0 757 return -EINVAL;
ian@0 758 } else {
ian@0 759 mask = (u64)0x1<<v.channel;
ian@0 760 }
ian@0 761 DBGMSG(ohci->host->id, "mask: %08X%08X usage: %08X%08X\n",
ian@0 762 (u32)(mask>>32),(u32)(mask&0xffffffff),
ian@0 763 (u32)(ohci->ISO_channel_usage>>32),
ian@0 764 (u32)(ohci->ISO_channel_usage&0xffffffff));
ian@0 765 if (ohci->ISO_channel_usage & mask) {
ian@0 766 PRINT(KERN_ERR, ohci->host->id,
ian@0 767 "Channel %d is already taken", v.channel);
ian@0 768 return -EBUSY;
ian@0 769 }
ian@0 770
ian@0 771 if (v.buf_size == 0 || v.buf_size > VIDEO1394_MAX_SIZE) {
ian@0 772 PRINT(KERN_ERR, ohci->host->id,
ian@0 773 "Invalid %d length buffer requested",v.buf_size);
ian@0 774 return -EINVAL;
ian@0 775 }
ian@0 776
ian@0 777 if (v.nb_buffers == 0 || v.nb_buffers > VIDEO1394_MAX_SIZE) {
ian@0 778 PRINT(KERN_ERR, ohci->host->id,
ian@0 779 "Invalid %d buffers requested",v.nb_buffers);
ian@0 780 return -EINVAL;
ian@0 781 }
ian@0 782
ian@0 783 if (v.nb_buffers * v.buf_size > VIDEO1394_MAX_SIZE) {
ian@0 784 PRINT(KERN_ERR, ohci->host->id,
ian@0 785 "%d buffers of size %d bytes is too big",
ian@0 786 v.nb_buffers, v.buf_size);
ian@0 787 return -EINVAL;
ian@0 788 }
ian@0 789
ian@0 790 if (cmd == VIDEO1394_IOC_LISTEN_CHANNEL) {
ian@0 791 d = alloc_dma_iso_ctx(ohci, OHCI_ISO_RECEIVE,
ian@0 792 v.nb_buffers + 1, v.buf_size,
ian@0 793 v.channel, 0);
ian@0 794
ian@0 795 if (d == NULL) {
ian@0 796 PRINT(KERN_ERR, ohci->host->id,
ian@0 797 "Couldn't allocate ir context");
ian@0 798 return -EAGAIN;
ian@0 799 }
ian@0 800 initialize_dma_ir_ctx(d, v.sync_tag, v.flags);
ian@0 801
ian@0 802 ctx->current_ctx = d;
ian@0 803
ian@0 804 v.buf_size = d->buf_size;
ian@0 805 list_add_tail(&d->link, &ctx->context_list);
ian@0 806
ian@0 807 DBGMSG(ohci->host->id,
ian@0 808 "iso context %d listen on channel %d",
ian@0 809 d->ctx, v.channel);
ian@0 810 }
ian@0 811 else {
ian@0 812 d = alloc_dma_iso_ctx(ohci, OHCI_ISO_TRANSMIT,
ian@0 813 v.nb_buffers + 1, v.buf_size,
ian@0 814 v.channel, v.packet_size);
ian@0 815
ian@0 816 if (d == NULL) {
ian@0 817 PRINT(KERN_ERR, ohci->host->id,
ian@0 818 "Couldn't allocate it context");
ian@0 819 return -EAGAIN;
ian@0 820 }
ian@0 821 initialize_dma_it_ctx(d, v.sync_tag,
ian@0 822 v.syt_offset, v.flags);
ian@0 823
ian@0 824 ctx->current_ctx = d;
ian@0 825
ian@0 826 v.buf_size = d->buf_size;
ian@0 827
ian@0 828 list_add_tail(&d->link, &ctx->context_list);
ian@0 829
ian@0 830 DBGMSG(ohci->host->id,
ian@0 831 "Iso context %d talk on channel %d", d->ctx,
ian@0 832 v.channel);
ian@0 833 }
ian@0 834
ian@0 835 if (copy_to_user(argp, &v, sizeof(v))) {
ian@0 836 /* FIXME : free allocated dma resources */
ian@0 837 return -EFAULT;
ian@0 838 }
ian@0 839
ian@0 840 ohci->ISO_channel_usage |= mask;
ian@0 841
ian@0 842 return 0;
ian@0 843 }
ian@0 844 case VIDEO1394_IOC_UNLISTEN_CHANNEL:
ian@0 845 case VIDEO1394_IOC_UNTALK_CHANNEL:
ian@0 846 {
ian@0 847 int channel;
ian@0 848 u64 mask;
ian@0 849 struct dma_iso_ctx *d;
ian@0 850
ian@0 851 if (copy_from_user(&channel, argp, sizeof(int)))
ian@0 852 return -EFAULT;
ian@0 853
ian@0 854 if (channel < 0 || channel >= ISO_CHANNELS) {
ian@0 855 PRINT(KERN_ERR, ohci->host->id,
ian@0 856 "Iso channel %d out of bound", channel);
ian@0 857 return -EINVAL;
ian@0 858 }
ian@0 859 mask = (u64)0x1<<channel;
ian@0 860 if (!(ohci->ISO_channel_usage & mask)) {
ian@0 861 PRINT(KERN_ERR, ohci->host->id,
ian@0 862 "Channel %d is not being used", channel);
ian@0 863 return -ESRCH;
ian@0 864 }
ian@0 865
ian@0 866 /* Mark this channel as unused */
ian@0 867 ohci->ISO_channel_usage &= ~mask;
ian@0 868
ian@0 869 if (cmd == VIDEO1394_IOC_UNLISTEN_CHANNEL)
ian@0 870 d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, channel);
ian@0 871 else
ian@0 872 d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, channel);
ian@0 873
ian@0 874 if (d == NULL) return -ESRCH;
ian@0 875 DBGMSG(ohci->host->id, "Iso context %d "
ian@0 876 "stop talking on channel %d", d->ctx, channel);
ian@0 877 free_dma_iso_ctx(d);
ian@0 878
ian@0 879 return 0;
ian@0 880 }
ian@0 881 case VIDEO1394_IOC_LISTEN_QUEUE_BUFFER:
ian@0 882 {
ian@0 883 struct video1394_wait v;
ian@0 884 struct dma_iso_ctx *d;
ian@0 885 int next_prg;
ian@0 886
ian@0 887 if (copy_from_user(&v, argp, sizeof(v)))
ian@0 888 return -EFAULT;
ian@0 889
ian@0 890 d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
ian@0 891 if (d == NULL) return -EFAULT;
ian@0 892
ian@0 893 if ((v.buffer<0) || (v.buffer>=d->num_desc - 1)) {
ian@0 894 PRINT(KERN_ERR, ohci->host->id,
ian@0 895 "Buffer %d out of range",v.buffer);
ian@0 896 return -EINVAL;
ian@0 897 }
ian@0 898
ian@0 899 spin_lock_irqsave(&d->lock,flags);
ian@0 900
ian@0 901 if (d->buffer_status[v.buffer]==VIDEO1394_BUFFER_QUEUED) {
ian@0 902 PRINT(KERN_ERR, ohci->host->id,
ian@0 903 "Buffer %d is already used",v.buffer);
ian@0 904 spin_unlock_irqrestore(&d->lock,flags);
ian@0 905 return -EBUSY;
ian@0 906 }
ian@0 907
ian@0 908 d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
ian@0 909
ian@0 910 next_prg = (d->last_buffer + 1) % d->num_desc;
ian@0 911 if (d->last_buffer>=0)
ian@0 912 d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress =
ian@0 913 cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg], 0)
ian@0 914 & 0xfffffff0) | 0x1);
ian@0 915
ian@0 916 d->last_buffer = next_prg;
ian@0 917 reprogram_dma_ir_prg(d, d->last_buffer, v.buffer, d->flags);
ian@0 918
ian@0 919 d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = 0;
ian@0 920
ian@0 921 spin_unlock_irqrestore(&d->lock,flags);
ian@0 922
ian@0 923 if (!(reg_read(ohci, d->ctrlSet) & 0x8000))
ian@0 924 {
ian@0 925 DBGMSG(ohci->host->id, "Starting iso DMA ctx=%d",d->ctx);
ian@0 926
ian@0 927 /* Tell the controller where the first program is */
ian@0 928 reg_write(ohci, d->cmdPtr,
ian@0 929 dma_prog_region_offset_to_bus(&d->prg_reg[d->last_buffer], 0) | 0x1);
ian@0 930
ian@0 931 /* Run IR context */
ian@0 932 reg_write(ohci, d->ctrlSet, 0x8000);
ian@0 933 }
ian@0 934 else {
ian@0 935 /* Wake up dma context if necessary */
ian@0 936 if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
ian@0 937 DBGMSG(ohci->host->id,
ian@0 938 "Waking up iso dma ctx=%d", d->ctx);
ian@0 939 reg_write(ohci, d->ctrlSet, 0x1000);
ian@0 940 }
ian@0 941 }
ian@0 942 return 0;
ian@0 943
ian@0 944 }
ian@0 945 case VIDEO1394_IOC_LISTEN_WAIT_BUFFER:
ian@0 946 case VIDEO1394_IOC_LISTEN_POLL_BUFFER:
ian@0 947 {
ian@0 948 struct video1394_wait v;
ian@0 949 struct dma_iso_ctx *d;
ian@0 950 int i = 0;
ian@0 951
ian@0 952 if (copy_from_user(&v, argp, sizeof(v)))
ian@0 953 return -EFAULT;
ian@0 954
ian@0 955 d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
ian@0 956 if (d == NULL) return -EFAULT;
ian@0 957
ian@0 958 if ((v.buffer<0) || (v.buffer>d->num_desc - 1)) {
ian@0 959 PRINT(KERN_ERR, ohci->host->id,
ian@0 960 "Buffer %d out of range",v.buffer);
ian@0 961 return -EINVAL;
ian@0 962 }
ian@0 963
ian@0 964 /*
ian@0 965 * I change the way it works so that it returns
ian@0 966 * the last received frame.
ian@0 967 */
ian@0 968 spin_lock_irqsave(&d->lock, flags);
ian@0 969 switch(d->buffer_status[v.buffer]) {
ian@0 970 case VIDEO1394_BUFFER_READY:
ian@0 971 d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
ian@0 972 break;
ian@0 973 case VIDEO1394_BUFFER_QUEUED:
ian@0 974 if (cmd == VIDEO1394_IOC_LISTEN_POLL_BUFFER) {
ian@0 975 /* for polling, return error code EINTR */
ian@0 976 spin_unlock_irqrestore(&d->lock, flags);
ian@0 977 return -EINTR;
ian@0 978 }
ian@0 979
ian@0 980 spin_unlock_irqrestore(&d->lock, flags);
ian@0 981 wait_event_interruptible(d->waitq,
ian@0 982 video1394_buffer_state(d, v.buffer) ==
ian@0 983 VIDEO1394_BUFFER_READY);
ian@0 984 if (signal_pending(current))
ian@0 985 return -EINTR;
ian@0 986 spin_lock_irqsave(&d->lock, flags);
ian@0 987 d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
ian@0 988 break;
ian@0 989 default:
ian@0 990 PRINT(KERN_ERR, ohci->host->id,
ian@0 991 "Buffer %d is not queued",v.buffer);
ian@0 992 spin_unlock_irqrestore(&d->lock, flags);
ian@0 993 return -ESRCH;
ian@0 994 }
ian@0 995
ian@0 996 /* set time of buffer */
ian@0 997 v.filltime = d->buffer_time[v.buffer];
ian@0 998
ian@0 999 /*
ian@0 1000 * Look ahead to see how many more buffers have been received
ian@0 1001 */
ian@0 1002 i=0;
ian@0 1003 while (d->buffer_status[(v.buffer+1)%(d->num_desc - 1)]==
ian@0 1004 VIDEO1394_BUFFER_READY) {
ian@0 1005 v.buffer=(v.buffer+1)%(d->num_desc - 1);
ian@0 1006 i++;
ian@0 1007 }
ian@0 1008 spin_unlock_irqrestore(&d->lock, flags);
ian@0 1009
ian@0 1010 v.buffer=i;
ian@0 1011 if (copy_to_user(argp, &v, sizeof(v)))
ian@0 1012 return -EFAULT;
ian@0 1013
ian@0 1014 return 0;
ian@0 1015 }
ian@0 1016 case VIDEO1394_IOC_TALK_QUEUE_BUFFER:
ian@0 1017 {
ian@0 1018 struct video1394_wait v;
ian@0 1019 unsigned int *psizes = NULL;
ian@0 1020 struct dma_iso_ctx *d;
ian@0 1021 int next_prg;
ian@0 1022
ian@0 1023 if (copy_from_user(&v, argp, sizeof(v)))
ian@0 1024 return -EFAULT;
ian@0 1025
ian@0 1026 d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
ian@0 1027 if (d == NULL) return -EFAULT;
ian@0 1028
ian@0 1029 if ((v.buffer<0) || (v.buffer>=d->num_desc - 1)) {
ian@0 1030 PRINT(KERN_ERR, ohci->host->id,
ian@0 1031 "Buffer %d out of range",v.buffer);
ian@0 1032 return -EINVAL;
ian@0 1033 }
ian@0 1034
ian@0 1035 if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) {
ian@0 1036 int buf_size = d->nb_cmd * sizeof(*psizes);
ian@0 1037 struct video1394_queue_variable __user *p = argp;
ian@0 1038 unsigned int __user *qv;
ian@0 1039
ian@0 1040 if (get_user(qv, &p->packet_sizes))
ian@0 1041 return -EFAULT;
ian@0 1042
ian@0 1043 psizes = kmalloc(buf_size, GFP_KERNEL);
ian@0 1044 if (!psizes)
ian@0 1045 return -ENOMEM;
ian@0 1046
ian@0 1047 if (copy_from_user(psizes, qv, buf_size)) {
ian@0 1048 kfree(psizes);
ian@0 1049 return -EFAULT;
ian@0 1050 }
ian@0 1051 }
ian@0 1052
ian@0 1053 spin_lock_irqsave(&d->lock,flags);
ian@0 1054
ian@0 1055 /* last_buffer is last_prg */
ian@0 1056 next_prg = (d->last_buffer + 1) % d->num_desc;
ian@0 1057 if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) {
ian@0 1058 PRINT(KERN_ERR, ohci->host->id,
ian@0 1059 "Buffer %d is already used",v.buffer);
ian@0 1060 spin_unlock_irqrestore(&d->lock,flags);
ian@0 1061 kfree(psizes);
ian@0 1062 return -EBUSY;
ian@0 1063 }
ian@0 1064
ian@0 1065 if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) {
ian@0 1066 initialize_dma_it_prg_var_packet_queue(
ian@0 1067 d, next_prg, psizes, ohci);
ian@0 1068 }
ian@0 1069
ian@0 1070 d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
ian@0 1071
ian@0 1072 if (d->last_buffer >= 0) {
ian@0 1073 d->it_prg[d->last_buffer]
ian@0 1074 [ d->last_used_cmd[d->last_buffer] ].end.branchAddress =
ian@0 1075 cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg],
ian@0 1076 0) & 0xfffffff0) | 0x3);
ian@0 1077
ian@0 1078 d->it_prg[d->last_buffer]
ian@0 1079 [ d->last_used_cmd[d->last_buffer] ].begin.branchAddress =
ian@0 1080 cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg],
ian@0 1081 0) & 0xfffffff0) | 0x3);
ian@0 1082 d->next_buffer[d->last_buffer] = (v.buffer + 1) % (d->num_desc - 1);
ian@0 1083 }
ian@0 1084 d->last_buffer = next_prg;
ian@0 1085 reprogram_dma_it_prg(d, d->last_buffer, v.buffer);
ian@0 1086 d->next_buffer[d->last_buffer] = -1;
ian@0 1087
ian@0 1088 d->it_prg[d->last_buffer][d->last_used_cmd[d->last_buffer]].end.branchAddress = 0;
ian@0 1089
ian@0 1090 spin_unlock_irqrestore(&d->lock,flags);
ian@0 1091
ian@0 1092 if (!(reg_read(ohci, d->ctrlSet) & 0x8000))
ian@0 1093 {
ian@0 1094 DBGMSG(ohci->host->id, "Starting iso transmit DMA ctx=%d",
ian@0 1095 d->ctx);
ian@0 1096 put_timestamp(ohci, d, d->last_buffer);
ian@0 1097
ian@0 1098 /* Tell the controller where the first program is */
ian@0 1099 reg_write(ohci, d->cmdPtr,
ian@0 1100 dma_prog_region_offset_to_bus(&d->prg_reg[next_prg], 0) | 0x3);
ian@0 1101
ian@0 1102 /* Run IT context */
ian@0 1103 reg_write(ohci, d->ctrlSet, 0x8000);
ian@0 1104 }
ian@0 1105 else {
ian@0 1106 /* Wake up dma context if necessary */
ian@0 1107 if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
ian@0 1108 DBGMSG(ohci->host->id,
ian@0 1109 "Waking up iso transmit dma ctx=%d",
ian@0 1110 d->ctx);
ian@0 1111 put_timestamp(ohci, d, d->last_buffer);
ian@0 1112 reg_write(ohci, d->ctrlSet, 0x1000);
ian@0 1113 }
ian@0 1114 }
ian@0 1115
ian@0 1116 kfree(psizes);
ian@0 1117 return 0;
ian@0 1118
ian@0 1119 }
ian@0 1120 case VIDEO1394_IOC_TALK_WAIT_BUFFER:
ian@0 1121 {
ian@0 1122 struct video1394_wait v;
ian@0 1123 struct dma_iso_ctx *d;
ian@0 1124
ian@0 1125 if (copy_from_user(&v, argp, sizeof(v)))
ian@0 1126 return -EFAULT;
ian@0 1127
ian@0 1128 d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
ian@0 1129 if (d == NULL) return -EFAULT;
ian@0 1130
ian@0 1131 if ((v.buffer<0) || (v.buffer>=d->num_desc-1)) {
ian@0 1132 PRINT(KERN_ERR, ohci->host->id,
ian@0 1133 "Buffer %d out of range",v.buffer);
ian@0 1134 return -EINVAL;
ian@0 1135 }
ian@0 1136
ian@0 1137 switch(d->buffer_status[v.buffer]) {
ian@0 1138 case VIDEO1394_BUFFER_READY:
ian@0 1139 d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
ian@0 1140 return 0;
ian@0 1141 case VIDEO1394_BUFFER_QUEUED:
ian@0 1142 wait_event_interruptible(d->waitq,
ian@0 1143 (d->buffer_status[v.buffer] == VIDEO1394_BUFFER_READY));
ian@0 1144 if (signal_pending(current))
ian@0 1145 return -EINTR;
ian@0 1146 d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
ian@0 1147 return 0;
ian@0 1148 default:
ian@0 1149 PRINT(KERN_ERR, ohci->host->id,
ian@0 1150 "Buffer %d is not queued",v.buffer);
ian@0 1151 return -ESRCH;
ian@0 1152 }
ian@0 1153 }
ian@0 1154 default:
ian@0 1155 return -ENOTTY;
ian@0 1156 }
ian@0 1157 }
ian@0 1158
ian@0 1159 static long video1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
ian@0 1160 {
ian@0 1161 int err;
ian@0 1162 lock_kernel();
ian@0 1163 err = __video1394_ioctl(file, cmd, arg);
ian@0 1164 unlock_kernel();
ian@0 1165 return err;
ian@0 1166 }
ian@0 1167
ian@0 1168 /*
ian@0 1169 * This maps the vmalloced and reserved buffer to user space.
ian@0 1170 *
ian@0 1171 * FIXME:
ian@0 1172 * - PAGE_READONLY should suffice!?
ian@0 1173 * - remap_pfn_range is kind of inefficient for page by page remapping.
ian@0 1174 * But e.g. pte_alloc() does not work in modules ... :-(
ian@0 1175 */
ian@0 1176
ian@0 1177 static int video1394_mmap(struct file *file, struct vm_area_struct *vma)
ian@0 1178 {
ian@0 1179 struct file_ctx *ctx = (struct file_ctx *)file->private_data;
ian@0 1180 int res = -EINVAL;
ian@0 1181
ian@0 1182 lock_kernel();
ian@0 1183 if (ctx->current_ctx == NULL) {
ian@0 1184 PRINT(KERN_ERR, ctx->ohci->host->id, "Current iso context not set");
ian@0 1185 } else
ian@0 1186 res = dma_region_mmap(&ctx->current_ctx->dma, file, vma);
ian@0 1187 unlock_kernel();
ian@0 1188
ian@0 1189 return res;
ian@0 1190 }
ian@0 1191
ian@0 1192 static int video1394_open(struct inode *inode, struct file *file)
ian@0 1193 {
ian@0 1194 int i = ieee1394_file_to_instance(file);
ian@0 1195 struct ti_ohci *ohci;
ian@0 1196 struct file_ctx *ctx;
ian@0 1197
ian@0 1198 ohci = hpsb_get_hostinfo_bykey(&video1394_highlevel, i);
ian@0 1199 if (ohci == NULL)
ian@0 1200 return -EIO;
ian@0 1201
ian@0 1202 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
ian@0 1203 if (!ctx) {
ian@0 1204 PRINT(KERN_ERR, ohci->host->id, "Cannot malloc file_ctx");
ian@0 1205 return -ENOMEM;
ian@0 1206 }
ian@0 1207
ian@0 1208 ctx->ohci = ohci;
ian@0 1209 INIT_LIST_HEAD(&ctx->context_list);
ian@0 1210 ctx->current_ctx = NULL;
ian@0 1211 file->private_data = ctx;
ian@0 1212
ian@0 1213 return 0;
ian@0 1214 }
ian@0 1215
ian@0 1216 static int video1394_release(struct inode *inode, struct file *file)
ian@0 1217 {
ian@0 1218 struct file_ctx *ctx = (struct file_ctx *)file->private_data;
ian@0 1219 struct ti_ohci *ohci = ctx->ohci;
ian@0 1220 struct list_head *lh, *next;
ian@0 1221 u64 mask;
ian@0 1222
ian@0 1223 lock_kernel();
ian@0 1224 list_for_each_safe(lh, next, &ctx->context_list) {
ian@0 1225 struct dma_iso_ctx *d;
ian@0 1226 d = list_entry(lh, struct dma_iso_ctx, link);
ian@0 1227 mask = (u64) 1 << d->channel;
ian@0 1228
ian@0 1229 if (!(ohci->ISO_channel_usage & mask))
ian@0 1230 PRINT(KERN_ERR, ohci->host->id, "On release: Channel %d "
ian@0 1231 "is not being used", d->channel);
ian@0 1232 else
ian@0 1233 ohci->ISO_channel_usage &= ~mask;
ian@0 1234 DBGMSG(ohci->host->id, "On release: Iso %s context "
ian@0 1235 "%d stop listening on channel %d",
ian@0 1236 d->type == OHCI_ISO_RECEIVE ? "receive" : "transmit",
ian@0 1237 d->ctx, d->channel);
ian@0 1238 free_dma_iso_ctx(d);
ian@0 1239 }
ian@0 1240
ian@0 1241 kfree(ctx);
ian@0 1242 file->private_data = NULL;
ian@0 1243
ian@0 1244 unlock_kernel();
ian@0 1245 return 0;
ian@0 1246 }
ian@0 1247
ian@0 1248 #ifdef CONFIG_COMPAT
ian@0 1249 static long video1394_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg);
ian@0 1250 #endif
ian@0 1251
ian@0 1252 static struct cdev video1394_cdev;
ian@0 1253 static struct file_operations video1394_fops=
ian@0 1254 {
ian@0 1255 .owner = THIS_MODULE,
ian@0 1256 .unlocked_ioctl = video1394_ioctl,
ian@0 1257 #ifdef CONFIG_COMPAT
ian@0 1258 .compat_ioctl = video1394_compat_ioctl,
ian@0 1259 #endif
ian@0 1260 .mmap = video1394_mmap,
ian@0 1261 .open = video1394_open,
ian@0 1262 .release = video1394_release
ian@0 1263 };
ian@0 1264
ian@0 1265 /*** HOTPLUG STUFF **********************************************************/
ian@0 1266 /*
ian@0 1267 * Export information about protocols/devices supported by this driver.
ian@0 1268 */
ian@0 1269 static struct ieee1394_device_id video1394_id_table[] = {
ian@0 1270 {
ian@0 1271 .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
ian@0 1272 .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
ian@0 1273 .version = CAMERA_SW_VERSION_ENTRY & 0xffffff
ian@0 1274 },
ian@0 1275 {
ian@0 1276 .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
ian@0 1277 .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
ian@0 1278 .version = (CAMERA_SW_VERSION_ENTRY + 1) & 0xffffff
ian@0 1279 },
ian@0 1280 {
ian@0 1281 .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
ian@0 1282 .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
ian@0 1283 .version = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff
ian@0 1284 },
ian@0 1285 { }
ian@0 1286 };
ian@0 1287
ian@0 1288 MODULE_DEVICE_TABLE(ieee1394, video1394_id_table);
ian@0 1289
ian@0 1290 static struct hpsb_protocol_driver video1394_driver = {
ian@0 1291 .name = "1394 Digital Camera Driver",
ian@0 1292 .id_table = video1394_id_table,
ian@0 1293 .driver = {
ian@0 1294 .name = VIDEO1394_DRIVER_NAME,
ian@0 1295 .bus = &ieee1394_bus_type,
ian@0 1296 },
ian@0 1297 };
ian@0 1298
ian@0 1299
ian@0 1300 static void video1394_add_host (struct hpsb_host *host)
ian@0 1301 {
ian@0 1302 struct ti_ohci *ohci;
ian@0 1303 int minor;
ian@0 1304
ian@0 1305 /* We only work with the OHCI-1394 driver */
ian@0 1306 if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
ian@0 1307 return;
ian@0 1308
ian@0 1309 ohci = (struct ti_ohci *)host->hostdata;
ian@0 1310
ian@0 1311 if (!hpsb_create_hostinfo(&video1394_highlevel, host, 0)) {
ian@0 1312 PRINT(KERN_ERR, ohci->host->id, "Cannot allocate hostinfo");
ian@0 1313 return;
ian@0 1314 }
ian@0 1315
ian@0 1316 hpsb_set_hostinfo(&video1394_highlevel, host, ohci);
ian@0 1317 hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
ian@0 1318
ian@0 1319 minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
ian@0 1320 class_device_create(hpsb_protocol_class, NULL, MKDEV(
ian@0 1321 IEEE1394_MAJOR, minor),
ian@0 1322 NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
ian@0 1323 }
ian@0 1324
ian@0 1325
ian@0 1326 static void video1394_remove_host (struct hpsb_host *host)
ian@0 1327 {
ian@0 1328 struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
ian@0 1329
ian@0 1330 if (ohci)
ian@0 1331 class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
ian@0 1332 IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
ian@0 1333 return;
ian@0 1334 }
ian@0 1335
ian@0 1336
ian@0 1337 static struct hpsb_highlevel video1394_highlevel = {
ian@0 1338 .name = VIDEO1394_DRIVER_NAME,
ian@0 1339 .add_host = video1394_add_host,
ian@0 1340 .remove_host = video1394_remove_host,
ian@0 1341 };
ian@0 1342
ian@0 1343 MODULE_AUTHOR("Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>");
ian@0 1344 MODULE_DESCRIPTION("driver for digital video on OHCI board");
ian@0 1345 MODULE_SUPPORTED_DEVICE(VIDEO1394_DRIVER_NAME);
ian@0 1346 MODULE_LICENSE("GPL");
ian@0 1347
ian@0 1348 #ifdef CONFIG_COMPAT
ian@0 1349
ian@0 1350 #define VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER \
ian@0 1351 _IOW ('#', 0x12, struct video1394_wait32)
ian@0 1352 #define VIDEO1394_IOC32_LISTEN_WAIT_BUFFER \
ian@0 1353 _IOWR('#', 0x13, struct video1394_wait32)
ian@0 1354 #define VIDEO1394_IOC32_TALK_WAIT_BUFFER \
ian@0 1355 _IOW ('#', 0x17, struct video1394_wait32)
ian@0 1356 #define VIDEO1394_IOC32_LISTEN_POLL_BUFFER \
ian@0 1357 _IOWR('#', 0x18, struct video1394_wait32)
ian@0 1358
ian@0 1359 struct video1394_wait32 {
ian@0 1360 u32 channel;
ian@0 1361 u32 buffer;
ian@0 1362 struct compat_timeval filltime;
ian@0 1363 };
ian@0 1364
ian@0 1365 static int video1394_wr_wait32(struct file *file, unsigned int cmd, unsigned long arg)
ian@0 1366 {
ian@0 1367 struct video1394_wait32 __user *argp = (void __user *)arg;
ian@0 1368 struct video1394_wait32 wait32;
ian@0 1369 struct video1394_wait wait;
ian@0 1370 mm_segment_t old_fs;
ian@0 1371 int ret;
ian@0 1372
ian@0 1373 if (copy_from_user(&wait32, argp, sizeof(wait32)))
ian@0 1374 return -EFAULT;
ian@0 1375
ian@0 1376 wait.channel = wait32.channel;
ian@0 1377 wait.buffer = wait32.buffer;
ian@0 1378 wait.filltime.tv_sec = (time_t)wait32.filltime.tv_sec;
ian@0 1379 wait.filltime.tv_usec = (suseconds_t)wait32.filltime.tv_usec;
ian@0 1380
ian@0 1381 old_fs = get_fs();
ian@0 1382 set_fs(KERNEL_DS);
ian@0 1383 if (cmd == VIDEO1394_IOC32_LISTEN_WAIT_BUFFER)
ian@0 1384 ret = video1394_ioctl(file,
ian@0 1385 VIDEO1394_IOC_LISTEN_WAIT_BUFFER,
ian@0 1386 (unsigned long) &wait);
ian@0 1387 else
ian@0 1388 ret = video1394_ioctl(file,
ian@0 1389 VIDEO1394_IOC_LISTEN_POLL_BUFFER,
ian@0 1390 (unsigned long) &wait);
ian@0 1391 set_fs(old_fs);
ian@0 1392
ian@0 1393 if (!ret) {
ian@0 1394 wait32.channel = wait.channel;
ian@0 1395 wait32.buffer = wait.buffer;
ian@0 1396 wait32.filltime.tv_sec = (int)wait.filltime.tv_sec;
ian@0 1397 wait32.filltime.tv_usec = (int)wait.filltime.tv_usec;
ian@0 1398
ian@0 1399 if (copy_to_user(argp, &wait32, sizeof(wait32)))
ian@0 1400 ret = -EFAULT;
ian@0 1401 }
ian@0 1402
ian@0 1403 return ret;
ian@0 1404 }
ian@0 1405
ian@0 1406 static int video1394_w_wait32(struct file *file, unsigned int cmd, unsigned long arg)
ian@0 1407 {
ian@0 1408 struct video1394_wait32 wait32;
ian@0 1409 struct video1394_wait wait;
ian@0 1410 mm_segment_t old_fs;
ian@0 1411 int ret;
ian@0 1412
ian@0 1413 if (copy_from_user(&wait32, (void __user *)arg, sizeof(wait32)))
ian@0 1414 return -EFAULT;
ian@0 1415
ian@0 1416 wait.channel = wait32.channel;
ian@0 1417 wait.buffer = wait32.buffer;
ian@0 1418 wait.filltime.tv_sec = (time_t)wait32.filltime.tv_sec;
ian@0 1419 wait.filltime.tv_usec = (suseconds_t)wait32.filltime.tv_usec;
ian@0 1420
ian@0 1421 old_fs = get_fs();
ian@0 1422 set_fs(KERNEL_DS);
ian@0 1423 if (cmd == VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER)
ian@0 1424 ret = video1394_ioctl(file,
ian@0 1425 VIDEO1394_IOC_LISTEN_QUEUE_BUFFER,
ian@0 1426 (unsigned long) &wait);
ian@0 1427 else
ian@0 1428 ret = video1394_ioctl(file,
ian@0 1429 VIDEO1394_IOC_TALK_WAIT_BUFFER,
ian@0 1430 (unsigned long) &wait);
ian@0 1431 set_fs(old_fs);
ian@0 1432
ian@0 1433 return ret;
ian@0 1434 }
ian@0 1435
ian@0 1436 static int video1394_queue_buf32(struct file *file, unsigned int cmd, unsigned long arg)
ian@0 1437 {
ian@0 1438 return -EFAULT; /* ??? was there before. */
ian@0 1439
ian@0 1440 return video1394_ioctl(file,
ian@0 1441 VIDEO1394_IOC_TALK_QUEUE_BUFFER, arg);
ian@0 1442 }
ian@0 1443
ian@0 1444 static long video1394_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg)
ian@0 1445 {
ian@0 1446 switch (cmd) {
ian@0 1447 case VIDEO1394_IOC_LISTEN_CHANNEL:
ian@0 1448 case VIDEO1394_IOC_UNLISTEN_CHANNEL:
ian@0 1449 case VIDEO1394_IOC_TALK_CHANNEL:
ian@0 1450 case VIDEO1394_IOC_UNTALK_CHANNEL:
ian@0 1451 return video1394_ioctl(f, cmd, arg);
ian@0 1452
ian@0 1453 case VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER:
ian@0 1454 return video1394_w_wait32(f, cmd, arg);
ian@0 1455 case VIDEO1394_IOC32_LISTEN_WAIT_BUFFER:
ian@0 1456 return video1394_wr_wait32(f, cmd, arg);
ian@0 1457 case VIDEO1394_IOC_TALK_QUEUE_BUFFER:
ian@0 1458 return video1394_queue_buf32(f, cmd, arg);
ian@0 1459 case VIDEO1394_IOC32_TALK_WAIT_BUFFER:
ian@0 1460 return video1394_w_wait32(f, cmd, arg);
ian@0 1461 case VIDEO1394_IOC32_LISTEN_POLL_BUFFER:
ian@0 1462 return video1394_wr_wait32(f, cmd, arg);
ian@0 1463 default:
ian@0 1464 return -ENOIOCTLCMD;
ian@0 1465 }
ian@0 1466 }
ian@0 1467
ian@0 1468 #endif /* CONFIG_COMPAT */
ian@0 1469
ian@0 1470 static void __exit video1394_exit_module (void)
ian@0 1471 {
ian@0 1472 hpsb_unregister_protocol(&video1394_driver);
ian@0 1473 hpsb_unregister_highlevel(&video1394_highlevel);
ian@0 1474 cdev_del(&video1394_cdev);
ian@0 1475 PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module");
ian@0 1476 }
ian@0 1477
ian@0 1478 static int __init video1394_init_module (void)
ian@0 1479 {
ian@0 1480 int ret;
ian@0 1481
ian@0 1482 cdev_init(&video1394_cdev, &video1394_fops);
ian@0 1483 video1394_cdev.owner = THIS_MODULE;
ian@0 1484 kobject_set_name(&video1394_cdev.kobj, VIDEO1394_DRIVER_NAME);
ian@0 1485 ret = cdev_add(&video1394_cdev, IEEE1394_VIDEO1394_DEV, 16);
ian@0 1486 if (ret) {
ian@0 1487 PRINT_G(KERN_ERR, "video1394: unable to get minor device block");
ian@0 1488 return ret;
ian@0 1489 }
ian@0 1490
ian@0 1491 hpsb_register_highlevel(&video1394_highlevel);
ian@0 1492
ian@0 1493 ret = hpsb_register_protocol(&video1394_driver);
ian@0 1494 if (ret) {
ian@0 1495 PRINT_G(KERN_ERR, "video1394: failed to register protocol");
ian@0 1496 hpsb_unregister_highlevel(&video1394_highlevel);
ian@0 1497 cdev_del(&video1394_cdev);
ian@0 1498 return ret;
ian@0 1499 }
ian@0 1500
ian@0 1501 PRINT_G(KERN_INFO, "Installed " VIDEO1394_DRIVER_NAME " module");
ian@0 1502 return 0;
ian@0 1503 }
ian@0 1504
ian@0 1505
ian@0 1506 module_init(video1394_init_module);
ian@0 1507 module_exit(video1394_exit_module);