⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ctc.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
                }                memset(privptr->channel[c].devstat, 0, sizeof(devstat_t));                if (ctc_no_auto == 0)                          ctc_adapter[m][i].devno[c] = channel_get_next(m);                else                          ctc_adapter[m][i].devno[c] = channel_get(m, ctc_adapter[m][i].devno[c]);                if ( ctc_adapter[m][i].devno[c] != -ENODEV){                         rc = request_irq(get_irq_by_devno(ctc_adapter[m][i].devno[c]),                              (void *)ctc_irq_handler, SA_INTERRUPT, dev->name,                               privptr->channel[c].devstat);                         if (rc) {                                  printk(KERN_WARNING "%s: requested device busy %02x\n", dev->name, rc);                                 return -EBUSY;                         }                } else {                                if (i == WRITE) {                                free_irq(get_irq_by_devno(ctc_adapter[m][i].devno[c]), privptr->channel[i].devstat);                                channel_free(m, ctc_adapter[m][i].devno[READ]);                                kfree(privptr->channel[READ].devstat);                        }                         kfree(privptr->channel[i].devstat);                        return -ENODEV;                }        }        privptr->channel[READ].devno = ctc_adapter[m][i].devno[READ];        privptr->channel[READ].irq = get_irq_by_devno(ctc_adapter[m][i].devno[READ]);        privptr->channel[WRITE].devno = ctc_adapter[m][i].devno[WRITE];        privptr->channel[WRITE].irq = get_irq_by_devno(ctc_adapter[m][i].devno[WRITE]);        privptr->protocol = ctc_adapter[m][i].protocol;        channel[m].left = channel[m].left - 2;        printk(KERN_INFO "%s: read dev: %04x irq: %04x - write dev: %04x irq: %04x \n",            dev->name, privptr->channel[READ].devno,   privptr->channel[READ].irq,            privptr->channel[WRITE].devno,  privptr->channel[WRITE].irq);         dev->mtu             = CTC_DEFAULT_MTU_SIZE;        dev->hard_start_xmit = ctc_tx;        dev->open            = ctc_open;        dev->stop            = ctc_release;        dev->get_stats       = ctc_stats;        dev->change_mtu      = ctc_change_mtu;        dev->hard_header_len = 0;        dev->addr_len        = 0;        dev->type            = ARPHRD_SLIP;        dev->tx_queue_len    = 100;        dev_init_buffers(dev);        dev->flags           = IFF_POINTOPOINT | IFF_NOARP;           return 0;} /* *   Interrupt processing  * */static void inline ccw_check_return_code (net_device *dev, int return_code){        if (return_code != 0) {                switch (return_code) {                        case -EBUSY:                                  printk(KERN_INFO "%s: Busy !\n", dev->name);                                break;                        case -ENODEV:                                printk(KERN_EMERG "%s: Invalid device called for IO\n", dev->name);                                break;                        case -EIO:                                printk(KERN_EMERG "%s: Status pending... \n", dev->name);                                break;                        default:                                printk(KERN_EMERG "%s: Unknown error in Do_IO %04x\n",                                     dev->name, return_code);                }        }} static void inline ccw_check_unit_check (net_device *dev, char sense){#ifdef DEBUG        printk(KERN_INFO "%s: Unit Check with sense code: %02x\n",            dev->name, sense);#endif        if (sense & 0x40) {#ifdef DEBUG                if (sense & 0x01)                         printk(KERN_DEBUG "%s: Interface disconnect or Selective reset occurred (remote side)\n", dev->name);                else                         printk(KERN_DEBUG "%s: System reset occured (remote side)\n", dev->name);#endif        } else if (sense & 0x20) {                if (sense & 0x04)                        printk(KERN_WARNING "%s: Data-streaming timeout)\n", dev->name);                else                         printk(KERN_WARNING "%s: Data-transfer parity error\n", dev->name);        } else if (sense & 0x10) {                if (sense & 0x20)                        printk(KERN_WARNING "%s: Hardware malfunction (remote side)\n", dev->name);                else                         printk(KERN_WARNING "%s: Read-data parity error (remote side)\n", dev->name);        }} static void ctc_irq_handler (int irq, void *initparm, struct pt_regs *regs){        int               rc = 0;        __u32             parm;        __u8              flags = 0x00;        struct  channel   *ctc = NULL;        struct  ctc_priv  *privptr = NULL;        net_device        *dev = NULL;                    ccw1_t            ccw_set_x_mode[2] = {{CCW_CMD_SET_EXTENDED, CCW_FLAG_SLI | CCW_FLAG_CC, 0, NULL},                                               {CCW_CMD_NOOP, CCW_FLAG_SLI, 0, NULL}};         devstat_t *devstat = ((devstat_t *)initparm);        /* Bypass all 'unsolited interrupts' */        if (devstat->intparm == 0) {#ifdef DEBUG                printk(KERN_DEBUG "ctc: unsolited interrupt for device: %04x received c-%02x d-%02x f-%02x\n",                    devstat->devno, devstat->cstat, devstat->dstat, devstat->flag);#endif                 /* FIXME - find the related intparm!!! No IO outstanding!!!! */                return;        }        ctc = (struct channel *) (devstat->intparm);        dev = (net_device *) ctc->dev;        privptr = dev->priv;#ifdef DEBUG        printk(KERN_DEBUG "%s: interrupt for device: %04x received c-%02x d-%02x f-%02x state-%02x\n",            dev->name, ctc->devno, devstat->cstat, devstat->dstat, devstat->flag, ctc->state);#endif         /* Check for good subchannel return code, otherwise error message */        if (devstat->cstat) {                printk(KERN_WARNING "%s: subchannel check for device: %04x - %02x\n",                     dev->name, ctc->devno, devstat->cstat);                return;        }        /* Check the reason-code of a unit check */        if (devstat->dstat & DEV_STAT_UNIT_CHECK)                ccw_check_unit_check(dev, devstat->ii.sense.data[0]);        /* State machine to bring the connection up / down and to restart */         ctc->last_dstat = devstat->dstat;        switch (ctc->state) {                   case CTC_STOP:           /* HALT_IO issued by ctc_release (halt sequence) */                        if (!devstat->flag & DEVSTAT_FINAL_STATUS)                                return;                        wake_up(&ctc->wait);   /* wake up ctc_release */                        return;                 case CTC_START_HALT_IO:  /* HALT_IO issued by ctc_open (start sequence) */                        if (!devstat->flag & DEVSTAT_FINAL_STATUS)                                return;                        ctc->state = CTC_START_SET_X_MODE;                        parm = (__u32) ctc;                        rc = do_IO (ctc->irq, &ccw_set_x_mode[0], parm, 0xff, flags);                        if (rc != 0)                                ccw_check_return_code(dev, rc);                        return;                         case CTC_START_SET_X_MODE:                        if (devstat->dstat & DEV_STAT_UNIT_CHECK) {                                if ((devstat->ii.sense.data[0] & 0x41) != 0x41 ||                                    (devstat->ii.sense.data[0] & 0x40) != 0x40) {                                        wake_up(&ctc->wait);  /* wake up ctc_open (READ or WRITE) */                                        return;                                 }                                }                        if (!devstat->flag & DEVSTAT_FINAL_STATUS)                                return;                        ctc->state =  CTC_START_SELECT;                 case CTC_START_SELECT:                        if (!ctc->flag & CTC_WRITE) {                                ctc->state = CTC_START_READ_TEST;                                ctc->ccw[1].cda  = (char *)virt_to_phys(ctc->free_anchor->block);                                parm = (__u32) ctc;                                rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags );                                if (rc != 0)                                         ccw_check_return_code(dev, rc);                                wake_up(&ctc->wait);  /* wake up ctc_open (READ) */                        } else {                                ctc->state = CTC_START_WRITE_TEST;                                /* ADD HERE THE RIGHT PACKET TO ISSUE A ROUND TRIP - PART 1 */                                ctc->ccw[1].count = 0;                                ctc->ccw[1].cda  = (char *)virt_to_phys(ctc->free_anchor->block);                                parm = (__u32) ctc;                                 rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags);                                if (rc != 0)                                        ccw_check_return_code(dev, rc);                        }                        return;                case CTC_START_READ_TEST:                        if (devstat->dstat & DEV_STAT_UNIT_CHECK) {                                if ((devstat->ii.sense.data[0] & 0x41) == 0x41 ||                                    (devstat->ii.sense.data[0] & 0x40) == 0x40 ||                                    devstat->ii.sense.data[0] == 0                ) {                                        init_timer(&ctc->timer);                                        ctc->timer.function = (void *)ctc_read_retry;                                         ctc->timer.data = (__u32)ctc;                                        ctc->timer.expires = jiffies + 10*HZ;                                        add_timer(&ctc->timer);#ifdef DEBUG                                         printk(KERN_DEBUG "%s: read connection restarted\n",dev->name); #endif                                }                                return;                        }                        if ((devstat->dstat &  ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) {                                if ((devstat->dstat & DEV_STAT_ATTENTION) &&                                     (devstat->dstat & DEV_STAT_BUSY)) {                                        printk(KERN_WARNING "%s: read channel is connected with the remote side read channel\n", dev->name);                                }                                 wake_up(&privptr->channel[WRITE].wait);  /* wake up ctc_open (WRITE) */                                return;                        }                        ctc->state = CTC_START_READ;                        set_bit(0, (void *)&ctc->IO_active);                        /* ADD HERE THE RIGHT PACKET TO ISSUE A ROUND TRIP - PART 2 */                        /* wake_up(&privptr->channel[WRITE].wait);*/  /* wake up ctc_open (WRITE) */                case CTC_START_READ:                         if (devstat->dstat & DEV_STAT_UNIT_CHECK) {                                if ((devstat->ii.sense.data[0] & 0x41) == 0x41 ||                                    (devstat->ii.sense.data[0] & 0x40) == 0x40 ||                                    devstat->ii.sense.data[0] == 0               ) {                                        privptr->stats.rx_errors++;					/* Need protection here cos we are in the read irq */					/*  handler the tbusy is for the write subchannel */					ctc_protect_busy(dev);				        ctc_setbit_busy(TB_RETRY,dev);					ctc_unprotect_busy(dev);				        init_timer(&ctc->timer);                                        ctc->timer.function = (void *)ctc_read_retry;                                         ctc->timer.data = (__u32)ctc;                                        ctc->timer.expires = jiffies + 30*HZ;                                        add_timer(&ctc->timer);                                         printk(KERN_INFO "%s: connection restarted!! problem on remote side\n",dev->name);                                }                                return;                        }                        if(!devstat->flag & DEVSTAT_FINAL_STATUS)                                return; 			ctc_protect_busy(dev);			ctc_clearbit_busy(TB_RETRY,dev);			ctc_unprotect_busy(dev);                        ctc_buffer_swap(&ctc->free_anchor, &ctc->proc_anchor);                        if (ctc->free_anchor != NULL) {                                  ctc->ccw[1].cda  = (char *)virt_to_phys(ctc->free_anchor->block);                                parm = (__u32) ctc;                                rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags );                                if (rc != 0)                                         ccw_check_return_code(dev, rc);                        } else {                                clear_bit(0, (void *)&ctc->IO_active);    #ifdef DEBUG                                printk(KERN_DEBUG "%s: No HOT READ started in IRQ\n",dev->name);#endif                        }                                                if (test_and_set_bit(CTC_BH_ACTIVE, (void *)&ctc->flag_a) == 0) {                                queue_task(&ctc->tq, &tq_immediate);                                mark_bh(IMMEDIATE_BH);                        }                        return;                case CTC_START_WRITE_TEST:                        if (devstat->dstat & DEV_STAT_UNIT_CHECK) {                                if ((devstat->ii.sense.data[0] & 0x41) == 0x41 ||                                    (devstat->ii.sense.data[0] & 0x40) == 0x40 ||                                    devstat->ii.sense.data[0] == 0                ) {                                        init_timer(&ctc->timer);                                        ctc->timer.function = (void *)ctc_write_retry;                                         ctc->timer.data = (__u32)ctc;                                        ctc->timer.expires = jiffies + 10*HZ;                                        add_timer(&ctc->timer);#ifdef DEBUG                                        printk(KERN_DEBUG "%s: write connection restarted\n",dev->name);#endif                                }                                return;                        }                        ctc->state = CTC_START_WRITE;                        wake_up(&ctc->wait);  /* wake up ctc_open (WRITE) */                        return;                 case CTC_START_WRITE:                        if (devstat->dstat & DEV_STAT_UNIT_CHECK) {                                privptr->stats.tx_errors += ctc->proc_anchor->packets;#ifdef DEBUG                                printk(KERN_DEBUG "%s: Unit Check on write channel\n",dev->name);#endif                        } else {                                 if (!devstat->flag & DEVSTAT_FINAL_STATUS)                                        return;                                 privptr->stats.tx_packets += ctc->proc_anchor->packets;                        }                         ctc->proc_anchor->block->length = 0;                        ctc_buffer_swap(&ctc->proc_anchor, &ctc->free_anchor);                        ctc_clearbit_busy(TB_NOBUFFER,dev);                              if (ctc->proc_anchor != NULL) {  #ifdef DEBUG                                printk(KERN_DEBUG "%s: IRQ early swap buffer\n",dev->name); #endif                                ctc->ccw[1].count = ctc->proc_anchor->block->length;                                ctc->ccw[1].cda  = (char *)virt_to_phys(ctc->proc_anchor->block);                                parm = (__u32) ctc;                                rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags );                                if (rc != 0)                                         ccw_check_return_code(dev, rc);                                dev->trans_start = jiffies;                                return;                        }                        if (ctc->free_anchor->block->length != 0) {                                if (ctc_test_and_setbit_busy(TB_TX,dev) == 0) {                                            /* set transmission to busy */                                        ctc_buffer_swap(&ctc->free_anchor, &ctc->proc_anchor);                                        ctc_clearbit_busy(TB_TX,dev);#ifdef DEBUG                                        printk(KERN_DEBUG "%s: last buffer move in IRQ\n",dev->name); #endif                                        ctc->ccw[1].count = ctc->proc_anchor->block->length;                                        ctc->ccw[1].cda  = (char *)virt_to_phys(ctc->proc_anchor->block);                                        parm = (__u32) ctc;                                        rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags );                                        if (rc != 0)                                                 ccw_check_return_code(dev, rc);                                        dev->trans_start = jiffies;                                        return;                                }                        }                         clear_bit(0, (void *)&ctc->IO_active);              /* set by ctc_tx or ctc_bh */                        return;                 default:                         printk(KERN_WARNING "%s: wrong selection code - irq\n",dev->name);                        return;          }} static void ctc_irq_bh (struct channel *ctc){        int                rc = 0;        __u16              data_len;        __u32              parm;        __u8               flags = 0x00;        __u32              saveflags;        net_device  *dev;        struct ctc_priv    *privptr;                     struct packet      *lp;        struct sk_buff     *skb;        dev = (net_device *) ctc->dev;         privptr = (struct ctc_priv *) dev->priv;    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -