📄 ctc.c
字号:
dev_info_t temp; for (m = 0; m < CHANNEL_MEDIA; m++) { for (c = 0; c < MAX_CHANNEL_DEVICES; c++){ channel[m].list[c].devno = -ENODEV; } } for (irq = 0; irq < NR_IRQS; irq++) { /* CTC/A */ if (channel[CTC].count < MAX_CHANNEL_DEVICES ) { if (get_dev_info(irq, &temp) == 0 && channel_check_for_type(&temp.sid_data) == channel_type_ctca) { channel[CTC].list[channel[CTC].count].devno = temp.devno; channel[CTC].count++; } } /* ESCON */ if (channel[ESCON].count < MAX_CHANNEL_DEVICES ) { if (get_dev_info(irq, &temp) == 0 && channel_check_for_type(&temp.sid_data) == channel_type_escon) { channel[ESCON].list[channel[ESCON].count].devno = temp.devno; channel[ESCON].count++; } } }} /* * free specific channel from the channel[].list */ static int channel_free(int media, int devno){ int i; for (i = 0; i < channel[media].count; i++) { if ((devno == channel[media].list[i].devno) && ((channel[media].list[i].flag & CHANNEL_IN_USE) != 0x00)) { channel[media].list[i].flag &= ~CHANNEL_IN_USE; return 0; } } printk(KERN_WARNING "channel: dev %04x is not a channel or in use\n", devno); return -ENODEV; }/* * get specific channel from the channel[].list */ static int channel_get(int media, int devno){ int i; for (i = 0; i < channel[media].count; i++) { if ((devno == channel[media].list[i].devno) && ((channel[media].list[i].flag & CHANNEL_IN_USE) == 0x00)) { channel[media].list[i].flag |= CHANNEL_IN_USE; return channel[media].list[i].devno; } } printk(KERN_WARNING "channel: dev %04x is not a channel or in use\n", devno); return -ENODEV; }/* * get the next free channel from the channel[].list */ static int channel_get_next(int media){ int i; for (i = 0; i < channel[media].count; i++) { if ((channel[media].list[i].flag & CHANNEL_IN_USE) == 0x00) {#ifdef DEBUG printk(KERN_DEBUG "channel: picked=%04x\n", channel[media].list[i].devno);#endif channel[media].list[i].flag |= CHANNEL_IN_USE; return channel[media].list[i].devno; } } return -ENODEV; } /* * picks the next free channel from the channel[].list */ static int channel_left(int media){ return channel[media].left; }/* * defines all devices which are channels */static channel_type_t channel_check_for_type (senseid_t *id) { channel_type_t type; switch (id->cu_type) { case 0x3088: switch (id->cu_model) { case 0x08: type = channel_type_ctca; /* 3088-08 ==> CTCA */ break; case 0x1F: type = channel_type_escon; /* 3088-1F ==> ESCON channel */ break; case 0x01: /* 3088-01 ==> P390 OSA emulation */ case 0x60: /* 3088-60 ==> OSA/2 adapter */ case 0x61: /* 3088-61 ==> CISCO 7206 CLAW protocol ESCON connected */ case 0x62: /* 3088-62 ==> OSA/D device */ type = channel_type_unsupported; break; default: type = channel_type_undefined; printk(KERN_INFO "channel: Unknown model found 3088-%02x\n",id->cu_model); } break; default: type = channel_type_none; } return type;}/* * sort the channel[].list */static void channel_sort(struct devicelist list[], int n){ int i; int sorted = 0; struct devicelist tmp; while (!sorted) { sorted = 1; for (i = 0; i < n-1; i++) { if (list[i].devno > list[i+1].devno) { tmp = list[i]; list[i] = list[i+1]; list[i+1] = tmp; sorted = 0; } } }} /* * General routines * */static int inline extract_channel_id(char *name){ if (name[0] == 'c') return (name[3]-'0'); else return (name[5]-'0');}static int inline extract_channel_media(char *name){ if (name[0] == 'c') return CTC; else return ESCON;}static void ctc_tab_init(void){ int m; int i; static int t; if (t == 0){ for (m = 0; m < CHANNEL_MEDIA; m++) { for (i = 0; i < MAX_ADAPTERS; i++) { ctc_adapter[m][i].devno[WRITE] = -ENODEV; ctc_adapter[m][i].devno[READ] = -ENODEV; } } t = 1; }} static int ctc_buffer_alloc(struct channel *ctc) { struct buffer *p; struct buffer *q; p = kmalloc(sizeof(p), GFP_KERNEL); if (p == NULL) return -ENOMEM; else { p->next = NULL; p->packets = 0; p->block = (struct block *) __get_free_pages(GFP_KERNEL+GFP_DMA, 4); if (p->block == NULL) { kfree(p); return -ENOMEM; } } if (ctc->free_anchor == NULL) ctc->free_anchor = p; else { q = ctc->free_anchor; while (q->next != NULL) q = q->next; q->next = p; } ctc->buffer_count++; return 0;}static int ctc_buffer_free(struct channel *ctc) { struct buffer *p; if (ctc->free_anchor == NULL) return -ENOMEM; p = ctc->free_anchor; ctc->free_anchor = p->next; free_pages((__u32)p->block, 4); kfree(p); return 0;}static int inline ctc_buffer_swap(struct buffer **from, struct buffer **to) { struct buffer *p = NULL; struct buffer *q = NULL; if (*from == NULL) return -ENOMEM; p = *from; *from = p->next; p->next = NULL; if (*to == NULL) *to = p; else { q = *to; while (q->next != NULL) q = q->next; q->next = p; } return 0;}/* * ctc_setup function * this function is called for each ctc= keyword passed into the kernel * * valid parameter are: ctc=n,0xnnnn,0xnnnn,ctcx * where n is the channel protocol always 0 * 0xnnnn is the cu number read * 0xnnnn is the cu number write * ctcx can be ctc0 to ctc7 or escon0 to escon7 */#if LINUX_VERSION_CODE>=0x020300static int __init ctc_setup(char *dev_name)#else__initfunc(void ctc_setup(char *dev_name,int *ints))#endif{ struct adapterlist tmp;#if LINUX_VERSION_CODE>=0x020300 #define CTC_MAX_PARMS 4 int ints[CTC_MAX_PARMS+1]; get_options(dev_name,CTC_MAX_PARMS,ints); #define ctc_setup_return return(1)#else #define ctc_setup_return return#endif ctc_tab_init(); ctc_no_auto = 1; if (!strcmp(dev_name,"noauto")) { printk(KERN_INFO "ctc: automatic channel selection deactivated\n"); ctc_setup_return; } tmp.devno[WRITE] = -ENODEV; tmp.devno[READ] = -ENODEV; switch (ints[0]) { case 3: /* write channel passed */ tmp.devno[WRITE] = ints[3]; case 2: /* read channel passed */ tmp.devno[READ] = ints[2]; if (tmp.devno[WRITE] == -ENODEV) tmp.devno[WRITE] = tmp.devno[READ] + 1; case 1: /* protocol type passed */ tmp.protocol = ints[1]; if (tmp.protocol == 0) { break; } else { printk(KERN_WARNING "%s: wrong Channel protocol type passed\n", dev_name); ctc_setup_return; } break; default: printk(KERN_WARNING "ctc: wrong number of parameter passed\n"); ctc_setup_return; } ctc_adapter[extract_channel_media(dev_name)][extract_channel_id(dev_name)] = tmp; #ifdef DEBUG printk(DEBUG "%s: protocol=%x read=%04x write=%04x\n", dev_name, tmp.protocol, tmp.devno[READ], tmp.devno[WRITE]);#endif ctc_setup_return; }#if LINUX_VERSION_CODE>=0x020300__setup("ctc=", ctc_setup);#endif/* * ctc_probe * this function is called for each channel network device, * which is defined in the /init/main.c */int ctc_probe(net_device *dev){ int rc; int c; int i; int m; struct ctc_priv *privptr; /* Only the first time the ctc_probe gets control */ if (channel_tab_initialized == 0) { channel_init(); } ctc_tab_init(); m = extract_channel_media(dev->name); i = extract_channel_id(dev->name); if (channel_left(m) <=1) return -ENODEV; if (ctc_no_auto == 1 && (ctc_adapter[m][i].devno[READ] == -ENODEV || ctc_adapter[m][i].devno[WRITE] == -ENODEV)) return -ENODEV; dev->priv = kmalloc(sizeof(struct ctc_priv), GFP_KERNEL); if (dev->priv == NULL) return -ENOMEM; memset(dev->priv, 0, sizeof(struct ctc_priv)); privptr = (struct ctc_priv *) (dev->priv); for (c = 0; c < 2; c++) { privptr->channel[c].devstat = kmalloc(sizeof(devstat_t), GFP_KERNEL); if (privptr->channel[c].devstat == NULL){ if (i == WRITE) kfree(privptr->channel[READ].devstat); return -ENOMEM;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -