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

📄 eicon_io.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: eicon_io.c,v 1.13 2000/05/07 08:51:04 armin Exp $ * * ISDN low-level module for Eicon active ISDN-Cards. * Code for communicating with hardware. * * Copyright 1999,2000  by Armin Schindler (mac@melware.de) * Copyright 1999,2000  Cytronics & Melware (info@melware.de) * * Thanks to	Eicon Technology GmbH & Co. oHG for  *		documents, informations and hardware.  * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  * */#include <linux/config.h>#include "eicon.h"#include "uxio.h"voideicon_io_rcv_dispatch(eicon_card *ccard) {	ulong flags;        struct sk_buff *skb, *skb2, *skb_new;        eicon_IND *ind, *ind2, *ind_new;        eicon_chan *chan;        if (!ccard) {	        eicon_log(ccard, 1, "eicon_err: NULL card in rcv_dispatch !\n");                return;        }	while((skb = skb_dequeue(&ccard->rcvq))) {        	ind = (eicon_IND *)skb->data;		spin_lock_irqsave(&eicon_lock, flags);        	if ((chan = ccard->IdTable[ind->IndId]) == NULL) {			spin_unlock_irqrestore(&eicon_lock, flags);			if (DebugVar & 1) {				switch(ind->Ind) {					case N_DISC_ACK: 						/* doesn't matter if this happens */ 						break;					default: 						eicon_log(ccard, 1, "idi: Indication for unknown channel Ind=%d Id=%x\n", ind->Ind, ind->IndId);						eicon_log(ccard, 1, "idi_hdl: Ch??: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n",							ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length);				}			}	                dev_kfree_skb(skb);	                continue;	        }		spin_unlock_irqrestore(&eicon_lock, flags);		if (chan->e.complete) { /* check for rec-buffer chaining */			if (ind->MLength == ind->RBuffer.length) {				chan->e.complete = 1;				idi_handle_ind(ccard, skb);				continue;			}			else {				chan->e.complete = 0;				ind->Ind = ind->MInd;				skb_queue_tail(&chan->e.R, skb);				continue;			}		}		else {			if (!(skb2 = skb_dequeue(&chan->e.R))) {				chan->e.complete = 1;                		eicon_log(ccard, 1, "eicon: buffer incomplete, but 0 in queue\n");	                	dev_kfree_skb(skb);				continue;				}	        	ind2 = (eicon_IND *)skb2->data;			skb_new = alloc_skb(((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length),					GFP_ATOMIC);			if (!skb_new) {                		eicon_log(ccard, 1, "eicon_io: skb_alloc failed in rcv_dispatch()\n");	                	dev_kfree_skb(skb);	                	dev_kfree_skb(skb2);				continue;				}			ind_new = (eicon_IND *)skb_put(skb_new,					((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length));			ind_new->Ind = ind2->Ind;			ind_new->IndId = ind2->IndId;			ind_new->IndCh = ind2->IndCh;			ind_new->MInd = ind2->MInd;			ind_new->MLength = ind2->MLength;			ind_new->RBuffer.length = ind2->RBuffer.length + ind->RBuffer.length;			memcpy(&ind_new->RBuffer.P, &ind2->RBuffer.P, ind2->RBuffer.length);			memcpy((&ind_new->RBuffer.P)+ind2->RBuffer.length, &ind->RBuffer.P, ind->RBuffer.length);                	dev_kfree_skb(skb);                	dev_kfree_skb(skb2);			if (ind->MLength == ind->RBuffer.length) {				chan->e.complete = 2;				idi_handle_ind(ccard, skb_new);				continue;			}			else {				chan->e.complete = 0;				skb_queue_tail(&chan->e.R, skb_new);				continue;			}		}	}}voideicon_io_ack_dispatch(eicon_card *ccard) {        struct sk_buff *skb;        if (!ccard) {		eicon_log(ccard, 1, "eicon_err: NULL card in ack_dispatch!\n");                return;        }	while((skb = skb_dequeue(&ccard->rackq))) {		idi_handle_ack(ccard, skb);	}}/* *  IO-Functions for ISA cards */u8 ram_inb(eicon_card *card, void *adr) {        u32 addr = (u32) adr;		return(readb(addr));}u16 ram_inw(eicon_card *card, void *adr) {        u32 addr = (u32) adr;	return(readw(addr));}void ram_outb(eicon_card *card, void *adr, u8 data) {        u32 addr = (u32) adr;	writeb(data, addr);}void ram_outw(eicon_card *card, void *adr , u16 data) {        u32 addr = (u32) adr;	writew(data, addr);}void ram_copyfromcard(eicon_card *card, void *adrto, void *adr, int len) {	memcpy_fromio(adrto, adr, len);}void ram_copytocard(eicon_card *card, void *adrto, void *adr, int len) {	memcpy_toio(adrto, adr, len);}#ifdef CONFIG_ISDN_DRV_EICON_PCI/* *  IDI-Callback function */voideicon_idi_callback(ENTITY *de){	eicon_card *ccard = (eicon_card *)de->R;	struct sk_buff *skb;	eicon_RC *ack;	eicon_IND *ind;	int len = 0;	if (de->complete == 255) {		/* Return Code */		skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC);		if (!skb) {			eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _idi_callback()\n");		} else {			ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));			ack->Rc = de->Rc;			if (de->Rc == ASSIGN_OK) {				ack->RcId = de->Id;				de->user[1] = de->Id;			} else {				ack->RcId = de->user[1];			}			ack->RcCh = de->RcCh;			ack->Reference = de->user[0];			skb_queue_tail(&ccard->rackq, skb);			eicon_schedule_ack(ccard);			eicon_log(ccard, 128, "idi_cbk: Ch%d: Rc=%x Id=%x RLen=%x compl=%x\n",				de->user[0], de->Rc, ack->RcId, de->RLength, de->complete);		}	} else {		/* Indication */		if (de->complete) {			len = de->RLength;		} else {			len = 270;			if (de->RLength <= 270)				eicon_log(ccard, 1, "eicon_cbk: ind not complete but <= 270\n");		}		skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC);		if (!skb) {			eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _idi_callback()\n");		} else {			ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));			ind->Ind = de->Ind;			ind->IndId = de->user[1];			ind->IndCh = de->IndCh;			ind->MInd  = de->Ind;			ind->RBuffer.length = len;			ind->MLength = de->RLength;			memcpy(&ind->RBuffer.P, &de->RBuffer->P, len);			skb_queue_tail(&ccard->rcvq, skb);			eicon_schedule_rx(ccard);			eicon_log(ccard, 128, "idi_cbk: Ch%d: Ind=%x Id=%x RLen=%x compl=%x\n",				de->user[0], de->Ind, ind->IndId, de->RLength, de->complete);		}	}	de->RNum = 0;	de->RNR = 0;	de->Rc = 0;	de->Ind = 0;}#endif /* CONFIG_ISDN_DRV_EICON_PCI *//* *  Transmit-Function */voideicon_io_transmit(eicon_card *ccard) {        eicon_isa_card *isa_card;        struct sk_buff *skb;        struct sk_buff *skb2;        unsigned long flags;	eicon_pr_ram  *prram = 0;	eicon_isa_com	*com = 0;	eicon_REQ *ReqOut = 0;	eicon_REQ *reqbuf = 0;	eicon_chan *chan;	eicon_chan_ptr *chan2;	int ReqCount;	int scom = 0;	int tmp = 0;	int tmpid = 0;	int quloop = 1;	int dlev = 0;	ENTITY *ep = 0;	isa_card = &ccard->hwif.isa;        if (!ccard) {               	eicon_log(ccard, 1, "eicon_transmit: NULL card!\n");                return;        }	switch(ccard->type) {#ifdef CONFIG_ISDN_DRV_EICON_ISA		case EICON_CTYPE_S:		case EICON_CTYPE_SX:		case EICON_CTYPE_SCOM:		case EICON_CTYPE_QUADRO:			scom = 1;			com = (eicon_isa_com *)isa_card->shmem;			break;		case EICON_CTYPE_S2M:			scom = 0;			prram = (eicon_pr_ram *)isa_card->shmem;			break;#endif#ifdef CONFIG_ISDN_DRV_EICON_PCI		case EICON_CTYPE_MAESTRAP:			scom = 2;			break;		case EICON_CTYPE_MAESTRAQ:			scom = 2;			break;		case EICON_CTYPE_MAESTRA:			scom = 2;			break;#endif		default:                	eicon_log(ccard, 1, "eicon_transmit: unsupported card-type!\n");			return;	}	ReqCount = 0;	if (!(skb2 = skb_dequeue(&ccard->sndq)))		quloop = 0; 	while(quloop) { 		spin_lock_irqsave(&eicon_lock, flags);		switch (scom) {		  case 1:			if ((ram_inb(ccard, &com->Req)) || (ccard->ReadyInt)) {				if (!ccard->ReadyInt) {					tmp = ram_inb(ccard, &com->ReadyInt) + 1;					ram_outb(ccard, &com->ReadyInt, tmp);					ccard->ReadyInt++;				}				spin_unlock_irqrestore(&eicon_lock, flags);                	        skb_queue_head(&ccard->sndq, skb2);       	                	eicon_log(ccard, 32, "eicon: transmit: Card not ready\n");	                        return;			}			break;		  case 0:	                if (!(ram_inb(ccard, &prram->ReqOutput) - ram_inb(ccard, &prram->ReqInput))) {				spin_unlock_irqrestore(&eicon_lock, flags);                	        skb_queue_head(&ccard->sndq, skb2);       	                	eicon_log(ccard, 32, "eicon: transmit: Card not ready\n");	                        return;        	        }			break;		}		spin_unlock_irqrestore(&eicon_lock, flags);		chan2 = (eicon_chan_ptr *)skb2->data;		chan = chan2->ptr;		if (!chan->e.busy) {		 if((skb = skb_dequeue(&chan->e.X))) { 		  reqbuf = (eicon_REQ *)skb->data;		  if ((reqbuf->Reference) && (chan->e.B2Id == 0) && (reqbuf->ReqId & 0x1f)) {			eicon_log(ccard, 16, "eicon: transmit: error Id=0 on %d (Net)\n", chan->No); 		  } else {			spin_lock_irqsave(&eicon_lock, flags);			switch (scom) {			  case 1:				ram_outw(ccard, &com->XBuffer.length, reqbuf->XBuffer.length);				ram_copytocard(ccard, &com->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);				ram_outb(ccard, &com->ReqCh, reqbuf->ReqCh);				break;				  case 0:				/* get address of next available request buffer */				ReqOut = (eicon_REQ *)&prram->B[ram_inw(ccard, &prram->NextReq)];				ram_outw(ccard, &ReqOut->XBuffer.length, reqbuf->XBuffer.length);				ram_copytocard(ccard, &ReqOut->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);				ram_outb(ccard, &ReqOut->ReqCh, reqbuf->ReqCh);				ram_outb(ccard, &ReqOut->Req, reqbuf->Req); 				break;			}			dlev = 160;			if (reqbuf->ReqId & 0x1f) { /* if this is no ASSIGN */				if (!reqbuf->Reference) { /* Signal Layer */					switch (scom) {					  case 1:						ram_outb(ccard, &com->ReqId, chan->e.D3Id); 						break;					  case 0:						ram_outb(ccard, &ReqOut->ReqId, chan->e.D3Id); 						break;					  case 2:						ep = &chan->de;						break;					}					tmpid = chan->e.D3Id;					chan->e.ReqCh = 0; 				}				else {			/* Net Layer */					switch(scom) {					  case 1:						ram_outb(ccard, &com->ReqId, chan->e.B2Id); 

⌨️ 快捷键说明

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