亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? short.c

?? linux設備驅動第二版例子程序
?? C
?? 第 1 頁 / 共 2 頁
字號:
};void short_interrupt(int irq, void *dev_id, struct pt_regs *regs){    struct timeval tv;    int written;    do_gettimeofday(&tv);    /* Write a 16 byte record. Assume PAGE_SIZE is a multiple of 16 */    written = sprintf((char *)short_head,"%08u.%06u\n",                          (int)(tv.tv_sec % 100000000), (int)(tv.tv_usec));    short_incr_bp(&short_head, written);    wake_up_interruptible(&short_queue); /* awake any reading process */}/* * The following two functions are equivalent to the previous one, * but split in top and bottom half. First, a few needed variables */#define NR_TIMEVAL 512 /* length of the array of time values */struct timeval tv_data[NR_TIMEVAL]; /* too lazy to allocate it */volatile struct timeval *tv_head=tv_data;volatile struct timeval *tv_tail=tv_data;static struct tq_struct short_task; /* 0 by now, filled by short_init code */int short_bh_count = 0;/* * Increment a circular buffer pointer in a way that nobody sees * an intermediate value. */static inline void short_incr_tv(volatile struct timeval **tvp){    if (*tvp == (tv_data + NR_TIMEVAL - 1))        *tvp = tv_data;  /* Wrap */    else        (*tvp)++;}void short_do_tasklet (unsigned long unused){    int savecount = short_bh_count, written;    short_bh_count = 0; /* we have already been removed from the queue */    /*     * The bottom half reads the tv array, filled by the top half,     * and prints it to the circular text buffer, which is then consumed     * by reading processes     */    /* First write the number of interrupts that occurred before this bh */    written = sprintf((char *)short_head,"bh after %6i\n",savecount);    short_incr_bp(&short_head, written);    /*     * Then, write the time values. Write exactly 16 bytes at a time,     * so it aligns with PAGE_SIZE     */    do {        written = sprintf((char *)short_head,"%08u.%06u\n",			(int)(tv_tail->tv_sec % 100000000),			(int)(tv_tail->tv_usec));	short_incr_bp(&short_head, written);	short_incr_tv(&tv_tail);    } while (tv_tail != tv_head);    wake_up_interruptible(&short_queue); /* awake any reading process */}void short_bh_interrupt(int irq, void *dev_id, struct pt_regs *regs){    /* cast to stop 'volatile' warning */    do_gettimeofday((struct timeval *) tv_head);    short_incr_tv(&tv_head);    /* Queue the bh. Don't care for multiple enqueueing */    queue_task(&short_task, &tq_immediate);    mark_bh(IMMEDIATE_BH);    short_bh_count++; /* record that an interrupt arrived */}#ifdef HAVE_TASKLETS/* * Tasklet top half */void short_tl_interrupt(int irq, void *dev_id, struct pt_regs *regs){    do_gettimeofday((struct timeval *) tv_head); /* cast to stop 'volatile' warning */    short_incr_tv(&tv_head);    tasklet_schedule(&short_tasklet);    short_bh_count++; /* record that an interrupt arrived */}#endif /* HAVE_TASKLETS */void short_sh_interrupt(int irq, void *dev_id, struct pt_regs *regs){    int value, written;    struct timeval tv;    /* If it wasn't short, return immediately */    value = inb(short_base);    if (!(value & 0x80)) return;            /* clear the interrupting bit */    outb(value & 0x7F, short_base);    /* the rest is unchanged */    do_gettimeofday(&tv);    written = sprintf((char *)short_head,"%08u.%06u\n",                          (int)(tv.tv_sec % 100000000), (int)(tv.tv_usec));    short_incr_bp(&short_head, written);    wake_up_interruptible(&short_queue); /* awake any reading process */}void short_kernelprobe(void){    int count = 0;    do {        unsigned long mask;        mask = probe_irq_on();        outb_p(0x10,short_base+2); /* enable reporting */        outb_p(0x00,short_base);   /* clear the bit */        outb_p(0xFF,short_base);   /* set the bit: interrupt! */        outb_p(0x00,short_base+2); /* disable reporting */        udelay(5);  /* give it some time */        short_irq = probe_irq_off(mask);        if (short_irq == 0) { /* none of them? */            printk(KERN_INFO "short: no irq reported by probe\n");            short_irq = -1;        }        /*         * if more than one line has been activated, the result is         * negative. We should service the interrupt (no need for lpt port)         * and loop over again. Loop at most five times, then give up         */    } while (short_irq < 0 && count++ < 5);    if (short_irq < 0)        printk("short: probe failed %i times, giving up\n", count);}void short_probing(int irq, void *dev_id, struct pt_regs *regs){    if (short_irq == 0) short_irq = irq;    /* found */    if (short_irq != irq) short_irq = -irq; /* ambiguous */}void short_selfprobe(void){    int trials[] = {3, 5, 7, 9, 0};    int tried[]  = {0, 0, 0, 0, 0};    int i, count = 0;     /*      * install the probing handler for all possible lines. Remember      * the result (0 for success, or -EBUSY) in order to only free      * what has been acquired      */    for (i=0; trials[i]; i++)        tried[i] = request_irq(trials[i], short_probing,                               SA_INTERRUPT, "short probe", NULL);    do {        short_irq = 0; /* none got, yet */        outb_p(0x10,short_base+2); /* enable */        outb_p(0x00,short_base);        outb_p(0xFF,short_base); /* toggle the bit */        outb_p(0x00,short_base+2); /* disable */        udelay(5);  /* give it some time */        /* the value has been set by the handler */        if (short_irq == 0) { /* none of them? */            printk(KERN_INFO "short: no irq reported by probe\n");        }        /*         * If more than one line has been activated, the result is         * negative. We should service the interrupt (but the lpt port         * doesn't need it) and loop over again. Do it at most 5 times         */    } while (short_irq <=0 && count++ < 5);    /* end of loop, uninstall the handler */    for (i=0; trials[i]; i++)        if (tried[i] == 0)            free_irq(trials[i], NULL);    if (short_irq < 0)        printk("short: probe failed %i times, giving up\n", count);}/* Two wrappers, to use non-page-aligned ioremap() on 2.0 *//* Remap a not (necessarily) aligned port region */void *short_remap(unsigned long phys_addr){    /* The code comes mainly from arch/any/mm/ioremap.c */    unsigned long offset, last_addr, size;    last_addr = phys_addr + SHORT_NR_PORTS - 1;    offset = phys_addr & ~PAGE_MASK;        /* Adjust the begin and end to remap a full page */    phys_addr &= PAGE_MASK;    size = PAGE_ALIGN(last_addr) - phys_addr;    return ioremap(phys_addr, size) + offset;}/* Unmap a region obtained with short_remap */void short_unmap(void *virt_add){    iounmap((void *)((unsigned long)virt_add & PAGE_MASK));}/* Finally, init and cleanup */int short_init(void){    int result;    /*     * first, sort out the base/short_base ambiguity: we'd better     * use short_base in the code, for clarity, but allow setting     * just "base" at load time. Same for "irq".     */    short_base = base;    short_irq = irq;    /* Set up owner pointers.*/    SET_MODULE_OWNER(&short_fops);    SET_MODULE_OWNER(&short_i_fops);    /* Get our needed resources. */    if (!use_mem) {	result = check_region(short_base, SHORT_NR_PORTS);	if (result) {	    printk(KERN_INFO "short: can't get I/O port address 0x%lx\n",		   short_base);	    return result;	}	request_region(short_base, SHORT_NR_PORTS, "short");    } else {	result = check_mem_region(short_base, SHORT_NR_PORTS);	if (result) {	    printk(KERN_INFO "short: can't get I/O mem address 0x%lx\n",		   short_base);	    return result;	}	request_mem_region(short_base, SHORT_NR_PORTS, "short");	/* also, ioremap it */	short_phys = short_base;	short_base = (unsigned long)short_remap(short_base);	/* Hmm... we should check the return value */    }    result = register_chrdev(major, "short", &short_fops);    if (result < 0) {        printk(KERN_INFO "short: can't get major number\n");        release_region(short_base,SHORT_NR_PORTS);        return result;    }    if (major == 0) major = result; /* dynamic */    short_buffer = __get_free_pages(GFP_KERNEL,0); /* never fails */    short_head = short_tail = short_buffer;    /*     * Fill the short_task structure, used for the bottom half handler.     * The cast is there to prevent warnings about the type of the     * (unused) argument.     */    short_task.routine = (void (*)(void *)) short_do_tasklet;    short_task.data = NULL; /* unused */    /*     * Now we deal with the interrupt: either kernel-based     * autodetection, DIY detection or default number     */    if (short_irq < 0 && probe == 1)        short_kernelprobe();    if (short_irq < 0 && probe == 2)        short_selfprobe();    if (short_irq < 0) /* not yet specified: force the default on */        switch(short_base) {          case 0x378: short_irq = 7; break;          case 0x278: short_irq = 2; break;          case 0x3bc: short_irq = 5; break;        }    /*     * If shared has been specified, installed the shared handler     * instead of the normal one. Do it first, before a -EBUSY will     * force short_irq to -1.     */    if (short_irq >= 0 && share > 0) {        result = request_irq(short_irq, short_sh_interrupt,                             SA_SHIRQ | SA_INTERRUPT,"short",                             short_sh_interrupt);        if (result) {            printk(KERN_INFO "short: can't get assigned irq %i\n", short_irq);            short_irq = -1;        }        else { /* actually enable it -- assume this *is* a parallel port */            outb(0x10,short_base+2);        }        return 0; /* the rest of the function only installs handlers */    }    if (short_irq >= 0) {        result = request_irq(short_irq, short_interrupt,                             SA_INTERRUPT, "short", NULL);        if (result) {            printk(KERN_INFO "short: can't get assigned irq %i\n",                   short_irq);            short_irq = -1;        }        else { /* actually enable it -- assume this *is* a parallel port */            outb(0x10,short_base+2);        }    }    /*     * Ok, now change the interrupt handler if using top/bottom halves     * has been requested     */    if (short_irq >= 0 && (bh + tasklet) > 0) {        free_irq(short_irq,NULL);        result = request_irq(short_irq,#ifdef HAVE_TASKLETS                        tasklet ? short_tl_interrupt :#endif                        short_bh_interrupt,                        SA_INTERRUPT,"short-bh", NULL);        if (result) {            printk(KERN_INFO "short-bh: can't get assigned irq %i\n",                   short_irq);            short_irq = -1;        }    }    return 0;}void short_cleanup(void){    if (short_irq >= 0) {        outb(0x0, short_base + 2);   /* disable the interrupt */        if (!share) free_irq(short_irq, NULL);        else free_irq(short_irq, short_sh_interrupt);    }            unregister_chrdev(major, "short");    if (use_mem) {	short_unmap((void *)short_base);	release_mem_region(short_base, SHORT_NR_PORTS);    } else {	release_region(short_base,SHORT_NR_PORTS);    }    if (short_buffer) free_page(short_buffer);}module_init(short_init);module_exit(short_cleanup);

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
欧美国产日韩亚洲一区| 久久国内精品自在自线400部| 国产**成人网毛片九色 | 国产河南妇女毛片精品久久久| 一本一本大道香蕉久在线精品| 日韩一区二区三区四区五区六区| 中文字幕人成不卡一区| 国产一区二区三区电影在线观看| 欧美专区在线观看一区| 国产精品电影一区二区| 韩国欧美国产1区| 欧美高清激情brazzers| 1000精品久久久久久久久| 国产精品自拍在线| 欧美成人艳星乳罩| 免费精品视频在线| 欧美日韩精品一区二区三区| 亚洲美女区一区| 99久久亚洲一区二区三区青草| 欧美精品一区二区高清在线观看| 免费在线看成人av| 欧美一级视频精品观看| 日韩成人精品视频| 91精品国产手机| 视频一区二区三区入口| 欧美日韩一级片网站| 亚洲午夜羞羞片| 欧美日韩电影在线播放| 丝袜亚洲另类欧美综合| 777xxx欧美| 另类欧美日韩国产在线| 欧美成人性福生活免费看| 久久电影网站中文字幕| 26uuu亚洲综合色欧美| 黄色精品一二区| 亚洲国产高清在线观看视频| 波多野结衣在线一区| 国产精品青草综合久久久久99| 成人激情文学综合网| 亚洲色图欧洲色图婷婷| 欧美在线视频日韩| 天堂一区二区在线| 精品国内二区三区| 国产精品123| 亚洲人成网站影音先锋播放| 欧美色精品在线视频| 日韩高清电影一区| 久久精品人人做| gogo大胆日本视频一区| 亚洲国产精品自拍| 欧美电影免费观看高清完整版| 国产一区二区三区四区五区入口| 国产精品伦一区二区三级视频| 91蜜桃在线免费视频| 国产麻豆成人精品| 中文字幕一区不卡| 欧美日韩国产免费一区二区| 精品一区二区三区在线视频| 国产精品人成在线观看免费 | voyeur盗摄精品| 午夜欧美在线一二页| 精品国产3级a| 色综合天天综合| 人人超碰91尤物精品国产| 国产欧美日韩在线| 欧美日韩一级黄| 成人性生交大合| 爽好久久久欧美精品| 欧美国产日韩在线观看| 在线成人av网站| 波多野结衣亚洲一区| 青娱乐精品视频| 亚洲欧美日韩精品久久久久| 精品久久久久久久久久久久包黑料 | 欧美三区在线观看| 国产激情视频一区二区在线观看| 亚洲最快最全在线视频| 久久亚洲免费视频| 欧美日韩高清影院| 99精品视频在线观看| 久久99最新地址| 亚洲一区二区三区四区五区黄| 国产日产欧美一区二区三区 | 日韩电影一二三区| 国产精品二区一区二区aⅴ污介绍| 日韩一区二区电影在线| 欧洲精品视频在线观看| 成人一区二区三区中文字幕| 久久狠狠亚洲综合| 午夜不卡在线视频| 一区二区三区色| 国产三级精品三级| 精品国产区一区| 欧美一区二区三区四区视频 | 国产视频一区在线观看| 日韩一区二区三区四区| 欧美丰满高潮xxxx喷水动漫| 欧美在线短视频| 91国偷自产一区二区开放时间 | 国产成人高清视频| 韩国三级在线一区| 美女视频免费一区| 亚洲18色成人| 亚洲国产欧美在线人成| 一区二区三区欧美久久| 亚洲色图欧洲色图婷婷| 中文字幕亚洲区| 亚洲免费在线播放| 亚洲视频你懂的| 亚洲男人的天堂在线观看| 中文字幕欧美日韩一区| 国产精品伦理在线| 日韩一区中文字幕| 一区在线观看视频| 亚洲精品视频在线| 亚洲一区中文在线| 偷拍日韩校园综合在线| 日韩av一区二| 久久国产免费看| 国产精品一区免费视频| 成人在线综合网站| 色老汉av一区二区三区| 欧美日韩一级片在线观看| 欧美喷水一区二区| 精品久久久久香蕉网| 欧美极品美女视频| 亚洲男人电影天堂| 天天免费综合色| 激情成人综合网| av电影在线不卡| 欧美日韩中文另类| 日韩视频免费直播| 国产欧美日韩精品一区| 亚洲码国产岛国毛片在线| 午夜精品一区二区三区电影天堂| 日本美女视频一区二区| 国产一区欧美一区| 91精品91久久久中77777| 欧美日韩国产123区| 久久久99精品久久| 亚洲免费三区一区二区| 日韩av电影天堂| 国产丶欧美丶日本不卡视频| 色成年激情久久综合| 日韩三级视频中文字幕| 国产精品天美传媒| 天天综合天天做天天综合| 国产呦萝稀缺另类资源| 欧洲av一区二区嗯嗯嗯啊| 欧美变态tickle挠乳网站| 亚洲日本在线视频观看| 精品一区二区综合| 一本色道**综合亚洲精品蜜桃冫| 欧美一区二区在线免费观看| 久久精品亚洲精品国产欧美 | 日韩免费观看高清完整版在线观看| 精品国产乱码久久久久久夜甘婷婷 | 欧美亚洲免费在线一区| 久久婷婷久久一区二区三区| 国产精品88888| 欧美日韩成人一区二区| 国产精品久久久久9999吃药| 日本三级韩国三级欧美三级| www.亚洲精品| 久久品道一品道久久精品| 亚洲国产精品久久人人爱蜜臀| 高清不卡在线观看av| 日韩欧美一级二级三级| 亚洲综合视频网| caoporm超碰国产精品| 日韩免费电影网站| 午夜伦理一区二区| 色94色欧美sute亚洲线路一久| 国产日韩欧美精品一区| 免费人成黄页网站在线一区二区| 色噜噜久久综合| 国产女人18水真多18精品一级做| 经典三级在线一区| 欧美一区二区不卡视频| 亚洲电影中文字幕在线观看| 不卡av免费在线观看| 国产清纯白嫩初高生在线观看91 | 人人狠狠综合久久亚洲| 在线亚洲高清视频| 伊人开心综合网| 日本久久电影网| 国产精品乱码一区二三区小蝌蚪| 国模无码大尺度一区二区三区| 欧美妇女性影城| 天堂va蜜桃一区二区三区| 欧美日韩亚洲综合一区二区三区| 夜夜夜精品看看| 欧美无乱码久久久免费午夜一区| 亚洲视频免费在线| 91在线观看免费视频| 成人欧美一区二区三区在线播放| 国产91精品一区二区| 国产精品色哟哟| 91在线视频播放地址| 亚洲三级视频在线观看|