static void drv_arithmetic_routine(struct work_struct* ws) { struct DataIn opData; int ans = 0; opData.a = myinb(DMAOPCODEADDR); opData.b = myinl(DMAOPERANDBADDR); opData.c = myinw(DMAOPERANDCADDR); if (opData.a == '+') { ans = opData.b + opData.c; } else if (opData.a == '-') { ans = opData.b - opData.c; } else if (opData.a == '*') { ans = opData.b * opData.c; } else if (opData.a == '/') { ans = opData.b / opData.c; } else if (opData.a == 'p') { ans = prime(opData.b, opData.c); } else { ans = 0; } printk("%s:%s():%d %c %d = %d\n", PREFIX_TITLE, __func__, opData.b, opData.a, opData.c, ans); myoutl(ans, DMAANSADDR); if(myinl(DMABLOCKADDR == FALSE)) { myoutl(TRUE, DMAREADABLEADDR); } }
static int drv_read(struct file *filp, char __user *buffer, size_t ss, loff_t* lo) { printk("%s:%s(): ans = %d\n", PREFIX_TITLE, __func__, myinl(DMAANSADDR)); *(int *)buffer = myinl(DMAANSADDR); // Clean answer & set readable to false myoutl(INITIANL_VALUE, DMAANSADDR); myoutl(FALSE, DMAREADABLEADDR); return 0; }
static int drv_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int value = 1; unsigned int studentID = 101062124; switch(cmd){ case HW5_IOCSETSTUID: // Copy data from user get_user(value, (int *)arg); myoutl(studentID, DMASTUIDADDR); printk("%s:%s(): My STUID is = %d\n", PREFIX_TITLE, __func__, myinl(DMASTUIDADDR)); break; case HW5_IOCSETRWOK: // Copy data from user get_user(value, (int *)arg); myoutl(value, DMARWOKADDR); printk("%s:%s(): RW OK\n", PREFIX_TITLE, __func__); break; case HW5_IOCSETIOCOK: // Copy data from user get_user(value, (int *)arg); myoutl(value, DMAIOCOKADDR); printk("%s:%s(): IOC OK\n", PREFIX_TITLE, __func__); break; case HW5_IOCSETIRQOK: // Copy data from user get_user(value, (int *)arg); myoutl(value, DMAIRQOKADDR); printk("%s:%s(): IRC OK\n", PREFIX_TITLE, __func__); break; case HW5_IOCSETBLOCK: // Copy data from user get_user(value, (int *)arg); myoutl(value, DMABLOCKADDR); if(value) { printk("%s:%s(): Blocking IO\n", PREFIX_TITLE, __func__); } else { printk("%s:%s(): Non-Blocking IO\n", PREFIX_TITLE, __func__); } break; case HW5_IOCWAITREADABLE: while(myinl(DMAREADABLEADDR) != TRUE) msleep(TIMEPERIOD); // Copy data to user put_user(TRUE, (int *)arg); printk("%s:%s(): wait readable 1\n", PREFIX_TITLE, __func__); break; default: return -1; } return 0; }
static void l_write(int p, const void *buff, int size) { int i; _Cli(); for(i = 0; i < size; i++) { myoutl( p , ( (int *) buff )[i] ); } _Sti(); }
static int drv_write(struct file *filp, const char __user *buffer, size_t ss, loff_t* lo) { // Get IO mode int IOMode = myinl(DMABLOCKADDR); printk("%s:%s(): queue work\n", PREFIX_TITLE, __func__); INIT_WORK(work_routine, drv_arithmetic_routine); // Get data dataIn = (struct DataIn *)buffer; myoutb(dataIn->a, DMAOPCODEADDR); myoutl(dataIn->b, DMAOPERANDBADDR); myoutw(dataIn->c, DMAOPERANDCADDR); // Decide io mode if(IOMode) { // Blocking IO printk("%s:%s(): block\n", PREFIX_TITLE, __func__); schedule_work(work_routine); flush_scheduled_work(); } else { // Non-locking IO schedule_work(work_routine); } return 0; }