static int do_release(struct inode * inode, struct file * filp) { struct apm_user * as; as = filp->private_data; if (check_apm_user(as, "release")) return 0; filp->private_data = NULL; lock_kernel(); if (as->suspends_pending > 0) { suspends_pending -= as->suspends_pending; if (suspends_pending <= 0) wake_up(&apm_suspend_waitqueue); } if (user_list == as) user_list = as->next; else { struct apm_user * as1; for (as1 = user_list; (as1 != NULL) && (as1->next != as); as1 = as1->next) ; if (as1 == NULL) printk(KERN_ERR "apm: filp not in user list\n"); else as1->next = as->next; } unlock_kernel(); kfree(as); return 0; }
static int do_release(struct inode * inode, struct file * filp) { struct apm_user * as; as = filp->private_data; if (check_apm_user(as, "release")) return 0; filp->private_data = NULL; lock_kernel(); /* * by zxf, 11/11/2002 * free memory malloced when open correctly */ if (user_list == as) user_list = as->next; else { struct apm_user * as1; for (as1 = user_list; (as1 != NULL) && (as1->next != as); as1 = as1->next) ; if (as1 == NULL) printk(KERN_ERR "apm: filp not in user list\n"); else as1->next = as->next; } unlock_kernel(); APM_DPRINTK("do_release: free mem at 0x%x\n", (unsigned int)as); kfree(as); return 0; }
static unsigned int do_poll(struct file *fp, poll_table * wait) { struct apm_user * as; as = fp->private_data; if (check_apm_user(as, "poll")) return 0; poll_wait(fp, &apm_waitqueue, wait); if (!queue_empty(as)) return POLLIN | POLLRDNORM; return 0; }
static ssize_t do_read(struct file *fp, char *buf, size_t count, loff_t *ppos) { struct apm_user * as; int i; apm_event_t event; DECLARE_WAITQUEUE(wait, current); as = fp->private_data; if (check_apm_user(as, "read")) return -EIO; if (count < sizeof(apm_event_t)) return -EINVAL; if (queue_empty(as)) { if (fp->f_flags & O_NONBLOCK) return -EAGAIN; add_wait_queue(&apm_waitqueue, &wait); repeat: set_current_state(TASK_INTERRUPTIBLE); if (queue_empty(as) && !signal_pending(current)) { schedule(); goto repeat; } set_current_state(TASK_RUNNING); remove_wait_queue(&apm_waitqueue, &wait); } i = count; while ((i >= sizeof(event)) && !queue_empty(as)) { event = get_queued_event(as); DBG("apm_emu: do_read, returning: %s\n", apm_event_name[event-1]); if (copy_to_user(buf, &event, sizeof(event))) { if (i < count) break; return -EFAULT; } switch (event) { case APM_SYS_SUSPEND: case APM_USER_SUSPEND: as->suspends_read++; break; } buf += sizeof(event); i -= sizeof(event); } if (i < count) return count - i; if (signal_pending(current)) return -ERESTARTSYS; return 0; }
static int do_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) { struct apm_user * as; DECLARE_WAITQUEUE(wait, current); as = filp->private_data; if (check_apm_user(as, "ioctl")) return -EIO; if (!as->suser) return -EPERM; switch (cmd) { case APM_IOC_SUSPEND: /* If a suspend message was sent to userland, we * consider this as a confirmation message */ if (as->suspends_read > 0) { as->suspends_read--; as->suspends_pending--; suspends_pending--; } else { // Route to PMU suspend ? break; } as->suspend_waiting = 1; add_wait_queue(&apm_waitqueue, &wait); DBG("apm_emu: ioctl waking up sleep waiter !\n"); wake_up(&apm_suspend_waitqueue); mb(); while(as->suspend_waiting && !signal_pending(current)) { set_current_state(TASK_INTERRUPTIBLE); schedule(); } set_current_state(TASK_RUNNING); remove_wait_queue(&apm_waitqueue, &wait); break; default: return -EINVAL; } return 0; }
static int do_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) { struct apm_user * as; struct pm_dev * pm; struct ipm_config conf; as = filp->private_data; if (check_apm_user(as, "ioctl")) return -EIO; memset(&conf, 0, sizeof(conf)); switch (cmd) { case APM_IOC_SUSPEND: pm_do_suspend(CPUMODE_SLEEP); break; case APM_IOC_SET_WAKEUP: if ((pm = pm_find((pm_dev_t)arg,NULL)) == NULL) return -EINVAL; pm_send(pm,PM_SET_WAKEUP,NULL); break; case APM_IOC_SLEEP: pm_go_sleep(arg); break; case APM_IOC_SET_SPROF_WIN: sleep_to = arg * HZ; APM_DPRINTK("do_ioctl: sleep timeout %ld\n", arg); break; case APM_IOC_WAKEUP_ENABLE: PWER |= arg; APM_DPRINTK("do_ioctl: enable wakeup source:PWER=0x%x\n", PWER); break; case APM_IOC_WAKEUP_DISABLE: PWER &= ~arg; APM_DPRINTK("do_ioctl: disable wakeup source:PWER=0x%x\n", PWER); break; case APM_IOC_POWEROFF: APM_DPRINTK("do_ioctl: do power off\n"); /* here all device should response ok */ pm_send_all(PM_SUSPEND, (void *)3); pm_do_poweroff(); pm_send_all(PM_RESUME, (void *)0); break; case APM_IOC_RESET_BP: APM_DPRINTK("do_ioctl: reset bp\n"); GPCR(GPIO_BB_RESET) = GPIO_bit(GPIO_BB_RESET); mdelay(1); GPSR(GPIO_BB_RESET) = GPIO_bit(GPIO_BB_RESET); break; case APM_IOC_USEROFF_ENABLE: APM_DPRINTK("do_ioctl: useroff support enable\n"); user_off_available = (int)arg; break; case APM_IOC_NOTIFY_BP: break; case APM_IOC_REFLASH: cpu_proc_fin(); *(unsigned long *)(phys_to_virt(FLAG_ADDR)) = REFLASH_FLAG; // power_ic_periph_set_usb_pull_up(0); //LIN mdelay(1000); //LIN let GPIO control the connectivity #include <linux/power_ic.h> set_GPIO_mode(GPIO_USB_READY|GPIO_OUT); clr_GPIO(GPIO_USB_READY); power_ic_periph_set_usb_pull_up(0); mdelay(10); power_ic_set_reg_bit(POWER_IC_REG_EOC_CONN_CONTROL,19,1);//LIN set USB_CNTRL(bit19) to disable emu control mdelay(1000); //LIN power_ic_periph_set_usb_pull_up(1); /* Initialize the watchdog and let it fire */ OWER = OWER_WME; OSSR = OSSR_M3; OSMR3 = OSCR + CLOCK_TICK_RATE/100; /* ... in 10 ms */ MDREFR |= MDREFR_SLFRSH; while(1); break; case APM_IOC_PASSTHRU: cpu_proc_fin(); *(unsigned long *)(phys_to_virt(FLAG_ADDR)) = PASS_THRU_FLAG; power_ic_periph_set_usb_pull_up(0); mdelay(1000); power_ic_periph_set_usb_pull_up(1); /* Initialize the watchdog and let it fire */ OWER = OWER_WME; OSSR = OSSR_M3; OSMR3 = OSCR + CLOCK_TICK_RATE/100; /* ... in 10 ms */ MDREFR |= MDREFR_SLFRSH; while(1); break; case APM_IOC_SET_IPROF_WIN: /* set profile window size */ break; case APM_IOC_STARTPMU: if( pipm_start_pmu !=NULL ) pipm_start_pmu(); break; case APM_IOC_GET_IPM_CONFIG: get_ipm_config(&conf); return (copy_to_user((void *)arg, &conf,sizeof(conf)))? -EFAULT:0; break; case APM_IOC_SET_IPM_CONFIG: if(copy_from_user(&conf,(void *)arg,sizeof(conf))) return -EFAULT; return set_ipm_config(&conf); break; default: return -EINVAL; } return 0; }