[Linux1394-cvslog] rev 563 - branches/rawiso
Brought to you by:
aeb,
bencollins
From: SVN U. <dm...@li...> - 2002-08-28 07:46:30
|
Author: dmaas Date: 2002-08-28 12:38:46 -0400 (Wed, 28 Aug 2002) New Revision: 563 Modified: branches/rawiso/raw1394.c branches/rawiso/raw1394.h Log: expose new ISO API through raw1394 Modified: branches/rawiso/raw1394.c ============================================================================== --- branches/rawiso/raw1394.c (original) +++ branches/rawiso/raw1394.c 2002-08-28 12:38:47.000000000 -0400 @@ -28,6 +28,7 @@ #include "ieee1394_core.h" #include "hosts.h" #include "highlevel.h" +#include "iso.h" #include "ieee1394_transactions.h" #include "raw1394.h" @@ -892,19 +893,168 @@ return retval; } +/* ISO operations */ + +static int raw1394_iso_start_xmit(struct file_info *fi, void *uaddr) +{ + struct raw1394_kernel_iso_config config; + + if(copy_from_user(&config, uaddr, sizeof(config))) + return -EFAULT; + + fi->iso_handle = hpsb_iso_xmit_start(fi->host, + config.buf_packets, + config.max_packet_size, + config.channel, + config.speed, + config.irq_interval, + &fi->poll_wait_complete); + if(!fi->iso_handle) + return -ENOMEM; + + fi->iso_state = RAW1394_ISO_XMIT; + return 0; +} + +static int raw1394_iso_start_recv(struct file_info *fi, void *uaddr) +{ + struct raw1394_kernel_iso_config config; + + if(copy_from_user(&config, uaddr, sizeof(config))) + return -EFAULT; + + fi->iso_handle = hpsb_iso_recv_start(fi->host, + config.buf_packets, + config.max_packet_size, + config.channel, + config.irq_interval, + &fi->poll_wait_complete); + if(!fi->iso_handle) + return -ENOMEM; + + fi->iso_state = RAW1394_ISO_RECV; + return 0; +} + +static int raw1394_iso_get_status(struct file_info *fi, void *uaddr) +{ + struct raw1394_kernel_iso_status stat; + struct hpsb_iso *iso = fi->iso_handle; + + stat.config.buf_packets = iso->buf_packets; + stat.config.max_packet_size = iso->max_packet_size; + stat.config.channel = iso->channel; + stat.config.speed = iso->speed; + stat.config.irq_interval = iso->irq_interval; + + stat.buf_stride = iso->buf_stride; + stat.packet_data_offset = iso->packet_data_offset; + stat.packet_info_offset = iso->packet_info_offset; + stat.first_packet = iso->first_packet; + stat.n_packets = hpsb_iso_n_ready(iso); + stat.overflows = atomic_read(&iso->overflows); + stat.first_packet_cycle = iso->first_packet_cycle; + + if(copy_to_user(uaddr, &stat, sizeof(stat))) + return -EFAULT; + + /* reset overflow counter */ + atomic_set(&iso->overflows, 0); + + return 0; +} + +static void raw1394_iso_stop(struct file_info *fi) +{ + if(fi->iso_state == RAW1394_ISO_RECV) + hpsb_iso_recv_stop(fi->iso_handle); + else + hpsb_iso_xmit_stop(fi->iso_handle); + + fi->iso_handle = NULL; + + fi->iso_state = RAW1394_ISO_INACTIVE; +} + +/* mmap the ISO xmit/recv buffer */ +static int raw1394_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct file_info *fi = file->private_data; + + if(fi->iso_state == RAW1394_ISO_INACTIVE) + return -EINVAL; + + return dma_region_mmap(&fi->iso_handle->buf, file, vma); +} + +static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + struct file_info *fi = file->private_data; + + /* ioctl is only used for ISO operations */ + + switch(fi->iso_state) { + case RAW1394_ISO_INACTIVE: + switch(cmd) { + case RAW1394_ISO_START_XMIT: + return raw1394_iso_start_xmit(fi, (void*) arg); + case RAW1394_ISO_START_RECV: + return raw1394_iso_start_recv(fi, (void*) arg); + default: + break; + } + break; + case RAW1394_ISO_RECV: + switch(cmd) { + case RAW1394_ISO_GET_STATUS: + return raw1394_iso_get_status(fi, (void*) arg); + case RAW1394_ISO_PRODUCE_CONSUME: + return hpsb_iso_recv_consume(fi->iso_handle, arg); + case RAW1394_ISO_STOP: + raw1394_iso_stop(fi); + return 0; + } + break; + case RAW1394_ISO_XMIT: + switch(cmd) { + case RAW1394_ISO_GET_STATUS: + return raw1394_iso_get_status(fi, (void*) arg); + case RAW1394_ISO_PRODUCE_CONSUME: + return hpsb_iso_xmit_produce(fi->iso_handle, arg); + case RAW1394_ISO_STOP: + raw1394_iso_stop(fi); + return 0; + } + break; + default: + break; + } + + return -EINVAL; +} + +/* + POLLIN/OUT is for read/write requests + POLLPRI is for ISO transmission and reception + */ static unsigned int raw1394_poll(struct file *file, poll_table *pt) { struct file_info *fi = file->private_data; - unsigned int mask = POLLOUT | POLLWRNORM; + unsigned int mask = 0; poll_wait(file, &fi->poll_wait_complete, pt); - - spin_lock_irq(&fi->reqlists_lock); + + spin_lock_irq(&fi->reqlists_lock); if (!list_empty(&fi->req_complete)) { mask |= POLLIN | POLLRDNORM; } spin_unlock_irq(&fi->reqlists_lock); + if(fi->iso_state != RAW1394_ISO_INACTIVE) { + if(hpsb_iso_n_ready(fi->iso_handle) > 0) + mask |= POLLPRI; + } + return mask; } @@ -929,7 +1079,7 @@ sema_init(&fi->complete_sem, 0); spin_lock_init(&fi->reqlists_lock); init_waitqueue_head(&fi->poll_wait_complete); - + file->private_data = fi; return 0; @@ -942,6 +1092,9 @@ struct pending_request *req; int done = 0, i; + if(fi->iso_state != RAW1394_ISO_INACTIVE) + raw1394_iso_stop(fi); + for (i = 0; i < 64; i++) { if (fi->listen_channels & (1ULL << i)) { hpsb_unlisten_channel(hl_handle, fi->host, i); @@ -995,7 +1148,9 @@ static struct file_operations file_ops = { .owner = THIS_MODULE, .read = raw1394_read, - .write = raw1394_write, + .write = raw1394_write, + .mmap = raw1394_mmap, + .ioctl = raw1394_ioctl, .poll = raw1394_poll, .open = raw1394_open, .release = raw1394_release, Modified: branches/rawiso/raw1394.h ============================================================================== --- branches/rawiso/raw1394.h (original) +++ branches/rawiso/raw1394.h 2002-08-28 12:38:47.000000000 -0400 @@ -69,6 +69,57 @@ __u8 name[32]; }; +/* new ISO API */ + +/* ioctls */ +#define RAW1394_ISO_START_XMIT 1 +#define RAW1394_ISO_START_RECV 2 +#define RAW1394_ISO_GET_STATUS 3 +#define RAW1394_ISO_STOP 4 +#define RAW1394_ISO_PRODUCE_CONSUME 5 + +/* argument to RAW1394_ISO_START_RECV, XMIT */ +struct raw1394_kernel_iso_config { + unsigned int buf_packets; + unsigned int max_packet_size; + int channel; + int speed; /* xmit only */ + int irq_interval; +}; + +struct raw1394_kernel_iso_status { + /* current settings */ + struct raw1394_kernel_iso_config config; + + /* byte offset between successive packets in the buffer */ + int buf_stride; + + /* byte offset of data payload within each packet */ + int packet_data_offset; + + /* byte offset of struct iso_packet_info within each packet */ + int packet_info_offset; + + /* index of next packet to fill with data (ISO transmission) + or next packet containing data recieved (ISO reception) */ + unsigned int first_packet; + + /* number of packets waiting to be filled with data (ISO transmission) + or containing data received (ISO reception) */ + unsigned int n_packets; + + /* approximate number of packets dropped due to overflow or + underflow of the packet buffer (a value of zero guarantees + that no packets have been dropped) */ + unsigned int overflows; + + /* the value the ISO CYCLE_COUNT register will have when the first_packet + is sent (ISO transmission) or received (ISO reception). + set to -1 if you don't care about cycle matching. + */ + int first_packet_cycle; +}; + #ifdef __KERNEL__ struct iso_block_store { @@ -77,6 +128,10 @@ quadlet_t data[0]; }; +enum raw1394_iso_state { RAW1394_ISO_INACTIVE = 0, + RAW1394_ISO_RECV = 1, + RAW1394_ISO_XMIT = 2 }; + struct file_info { struct list_head list; @@ -93,9 +148,14 @@ u8 *fcp_buffer; + /* old ISO API */ u64 listen_channels; quadlet_t *iso_buffer; size_t iso_buffer_length; + + /* new ISO API */ + enum raw1394_iso_state iso_state; + struct hpsb_iso *iso_handle; }; struct pending_request { |