[Linux1394-cvslog] rev 656 - trunk
Brought to you by:
aeb,
bencollins
From: SVN U. <dm...@li...> - 2002-10-29 02:45:14
|
Author: dmaas Date: 2002-10-28 21:45:09 -0500 (Mon, 28 Oct 2002) New Revision: 656 Modified: trunk/raw1394.c trunk/raw1394.h Log: rawiso merge part 4 - expose rawiso to user-space through raw1394 (except poll() change) Modified: trunk/raw1394.c ============================================================================== --- trunk/raw1394.c (original) +++ trunk/raw1394.c 2002-10-28 21:45:10.000000000 -0500 @@ -47,6 +47,7 @@ #include "ieee1394_core.h" #include "hosts.h" #include "highlevel.h" +#include "iso.h" #include "ieee1394_transactions.h" #include "raw1394.h" @@ -1992,6 +1993,170 @@ return retval; } +/* rawiso operations */ + +/* helper function - gather all the kernel iso status bits for returning to user-space */ +static void raw1394_iso_fill_status(struct hpsb_iso *iso, struct raw1394_iso_status *stat) +{ + 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; +} + +static int raw1394_iso_xmit_init(struct file_info *fi, void *uaddr) +{ + struct raw1394_iso_status stat; + + if(copy_from_user(&stat, uaddr, sizeof(stat))) + return -EFAULT; + + fi->iso_handle = hpsb_iso_xmit_init(fi->host, + stat.config.buf_packets, + stat.config.max_packet_size, + stat.config.channel, + stat.config.speed, + stat.config.irq_interval, + &fi->poll_wait_complete); + if(!fi->iso_handle) + return -ENOMEM; + + fi->iso_state = RAW1394_ISO_XMIT; + + raw1394_iso_fill_status(fi->iso_handle, &stat); + if(copy_to_user(uaddr, &stat, sizeof(stat))) + return -EFAULT; + return 0; +} + +static int raw1394_iso_recv_init(struct file_info *fi, void *uaddr) +{ + struct raw1394_iso_status stat; + + if(copy_from_user(&stat, uaddr, sizeof(stat))) + return -EFAULT; + + fi->iso_handle = hpsb_iso_recv_init(fi->host, + stat.config.buf_packets, + stat.config.max_packet_size, + stat.config.channel, + stat.config.irq_interval, + &fi->poll_wait_complete); + if(!fi->iso_handle) + return -ENOMEM; + + fi->iso_state = RAW1394_ISO_RECV; + + raw1394_iso_fill_status(fi->iso_handle, &stat); + if(copy_to_user(uaddr, &stat, sizeof(stat))) + return -EFAULT; + return 0; +} + +static int raw1394_iso_get_status(struct file_info *fi, void *uaddr) +{ + struct raw1394_iso_status stat; + struct hpsb_iso *iso = fi->iso_handle; + + raw1394_iso_fill_status(fi->iso_handle, &stat); + if(copy_to_user(uaddr, &stat, sizeof(stat))) + return -EFAULT; + + /* reset overflow counter */ + atomic_set(&iso->overflows, 0); + + return 0; +} + +static void raw1394_iso_shutdown(struct file_info *fi) +{ + if(fi->iso_handle) + hpsb_iso_shutdown(fi->iso_handle); + + fi->iso_handle = NULL; + fi->iso_state = RAW1394_ISO_INACTIVE; +} + +/* mmap the rawiso 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); +} + +/* ioctl is only used for rawiso operations */ +static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + struct file_info *fi = file->private_data; + + switch(fi->iso_state) { + case RAW1394_ISO_INACTIVE: + switch(cmd) { + case RAW1394_ISO_XMIT_INIT: + return raw1394_iso_xmit_init(fi, (void*) arg); + case RAW1394_ISO_RECV_INIT: + return raw1394_iso_recv_init(fi, (void*) arg); + default: + break; + } + break; + case RAW1394_ISO_RECV: + switch(cmd) { + case RAW1394_ISO_START: + return hpsb_iso_start(fi->iso_handle, arg); + case RAW1394_ISO_STOP: + hpsb_iso_stop(fi->iso_handle); + return 0; + + case RAW1394_ISO_GET_STATUS: + return raw1394_iso_get_status(fi, (void*) arg); + + case RAW1394_ISO_PRODUCE_CONSUME: + return hpsb_iso_recv_release_packets(fi->iso_handle, arg); + + case RAW1394_ISO_SHUTDOWN: + raw1394_iso_shutdown(fi); + return 0; + } + break; + case RAW1394_ISO_XMIT: + switch(cmd) { + case RAW1394_ISO_START: + return hpsb_iso_start(fi->iso_handle, arg); + case RAW1394_ISO_STOP: + hpsb_iso_stop(fi->iso_handle); + return 0; + + case RAW1394_ISO_GET_STATUS: + return raw1394_iso_get_status(fi, (void*) arg); + + case RAW1394_ISO_PRODUCE_CONSUME: + return hpsb_iso_xmit_queue_packets(fi->iso_handle, arg); + + case RAW1394_ISO_SHUTDOWN: + raw1394_iso_shutdown(fi); + return 0; + } + break; + default: + break; + } + + return -EINVAL; +} + static unsigned int raw1394_poll(struct file *file, poll_table *pt) { struct file_info *fi = file->private_data; @@ -2052,6 +2217,9 @@ struct arm_addr *arm_addr = NULL; int another_host; + if(fi->iso_state != RAW1394_ISO_INACTIVE) + raw1394_iso_shutdown(fi); + for (i = 0; i < 64; i++) { if (fi->listen_channels & (1ULL << i)) { hpsb_unlisten_channel(hl_handle, fi->host, i); @@ -2159,7 +2327,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: trunk/raw1394.h ============================================================================== --- trunk/raw1394.h (original) +++ trunk/raw1394.h 2002-10-28 21:45:10.000000000 -0500 @@ -115,6 +115,67 @@ struct arm_response *response; } *arm_request_response_t; +/* rawiso API */ + +/* ioctls */ +#define RAW1394_ISO_XMIT_INIT 1 +#define RAW1394_ISO_RECV_INIT 2 +#define RAW1394_ISO_START 3 +#define RAW1394_ISO_STOP 4 +#define RAW1394_ISO_GET_STATUS 5 +#define RAW1394_ISO_PRODUCE_CONSUME 6 +#define RAW1394_ISO_SHUTDOWN 7 + +/* per-packet metadata embedded in the ringbuffer */ +/* must be identical to hpsb_iso_packet_info in iso.h! */ +struct raw1394_iso_packet_info { + unsigned short len; + unsigned short cycle; + unsigned char channel; + unsigned char tag; + unsigned char sy; +}; + +struct raw1394_iso_config { + unsigned int buf_packets; + unsigned int max_packet_size; + int channel; + int speed; /* xmit only */ + int irq_interval; +}; + +/* argument to RAW1394_ISO_XMIT/RECV_INIT and RAW1394_ISO_GET_STATUS */ +struct raw1394_iso_status { + /* current settings */ + struct raw1394_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; + + /* (transmission only) the value the ISO CYCLE_COUNT register + will have when the first_packet is sent */ + int first_packet_cycle; +}; + #ifdef __KERNEL__ struct iso_block_store { @@ -123,6 +184,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; @@ -141,11 +206,16 @@ u8 *fcp_buffer; + /* old ISO API */ u64 listen_channels; quadlet_t *iso_buffer; size_t iso_buffer_length; u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */ + + /* new rawiso API */ + enum raw1394_iso_state iso_state; + struct hpsb_iso *iso_handle; }; struct arm_addr { |