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

📄 c7000.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	/*		Do the IO and wait for write to complete.	*/	if ((rc = c7000_doio(cup)) != 0) {		CPrintk(0, "c7000: c7000_send_disc: failed with rc = %d for unit 0x%x\n", rc, cup->devno);		return(-1);	}	return(0);}/*	Resolve the race condition based on the link identifier value.	The adapter microcode assigns the identifiers.  A higher value implies	that the race was lost. A side effect of this function is that	ccp->linkid is set to the link identifier to be used for this	connection (provided that 0 is returned).*/static intc7000_resolve_race(struct c7000_unit *cup, int local_linkid, int remote_linkid){	struct c7000_controller 	*ccp = cup->cntlp;	CPrintk(1, "c7000: c7000_resolve_race: for unit 0x%x, local linkid %d, remote linkid %d\n", cup->devno, local_linkid, remote_linkid);	/*		This local link identifier should not be zero..	*/	if (local_linkid == 0) {		CPrintk(0, "c7000: c7000_resolve_race: error for unit 0x%x, local linkid is null\n", cup->devno);		return(-1);	}	/*		This indicates that there is no race.  Just use our		local link identifier.	*/	if (remote_linkid == 0) {		ccp->linkid = local_linkid;		return(0);	}	/*		Send a connection confirm message if we lost the race to		the winning link identifier.		Either way, save the winning link identifier.	*/	if (local_linkid > remote_linkid) {		if (c7000_conn_confrm(&ccp->cunits[C7000_WR], cup->control_blk.correlator, remote_linkid) != 0) {			CPrintk(0, "c7000: c7000_resolve_race: failed for unit 0x%x\n", cup->devno);			return(-1);		}		ccp->linkid = remote_linkid;	} else {		ccp->linkid = local_linkid;	}	return(0);}/*	Get connected by processing the connection request/response/confirm	control messages.  A connection request has already been sent by	calling function c7000_send_conn.*/static intc7000_get_conn(struct c7000_unit *cup){	struct c7000_controller 	*ccp = cup->cntlp;	int				rc;	int				cont = 1;	int				remote_linkid = 0;	int				local_linkid = 0;	CPrintk(1, "c7000: c7000_get_conn: read the connected message for unit 0x%x\n", cup->devno);	ccp->linkid = 0;	while (cont == 1) {		/*			Build the read channel program.		*/		c7000_bld_readctl_chpgm(cup);		/*			Start the channel program to read a control message.		*/		if ((rc = c7000_doio(cup)) != 0) {			CPrintk(0, "c7000: c7000_get_conn: failed with rc = %d for unit 0x%x\n", rc, cup->devno);			return(-1);		}		/*			Process the control message that was received based			on the command code.		*/		CPrintk(1, "c7000: c7000_get_conn: received command %d for unit 0x%x\n", cup->control_blk.cmd, cup->devno);		switch(cup->control_blk.cmd) {			/*				Save the remote link_id in the message for				a check in c7000_resolve_race.			*/			case C7000_CONN_REQ:				remote_linkid = cup->control_blk.link_id;				break;			/*				A connection response received.  Resolve				the network race condition (if any) by				comparing the link identifier values.			*/			case C7000_CONN_RESP:				if (cup->control_blk.ret_code != 0) {					CPrintk(0, "c7000: c7000_get_conn: failed for unit 0x%x , connection response return code %d\n",						cup->devno, cup->control_blk.ret_code);					return(-1);				}				local_linkid = cup->control_blk.link_id;				if (c7000_resolve_race(cup, local_linkid, remote_linkid) != 0)					return(-1);				break;			/*				Got a confirmation to our connection request.				Disconnect the remote link identifier (if any).				Break out of the loop.			*/			case C7000_CONN_CONFRM:				if (remote_linkid != 0) {					if (c7000_send_disc(&ccp->cunits[C7000_WR], remote_linkid) != 0) {						CPrintk(0, "c7000: c7000_get_conn: send disconnect failed for unit 0x%x\n", cup->devno);						return(-1);					}				}				cont = 0;				break;			/*				Got a disconnect to our connection request.				Break out of the loop.			*/			case C7000_DISCONN:				cont = 0;				break;			/*				Anything else must be an error.				Return with an error immediately.			*/			default:				CPrintk(0, "c7000: c7000_get_conn: failed for unit 0x%x unexpected command %d\n",					cup->devno, cup->control_blk.cmd);				return(-1);		}	}	/*		Be sure that we now have a link identifier.	*/	if (ccp->linkid == 0)		return(-1);	return(0);}/*	Get statistics method.*/struct net_device_stats *c7000_stats(struct net_device *dev){	struct	c7000_controller	*ccp = (struct c7000_controller *)dev->priv;	return(&ccp->stats);}/*	Open method.*/static intc7000_open(struct net_device *dev){	int				i;	struct	c7000_controller	*ccp = (struct c7000_controller *)dev->priv;	struct	c7000_unit		*cup;	int				rc;	unsigned long			parm;	__u8				flags = 0x00;	c7000_set_busy(dev);	/*		Allocate space for the unit buffers.	*/	if (c7000_alloc_buffers(dev) == -1) {		CPrintk(0, "c7000: c7000_open: can not allocate buffer space for base unit 0x%lx\n", dev->base_addr);		c7000_free_buffers(dev);  /* free partially allocated buffers */		c7000_clear_busy(dev);		return(-ENOMEM);	}		/*		Perform the initialization for all units.	*/	for (i = 0; i < NUNITS; i++) {		cup = &ccp->cunits[i];		/*			Initialize task queue structure used for the bottom			half routine.		*/		cup->tq.sync = 0;		cup->tq.routine = (void *)(void *)c7000_irq_bh;		cup->tq.data = cup;		cup->state = C7000_HALT;		init_waitqueue_head(&cup->wait);		CPrintk(1, "c7000: c7000_open: issuing halt to unit 0x%x\n", cup->devno);		/*			Issue a halt I/O to the unit		*/		if ((rc = c7000_haltio(cup)) != 0) {			CPrintk(0, "c7000: c7000_open: halt_IO failed with rc = %d for unit 0x%x\n", rc, cup->devno);			continue;		}		cup->IO_active = 0;		cup->flag_a = 0;		cup->sigsmod = 0x00;		CPrintk(1, "c7000: c7000_open: halt complete for unit 0x%x\n", cup->devno);	}	/*		On each subchannel send a sense id.	*/	for (i = 0; i < NUNITS; i++) {		cup = &ccp->cunits[i];		/*			Build SENSE ID channel program.		*/		c7000_bld_senseid_chpgm(cup);			/*			Issue the start I/O for SENSE ID channel program.		*/		CPrintk(1, "c7000: c7000_open: issuing SENSEID to unit 0x%x\n", cup->devno);		if ((rc = c7000_doio(cup)) != 0) {			CPrintk(0, "c7000: c7000_open: SENSEID failed with rc = %d for unit 0x%x\n", rc, cup->devno);			c7000_clear_busy(dev);			return(-EIO);		}			CPrintk(1, "c7000: c7000_open: SENSEID complete for unit 0x%x\n", cup->devno);	}	/*		Send the system validation control message.	*/	cup = &ccp->cunits[C7000_WR];	if (c7000_send_sysval(cup) != 0) {		CPrintk(0, "c7000: c7000_open: can not send sysval for unit 0x%x\n", cup->devno);		c7000_clear_busy(dev);		return(-EIO);	}	CPrintk(1, "c7000: c7000_open: successfully sent sysval for unit 0x%x\n", cup->devno);	/*		Get the system validation response message.	*/	cup = &ccp->cunits[C7000_RD];	if (c7000_get_sysval_resp(cup) != 0) {		CPrintk(0, "c7000: c7000_open: can not read sysval response for unit 0x%x\n", cup->devno);		c7000_clear_busy(dev);		return(-EIO);	}	CPrintk(1, "c7000: c7000_open: successfully received sysval reply for unit 0x%x\n", cup->devno);	ccp->cunits[C7000_RD].state = ccp->cunits[C7000_WR].state = C7000_CONNECT;	cup = &ccp->cunits[C7000_WR];	/*		Send a connection request.	*/	if (c7000_send_conn(cup) != 0) {		CPrintk(0, "c7000: c7000_open: connection failed for unit 0x%x\n", cup->devno);		c7000_clear_busy(dev);		return(-EIO);	}	cup = &ccp->cunits[C7000_RD];	/*		Get the response to our connection request Note that a		network race may occur.  This is handled in c7000_get_conn.	*/	if (c7000_get_conn(cup) != 0) {		CPrintk(0, "c7000: c7000_open: unit 0x%x has connected\n", cup->devno);		c7000_clear_busy(dev);		return(-EIO);	}	CPrintk(1, "c7000: c7000_open: successfully received connection request for unit 0x%x\n", cup->devno);	ccp->cunits[C7000_RD].state = ccp->cunits[C7000_WR].state = C7000_READY;	/*		Clear the interface statistics.	*/	memset(&ccp->stats, '\0', sizeof(struct net_device_stats));	if ((rc = c7000_bld_read_chain(cup)) != 0) {		c7000_clear_busy(dev);		return(rc);	}	/*		Start the C7000_READ channel program but do not wait for it's		completion.	*/	cup->state = C7000_READ;	parm = (unsigned long)cup;	set_bit(0, (void *)&cup->IO_active);	if ((rc = do_IO(cup->irq, &cup->proc_head->ccws[0], parm, 0xff, flags)) != 0) {		CPrintk(0, "c7000: c7000_open: READ failed with return code %d for unit 0x%x\n", rc, cup->devno);		c7000_error(cup->cntlp);		clear_bit(0, (void *)&cup->IO_active);		c7000_clear_busy(dev);		return(-EIO);	}	netif_start_queue(dev);	CPrintk(0, "c7000: c7000_open: base unit 0x%lx is opened\n", dev->base_addr);	c7000_clear_busy(dev);	MOD_INC_USE_COUNT;	/* increment module usage count */	return(0);}/*	Stop method.*/static intc7000_stop(struct net_device *dev){	int				i;	struct	c7000_controller	*ccp = (struct c7000_controller *)dev->priv;	struct	c7000_unit		*cup;	int				rc;	c7000_set_busy(dev);	/*		Send a disconnect message.	*/	ccp->cunits[C7000_RD].state = ccp->cunits[C7000_WR].state = C7000_DISC;	cup = &ccp->cunits[C7000_WR];	if (c7000_send_disc(cup, ccp->linkid) != 0) {		CPrintk(0, "c7000: c7000_stop: send of disconnect message failed for unit 0x%x\n", cup->devno);	}	CPrintk(1, "c7000: c7000_stop: successfully sent disconnect message to unit 0x%x\n", cup->devno);	/*		Issue a halt I/O to all units.	*/	for (i = 0; i < NUNITS; i++) {		cup = &ccp->cunits[i];		cup->state = C7000_STOP;		CPrintk(1, "c7000: c7000_stop: issuing halt to unit 0x%x\n", cup->devno);		if ((rc = c7000_haltio(cup)) != 0) {			CPrintk(0, "c7000: c7000_stop: halt_IO failed with rc = %d for unit 0x%x\n", rc, cup->devno);			continue;		}		CPrintk(1, "c7000: c7000_stop: halt complete for unit 0x%x\n", cup->devno);	}	c7000_free_buffers(dev);	CPrintk(0, "c7000: c7000_stop: base unit 0x%lx is stopped\n", dev->base_addr);	MOD_DEC_USE_COUNT;	/* Decrement module usage count */	return(0);}/*	Configure the interface.*/static intc7000_config(struct net_device *dev, struct ifmap *map){	CPrintk(1, "c7000: c7000_config: entered for base unit 0x%lx\n", dev->base_addr);	return(0);}/*	Transmit a packet.*/static intc7000_xmit(struct sk_buff *skb, struct net_device *dev){	struct	c7000_controller	*ccp = (struct c7000_controller *)dev->priv;	struct	c7000_unit		*cup;	unsigned long			saveflags;	unsigned long			parm;	__u8				flags = 0x00;	struct	c7000_buffer		*buf, *pbuf;	int				rc;	CPrintk(1, "c7000: c7000_xmit: entered for base unit 0x%lx\n", dev->base_addr);	/*		When the skb pointer is NULL return.	*/	if (skb == NULL) {		CPrintk(0, "c7000: c7000_xmit: skb pointer is null for base unit 0x%lx\n", dev->base_addr);		ccp->stats.tx_dropped++;		return(-EIO);	}	cup = &ccp->cunits[C7000_WR];	/*		Lock the irq.	*/	s390irq_spin_lock_irqsave(cup->irq, saveflags);		/*		When the device transmission busy flag is on , no data		can be sent.  Unlock the irq and return EBUSY.	*/	if (c7000_check_busy(dev)) {		CPrintk(1, "c7000: c7000_xmit: c7000_check_busy returns true for base unit 0x%lx\n", dev->base_addr);		s390irq_spin_unlock_irqrestore(cup->irq, saveflags);		return(-EBUSY);	}	/*		Set the device transmission busy flag on atomically.	*/	if (c7000_ts_busy(TB_TX, dev)) {		CPrintk(1, "c7000: c7000_xmit: c7000_ts_busy returns true for base unit 0x%lx\n", dev->base_addr);		s390irq_spin_unlock_irqrestore(cup->irq, saveflags);		return(-EBUSY);	}	CPrintk(1, "c7000: c7000_xmit: set TB_TX for unit 0x%x\n", cup->devno);	/*		Obtain a free buffer.  If none are free then mark tbusy		with TB_NOBUFFER and return EBUSY.	*/	if ((buf = c7000_get_buffer(cup)) == NULL) {		CPrintk(1, "c7000: c7000_xmit: setting TB_NOBUFFER for base unit 0x%lx\n", dev->base_addr);		c7000_setbit_busy(TB_NOBUFFER, dev);		c7000_clearbit_busy(TB_TX, dev);		s390irq_spin_unlock_irqrestore(cup->irq, saveflags);		return(-EBUSY);	}	CPrintk(1, "c7000: c7000_xmit: Got buffer for unit 0x%x\n", cup->devno);	/*		Save the length of the skb data and then copy it to the		buffer.  Queue the buffer on the processing list.	*/	buf->len = skb->len;	memcpy(buf->data, skb->data, skb->len);	memset(buf->data + C7000_DATAL + C7000_READHDRL, '\0', C7000_READFFL);	pbuf = cup->proc_tail;	c7000_queue_buffer(cup, buf);	/*		Chain the buffer to the running channel program.	*/	if (test_bit(0, (void *)&cup->IO_active) && pbuf != NULL) {		c7000_bld_wrt_chpgm(cup, buf);		pbuf->ccws[2].cda = (__u32)virt_to_phys(&buf->ccws[0]);	}	/*		Free the socket buffer.	*/	dev_kfree_skb(skb);	/*		If the unit is not currently doing IO, build a channel		program and start the IO for the buffers on the processing		chain.	*/	if (test_and_set_bit(0, (void *)&cup->IO_active) == 0) {		CPrintk(1, "c7000: c7000_xmit: start IO for unit 0x%x\n", cup->devno);		c7000_bld_wrt_chain(cup);		parm = (unsigned long)cup;		cup->state = C7000_WRITE;		if ((rc = do_IO(cup->irq, &cup->proc_head->ccws[0], parm, 0xff, flags)) != 0) {			CPrintk(0, "c7000: c7000_xmit: do_IO failed with return code %d for unit 0x%x\n", rc, cup->devno);			c7000_error(cup->cntlp);			c7000_clearbit_busy(TB_TX, dev);			s390irq_spin_unlock_irqrestore(cup->irq, saveflags);			return(-EIO);		}		dev->trans_start = jiffies;		CPrintk(1, "c7000: c7000_xmit: do_IO succeeds for unit 0x%x\n", cup->devno);	}			/*		If the free chain is now NULL, set the TB_NOBUFFER flag.	*/	if (cup->free == NULL) {		CPrintk(1, "c7000: c7000_xmit: setting TB_NOBUFFER for base unit 0x%lx\n", dev->base_addr);		c7000_setbit_busy(TB_NOBUFFER, dev);	}

⌨️ 快捷键说明

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