/* * Copyright (C) Eicon Technology Corporation, 2000. * * Eicon File Revision : 1.12 * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * */ #define __NO_VERSION__ #include #include #include #include #include #undef N_DATA #include "adapter.h" #include "divas.h" #include "divalog.h" extern int DivasCardNext; void UxPause(long ms); int DivasGetMem(mem_block_t *); #define DIA_IOCTL_UNLOCK 12 void UnlockDivas(void); int do_ioctl(struct inode *pDivasInode, struct file *pDivasFile, unsigned int command, unsigned long arg) { byte *pUserCards, card_i; word wCardNum; switch (command) { case DIA_IOCTL_CONFIG: { dia_config_t DivaConfig; if (copy_from_user(&DivaConfig, (void *)arg, sizeof(dia_config_t))) return -EFAULT; DivasCardConfig(&DivaConfig); return 0; } case DIA_IOCTL_DETECT: pUserCards = (byte *) arg; if (!verify_area(VERIFY_WRITE, pUserCards, 20)) { if(__put_user(DivasCardNext, pUserCards++)) return -EFAULT; for (card_i=1; card_i < 20; card_i++) { if(__put_user((byte) DivasCards[card_i - 1].cfg.card_type, pUserCards++)) return -EFAULT; } } else return -EFAULT; return 0; case DIA_IOCTL_START: { dia_start_t DivaStart; if (copy_from_user(&DivaStart, (void *)arg, sizeof(dia_start_t))) return -EFAULT; return DivasCardStart(DivaStart.card_id); } case DIA_IOCTL_FLAVOUR: return 0; case DIA_IOCTL_LOAD: { dia_load_t DivaLoad; if(copy_from_user(&DivaLoad, (void *)arg, sizeof(dia_load_t))) return -EFAULT; if (!verify_area(VERIFY_READ, DivaLoad.code,DivaLoad.length)) { if (DivasCardLoad(&DivaLoad)) { printk(KERN_WARNING "Divas: Error loading DIVA Server adapter\n"); return -EINVAL; } return 0; } return -EFAULT; } case DIA_IOCTL_LOG: { dia_log_t DivaLog; if (copy_from_user(&DivaLog, (void *) arg, sizeof(dia_log_t))) return -EFAULT; DivasLog(&DivaLog); return 0; } case DIA_IOCTL_XLOG_REQ: if(get_user(wCardNum, (word *) arg)) return -EFAULT; DivasXlogReq(wCardNum); return 0; case DIA_IOCTL_GET_NUM: if(put_user(DivasCardNext, (int *)arg)) return -EFAULT; return 0; case DIA_IOCTL_GET_LIST: { dia_card_list_t cards; DPRINTF(("divas: DIA_IOCTL_GET_LIST")); DivasGetList(&cards); if(copy_to_user((void *)arg, &cards, sizeof(cards))) return -EFAULT; return 0; } case DIA_IOCTL_GET_MEM: { mem_block_t mem_block; if (copy_from_user(&mem_block, (void *)arg, sizeof(mem_block_t))) return -EFAULT; DivasGetMem(&mem_block); return 0; } case DIA_IOCTL_UNLOCK: UnlockDivas(); return 0; default: return -EINVAL; } return -EINVAL; } unsigned int do_poll(struct file *pFile, struct poll_table_struct *pPollTable) { word wMask = 0; if (!DivasLogFifoEmpty()) wMask |= POLLIN | POLLRDNORM; return wMask; } ssize_t do_read(struct file *pFile, char *pUserBuffer, size_t BufferSize, loff_t *pOffset) { klog_t *pClientLogBuffer = (klog_t *) pUserBuffer; klog_t *pHeadItem; if (BufferSize < sizeof(klog_t)) { printk(KERN_WARNING "Divas: Divalog buffer specifed a size that is too small (%d - %d required)\n", BufferSize, sizeof(klog_t)); return -EIO; } pHeadItem = (klog_t *) DivasLogFifoRead(); if (pHeadItem) { memcpy(pClientLogBuffer, pHeadItem, sizeof(klog_t)); kfree(pHeadItem); return sizeof(klog_t); } return 0; } static int private_usage_count; int do_open(struct inode *pInode, struct file *pFile) { MOD_INC_USE_COUNT; #ifdef MODULE private_usage_count++; #endif return 0; } int do_release(struct inode *pInode, struct file *pFile) { MOD_DEC_USE_COUNT; #ifdef MODULE private_usage_count--; #endif return 0; } void UnlockDivas(void) { while (private_usage_count > 0) { private_usage_count--; MOD_DEC_USE_COUNT; } }