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

📄 module.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
			chan->l3prot = (c->arg >> 8);			return 0;        }	        return -EINVAL;}static intact2000_sendbuf(act2000_card *card, int channel, int ack, struct sk_buff *skb){        struct sk_buff *xmit_skb;        int len;        act2000_chan *chan;	actcapi_msg *msg;        if (!(chan = find_channel(card, channel)))		return -1;        if (chan->fsm_state != ACT2000_STATE_ACTIVE)                return -1;        len = skb->len;        if ((chan->queued + len) >= ACT2000_MAX_QUEUED)                return 0;	if (!len)		return 0;	if (skb_headroom(skb) < 19) {		printk(KERN_WARNING "act2000_sendbuf: Headroom only %d\n",		       skb_headroom(skb));		xmit_skb = alloc_skb(len + 19, GFP_ATOMIC);		if (!xmit_skb) {			printk(KERN_WARNING "act2000_sendbuf: Out of memory\n");			return 0;		}		skb_reserve(xmit_skb, 19);		memcpy(skb_put(xmit_skb, len), skb->data, len);	} else {		xmit_skb = skb_clone(skb, GFP_ATOMIC);		if (!xmit_skb) {			printk(KERN_WARNING "act2000_sendbuf: Out of memory\n");			return 0;		}	}	dev_kfree_skb(skb);	msg = (actcapi_msg *)skb_push(xmit_skb, 19);	msg->hdr.len = 19 + len;	msg->hdr.applicationID = 1;	msg->hdr.cmd.cmd = 0x86;	msg->hdr.cmd.subcmd = 0x00;	msg->hdr.msgnum = actcapi_nextsmsg(card);	msg->msg.data_b3_req.datalen = len;	msg->msg.data_b3_req.blocknr = (msg->hdr.msgnum & 0xff);	msg->msg.data_b3_req.fakencci = MAKE_NCCI(chan->plci, 0, chan->ncci);	msg->msg.data_b3_req.flags = ack; /* Will be set to 0 on actual sending */	actcapi_debug_msg(xmit_skb, 1);        chan->queued += len;	skb_queue_tail(&card->sndq, xmit_skb);	act2000_schedule_tx(card);        return len;}/* Read the Status-replies from the Interface */static intact2000_readstatus(u_char __user * buf, int len, act2000_card * card){        int count;        u_char __user *p;        for (p = buf, count = 0; count < len; p++, count++) {                if (card->status_buf_read == card->status_buf_write)                        return count;		put_user(*card->status_buf_read++, p);                if (card->status_buf_read > card->status_buf_end)                        card->status_buf_read = card->status_buf;        }        return count;}/* * Find card with given driverId */static inline act2000_card *act2000_findcard(int driverid){        act2000_card *p = cards;        while (p) {                if (p->myid == driverid)                        return p;                p = p->next;        }        return (act2000_card *) 0;}/* * Wrapper functions for interface to linklevel */static intif_command(isdn_ctrl * c){        act2000_card *card = act2000_findcard(c->driver);        if (card)                return (act2000_command(card, c));        printk(KERN_ERR             "act2000: if_command %d called with invalid driverId %d!\n",               c->command, c->driver);        return -ENODEV;}static intif_writecmd(const u_char __user *buf, int len, int id, int channel){        act2000_card *card = act2000_findcard(id);        if (card) {                if (!card->flags & ACT2000_FLAGS_RUNNING)                        return -ENODEV;                return (len);        }        printk(KERN_ERR               "act2000: if_writecmd called with invalid driverId!\n");        return -ENODEV;}static intif_readstatus(u_char __user * buf, int len, int id, int channel){        act2000_card *card = act2000_findcard(id);	        if (card) {                if (!card->flags & ACT2000_FLAGS_RUNNING)                        return -ENODEV;                return (act2000_readstatus(buf, len, card));        }        printk(KERN_ERR               "act2000: if_readstatus called with invalid driverId!\n");        return -ENODEV;}static intif_sendbuf(int id, int channel, int ack, struct sk_buff *skb){        act2000_card *card = act2000_findcard(id);	        if (card) {                if (!card->flags & ACT2000_FLAGS_RUNNING)                        return -ENODEV;		return (act2000_sendbuf(card, channel, ack, skb));        }        printk(KERN_ERR               "act2000: if_sendbuf called with invalid driverId!\n");        return -ENODEV;}/* * Allocate a new card-struct, initialize it * link it into cards-list. */static voidact2000_alloccard(int bus, int port, int irq, char *id){	int i;        act2000_card *card;        if (!(card = (act2000_card *) kmalloc(sizeof(act2000_card), GFP_KERNEL))) {                printk(KERN_WARNING		       "act2000: (%s) Could not allocate card-struct.\n", id);                return;        }        memset((char *) card, 0, sizeof(act2000_card));        spin_lock_init(&card->lock);        spin_lock_init(&card->mnlock);	skb_queue_head_init(&card->sndq);	skb_queue_head_init(&card->rcvq);	skb_queue_head_init(&card->ackq);	INIT_WORK(&card->snd_tq, (void *) (void *) act2000_transmit, card);	INIT_WORK(&card->rcv_tq, (void *) (void *) actcapi_dispatch, card);	INIT_WORK(&card->poll_tq, (void *) (void *) act2000_receive, card);	init_timer(&card->ptimer);	card->interface.owner = THIS_MODULE;        card->interface.channels = ACT2000_BCH;        card->interface.maxbufsize = 4000;        card->interface.command = if_command;        card->interface.writebuf_skb = if_sendbuf;        card->interface.writecmd = if_writecmd;        card->interface.readstat = if_readstatus;        card->interface.features =		ISDN_FEATURE_L2_X75I |		ISDN_FEATURE_L2_HDLC |		ISDN_FEATURE_L3_TRANS |		ISDN_FEATURE_P_UNKNOWN;        card->interface.hl_hdrlen = 20;        card->ptype = ISDN_PTYPE_EURO;        strlcpy(card->interface.id, id, sizeof(card->interface.id));        for (i=0; i<ACT2000_BCH; i++) {                card->bch[i].plci = 0x8000;                card->bch[i].ncci = 0x8000;                card->bch[i].l2prot = ISDN_PROTO_L2_X75I;                card->bch[i].l3prot = ISDN_PROTO_L3_TRANS;        }        card->myid = -1;        card->bus = bus;        card->port = port;        card->irq = irq;        card->next = cards;        cards = card;}/* * register card at linklevel */static intact2000_registercard(act2000_card * card){        switch (card->bus) {		case ACT2000_BUS_ISA:			break;		case ACT2000_BUS_MCA:		case ACT2000_BUS_PCMCIA:		default:			printk(KERN_WARNING			       "act2000: Illegal BUS type %d\n",			       card->bus);			return -1;        }        if (!register_isdn(&card->interface)) {                printk(KERN_WARNING                       "act2000: Unable to register %s\n",                       card->interface.id);                return -1;        }        card->myid = card->interface.channels;        sprintf(card->regname, "act2000-isdn (%s)", card->interface.id);        return 0;}static voidunregister_card(act2000_card * card){        isdn_ctrl cmd;        cmd.command = ISDN_STAT_UNLOAD;        cmd.driver = card->myid;        card->interface.statcallb(&cmd);        switch (card->bus) {		case ACT2000_BUS_ISA:			act2000_isa_release(card);			break;		case ACT2000_BUS_MCA:		case ACT2000_BUS_PCMCIA:		default:			printk(KERN_WARNING			       "act2000: Invalid BUS type %d\n",			       card->bus);			break;        }}static intact2000_addcard(int bus, int port, int irq, char *id){	act2000_card *p;	act2000_card *q = NULL;	int initialized;	int added = 0;	int failed = 0;	int i;	if (!bus)		bus = ACT2000_BUS_ISA;	if (port != -1) {		/* Port defined, do fixed setup */		act2000_alloccard(bus, port, irq, id);	} else {		/* No port defined, perform autoprobing.		 * This may result in more than one card detected.		 */		switch (bus) {			case ACT2000_BUS_ISA:				for (i = 0; i < ISA_NRPORTS; i++)					if (act2000_isa_detect(act2000_isa_ports[i])) {						printk(KERN_INFO						       "act2000: Detected ISA card at port 0x%x\n",						       act2000_isa_ports[i]);						act2000_alloccard(bus, act2000_isa_ports[i], irq, id);					}				break;			case ACT2000_BUS_MCA:			case ACT2000_BUS_PCMCIA:			default:				printk(KERN_WARNING				       "act2000: addcard: Invalid BUS type %d\n",				       bus);		}	}	if (!cards)		return 1;        p = cards;        while (p) {		initialized = 0;		if (!p->interface.statcallb) {			/* Not yet registered.			 * Try to register and activate it.			 */			added++;			switch (p->bus) {				case ACT2000_BUS_ISA:					if (act2000_isa_detect(p->port)) {						if (act2000_registercard(p))							break;						if (act2000_isa_config_port(p, p->port)) {							printk(KERN_WARNING							       "act2000: Could not request port 0x%04x\n",							       p->port);							unregister_card(p);							p->interface.statcallb = NULL;							break;						}						if (act2000_isa_config_irq(p, p->irq)) {							printk(KERN_INFO							       "act2000: No IRQ available, fallback to polling\n");							/* Fall back to polled operation */							p->irq = 0;						}						printk(KERN_INFO						       "act2000: ISA"						       "-type card at port "						       "0x%04x ",						       p->port);						if (p->irq)							printk("irq %d\n", p->irq);						else							printk("polled\n");						initialized = 1;					}					break;				case ACT2000_BUS_MCA:				case ACT2000_BUS_PCMCIA:				default:					printk(KERN_WARNING					       "act2000: addcard: Invalid BUS type %d\n",					       p->bus);			}		} else			/* Card already initialized */			initialized = 1;                if (initialized) {			/* Init OK, next card ... */                        q = p;                        p = p->next;                } else {                        /* Init failed, remove card from list, free memory */                        printk(KERN_WARNING                               "act2000: Initialization of %s failed\n",                               p->interface.id);                        if (q) {                                q->next = p->next;                                kfree(p);                                p = q->next;                        } else {                                cards = p->next;                                kfree(p);                                p = cards;                        }			failed++;                }	}        return (added - failed);}#define DRIVERNAME "IBM Active 2000 ISDN driver"static int __init act2000_init(void){        printk(KERN_INFO "%s\n", DRIVERNAME);        if (!cards)		act2000_addcard(act_bus, act_port, act_irq, act_id);        if (!cards)                printk(KERN_INFO "act2000: No cards defined yet\n");        return 0;}static void __exit act2000_exit(void){        act2000_card *card = cards;        act2000_card *last;        while (card) {                unregister_card(card);		del_timer(&card->ptimer);                card = card->next;        }        card = cards;        while (card) {                last = card;                card = card->next;		act2000_clear_msn(last);                kfree(last);        }        printk(KERN_INFO "%s unloaded\n", DRIVERNAME);}module_init(act2000_init);module_exit(act2000_exit);

⌨️ 快捷键说明

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