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

📄 s390io.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
		debug_text_event(cio_debug_trace_id, 2, dbf_txt);	}	return( ret );}/* * Disable IRQ by modifying the subchannel */static int disable_subchannel( unsigned int irq){	int  cc;          /* condition code */	int  ret = 0;     /* function return value */	int  retry = 5;	char dbf_txt[15];	SANITY_CHECK(irq);		if ( ioinfo[irq]->ui.flags.busy )	{		/*		 * the disable function must not be called while there are		 *  requests pending for completion !		 */		ret = -EBUSY;	}	else	{		if (cio_debug_initialized) {			sprintf(dbf_txt, "dissch%x", irq);			debug_text_event(cio_debug_trace_id, 2, dbf_txt);		}				/*		 * If device isn't operational we have to perform delayed		 *  disabling when the next interrupt occurs - unless the		 *  irq is re-requested prior to the interrupt to occur.		 */		cc = stsch(irq, &(ioinfo[irq]->schib) );		if ( cc == 3 )		{			ioinfo[irq]->ui.flags.oper      = 0;			ioinfo[irq]->ui.flags.d_disable = 1;			ret = 0;		}		else // cc == 0		{			ioinfo[irq]->schib.pmcw.ena = 0;			do			{				cc = msch( irq, &(ioinfo[irq]->schib) );				switch (cc) {				case 0: /* ok */					retry = 0;					ret = 0;   					break;				case 1: /* status pending */					ioinfo[irq]->ui.flags.s_pend = 1;					s390_process_IRQ( irq );					ioinfo[irq]->ui.flags.s_pend = 0;					ret = -EIO; /* might be overwritten  */					            /* ... on re-driving the */					            /* ... msch() call       */					retry--;					break;				case 2: /* busy; this should not happen! */					printk( KERN_CRIT"disable_subchannel(%04X) "					        "- unexpected busy condition for "						"device %04X received !\n",					        irq,					        ioinfo[irq]->devstat.devno);					if (cio_debug_initialized)						debug_sprintf_event(cio_debug_msg_id, 0, 								    "disable_subchannel(%04X) - unexpected busy condition for device %04X received !\n",								    irq, ioinfo[irq]->devstat.devno);					retry = 0;					ret = -EBUSY;					break;				case 3: /* not oper */					/*					 * should hardly occur ?!					 */					ioinfo[irq]->ui.flags.oper      = 0;					ioinfo[irq]->ui.flags.d_disable = 1;					retry = 0;					ret = 0; /* if the device has gone we */					         /* ... don't need to disable */					         /* ... it anymore !          */					break;				} /* endswitch */			} while ( retry );		} /* endif */	} /* endif */	if (cio_debug_initialized) {		sprintf(dbf_txt, "ret:%d",ret);		debug_text_event(cio_debug_trace_id, 2, dbf_txt);	}	return( ret);}void s390_init_IRQ( void ){	unsigned long flags;     /* PSW flags */	long          cr6 __attribute__ ((aligned (8)));	asm volatile ("STCK %0" : "=m" (irq_IPL_TOD));	p_init_schib = alloc_bootmem_low( sizeof(schib_t));	p_init_irb   = alloc_bootmem_low( sizeof(irb_t));			/*	 * As we don't know about the calling environment	 *  we assure running disabled. Before leaving the	 *  function we resestablish the old environment.	 *	 * Note : as we don't need a system wide lock, therefore	 *        we shouldn't use cli(), but __cli() as this	 *        affects the current CPU only.	 */	__save_flags(flags);	__cli();	/*	 * disable all interrupts	 */	cr6 = 0;	__ctl_load( cr6, 6, 6);	s390_process_subchannels();	if (cio_count_irqs) {		int i;		for (i=0; i<NR_CPUS; i++) 			s390_irq_count[i]=0;	}	/*	 * enable default I/O-interrupt sublass 3	 */	cr6 = 0x10000000;	__ctl_load( cr6, 6, 6);	s390_device_recognition_all();	init_IRQ_complete = 1;	__restore_flags(flags);	return;}/* * dummy handler, used during init_IRQ() processing for compatibility only */void  init_IRQ_handler( int irq, void *dev_id, struct pt_regs *regs){   /* this is a dummy handler only ... */}int s390_start_IO( int            irq,      /* IRQ */                   ccw1_t        *cpa,      /* logical channel prog addr */                   unsigned long  user_intparm,  /* interruption parameter */                   __u8           lpm,      /* logical path mask */                   unsigned long  flag)     /* flags */{	int            ccode;	int            ret = 0;	char buffer[80];	char dbf_txt[15];	SANITY_CHECK(irq);	/*	 * The flag usage is mutal exclusive ...	 */	if (    (flag & DOIO_EARLY_NOTIFICATION)	     && (flag & DOIO_REPORT_ALL     ) )	{		return( -EINVAL );	} /* endif */	if (cio_debug_initialized) {		sprintf(dbf_txt, "stIO%x", irq);		debug_text_event(cio_debug_trace_id, 4, dbf_txt);	}	/*	 * setup ORB	 */  	ioinfo[irq]->orb.intparm = (__u32)(long)&ioinfo[irq]->u_intparm;	ioinfo[irq]->orb.fmt     = 1;	ioinfo[irq]->orb.pfch = !(flag & DOIO_DENY_PREFETCH);	ioinfo[irq]->orb.spnd =  (flag & DOIO_ALLOW_SUSPEND ? TRUE : FALSE);	ioinfo[irq]->orb.ssic =  (    (flag & DOIO_ALLOW_SUSPEND )	                           && (flag & DOIO_SUPPRESS_INTER) );	if ( flag & DOIO_VALID_LPM )	{		ioinfo[irq]->orb.lpm = lpm;	}	else	{		ioinfo[irq]->orb.lpm = ioinfo[irq]->opm;	} /* endif */#ifdef CONFIG_ARCH_S390X	/* 	 * for 64 bit we always support 64 bit IDAWs with 4k page size only	 */	ioinfo[irq]->orb.c64 = 1;	ioinfo[irq]->orb.i2k = 0;#endif	ioinfo[irq]->orb.cpa = (__u32)virt_to_phys( cpa);	/*	 * 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 */	if ( flag & DOIO_DONT_CALL_INTHDLR )	{		ioinfo[irq]->ui.flags.repnone = 1;	} /* endif */	/*	 * Issue "Start subchannel" and process condition code	 */	ccode = ssch( irq, &(ioinfo[irq]->orb) );	if (cio_debug_initialized) {		sprintf(dbf_txt, "ccode:%d", ccode);		debug_text_event(cio_debug_trace_id, 4, dbf_txt);	}	switch ( ccode ) {	case 0:		if ( !ioinfo[irq]->ui.flags.w4sense )		{			/*			 * init the device driver specific devstat irb area			 *			 * Note : don磘 clear saved irb info in case of sense !			 */			memset( &((devstat_t *)ioinfo[irq]->irq_desc.dev_id)->ii.irb,				'\0', sizeof( irb_t) );		} /* endif */		memset( &ioinfo[irq]->devstat.ii.irb,		        '\0',		        sizeof( irb_t) );		/*		 * initialize device status information		 */		ioinfo[irq]->ui.flags.busy   = 1;		ioinfo[irq]->ui.flags.doio   = 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_START_FUNCTION;		ioinfo[irq]->devstat.scnt    = 0;		ioinfo[irq]->ui.flags.fast   = 0;		ioinfo[irq]->ui.flags.repall = 0;		/*		 * Check for either early (FAST) notification requests		 *  or if we are to return all interrupt info.		 * Default is to call IRQ handler at secondary status only		 */		if ( flag & DOIO_EARLY_NOTIFICATION )		{			ioinfo[irq]->ui.flags.fast = 1;		}		else if ( flag & DOIO_REPORT_ALL )		{			ioinfo[irq]->ui.flags.repall = 1;		} /* endif */		ioinfo[irq]->ulpm = ioinfo[irq]->orb.lpm;		/*		 * 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 )		{			psw_t            io_new_psw;			int              ccode;			uint64_t         time_start;    				uint64_t         time_curr;    				int              ready    = 0;			int              io_sub   = -1;			struct _lowcore *lc       = NULL;			int              do_retry = 1;			/*			 * 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( "start_IO() : unexpected "				       "address-space-control %d\n",				       ccode);				break;			} /* endswitch */			io_sync_wait.addr = FIX_PSW(&&io_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;			asm volatile ("STCK %0" : "=m" (time_start));			time_start = time_start >> 32;			do			{				if ( flag & DOIO_TIMEOUT )				{					tpi_info_t tpi_info={0,};					do					{						if ( tpi(&tpi_info) == 1 )						{							io_sub = tpi_info.irq;							break;						}						else						{							udelay(100); /* usecs */							asm volatile ("STCK %0" : "=m" (time_curr));							if ( ((time_curr >> 32) - time_start ) >= 3 )								do_retry = 0;          													} /* endif */									} while ( do_retry );				}				else				{					__load_psw( io_sync_wait );io_wakeup:					io_sub  = (__u32)*(__u16 *)__LC_SUBCHANNEL_NR;				} /* endif */ 				if ( do_retry )					ready = s390_process_IRQ( io_sub );				/*				 * surrender when retry count's exceeded ...				 */			} while ( !(     ( io_sub == irq )			              && ( ready  == 1   ))			            && do_retry             );			*(__u32 *)__LC_SYNC_IO_WORD = 0;			if ( !do_retry )				ret = -ETIMEDOUT;		} /* endif */		break;	case 1 :            /* status pending */		ioinfo[irq]->devstat.flag =   DEVSTAT_START_FUNCTION		                            | DEVSTAT_STATUS_PENDING;		/*		 * initialize the device driver specific devstat irb area		 */		memset( &((devstat_t *) ioinfo[irq]->irq_desc.dev_id)->ii.irb,		        '\0', sizeof( irb_t) );		/*		 * Let the common interrupt handler process the pending status.		 *  However, we must avoid calling the user action handler, as		 *  it won't be prepared to handle a pending status during		 *  do_IO() processing inline. This also implies that process_IRQ		 *  must terminate synchronously - especially if device sensing		 *  is required.		 */		ioinfo[irq]->ui.flags.s_pend   = 1;		ioinfo[irq]->ui.flags.busy     = 1;		ioinfo[irq]->ui.flags.doio     = 1;		s390_process_IRQ( irq );		ioinfo[irq]->ui.flags.s_pend   = 0;		ioinfo[irq]->ui.flags.busy     = 0;		ioinfo[irq]->ui.flags.doio     = 0;		ioinfo[irq]->ui.flags.repall   = 0;		ioinfo[irq]->ui.flags.w4final  = 0;		ioinfo[irq]->devstat.flag     |= DEVSTAT_FINAL_STATUS;		/*		 * In multipath mode a condition code 3 implies the last path		 *  has gone, except we have previously restricted the I/O to		 *  a particular path. A condition code 1 (0 won't occur)		 *  results in return code EIO as well as 3 with another path		 *  than the one used (i.e. path available mask is non-zero).		 */		if ( ioinfo[irq]->devstat.ii.irb.scsw.cc == 3 )		{			if ( flag & DOIO_VALID_LPM )			{				ioinfo[irq]->opm &= ~(ioinfo[irq]->devstat.ii.irb.esw.esw1.lpum);			}			else			{				ioinfo[irq]->opm = 0;			} /* endif */				if ( ioinfo[irq]->opm == 0 ) 				{				ret                         = -ENODEV;				ioinfo[irq]->ui.flags.oper  = 0;			}			else			{				ret = -EIO;			} /* endif */			ioinfo[irq]->devstat.flag  |= DEVSTAT_NOT_OPER;#ifdef CONFIG_DEBUG_IO			{			stsch(irq, &(ioinfo[irq]->schib) );			sprintf( buffer, "s390_start_IO(%04X) - irb for "			         "device %04X, after status pending\n",			         irq,			         ioinfo[irq]->devstat.devno );			s390_displayhex( buffer,			                 &(ioinfo[irq]->devstat.ii.irb) ,			                 sizeof(irb_t));			sprintf( buffer, "s390_start_IO(%04X) - schib for "			         "device %04X, after status pending\n",			         irq,			         ioinfo[irq]->devstat.devno );			s390_displayhex( buffer,			                 &(ioinfo[irq]->schib) ,			                 sizeof(schib_t));			if (ioinfo[irq]->devstat.flag & DEVSTAT_FLAG_SENSE_AVAIL)			{				sprintf( buffer, "s390_start_IO(%04X) - sense "				         "data for "				         "device %04X, after status pending\n",				         irq,

⌨️ 快捷键说明

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