Main Page   Modules   Alphabetical List   Data Structures   File List   Related Pages  

E12fops.c

00001 /*E12fops.c
00002 file operations module for the 37E12 driver
00003 */
00004 #include "E12.h"
00005 #include "E12fops.h"
00006 #include "sE12.h"
00007 #include "../includes/E12user.h"
00008 #include <linux/vmalloc.h>
00009 #include <linux/mm.h>
00010 #include <linux/slab.h>
00011 
00012 
00013 
00014 
00015 struct file_operations E12fops={
00016   open:    E12_Open,
00017   read:    E12_Read,
00018   write:   E12_Write,
00019   ioctl:   E12_Ioctl,
00020   fasync:  E12_fasync,
00021   release: E12_Release,
00022 };
00023 
00024 
00025 static int AllocDevice(E12_device *device)
00026 {
00027 request_region(device->address,E12_IOSIZE,device->devicename);
00028 request_irq(device->IRQ, E12_Interrupt, 0, device->devicename, device);
00029 return 0;
00030 }
00031 
00032 static int DeallocDevice(E12_device *device)
00033 {
00034 if(device->valid!=TRUE)
00035   return -1;//device not allocated properly
00036 
00037 if(device->IRQ!=UNSET)
00038   free_irq(device->IRQ,device);
00039 
00040 if(device->address!=UNSET)
00041   release_region(device->address,E12_IOSIZE);
00042 return 0;
00043 }
00044 
00045 
00046 int E12_Open (struct inode *inode, struct file *filp)
00047 {
00048 int minor = NUM(inode->i_rdev);
00049 extern E12_device Global_E12device[E12MAXBOARDS];
00050 E12_device *device;
00051 
00052 if(minor>=E12MAXBOARDS) /*if the minor number is too high return with an error*/
00053   {
00054     GENDEBUG("invalid board number\n");
00055     return -ENODEV;
00056   }
00057 
00058 
00059 MOD_INC_USE_COUNT;
00060 
00061 
00062 GENDEBUG("device memory allocated\n");
00063 
00064 device =  &Global_E12device[minor];
00065 
00066 filp->private_data = device;
00067 
00068 if(device->valid==TRUE)
00069   AllocDevice(device);
00070 
00071 GENDEBUG(E12NAME"device %x opened\n",minor);
00072 return 0;
00073 }
00074 
00075 int E12_Ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
00076 {
00077 E12_device *device = filp->private_data;
00078 E12_config_struct config; 
00079 u8 identity; 
00080 isodata data;
00081 
00082 switch(cmd)
00083   {
00084   case E12_CONFIG:
00085  
00086 DeallocDevice(device);//first deallocate old device if needed;
00087 if(access_ok(VERIFY_READ,(void *)arg,sizeof(E12_config_struct)))
00088     copy_from_user(&config,(E12_config_struct *)arg,sizeof(E12_config_struct));
00089 else
00090   {
00091     E12MESSAGE("couldn't copy 37E12 config structure from user space\n");
00092     return -1;
00093   }
00094 
00095 
00096 if(0>check_region(config.address,E12_IOSIZE))
00097   {
00098     E12MESSAGE("IO address %x not available\n",config.address);
00099     return -1;
00100   }
00101 
00102 request_region(config.address,E12_IOSIZE,device->devicename);
00103 device->address = config.address;
00104 
00105 IDENT_CHECK(device,identity);
00106 
00107 if(identity!=PLDR1_IDENT)
00108   {
00109     E12MESSAGE("37e12 device not found at %x\n",config.address);
00110     release_region(device->address,E12_IOSIZE);
00111     device->address = UNSET;
00112     return -1;
00113   }
00114 
00115 IODEBUG("37e12 found at address %x\n",device->address);
00116 
00117 if(0>request_irq(config.IRQ, E12_Interrupt, 0, device->devicename, device))
00118   {
00119     E12MESSAGE("IRQ %u not available\n",config.IRQ);
00120     return -1;
00121   }
00122 
00123 device->IRQ = config.IRQ;
00124 
00125 if(config.IRQedge)
00126   device->IRQedge = RISING_EDGE;
00127 else
00128   device->IRQedge = FALLING_EDGE;
00129 
00130 device->valid = TRUE;
00131 
00132 
00133 IRQ_EDGE_INIT(device);
00134 return 0;
00135 
00136   case ISO_DIG_OUT:
00137     if(device->valid!=TRUE)
00138       {     
00139     E12MESSAGE("invalid device configuration\n"); 
00140     return -ENODEV;
00141       }
00142     if(access_ok(VERIFY_READ,(void *)arg,sizeof(isodata)))
00143       copy_from_user(&data,(isodata *)arg,sizeof(isodata));
00144     else
00145       {
00146     E12MESSAGE("couldn't copy 37E12 ISO data from user space\n");
00147     return -1;
00148       }
00149     ISO_OUT(device,data);
00150     return 0;
00151 
00152 
00153   case ISO_DIG_IN:
00154     if(device->valid!=TRUE)
00155       {
00156     E12MESSAGE("invalid device configuration\n");
00157     return -ENODEV;
00158       }
00159     ISO_IN(device,data);
00160     if(access_ok(VERIFY_READ,(void *)arg,sizeof(isodata)))
00161       copy_to_user((isodata *)arg,&data,sizeof(isodata));
00162     else
00163       {
00164     E12MESSAGE("couldn't copy 37E12 ISO data to user space\n");
00165     return -1;
00166       }
00167     return 0;
00168   }
00169 IODEBUG("invalid command\n");
00170 return -1;
00171 }
00172 
00173 
00174 ssize_t E12_Write(struct file *filp, const char *buff, size_t count, loff_t *offp)
00175 {
00176 E12_device *device = filp->private_data;
00177 u8 *data;
00178 int bytenum;
00179 
00180 if(device->valid!=TRUE)
00181   {
00182  E12MESSAGE("invalid device configuration\n");
00183   return -ENODEV;
00184   }
00185 IODEBUG("writing data\n");
00186 
00187 data = vmalloc(count);
00188 disable_irq(device->IRQ);
00189 
00190 copy_from_user(data,buff,count); 
00191 
00192 WRITE_MODE(device);
00193 
00194 for(bytenum=0;bytenum<count;bytenum++)
00195   {
00196     WAIT_FOR_IRQ_HIGH(device);/*wait for IRQ*/
00197 
00198     BUSOUT(device,data[bytenum]);
00199  
00200     DTACK_ON(device);
00201 
00202 WAIT_FOR_IRQ_LOW(device);/*wait for ACK*/
00203     
00204     if(bytenum<(count-1))
00205     DTACK_OFF(device);/*give bus away for next transfer*/
00206 
00207   }
00208 
00209 enable_irq(device->IRQ);/*this should generate a blank IRQ*/
00210 READ_MODE(device);
00211 DTACK_OFF(device);/*return bus control to COP*/
00212 vfree(data);
00213 IODEBUG("wrote %u bytes\n",bytenum);\
00214 return bytenum;
00215 }
00216 
00217 ssize_t E12_Read(struct file *filp, char *buff, size_t count, loff_t *offp)
00218 {
00219 E12_device *device = filp->private_data;
00220 char *data;
00221 int bytenum;
00222 u8 bitnine=0;
00223 
00224 IODEBUG("E12_Read\n");
00225 
00226 if(device->valid!=TRUE)
00227   {
00228     E12MESSAGE("invalid device configuration\n");
00229     return -ENODEV;
00230   }
00231 rmb();
00232 if(MIRQ_LOW(device))
00233   {
00234     IODEBUG("Transfer not pending\n");
00235 
00236     if(filp->f_flags & O_NONBLOCK)
00237       return 0;/*non-blocking operation, return immediatly*/
00238 
00239     IODEBUG("device is in blocking mode, sleeping\n");
00240     rmb();
00241     /*else it's a blocking operation, sleep until data arrives*/
00242     if(wait_event_interruptible(device->readqueue, MIRQ_HIGH(device))==-ERESTARTSYS){
00243       E12MESSAGE("37e12 read killed while waiting for data");
00244       return 0;
00245     }
00246 
00247     rmb();
00248     IODEBUG("device awoken\n");
00249   }
00250 
00251 disable_irq(device->IRQ);
00252 data = vmalloc(count);
00253 
00254 for(bytenum=0;bytenum<count;bytenum++)
00255   {
00256 DTACK_ON(device);
00257 //IODEBUG("wait for COP IRQ ack\n");
00258 WAIT_FOR_IRQ_LOW(device);/*wait for coprocessor to ack*/
00259 
00260 DATA_PORT(device,data[bytenum]);
00261 IODEBUG(" %c",data[bytenum]);
00262 BIT_NINE_READ(device,bitnine);
00263 
00264 //IODEBUG("%x %x\n",bytenum,bitnine);
00265 
00266 if(bitnine)
00267   {
00268     IODEBUG("transfer completed - bit nine set\n");
00269     enable_irq(device->IRQ);/*this should generate a blank*/
00270     copy_to_user(buff,data,(bytenum+1));/*move data to user space*/
00271     vfree(data);
00272     DTACK_OFF(device);
00273     return(bytenum+1);
00274   }
00275 
00276 if(bytenum<(count-1))/*wait for next byte if the buffer isn't full*/
00277   {
00278     DTACK_OFF(device);
00279     WAIT_FOR_IRQ_HIGH(device);
00280   }
00281 
00282   }
00283 IODEBUG("transfer completed - buffer filled\n");
00284 enable_irq(device->IRQ);/*this doesn't seem to  generate a blank*/
00285 copy_to_user(buff,data,bytenum);/*move data to user space*/
00286 vfree(data);
00287 DTACK_OFF(device);/*give the COP it's bus back*/
00288 IODEBUG("returned %u bytes\n",bytenum);
00289 return bytenum;
00290 }
00291 
00292 
00293 int E12_fasync(int fd, struct file *filp, int mode)
00294 {
00295 E12_device *device = filp->private_data;
00296 IODEBUG("fasync call\n");
00297 
00298 if(device==NULL)
00299   {
00300 GENDEBUG("NULL device, async failed\n");
00301 return -1;
00302   }
00303 
00304 return(fasync_helper(fd, filp, mode, &device->dataready)); 
00305 }
00306 
00307 
00308 
00309 int E12_Release(struct inode *inode, struct file *filp)
00310 {
00311 E12_device *device = filp->private_data;
00312 int minor = device->num;
00313 DeallocDevice(device);
00314 E12_fasync(-1,filp,0);
00315 GENDEBUG(E12NAME"-%u device closed\n",minor);
00316 MOD_DEC_USE_COUNT;
00317 return SUCCESS;
00318 }
00319 
00320 
00321 
00322 
00323 
00324 
00325 

Generated on Mon Dec 29 09:25:43 2003 for PCM-37e12 by doxygen1.2.15