void debug_print_debugstts( zion_params_t *params, int ch, char *str ) { unsigned short extmode = 0; int itr = 0; for ( itr = 0; itr < 3; ++itr ) { /* Disable TestEn all channel */ mbus_writew( 0, MBUS_ADDR(params, ZION_MBUS_EDMA_EXT_MODE(itr)) ); } /* Test mode 2 */ mbus_writeb( 0x21, MBUS_ADDR(params, ZION_MBUS_EDMA_EXT_MODE(ch)+1) ); extmode = (unsigned short)mbus_readw( MBUS_ADDR(params, ZION_MBUS_EDMA_EXT_MODE(ch)) ); PDEBUG( "%sCH%d ExtMode mode 2: 0x%04X\n", str, ch, extmode ); /* Test mode 5 */ mbus_writeb( 0x51, MBUS_ADDR(params, ZION_MBUS_EDMA_EXT_MODE(ch)+1) ); extmode = (unsigned short)mbus_readw( MBUS_ADDR(params, ZION_MBUS_EDMA_EXT_MODE(ch)) ); PDEBUG( "%sCH%d ExtMode mode 5: 0x%04X\n", str, ch, extmode ); /* Test mode 6 */ mbus_writeb( 0x61, MBUS_ADDR(params, ZION_MBUS_EDMA_EXT_MODE(ch)+1) ); extmode = (unsigned short)mbus_readw( MBUS_ADDR(params, ZION_MBUS_EDMA_EXT_MODE(ch)) ); PDEBUG( "%sCH%d ExtMode mode 6: 0x%04X\n", str, ch, extmode ); }
/*************************************************************************** * zion_dmaif_port_open **************************************************************************/ int zion_dmaif_port_open(zion_params_t * zion_params, struct inode *inode, struct file *filp) { int zion_minor = MINOR(inode->i_rdev); /* The case of EDMA port opened */ if (is_edma_port(zion_minor)) { int zion_edma_port = zion_minor - ZION_DMAIF; zion_edma_params_t *edma_prms = &(ZION_DMAIF_PARAM(zion_params)->port_params[zion_edma_port]); unsigned long irq_flags = 0; /* Spin lock */ spin_lock_irqsave( &(edma_prms->params_lock), irq_flags ); /* PDEBUG("EDMA port%d opened\n", zion_edma_port); */ /* Initialize EDMA parameters */ edma_prms->ch_no = (int)(zion_edma_port / ZION_EDMA_CH_PORT); edma_prms->condition = ZION_DMAIF_DISPATCH_PENDING; edma_prms->int_status = 0x0000; /* PDEBUG("Initialize EDMA CH%d\n", edma_prms->ch_no); */ /* Use private data of file structure */ filp->private_data = (void *)edma_prms; /* Clear DMA command register */ mbus_writeb( 0, MBUS_ADDR(zion_params, ZION_MBUS_EDMA_DMACMD(edma_prms->ch_no)+1) ); /** Success **/ /* Unlock spin lock */ spin_unlock_irqrestore( &(edma_prms->params_lock), irq_flags ); // MOD_INC_USE_COUNT; return 0; } /** The case of NOT EDMA port opened **/ PERROR("Minor number is invalid(%d)!\n", zion_minor); return (-ENODEV); }
/*************************************************************************** * zion_dmaif_event * @func * Interruption handler for EDMA * @args * zion_params_t *params [in/out]: parameters of ZION driver * int irq [in] : IRQ number * void *dev_id [in] : Device ID * u16 pci_status[in] : PCI config interrupt status * @return * void * @comment * * @author * H. Hoshino **************************************************************************/ void zion_dmaif_event(zion_params_t * params, int bit, int irq, void *dev_id, u16 pci_status) { unsigned short int_status = 0; unsigned short int_mask = 0; int ch = 0; zion_edma_params_t *edma_prms = NULL; /*** Check EDMA interruption for each channel ***/ for (ch = 0; ch < ZION_EDMA_NR_CH; ++ch) { /* Get interrupt status and mask(enable) */ int_status = (unsigned short)mbus_readw( MBUS_ADDR(params, ZION_MBUS_EDMA_INTSTTS(ch)) ); int_mask = (unsigned short)mbus_readw( MBUS_ADDR(params, ZION_MBUS_EDMA_INTENB(ch)) ); /* Memorize it ! */ params->interrupt_bits.DMA_INT[ch] |= int_status; /* for DEBUG */ /* PDEBUG( "CH%d int_status: 0x%04X, mask: 0x%04X\n", */ /* ch, int_status, int_mask ); */ /** Check interruptions (Common port) **/ if ( int_status & int_mask ) { /* Get EDMA params */ edma_prms = &(ZION_DMAIF_PARAM(params)->port_params[ZION_EDMA_CMN_PORTNO(ch)]); /* for DEBUG */ /* PDEBUG( "[CH%d port%d] Get interruptions!\n", */ /* ch, ZION_EDMA_CMN_PORTNO(ch) ); */ if ( NULL == edma_prms ) { PERROR( "[CH%d port%d] EDMA params is NULL!!\n", ch, ZION_EDMA_CMN_PORTNO(ch) ); mbus_writew( (ZION_MBUS_EDMA_DMADONEINT | ZION_MBUS_EDMA_SYNCFRMINT | ZION_MBUS_EDMA_BUFFINT_MASK | ZION_MBUS_EDMA_ERRINT_MASK), MBUS_ADDR(params, ZION_MBUS_EDMA_INTCLR(ch))); /** Clear interrupt status INT B reg **/ zion_mbus_int_clear(params, Dmaif_Int); return; } /* Set interrupt status */ spin_lock( &(edma_prms->params_lock) ); /* Spin lock */ edma_prms->int_status |= int_status; /* edma_prms->int_status = int_status; */ spin_unlock( &(edma_prms->params_lock) ); /* Unlock spin lock */ /* Wake up */ spin_lock( &(edma_prms->params_lock) ); /* Spin lock */ edma_prms->condition = ZION_DMAIF_DISPATCH_DONE; spin_unlock( &(edma_prms->params_lock) ); /* Unlock spin lock */ wake_up(&(edma_prms->zion_dmaif_wait_queue)); } /** Check sync frame pulse interruption **/ if ( int_status & int_mask & ZION_MBUS_EDMA_SYNCFRMINT ) { /* Get EDMA params */ edma_prms = &(ZION_DMAIF_PARAM(params)->port_params[ZION_EDMA_FRM_PORTNO(ch)]); /* for DEBUG */ /* PDEBUG( "[CH%d port%d] Sync frame pulse!\n", */ /* ch, ZION_EDMA_FRM_PORTNO(ch) ); */ /* Set interrupt status */ spin_lock( &(edma_prms->params_lock) ); /* Spin lock */ if ( 0 == edma_prms->int_status ) { edma_prms->int_status = int_status; } else { /* PDEBUG( "[CH%d port%d] int_status is already set(0x%04X, 0x%04X)!\n", */ /* ch, ZION_EDMA_DMA_PORTNO(ch), edma_prms->int_status, int_status ); */ } spin_unlock( &(edma_prms->params_lock) ); /* Unlock spin lock */ /* Clear interrupt status: sync frame pulse */ mbus_writew(ZION_MBUS_EDMA_SYNCFRMINT, MBUS_ADDR(params, ZION_MBUS_EDMA_INTCLR(ch))); /* Wake up */ spin_lock( &(edma_prms->params_lock) ); /* Spin lock */ edma_prms->condition = ZION_DMAIF_DISPATCH_DONE; spin_unlock( &(edma_prms->params_lock) ); /* Unlock spin lock */ wake_up(&(edma_prms->zion_dmaif_wait_queue)); } /** Check DMA done interruption **/ if ( int_status & int_mask & ZION_MBUS_EDMA_DMADONEINT ) { /* Get EDMA params */ edma_prms = &(ZION_DMAIF_PARAM(params)->port_params[ZION_EDMA_DMA_PORTNO(ch)]); /* for DEBUG */ PDEBUG( "[CH%d port%d] DMA Done!\n", ch, ZION_EDMA_DMA_PORTNO(ch) ); /* PINFO( "[CH%d port%d] DMA Done!\n", */ /* ch, ZION_EDMA_DMA_PORTNO(ch) ); */ /* Stop DMA for G1&G2 transfer mode */ { unsigned char cmd = mbus_readb( MBUS_ADDR(params, (ZION_MBUS_EDMA_DMACMD(ch)+1)) ); mbus_writeb( (cmd & (~0x02)), MBUS_ADDR(params, (ZION_MBUS_EDMA_DMACMD(ch)+1)) ); } /* for DEBUG XXX*/ /* { */ /* unsigned short usPMT = mbus_readw( MBUS_ADDR(params, ZION_MBUS_EDMA_CURRPMT(ch)) ); */ /* PDEBUG( "[CH%d port%d] CurrPMT: 0x%04X\n", */ /* ch, ZION_EDMA_DMA_PORTNO(ch), usPMT ); */ /* } */ spin_lock( &(edma_prms->params_lock) ); /* Spin lock */ /* Set interrupt status */ /* PDEBUG( "[CH%d] int_status: 0x%04X, old: 0x%04X!\n", */ /* ch, int_status, edma_prms->int_status ); */ if ( 0 == edma_prms->int_status ) { edma_prms->int_status = int_status; } else { /* PDEBUG( "[CH%d port%d] int_status is already set(0x%04X, 0x%04X)!\n", */ /* ch, ZION_EDMA_DMA_PORTNO(ch), edma_prms->int_status, int_status ); */ } /* Delete timer */ del_timer_sync(&(edma_prms->timer)); spin_unlock( &(edma_prms->params_lock) ); /* Unlock spin lock */ /* Clear interrupt status: DMA done */ mbus_writew(ZION_MBUS_EDMA_DMADONEINT, MBUS_ADDR(params, ZION_MBUS_EDMA_INTCLR(ch))); /* Wake up */ spin_lock( &(edma_prms->params_lock) ); /* Spin lock */ edma_prms->condition = ZION_DMAIF_DISPATCH_DONE; spin_unlock( &(edma_prms->params_lock) ); /* Unlock spin lock */ wake_up(&(edma_prms->zion_dmaif_wait_queue)); } /** Check error and buffer empty/almost empty/almost full/full interruption **/ if ( int_status & int_mask & (ZION_MBUS_EDMA_BUFFINT_MASK | ZION_MBUS_EDMA_ERRINT_MASK) ) { /* Get EDMA parameters */ edma_prms = &(ZION_DMAIF_PARAM (params)->port_params[ZION_EDMA_BUF_PORTNO(ch)]); /* for DEBUG */ PDEBUG( "[CH%d port%d] Error or warning!\n", ch, ZION_EDMA_BUF_PORTNO(ch) ); /* Set interrupt status */ spin_lock( &(edma_prms->params_lock) ); /* Spin lock */ /* PDEBUG( "[CH%d] int_status: 0x%04X, old: 0x%04X!\n", */ /* ch, int_status, edma_prms->int_status ); */ if ( 0 == edma_prms->int_status ) { edma_prms->int_status = int_status; } else { /* PDEBUG( "[CH%d port%d] int_status is already set(0x%04X, 0x%04X)!\n", */ /* ch, ZION_EDMA_BUF_PORTNO(ch), edma_prms->int_status, int_status ); */ } spin_unlock( &(edma_prms->params_lock) ); /* Unlock spin lock */ /* Clear interrupt status */ mbus_writew((ZION_MBUS_EDMA_BUFFINT_MASK | ZION_MBUS_EDMA_ERRINT_MASK), MBUS_ADDR(params, ZION_MBUS_EDMA_INTCLR(ch))); /* Wake up */ spin_lock( &(edma_prms->params_lock) ); /* Spin lock */ edma_prms->condition = ZION_DMAIF_DISPATCH_DONE; spin_unlock( &(edma_prms->params_lock) ); /* Unlock spin lock */ wake_up(&(edma_prms->zion_dmaif_wait_queue)); } } /* The end of FOR(ch) */ /** Clear interrupt status INT B reg **/ zion_mbus_int_clear(params, Dmaif_Int); /* PDEBUG ("exit %s\n", __FUNCTION__); */ return; }
/*************************************************************************** * zion_dmaif_port_ioctl **************************************************************************/ int zion_dmaif_port_ioctl(zion_params_t * params, struct inode *inode, struct file *file, unsigned int function, unsigned long arg) { switch (function) { case ZION_EDMA_IOC_OPEN: { unsigned char ucReg = 0; zion_edma_params_t *edma_prms = (zion_edma_params_t *)file->private_data; int ch = -1; int rw = -1; unsigned long irq_flags = 0; /* Check EDMA parameters */ if (NULL == edma_prms) { PERROR("Private data is NULL!\n"); return (-ENODEV); } /* Get and check EDMA channel number */ ch = edma_prms->ch_no; if (ch < 0 || ZION_EDMA_NR_CH <= ch) { PERROR("Invalid ZION EDMA channel number(%d)!", ch); return (-ENODEV); } /* Get argument: I/O direction */ if (copy_from_user((void *)&rw, (void *)arg, sizeof(int))) return (-EFAULT); /* Check argument: I/O direction */ if ((ZION_EDMA_READ != rw) && (ZION_EDMA_WRITE != rw)) { PERROR("[CH%d] Invalid I/O direction(%d)!\n", ch, rw); return (-EINVAL); } /* Read EDMA command register */ ucReg = mbus_readb(MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(ch) + 1)); /* Write EDMA command register: DmaOpen=1 */ ucReg |= (ZION_MBUS_EDMA_OPEN | (rw << 2)) & 0x0F; /* PDEBUG("[CH%d] EDMA open(0x%02X)\n", ch, ucReg); */ mbus_writeb(ucReg, MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(ch) + 1)); /* Clear interrupt status */ spin_lock_irqsave( &(edma_prms->params_lock), irq_flags ); edma_prms->int_status = 0x0000; spin_unlock_irqrestore( &(edma_prms->params_lock), irq_flags ); break; } case ZION_EDMA_IOC_CLOSE: { unsigned char ucReg = 0; zion_edma_params_t *edma_prms = (zion_edma_params_t *)file->private_data; int ch = -1; /* Check EDMA parameters */ if (NULL == edma_prms) { PERROR("Private data is NULL!\n"); return (-ENODEV); } /* Get and check EDMA channel number */ ch = edma_prms->ch_no; if (ch < 0 || ZION_EDMA_NR_CH <= ch) { PERROR("Invalid ZION EDMA channel number(%d)!", ch); return (-ENODEV); } /* Read EDMA command register */ ucReg = mbus_readb( MBUS_ADDR(params, (ZION_MBUS_EDMA_DMACMD(ch)+1)) ); /* Write EDMA command register: DmaOpen=0 */ ucReg &= ZION_MBUS_EDMA_CLOSE & 0x0F; /* PDEBUG("[CH%d] EDMA close(0x%02X)\n", ch, ucReg); */ mbus_writeb( ucReg, MBUS_ADDR(params, (ZION_MBUS_EDMA_DMACMD(ch)+1)) ); /* Success */ break; } case ZION_EDMA_IOC_RUN: { unsigned char ucReg = 0; zion_edma_params_t *edma_prms = (zion_edma_params_t *)file->private_data; int ch = -1; unsigned short usCmdReg = 0; /* Check EDMA parameters */ if (NULL == edma_prms) { PERROR("Private data is NULL!\n"); return (-ENODEV); } /* Get and check EDMA channel number */ ch = edma_prms->ch_no; if (ch < 0 || ZION_EDMA_NR_CH <= ch) { PERROR("Invalid ZION EDMA channel number(%d)!", ch); return (-ENODEV); } /* Read EDMA command register */ ucReg = mbus_readb(MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(ch) + 1)); /* Write EDMA command register: DmaRun=1 */ ucReg |= ZION_MBUS_EDMA_RUN; PDEBUG ("[CH%d] EDMA run(0x%02X)\n", ch, ucReg); mbus_writeb(ucReg, MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(ch) + 1)); #ifdef NEO_WRITEBACK /* for DEBUG -- write back XXX */ usCmdReg = (unsigned short)mbus_readw( MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(edma_prms->ch_no)) ); /* PDEBUG( "[CH%d] Write back DMA RUN: 0x%04X\n", */ /* edma_prms->ch_no, usCmdReg ); */ #endif /* NEO_WRITEBACK */ /* Success */ break; } case ZION_EDMA_IOC_STOP: { unsigned char ucReg = 0; zion_edma_params_t *edma_prms = (zion_edma_params_t *)file->private_data; int ch = -1; /* Check EDMA parameters */ if (NULL == edma_prms) { PERROR("Private data is NULL!\n"); return (-ENODEV); } /* Get and check EDMA channel number */ ch = edma_prms->ch_no; if (ch < 0 || ZION_EDMA_NR_CH <= ch) { PERROR("Invalid ZION EDMA channel number(%d)!", ch); return (-ENODEV); } /* Read EDMA command register */ ucReg = mbus_readb(MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(ch) + 1)); /* Write EDMA command register: DmaRun=0 */ ucReg &= ZION_MBUS_EDMA_STOP & 0x0F; /* PDEBUG("[CH%d] EDMA stop(0x%02X)\n", ch, ucReg); */ mbus_writeb(ucReg, MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(ch) + 1)); /* Success */ break; } case ZION_EDMA_IOC_READ: { /* EDMA read */ return (zion_edma_run(params, inode, file, ZION_EDMA_READ)); } case ZION_EDMA_IOC_WRITE: { /* EDMA write */ return (zion_edma_run(params, inode, file, ZION_EDMA_WRITE)); } case ZION_EDMA_IOC_SET_REGION: { struct zion_edma_region s_zion_edma_region; if (copy_from_user((void *)&s_zion_edma_region, (void *)arg, sizeof(struct zion_edma_region))) return (-EFAULT); return zion_edma_set_region(params, s_zion_edma_region.dma_ch, s_zion_edma_region.num, s_zion_edma_region.lower, s_zion_edma_region.upper); } case ZION_EDMA_IOC_GET_REGION: { struct zion_edma_region s_zion_edma_region; if (copy_from_user((void *)&s_zion_edma_region, (void *)arg, sizeof(struct zion_edma_region))) return (-EFAULT); if (zion_edma_get_region(params, s_zion_edma_region.dma_ch, s_zion_edma_region.num, &s_zion_edma_region.lower, &s_zion_edma_region.upper)) return -EINVAL; if (copy_to_user((void *)arg, (void *)&s_zion_edma_region, sizeof(struct zion_edma_region))) return -EFAULT; /* Success */ break; } /* Get interrupt status for poll-select */ case ZION_EDMA_IOC_GET_INTSTTS: { zion_edma_params_t *edma_prms = (zion_edma_params_t *)file->private_data; int ch = -1; unsigned long irq_flags = 0; /* Check EDMA parameters */ if (NULL == edma_prms) { PERROR("Invalid ZION EDMA parameters!\n"); return (-ENODEV); } /* Set and check EDMA channel number */ ch = edma_prms->ch_no; if (ch < 0 || ZION_EDMA_NR_CH <= ch) { PERROR("Invalid ZION EDMA channel number(%d)!", ch); return (-ENODEV); } /* Set interrupt status */ if (copy_to_user((void *)arg, (void *)&(edma_prms->int_status), sizeof(unsigned short))) return (-EFAULT); /* Clear interrupt status */ spin_lock_irqsave( &(edma_prms->params_lock), irq_flags ); edma_prms->int_status = 0x0000; spin_unlock_irqrestore( &(edma_prms->params_lock), irq_flags ); /* Success */ break; } default: PERROR("No such Ioctl command!\n"); return (-EINVAL); } /* The end of SWITCH(function) */ return 0; }
/*************************************************************************** * zion_edma_run * @func * Run ZION-NEO EDMA * @args * zion_params_t *params [in/out]: parameters of ZION driver * struct inode *inode [in] : inode * struct file *file [in] : file structure * int rw [in] : command * @return * int * 0 : success * < 0 : error * @comment * * @author * H. Hoshino **************************************************************************/ static int zion_edma_run(zion_params_t * params, struct inode *inode, struct file *file, int rw) { unsigned char ucDmaWnR = 0; #ifdef NEO_WRITEBACK unsigned short usCmdReg = 0; #endif /* NEO_WRITEBACK */ /* Get minor number */ int zion_minor = MINOR(inode->i_rdev); /* Get EDMA parameters */ zion_edma_params_t *edma_prms = (zion_edma_params_t *)file->private_data; /* Check EDMA parameters */ if (NULL == edma_prms) { PERROR("Private data is NULL!(minor:%d)\n", zion_minor); return (-ENODEV); } /* Check argument: rw and set DMA I/O direction */ switch (rw) { case ZION_EDMA_READ: /* for DEBUG */ /* PDEBUG("[CH%d minor%d]EDMA read\n", edma_prms->ch_no, zion_minor); */ ucDmaWnR = ZION_MBUS_EDMA_READ; break; case ZION_EDMA_WRITE: /* for DEBUG */ /* PDEBUG("[CH%d minor%d]EDMA write\n", edma_prms->ch_no, zion_minor); */ ucDmaWnR = ZION_MBUS_EDMA_WRITE; break; default: PERROR("[CH%d minor%d]Invalid I/O direction!(%d)\n", edma_prms->ch_no, zion_minor, rw); return (-EINVAL); } /* end of switch (rw) */ /* Set condition */ edma_prms->condition = ZION_DMAIF_DISPATCH_PENDING; /* Set timed out */ init_timer(&(edma_prms->timer)); edma_prms->timer.function = zion_edma_timeout; edma_prms->timer.data = (unsigned long)params; edma_prms->timer.expires = jiffies + ZION_DMAIF_TIMEOUT; add_timer(&(edma_prms->timer)); /* DMA Run */ mbus_writeb( ((ucDmaWnR | ZION_MBUS_EDMA_RUN | ZION_MBUS_EDMA_OPEN) & 0x0F), MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(edma_prms->ch_no) + 1)); #ifdef NEO_WRITEBACK /* for DEBUG -- write back XXX */ usCmdReg = (unsigned short)mbus_readw( MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(edma_prms->ch_no)) ); /* PDEBUG( "[CH%d minor%d] Write back DMA RUN: 0x%04X\n", */ /* edma_prms->ch_no, zion_minor, usCmdReg ); */ #endif /* NEO_WRITEBACK */ /* Sleep */ wait_event(edma_prms->zion_dmaif_wait_queue, (edma_prms->condition != ZION_DMAIF_DISPATCH_PENDING)); /* DMA End -- check timedout */ if (ZION_DMAIF_DISPATCH_TIMEOUT == edma_prms->condition) { PERROR("[CH%d minor%d]ZION EDMA Write Timedout!\n", edma_prms->ch_no, zion_minor); /* for DEBUG XXX */ debug_print_debugstts( params, 0, "" ); debug_print_debugstts( params, 2, "" ); debug_print_stts( params, 0, "" ); debug_print_stts( params, 1, "" ); debug_print_stts( params, 2, "" ); return (-ETIME); } /* Success */ return (0); }
static int zion_common_ioctl(zion_params_t *zion_params, struct inode *inode, struct file *filp, unsigned int function, unsigned long arg) { struct zion_config_byte zion_config_byte = {0}; struct zion_config_word zion_config_word = {0}; struct zion_config_dword zion_config_dword = {0}; struct zion_buf zion_buf; struct ZION_Interrupt_Bits zion_interrupt = {0}; u16 revision; switch(function) { case ZION_MBUS_READ_CONFIG_BYTE: if(copy_from_user((void *)&zion_config_byte, (void *)arg, sizeof(struct zion_config_byte))) return -EFAULT; zion_config_byte.val = (u8) mbus_readb( MBUS_ADDR(zion_params, zion_config_byte.where) ); if(copy_to_user((void *)arg, (void *)&zion_config_byte, sizeof(struct zion_config_byte))) return -EFAULT; break; case ZION_MBUS_READ_CONFIG_WORD: if(copy_from_user((void *)&zion_config_word, (void *)arg, sizeof(struct zion_config_word))) return -EFAULT; zion_config_word.val = (u16) mbus_readw( MBUS_ADDR(zion_params,zion_config_word.where) ); if(copy_to_user((void *)arg, (void *)&zion_config_word, sizeof(struct zion_config_word))) return -EFAULT; break; case ZION_MBUS_READ_CONFIG_DWORD: if(copy_from_user((void *)&zion_config_dword, (void *)arg, sizeof(struct zion_config_dword))) return -EFAULT; zion_config_dword.val = (u32) mbus_readl( MBUS_ADDR(zion_params,zion_config_dword.where) ); if(copy_to_user((void *)arg, (void *)&zion_config_dword, sizeof(struct zion_config_dword))) return -EFAULT; break; case ZION_MBUS_WRITE_CONFIG_BYTE: if(copy_from_user((void *)&zion_config_byte, (void *)arg, sizeof(struct zion_config_byte))) return -EFAULT; mbus_writeb(zion_config_byte.val, MBUS_ADDR(zion_params, zion_config_byte.where) ); if(copy_to_user((void *)arg, (void *)&zion_config_byte, sizeof(struct zion_config_byte))) return -EFAULT; break; case ZION_MBUS_WRITE_CONFIG_WORD: if(copy_from_user((void *)&zion_config_word, (void *)arg, sizeof(struct zion_config_word))) return -EFAULT; mbus_writew(zion_config_word.val, MBUS_ADDR(zion_params, zion_config_word.where) ); if(copy_to_user((void *)arg, (void *)&zion_config_word, sizeof(struct zion_config_word))) return -EFAULT; break; case ZION_MBUS_WRITE_CONFIG_DWORD: if(copy_from_user((void *)&zion_config_dword, (void *)arg, sizeof(struct zion_config_dword))) return -EFAULT; mbus_writel(zion_config_dword.val, MBUS_ADDR(zion_params, zion_config_dword.where) ); if(copy_to_user((void *)arg, (void *)&zion_config_dword, sizeof(struct zion_config_dword))) return -EFAULT; break; case ZION_WRAM_READ: if(copy_from_user((void *)&zion_buf, (void *)arg, sizeof(struct zion_buf))) return -EFAULT; if((zion_buf.size = neo_wram_pio_read(zion_params, zion_buf.addr, zion_buf.buf, zion_buf.size, zion_buf.access_type))==0) return -EINVAL; if(copy_to_user((void *)arg, (void *)&zion_buf, sizeof(struct zion_buf))) return -EFAULT; break; case ZION_WRAM_WRITE: if(copy_from_user((void *)&zion_buf, (void *)arg, sizeof(struct zion_buf))) return -EFAULT; if((zion_buf.size = neo_wram_pio_write(zion_params, zion_buf.addr, zion_buf.buf, zion_buf.size, zion_buf.access_type))==0) return -EINVAL; if(copy_to_user((void *)arg, (void *)&zion_buf, sizeof(struct zion_buf))) return -EFAULT; break; case ZION_WAIT_INTERRUPT: zion_goto_bed(zion_params, &zion_interrupt); /* zion_interrupt.c */ if(copy_to_user((void *)arg, (void *)&zion_interrupt, sizeof(struct ZION_Interrupt_Bits))) return -EFAULT; break; case ZION_WAKE_THREADS_UP: zion_rout_them_up(zion_params); /* zion_interrupt.c */ break; case ZION_SET_ENABLE_BITS: if(copy_from_user((void *)&zion_interrupt, (void *)arg, sizeof(struct ZION_Interrupt_Bits))) return -EFAULT; zion_set_enable_bits(zion_params, &zion_interrupt); /* zion_interrupt.c */ break; case ZION_GET_ENABLE_BITS: zion_get_enable_bits(zion_params, &zion_interrupt); /* zion_interrupt.c */ if(copy_to_user((void *)arg, (void *)&zion_interrupt, sizeof(struct ZION_Interrupt_Bits))) return -EFAULT; break; case ZION_SET_TIMEOUT: zion_params->wait_timeout = arg; /* by jiffies */ break; case ZION_GET_REVISION: revision = zion_params->revision; if(copy_to_user((void *)arg, (void *)&revision, sizeof(u16))) { return -EFAULT; } break; default: PERROR("No such IOCTL.\n"); return -EINVAL; } return 0; }