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

📄 c7000.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*	Dequeue a buffer from the start of the bh routine chain.*/struct c7000_buffer *c7000_dequeue_bh_buffer(struct c7000_unit *cup){	struct	c7000_buffer	*buf = cup->bh_head;	if (buf == NULL)		return(NULL);	cup->bh_head = buf->next;	if (cup->bh_head == NULL)		cup->bh_tail = NULL;	buf->next = NULL;	return(buf);}/*	Build up a list of buffers to read.  Each buffer is described	by one c7000_buffer structure.  The c7000_buffer structure	contains a channel segment that will read that one buffer.	The channel program segments are chained together via TIC	CCWS.*/static intc7000_bld_read_chain(struct c7000_unit *cup){	struct	c7000_buffer	*buf, *pbuf = NULL;	struct	c7000_rd_header	*head;	int			num = 0;	while (cup->free != NULL) {		/*			Obtain a buffer for a read channel segment.		*/		if ((buf = c7000_get_buffer(cup)) == NULL) {			CPrintk(0, "c7000: c7000_bld_read_chain: can not obtain a read buffer for unit 0x%x\n", cup->devno);			return(-ENOMEM);		}		num++;		buf->len = 0;		/*			Clear out the read header flag.		*/		head = (struct c7000_rd_header *)(buf->data + C7000_DATAL);		head->flag = 0x00;		c7000_queue_buffer(cup, buf);		/*			Build the read channel program segment.		*/		c7000_bld_read_chpgm(cup, buf);		/*			Chain the prior (if any) channel program segment to			this one.		*/		if (pbuf != NULL)			pbuf->ccws[3].cda = pbuf->ccws[5].cda = (__u32)virt_to_phys(&buf->ccws[0]);		pbuf = buf;	}	CPrintk(1, "c7000: c7000_bld_read_chain: chained %d buffers for unit 0x%x\n", num, cup->devno);	return(0);}/*	Build up a list of buffers to write.  Each buffer is described	by one c7000_buffer structure.  The c7000_buffer structure	contains a channel segment that will write that one buffer.	The channel program segments are chained together via TIC	CCWS.*/static voidc7000_bld_wrt_chain(struct c7000_unit *cup){	struct	c7000_buffer	*buf = cup->proc_head, *pbuf = NULL;	int			num = 0;	while (buf != NULL) {		c7000_bld_wrt_chpgm(cup, buf);		/*			Chain the channel program segments together.		*/		if (pbuf != NULL)			pbuf->ccws[2].cda = (__u32)virt_to_phys(&buf->ccws[0]);		pbuf = buf;		buf = buf->next;		num++;	}	CPrintk(1, "c7000: c7000_bld_wrt_chain: chained %d buffers for unit 0x%x\n", num, cup->devno);	return;}/*	Interrupt handler bottom half (bh) routine.	Process all of the buffers on the c7000_unit bh chain.	The bh chain is populated by the interrupt routine when	a READ channel program completes on a buffer.*/static voidc7000_irq_bh(struct c7000_unit *cup){	struct	c7000_buffer		*buf, *pbuf;	struct	c7000_rd_header		*head;		struct	sk_buff			*skb;	struct	c7000_controller	*ccp;	struct	net_device		*dev;	int				rc;	__u16				data_length;	unsigned long			parm;	__u8				flags = 0x00;	unsigned long			saveflags;	ccp = cup->cntlp;	dev = ccp->dev;	s390irq_spin_lock_irqsave(cup->irq, saveflags);	/*		Process all buffers sent to bh by the interrupt routine.	*/	while (cup->bh_head != NULL) {		buf = c7000_dequeue_bh_buffer(cup);		/*			Deference the data as a c7000 header.		*/		head = (struct c7000_rd_header *)(buf->data + C7000_DATAL);		/*			If it is a control message, release the buffer and 			continue the loop.		*/		if (C7000_LINKID(head->cmd) == 0) {			CPrintk(0, "c7000: c7000_irq_bh: unexpected control command %d on unit 0x%x\n", head->cmd, cup->devno);			c7000_release_buffer(cup, buf);			continue;		}					/*			Allocate a socket buffer.		*/		data_length = head->len;		skb = dev_alloc_skb(data_length);		/*			Copy the data to the skb.			Send it to the upper layers.		*/		if (skb != NULL) {			memcpy(skb_put(skb, data_length), buf->data, data_length);			skb->dev = dev;			skb->protocol = htons(ETH_P_IP);			skb->pkt_type = PACKET_HOST;			skb->mac.raw = skb->data;			skb->ip_summed = CHECKSUM_UNNECESSARY;			netif_rx(skb);			ccp->stats.rx_packets++;			ccp->stats.rx_bytes += skb->len;		} else {			CPrintk(0, "c7000: c7000_irq_bh: can not allocate a skb for unit 0x%x\n", cup->devno);			ccp->stats.rx_dropped++;		}		/*			Rechain the buffer on the processing list.		*/		head->flag = 0x00;		buf->len = 0;		pbuf = cup->proc_tail;		c7000_queue_buffer(cup, buf);		/*			Rechain the buffer on the running channel program.		*/		buf->ccws[3].cda = buf->ccws[5].cda = (__u32)virt_to_phys(&buf->ccws[6]);		if (pbuf != NULL)			pbuf->ccws[3].cda = pbuf->ccws[5].cda = (__u32)virt_to_phys(&buf->ccws[0]);	}	/*		Restart the READ channel program if IO_active is 0.	*/	if (test_and_set_bit(0, (void *)&cup->IO_active) == 0) {		if ((rc = c7000_bld_read_chain(cup)) != 0) {			CPrintk(0, "c7000: c7000_irq_bh: can not build read chain for unit 0x%x, return code %d\n", cup->devno, rc);			c7000_error(cup->cntlp);			clear_bit(C7000_BH_ACTIVE, (void *)&cup->flag_a);			s390irq_spin_unlock_irqrestore(cup->irq, saveflags);			return;		}		parm = (unsigned long)cup;		cup->state = C7000_READ;		if ((rc = do_IO(cup->irq, &cup->proc_head->ccws[0], parm, 0xff, flags)) != 0) {			CPrintk(0, "c7000: c7000_irq_bh: can not start READ IO to unit 0x%x, return code %d\n", cup->devno, rc);			c7000_error(cup->cntlp);			clear_bit(C7000_BH_ACTIVE, (void *)&cup->flag_a);			s390irq_spin_unlock_irqrestore(cup->irq, saveflags);			return;		}		CPrintk(1, "c7000: c7000_irq_bh: started READ IO to unit 0x%x\n", cup->devno);	}				/*		Clear the bh active indication.	*/	clear_bit(C7000_BH_ACTIVE, (void *)&cup->flag_a);	s390irq_spin_unlock_irqrestore(cup->irq, saveflags);	return;}/*	Send a system validate control command to a unit.*/static intc7000_send_sysval(struct c7000_unit *cup){	int				rc;	struct	c7000_controller	*ccp = cup->cntlp;	struct	c7000_control_blk	*ctlblkp = &(cup->control_blk);	CPrintk(1, "c7000: c7000_send_sysval: send sysval for device 0x%x\n", cup->devno);	/*		Build the system validate control message.	*/	memset(ctlblkp, '\0', sizeof(struct c7000_control_blk));	ctlblkp->cmd = C7000_SYS_VALIDATE;	ctlblkp->correlator = 0;	ctlblkp->link_id = ccp->linkid;	ctlblkp->ver = ccp->version; 	memcpy(ctlblkp->hostname, ccp->lhost, NAMLEN);	memcpy(ctlblkp->unitname, ccp->uhost, NAMLEN);	ctlblkp->rdsize = C7000_DATAL;        ctlblkp->wrtsize = C7000_DATAL;	/*		Build the channel program.	*/	c7000_bld_wrtctl_chpgm(cup);	/*		Do the IO and wait for write to complete.	*/	if ((rc = c7000_doio(cup)) != 0) {		CPrintk(0, "c7000: c7000_send_sysval failed with rc = %d for unit 0x%x\n", rc, cup->devno);		return(-1);	}	return(0);}/*	Send a system validate response control command to a unit.*/static intc7000_send_sysval_resp(struct c7000_unit *cup, unsigned char correlator, int ret_code){	int				rc;	struct	c7000_controller	*ccp = cup->cntlp;	struct	c7000_control_blk	*ctlblkp = &(cup->control_blk);	CPrintk(1, "c7000: c7000_send_sysval_resp: send sysval response for device 0x%x\n", cup->devno);	/*		Build the system validate response control message.	*/	memset(ctlblkp, '\0', sizeof(struct c7000_control_blk));	ctlblkp->cmd = C7000_SYS_VALIDATE_RESP;	ctlblkp->correlator = correlator;	ctlblkp->ret_code = ret_code;	ctlblkp->link_id = ccp->linkid;	ctlblkp->ver = ccp->version; 	memcpy(ctlblkp->hostname, ccp->lhost, NAMLEN);	memcpy(ctlblkp->unitname, ccp->uhost, NAMLEN);	ctlblkp->rdsize = C7000_DATAL;        ctlblkp->wrtsize = C7000_DATAL;	/*		Build the channel program.	*/	c7000_bld_wrtctl_chpgm(cup);	/*		Do the IO and wait for write to complete.	*/	if ((rc = c7000_doio(cup)) != 0) {		CPrintk(0, "c7000: c7000_send_sysval_resp failed with rc = %d for unit 0x%x\n", rc, cup->devno);		return(-1);	}	return(0);}/*	Check the information read in a SYS_VALIDATE control message.*/static intc7000_checkinfo(struct c7000_unit *cup){	struct	c7000_controller	*ccp = cup->cntlp; 	struct	c7000_control_blk	*ctlblkp = &cup->control_blk;	int				ret_code = 0;	if (memcmp(ccp->lhost, ctlblkp->hostname, NAMLEN) ||		memcmp(ccp->uhost, ctlblkp->unitname, NAMLEN))		ret_code = Err_Names_not_Matched;	if (ctlblkp->ver != ccp->version)		ret_code = Err_Wrong_Version;        if ((ctlblkp->rdsize < C7000_DATAL) || (ctlblkp->wrtsize < C7000_DATAL))		ret_code = Err_Wrong_Frame_Size;	if (ret_code != 0)		CPrintk(0, "c7000: c7000_checkinfo: ret_code %d for device 0x%x\n", ret_code, cup->devno);	return(ret_code);}/*	Keep reading until a sysval response comes in or an error.*/static intc7000_get_sysval_resp(struct c7000_unit *cup){	struct	c7000_controller	*ccp = cup->cntlp;	int				resp = 1;	int				req = 1;	int				rc;	int				ret_code = 0;	CPrintk(1, "c7000: c7000_get_sysval_resp: get sysval response for unit 0x%x\n", cup->devno);	/*		Wait for the response to C7000_SYS_VALIDATE and for an		inbound C7000_SYS_VALIDATE.	*/	while (resp || req) {		/*			Build the read channel program.		*/		c7000_bld_readctl_chpgm(cup);		if ((rc = c7000_doio(cup)) != 0) {			CPrintk(0, "c7000: c7000_get_sysval_resp: failed with rc = %d for unit 0x%x\n", rc, cup->devno);			return(-1);		}		/*			Process the control message.		*/		switch (cup->control_blk.cmd) {			/*				Check that response is positive and return				with success. Otherwise, return with an				error.			*/			case C7000_SYS_VALIDATE_RESP:				if (cup->control_blk.ret_code == 0)					resp = 0;				else {					CPrintk(0, "c7000: c7000_get_sysval_resp: receive sysval response for device 0x%x, return code %d\n",						cup->devno,						cup->control_blk.ret_code);					return(-1);				}				break;			/*				Check that the request is reasonable and				send a SYS_VALIDATE_RESP.  Otherwise,				return with an error.			*/			case C7000_SYS_VALIDATE:				CPrintk(1, "c7000: c7000_get_sysval_resp: receive sysval for device 0x%x\n", cup->devno);				req = 0;				ret_code = c7000_checkinfo(cup);				if (c7000_send_sysval_resp(&ccp->cunits[C7000_WR], cup->control_blk.correlator, ret_code) != 0)					return(-1);				if (ret_code != 0)					return(-1);				break;			/*				Anything else is unexpected and will result				in a return with an error.			*/			default:				CPrintk(0, "c7000: c7000_get_sysval_resp: receive unexpected command for device 0x%x, command %d\n", cup->devno, cup->control_blk.cmd);				return(-1);				break;		}	}	return(0);}/*	Send a connection confirm control message.*/static intc7000_conn_confrm(struct c7000_unit *cup, unsigned char correlator, int linkid){	int				rc;	struct	c7000_controller	*ccp = cup->cntlp;	struct	c7000_control_blk	*ctlblkp = &(cup->control_blk);	CPrintk(1, "c7000: c7000_conn_confrm: send the connection confirmation message for unit 0x%x\n", cup->devno);	/*		Build the connection confirm control message.	*/	memset(ctlblkp, '\0', sizeof(struct c7000_control_blk));	ctlblkp->cmd = C7000_CONN_CONFRM;	ctlblkp->ver = ccp->version;	ctlblkp->link_id = linkid;	ctlblkp->correlator = correlator;	ctlblkp->rdsize = 0;	ctlblkp->wrtsize = 0;	memcpy(ctlblkp->hostname, ccp->lappl, NAMLEN);	memcpy(ctlblkp->unitname, ccp->uappl, NAMLEN);	/*		Build the channel program.	*/	c7000_bld_wrtctl_chpgm(cup);	/*		Do the IO and wait for write to complete.	*/	if ((rc = c7000_doio(cup)) != 0) {		CPrintk(0, "c7000: c7000_conn_confrm: failed with rc = %d for unit 0x%x\n", rc, cup->devno);		return(-1);	}	return(0);}/*	Send a connection request control message.*/static intc7000_send_conn(struct c7000_unit *cup){	int				rc;	struct	c7000_controller	*ccp = cup->cntlp;	struct	c7000_control_blk	*ctlblkp = &(cup->control_blk);	CPrintk(1, "c7000: c7000_send_conn: send the connection request message for unit 0x%x\n", cup->devno);	/*		Build the connection request control message.	*/	memset(ctlblkp, '\0', sizeof(struct c7000_control_blk));	ctlblkp->cmd = C7000_CONN_REQ;	ctlblkp->ver = ccp->version;	ctlblkp->link_id = 0;	ctlblkp->correlator = 0;	ctlblkp->rdsize = C7000_DATAL;	ctlblkp->wrtsize = C7000_DATAL;	memcpy(ctlblkp->hostname, ccp->lappl, NAMLEN);	memcpy(ctlblkp->unitname, ccp->uappl, NAMLEN);	/*		Build the channel program.	*/	c7000_bld_wrtctl_chpgm(cup);	/*		Do the IO and wait for write to complete.	*/	if ((rc = c7000_doio(cup)) != 0) {		CPrintk(0, "c7000: c7000_send_conn: failed with rc = %d for unit 0x%x\n", rc, cup->devno);		return(-1);	}	return(0);}/*	Send a disconnect control message to the link with the value of	linkid.*/static intc7000_send_disc(struct c7000_unit *cup, int linkid){	int				rc;	struct	c7000_controller	*ccp = cup->cntlp;	struct	c7000_control_blk	*ctlblkp = &(cup->control_blk);	CPrintk(1, "c7000: c7000_send_disc: send disconnect message for unit 0x%x\n", cup->devno);	/*		Build the disconnect control message.	*/	memset(ctlblkp, '\0', sizeof(struct c7000_control_blk));	ctlblkp->cmd = C7000_DISCONN;	ctlblkp->ver = ccp->version;	ctlblkp->link_id = linkid;	ctlblkp->correlator = 0;	ctlblkp->rdsize = C7000_DATAL;	ctlblkp->wrtsize = C7000_DATAL;	memcpy(ctlblkp->hostname, ccp->lappl, NAMLEN);	memcpy(ctlblkp->unitname, ccp->uappl, NAMLEN);	/*		Build the channel program.	*/	c7000_bld_wrtctl_chpgm(cup);

⌨️ 快捷键说明

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