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

📄 s390io.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	/*	 * we ignore the clear_io() request if ending_status was received but	 *  a SENSE operation is waiting for completion.	 */	else if ( ioinfo[irq]->ui.flags.w4sense )	{		ret = 0;	}	else	{		if (cio_debug_initialized) {			sprintf(dbf_txt, "clearIO%x", irq);			debug_text_event(cio_debug_trace_id, 2, dbf_txt);		}		/*		 * If sync processing was requested we lock the sync ISC,		 *  modify the device to present interrupts for this ISC only		 *  and switch the CPU to handle this ISC + the console ISC		 *  exclusively.		 */		if ( flag & DOIO_WAIT_FOR_INTERRUPT )		{			ret = enable_cpu_sync_isc( irq);			if ( ret )			{				return( ret);  				} /* endif */		} /* endif */		/*		 * Issue "Clear subchannel" and process condition code		 */		ccode = csch( irq );		if (cio_debug_initialized) {			sprintf(dbf_txt, "ccode:%d",ccode);			debug_text_event(cio_debug_trace_id, 2, dbf_txt);		}		switch ( ccode ) {		case 0:			ioinfo[irq]->ui.flags.haltio = 1;			if ( !ioinfo[irq]->ui.flags.doio )			{				ioinfo[irq]->ui.flags.busy   = 1;				ioinfo[irq]->u_intparm       = user_intparm;				ioinfo[irq]->devstat.cstat   = 0;				ioinfo[irq]->devstat.dstat   = 0;				ioinfo[irq]->devstat.lpum    = 0;				ioinfo[irq]->devstat.flag    = DEVSTAT_CLEAR_FUNCTION;				ioinfo[irq]->devstat.scnt    = 0;			}			else			{				ioinfo[irq]->devstat.flag   |= DEVSTAT_CLEAR_FUNCTION;			} /* endif */			/*			 * If synchronous I/O processing is requested, we have			 *  to wait for the corresponding interrupt to occur by			 *  polling the interrupt condition. However, as multiple			 *  interrupts may be outstanding, we must not just wait			 *  for the first interrupt, but must poll until ours			 *  pops up.			 */			if ( flag & DOIO_WAIT_FOR_INTERRUPT )			{				int              io_sub;				__u32            io_parm;				psw_t            io_new_psw;				int              ccode;  					int              ready = 0;				struct _lowcore *lc    = NULL;				/*				 * We shouldn't perform a TPI loop, waiting for				 *  an interrupt to occur, but should load a				 *  WAIT PSW instead. Otherwise we may keep the				 *  channel subsystem busy, not able to present				 *  the interrupt. When our sync. interrupt				 *  arrived we reset the I/O old PSW to its				 *  original value.				 */				memcpy( &io_new_psw,				        &lc->io_new_psw,				        sizeof(psw_t));				ccode = iac();				switch (ccode) {				case 0:  		// primary-space					io_sync_wait.mask =   _IO_PSW_MASK					                    | _PSW_PRIM_SPACE_MODE					                    | _PSW_IO_WAIT;					break;				case 1:			// secondary-space					io_sync_wait.mask =   _IO_PSW_MASK					                    | _PSW_SEC_SPACE_MODE					                    | _PSW_IO_WAIT;					break;				case 2:			// access-register					io_sync_wait.mask =   _IO_PSW_MASK					                    | _PSW_ACC_REG_MODE					                    | _PSW_IO_WAIT;					break;				case 3:			// home-space						io_sync_wait.mask =   _IO_PSW_MASK					                    | _PSW_HOME_SPACE_MODE					                    | _PSW_IO_WAIT;					break;				default:					panic( "clear_IO() : unexpected "					       "address-space-control %d\n",					       ccode);					break;				} /* endswitch */				io_sync_wait.addr = FIX_PSW(&&cio_wakeup);				/*				 * Martin didn't like modifying the new PSW, now we take				 *  a fast exit in do_IRQ() instead				 */				*(__u32 *)__LC_SYNC_IO_WORD  = 1;				do				{					__load_psw( io_sync_wait );cio_wakeup:				   io_parm = *(__u32 *)__LC_IO_INT_PARM;				   io_sub  = (__u32)*(__u16 *)__LC_SUBCHANNEL_NR;				   ready = s390_process_IRQ( io_sub );				} while ( !((io_sub == irq) && (ready == 1)) );				*(__u32 *)__LC_SYNC_IO_WORD = 0;			} /* endif */			ret = 0;			break;		case 1 :            /* no status pending for csh */			BUG();			break;		case 2 :            /* no busy for csh*/			BUG();			break;		default:            /* device not operational */			ret = -ENODEV;			break;		} /* endswitch */		if ( flag & DOIO_WAIT_FOR_INTERRUPT )		{			disable_cpu_sync_isc( irq );		} /* endif */	} /* endif */	return( ret );}/* * do_IRQ() handles all normal I/O device IRQ's (the special *          SMP cross-CPU interrupts have their own specific *          handlers). * */asmlinkage void do_IRQ( struct pt_regs regs ){	/*	 * Get interrupt info from lowcore	 */	volatile tpi_info_t *tpi_info = (tpi_info_t*)(__LC_SUBCHANNEL_ID);	int cpu = smp_processor_id();	/*	 * take fast exit if CPU is in sync. I/O state	 *	 * Note: we have to turn off the WAIT bit and re-disable	 *       interrupts prior to return as this was the initial	 *       entry condition to synchronous I/O.	 */ 	if (    *(__u32 *)__LC_SYNC_IO_WORD )	{		regs.psw.mask &= ~(_PSW_WAIT_MASK_BIT | _PSW_IO_MASK_BIT);		return;	} /* endif */#ifdef CONFIG_FAST_IRQ	do {#endif /*  CONFIG_FAST_IRQ */				/*		 * Non I/O-subchannel thin interrupts are processed differently		 */		if ( tpi_info->adapter_IO == 1 &&		     tpi_info->int_type == IO_INTERRUPT_TYPE )		{			irq_enter(cpu, -1);			do_adapter_IO( tpi_info->intparm );			irq_exit(cpu, -1);		} 		else 		{			unsigned int irq = tpi_info->irq;				/*			 * fix me !!!			 *			 * instead of boxing the device, we need to schedule device			 * recognition, the interrupt stays pending. We need to			 * dynamically allocate an ioinfo structure, etc..			 */			if ( ioinfo[irq] == INVALID_STORAGE_AREA )			{				return;	/* this keeps the device boxed ... */			}				irq_enter(cpu, irq);			s390irq_spin_lock( irq );			s390_process_IRQ( irq );			s390irq_spin_unlock( irq );			irq_exit(cpu, irq);		}#ifdef CONFIG_FAST_IRQ		/*		 * Are more interrupts pending?		 * If so, the tpi instruction will update the lowcore 		 * to hold the info for the next interrupt.		 */	} while ( tpi( NULL ) != 0 );#endif /*  CONFIG_FAST_IRQ */	return;}/* * s390_process_IRQ() handles status pending situations and interrupts * * Called by : do_IRQ()             - for "real" interrupts *             s390_start_IO, halt_IO() *                                  - status pending cond. after SSCH, or HSCH *             disable_subchannel() - status pending conditions (after MSCH) * * Returns: 0 - no ending status received, no further action taken *          1 - interrupt handler was called with ending status */int s390_process_IRQ( unsigned int irq ){	int                    ccode;      /* cond code from tsch() operation */	int                    irb_cc;     /* cond code from irb */	int                    sdevstat;   /* struct devstat size to copy */	unsigned int           fctl;       /* function control */	unsigned int           stctl;      /* status   control */	unsigned int           actl;       /* activity control */	int               issense         = 0;	int               ending_status   = 0;	int               allow4handler   = 1;	int               chnchk          = 0;	devstat_t        *dp;	devstat_t        *udp;	char dbf_txt[15];	char buffer[80];	if (cio_count_irqs) {		int cpu = smp_processor_id();		s390_irq_count[cpu]++;	}			if (cio_debug_initialized) {		sprintf(dbf_txt, "procIRQ%x", irq);		debug_text_event(cio_debug_trace_id, 3, dbf_txt);	}	if ( ioinfo[irq] == INVALID_STORAGE_AREA )	{		/* we can't properly process the interrupt ... */		tsch( irq, p_init_irb );		return( 1 );	} /* endif */	dp  = &ioinfo[irq]->devstat;	udp = ioinfo[irq]->irq_desc.dev_id;		/*	 * It might be possible that a device was not-oper. at the time	 *  of free_irq() processing. This means the handler is no longer	 *  available when the device possibly becomes ready again. In	 *  this case we perform delayed disable_subchannel() processing.	 */	if ( !ioinfo[irq]->ui.flags.ready )	{		if ( !ioinfo[irq]->ui.flags.d_disable )		{#ifdef CONFIG_DEBUG_IO			printk( KERN_CRIT"s390_process_IRQ(%04X) "			        "- no interrupt handler registered "					  "for device %04X !\n",			        irq,			        ioinfo[irq]->devstat.devno);#endif /* CONFIG_DEBUG_IO */			if (cio_debug_initialized)				debug_sprintf_event(cio_debug_msg_id, 0,						    "s390_process_IRQ(%04X) - no interrupt handler registered for device %04X !\n",						    irq, ioinfo[irq]->devstat.devno);		} /* endif */	} /* endif */	/*	 * retrieve the i/o interrupt information (irb),	 *  update the device specific status information	 *  and possibly call the interrupt handler.	 *	 * Note 1: At this time we don't process the resulting	 *         condition code (ccode) from tsch(), although	 *         we probably should.	 *	 * Note 2: Here we will have to check for channel	 *         check conditions and call a channel check	 *         handler.	 *	 * Note 3: If a start function was issued, the interruption	 *         parameter relates to it. If a halt function was	 *         issued for an idle device, the intparm must not	 *         be taken from lowcore, but from the devstat area.	 */	ccode = tsch( irq, &(dp->ii.irb) );	if (cio_debug_initialized) {		sprintf(dbf_txt, "ccode:%d", ccode);		debug_text_event(cio_debug_trace_id, 3, dbf_txt);	}	//	// We must only accumulate the status if the device is busy already	//	if ( ioinfo[irq]->ui.flags.busy )	{		dp->dstat   |= dp->ii.irb.scsw.dstat;		dp->cstat   |= dp->ii.irb.scsw.cstat;                dp->intparm  = ioinfo[irq]->u_intparm;	}	else	{		dp->dstat    = dp->ii.irb.scsw.dstat;		dp->cstat    = dp->ii.irb.scsw.cstat;		dp->flag     = 0;   // reset status flags		dp->intparm  = 0;	} /* endif */	dp->lpum = dp->ii.irb.esw.esw1.lpum;	/*	 * reset device-busy bit if no longer set in irb	 */	if (    (dp->dstat & DEV_STAT_BUSY                   ) 	     && ((dp->ii.irb.scsw.dstat & DEV_STAT_BUSY) == 0))	{		dp->dstat &= ~DEV_STAT_BUSY;	} /* endif */	/*	 * Save residual count and CCW information in case primary and	 *  secondary status are presented with different interrupts.	 */	if ( dp->ii.irb.scsw.stctl	     & ( SCSW_STCTL_PRIM_STATUS | SCSW_STCTL_INTER_STATUS ) ) {		/*		 * If the subchannel status shows status pending		 * and we received a check condition, the count		 * information is not meaningful.		 */				 if ( !(    (dp->ii.irb.scsw.stctl & SCSW_STCTL_STATUS_PEND) 			 && (   dp->ii.irb.scsw.cstat 			      & (   SCHN_STAT_CHN_DATA_CHK				  | SCHN_STAT_CHN_CTRL_CHK				  | SCHN_STAT_INTF_CTRL_CHK				  | SCHN_STAT_PROG_CHECK				  | SCHN_STAT_PROT_CHECK				  | SCHN_STAT_CHAIN_CHECK )))) {			 dp->rescnt = dp->ii.irb.scsw.count;		 } else {			 dp->rescnt = SENSE_MAX_COUNT;		 }		dp->cpa    = dp->ii.irb.scsw.cpa;#ifdef CONFIG_DEBUG_IO		if ( irq != cons_dev )			printk( KERN_DEBUG "s390_process_IRQ( %04X ) : "			        "residual count from irb after tsch() %d\n",			        irq, dp->rescnt );#endif		if (cio_debug_initialized)			debug_sprintf_event(cio_debug_msg_id, 6,					    "s390_process_IRQ( %04X ) : residual count from irq after tsch() %d\n",					    irq, dp->rescnt);	} /* endif */	irb_cc = dp->ii.irb.scsw.cc;	//	// check for any kind of channel or interface control check but don't	//  issue the message for the console device	//	if (    (dp->ii.irb.scsw.cstat	            & (  SCHN_STAT_CHN_DATA_CHK	               | SCHN_STAT_CHN_CTRL_CHK			 | SCHN_STAT_INTF_CTRL_CHK )))	{		if (irq != cons_dev)			printk( KERN_WARNING "Channel-Check or Interface-Control-Check "				"received\n"				" ... device %04X on subchannel %04X, dev_stat "				": %02X sch_stat : %02X\n",				ioinfo[irq]->devstat.devno,				irq,				dp->dstat,				dp->cstat);		if (cio_debug_initialized) {			debug_sprintf_event(cio_debug_msg_id, 0,					    "Channel-Check or Interface-Control-Check received\n");			debug_sprintf_event(cio_debug_msg_id, 0,					    "... device %04X on subchannel %04X, dev_stat: %02X sch_stat: %02X\n",					    ioinfo[irq]->devstat.devno, irq, dp->dstat, dp->cstat);		}		chnchk = 1;	} /* endif */	if( dp->ii.irb.scsw.ectl==0)	{		issense=0;	}	else if (    (dp->ii.irb.scsw.stctl == SCSW_STCTL_STATUS_PEND)	          && (dp->ii.irb.scsw.eswf  == 0                     ))	{		issense = 0;	}	else if (   (dp->ii.irb.scsw.stctl ==		      (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_INTER_STATUS)) 		 && ((dp->ii.irb.scsw.actl & SCSW_ACTL_SUSPENDED) == 0)  )	{		issense = 0;	}	else	{		issense = dp->ii.irb.esw.esw0.erw.cons;	} /* endif */	if ( issense )	{		dp->scnt  = dp->ii.irb.esw.esw0.erw.scnt;		dp->flag |= DEVSTAT_FLAG_SENSE_AVAIL;                  			sdevstat = sizeof( devstat_t);#ifdef CONFIG_DEBUG_IO		if ( irq != cons_dev )			printk( KERN_DEBUG "s390_process_IRQ( %04X ) : "			        "concurrent sense bytes avail %d\n",			        irq, dp->scnt );#endif		if (cio_debug_initialized)			debug_sprintf_event(cio_debug_msg_id, 4,					    "s390_process_IRQ( %04X ): concurrent sense bytes avail %d\n",					    irq, dp->scnt);	}	else	{		/* don't copy the sense data area ! */		sdevstat = sizeof( devstat_t) - SENSE_MAX_COUNT;	} /* endif */	switch ( irb_cc ) {	case 1:      /* status pending */		dp->flag |= DEVSTAT_STATUS_PENDING;	case 0:      /* normal i/o interruption */		fctl  = dp->ii.irb.scsw.fctl;		stctl = dp->ii.irb.scsw.stctl;		actl  = dp->ii.irb.scsw.actl;		if ( chnchk )		{			sprintf( buffer, "s390_process_IRQ(%04X) - irb for "			         "device %04X after channel check\n",			         irq,			         dp->devno );			s390_displayhex( buffer,			                 &(dp->ii.irb) ,			                 sizeof(irb_t));			if (cio_debug_initialized) {								sp

⌨️ 快捷键说明

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