struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host, unsigned int data_buf_size, unsigned int buf_packets, int channel, int dma_mode, int irq_interval, void (*callback)(struct hpsb_iso*)) { struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_RECV, data_buf_size, buf_packets, channel, dma_mode, irq_interval, callback); if (!iso) return NULL; /* tell the driver to start working */ if (host->driver->isoctl(iso, RECV_INIT, 0)) goto err; iso->flags |= HPSB_ISO_DRIVER_INIT; return iso; err: hpsb_iso_shutdown(iso); return NULL; }
struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host, unsigned int data_buf_size, unsigned int buf_packets, int channel, int speed, int irq_interval, void (*callback)(struct hpsb_iso*)) { struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_XMIT, data_buf_size, buf_packets, channel, HPSB_ISO_DMA_DEFAULT, irq_interval, callback); if (!iso) return NULL; iso->speed = speed; /* tell the driver to start working */ if (host->driver->isoctl(iso, XMIT_INIT, 0)) goto err; iso->flags |= HPSB_ISO_DRIVER_INIT; return iso; err: hpsb_iso_shutdown(iso); return NULL; }
static void stop_iso(struct firedtv *fdtv) { struct hpsb_iso *iso_handle = fdtv->backend_data; if (iso_handle != NULL) { hpsb_iso_stop(iso_handle); hpsb_iso_shutdown(iso_handle); } fdtv->backend_data = NULL; }
static int start_iso(struct firedtv *fdtv) { struct hpsb_iso *iso_handle; int ret; iso_handle = hpsb_iso_recv_init(node_of(fdtv)->host, FDTV_ISO_BUFFER_SIZE, FDTV_ISO_BUFFER_PACKETS, fdtv->isochannel, HPSB_ISO_DMA_DEFAULT, -1, /* stat.config.irq_interval */ rawiso_activity_cb); if (iso_handle == NULL) { dev_err(fdtv->device, "cannot initialize iso receive\n"); return -ENOMEM; } fdtv->backend_data = iso_handle; ret = hpsb_iso_recv_start(iso_handle, -1, -1, 0); if (ret != 0) { dev_err(fdtv->device, "cannot start iso receive\n"); hpsb_iso_shutdown(iso_handle); fdtv->backend_data = NULL; } return ret; }
static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_iso_type type, unsigned int data_buf_size, unsigned int buf_packets, int channel, int dma_mode, int irq_interval, void (*callback)(struct hpsb_iso*)) { struct hpsb_iso *iso; int dma_direction; /* make sure driver supports the ISO API */ if (!host->driver->isoctl) { printk(KERN_INFO "ieee1394: host driver '%s' does not support the rawiso API\n", host->driver->name); return NULL; } /* sanitize parameters */ if (buf_packets < 2) buf_packets = 2; if ((dma_mode < HPSB_ISO_DMA_DEFAULT) || (dma_mode > HPSB_ISO_DMA_PACKET_PER_BUFFER)) dma_mode=HPSB_ISO_DMA_DEFAULT; if (irq_interval == 0) /* really interrupt for each packet*/ irq_interval = 1; else if ((irq_interval < 0) || (irq_interval > buf_packets / 4)) irq_interval = buf_packets / 4; if (channel < -1 || channel >= 64) return NULL; /* channel = -1 is OK for multi-channel recv but not for xmit */ if (type == HPSB_ISO_XMIT && channel < 0) return NULL; /* allocate and write the struct hpsb_iso */ iso = kmalloc(sizeof(*iso) + buf_packets * sizeof(struct hpsb_iso_packet_info), GFP_KERNEL); if (!iso) return NULL; iso->infos = (struct hpsb_iso_packet_info *)(iso + 1); iso->type = type; iso->host = host; iso->hostdata = NULL; iso->callback = callback; init_waitqueue_head(&iso->waitq); iso->channel = channel; iso->irq_interval = irq_interval; iso->dma_mode = dma_mode; dma_region_init(&iso->data_buf); iso->buf_size = round_up_to_page(data_buf_size); iso->buf_packets = buf_packets; iso->pkt_dma = 0; iso->first_packet = 0; spin_lock_init(&iso->lock); if (iso->type == HPSB_ISO_XMIT) { iso->n_ready_packets = iso->buf_packets; dma_direction = PCI_DMA_TODEVICE; } else { iso->n_ready_packets = 0; dma_direction = PCI_DMA_FROMDEVICE; } atomic_set(&iso->overflows, 0); iso->flags = 0; iso->prebuffer = 0; /* allocate the packet buffer */ if (dma_region_alloc(&iso->data_buf, iso->buf_size, host->pdev, dma_direction)) goto err; return iso; err: hpsb_iso_shutdown(iso); return NULL; }