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

📄 s390io.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		/*		 * Check whether we must issue a SENSE CCW ourselves if there is no		 *  concurrent sense facility installed for the subchannel.		 *		 * Note: We should check for ioinfo[irq]->ui.flags.consns but VM		 *       violates the ESA/390 architecture and doesn't present an		 *       operand exception for virtual devices without concurrent		 *       sense facility available/supported when enabling the       *       concurrent sense facility.		 */		if (    (    ( ioinfo[irq]->devstat.ii.irb.scsw.dstat & DEV_STAT_UNIT_CHECK )			       && ( !issense                                                     ) )           || ( ioinfo[irq]->ui.flags.delsense && ending_status                     ) )		{			int            ret_io;			ccw1_t        *s_ccw  = &ioinfo[irq]->senseccw;			unsigned long  s_flag = 0;         if ( ending_status )         {				/*				 * We copy the current status information into the device driver				 *  status area. Then we can use the local devstat area for device				 *  sensing. When finally calling the IRQ handler we must not overlay				 *  the original device status but copy the sense data only.				 */				memcpy( action->dev_id,				        &(ioinfo[irq]->devstat),				        sizeof( devstat_t) );				s_ccw->cmd_code = CCW_CMD_BASIC_SENSE;				s_ccw->cda      = (__u32)virt_to_phys( ioinfo[irq]->devstat.ii.sense.data);				s_ccw->count    = SENSE_MAX_COUNT;				s_ccw->flags    = CCW_FLAG_SLI;				/*				 * If free_irq() or a sync do_IO/s390_start_IO() is in				 *  process we have to sense synchronously				 */				if ( ioinfo[irq]->ui.flags.unready || ioinfo[irq]->ui.flags.syncio )				{					s_flag = DOIO_WAIT_FOR_INTERRUPT;				} /* endif */				/*				 * Reset status info				 *				 * It does not matter whether this is a sync. or async.				 *  SENSE request, but we have to assure we don't call				 *  the irq handler now, but keep the irq in busy state.				 *  In sync. mode s390_process_IRQ() is called recursively,				 *  while in async. mode we re-enter do_IRQ() with the				 *  next interrupt.				 *				 * Note : this may be a delayed sense request !				 */				allow4handler                  = 0;				ioinfo[irq]->ui.flags.fast     = 0;				ioinfo[irq]->ui.flags.repall   = 0;				ioinfo[irq]->ui.flags.w4final  = 0;				ioinfo[irq]->ui.flags.delsense = 0;				ioinfo[irq]->devstat.cstat     = 0;				ioinfo[irq]->devstat.dstat     = 0;				ioinfo[irq]->devstat.rescnt    = SENSE_MAX_COUNT;				ioinfo[irq]->ui.flags.w4sense  = 1;							ret_io = s390_start_IO( irq,				                        s_ccw,				                        0xE2C5D5E2,  // = SENSe				                        0,           // n/a				                        s_flag);			}			else			{				/*				 * we received an Unit Check but we have no final				 *  status yet, therefore we must delay the SENSE				 *  processing. However, we must not report this				 *  intermediate status to the device interrupt				 *  handler.				 */				ioinfo[irq]->ui.flags.fast     = 0;				ioinfo[irq]->ui.flags.repall   = 0;				ioinfo[irq]->ui.flags.delsense = 1;				allow4handler                  = 0;			} /* endif */		} /* endif */		/*		 * we allow for the device action handler if .		 *  - we received ending status		 *  - the action handler requested to see all interrupts		 *  - we received a PCI		 *  - fast notification was requested (primary status)		 *  - unsollicited interrupts		 *		 */		if ( allow4handler )		{			allow4handler =    ending_status			   || ( ioinfo[irq]->ui.flags.repall                                      )			   || ( ioinfo[irq]->devstat.ii.irb.scsw.cstat & SCHN_STAT_PCI            )				|| ( (ioinfo[irq]->ui.flags.fast ) && (stctl & SCSW_STCTL_PRIM_STATUS) )				|| ( ioinfo[irq]->ui.flags.oper == 0                                   );		} /* endif */		/*		 * We used to copy the device status information right before		 *  calling the device action handler. However, in status		 *  pending situations during do_IO() or halt_IO(), as well as		 *  enable_subchannel/disable_subchannel processing we must		 *  synchronously return the status information and must not		 *  call the device action handler.		 *		 */		if ( allow4handler )		{			/*			 * if we were waiting for sense data we copy the sense			 *  bytes only as the original status information was			 *  saved prior to sense already.			 */			if ( ioinfo[irq]->ui.flags.w4sense )			{				int sense_count = SENSE_MAX_COUNT-ioinfo[irq]->devstat.rescnt;#if CONFIG_DEBUG_IO      if ( irq != cons_dev )         printk( "s390_process_IRQ( %04X ) : "                 "BASIC SENSE bytes avail %d\n",                 irq, sense_count );#endif				ioinfo[irq]->ui.flags.w4sense          = 0;				((devstat_t *)(action->dev_id))->flag |= DEVSTAT_FLAG_SENSE_AVAIL;				((devstat_t *)(action->dev_id))->scnt  = sense_count;				if ( sense_count >= 0 )				{					memcpy( ((devstat_t *)(action->dev_id))->ii.sense.data,					        &(ioinfo[irq]->devstat.ii.sense.data),					        sense_count);				}				else				{#if 1					panic( "s390_process_IRQ(%04x) encountered "					       "negative sense count\n",					       irq);#else					printk( KERN_CRIT"s390_process_IRQ(%04x) encountered "					        "negative sense count\n",					        irq);#endif				} /* endif */			}			else			{				memcpy( action->dev_id, &(ioinfo[irq]->devstat), sdevstat );			}  /* endif */      } /* endif */		/*		 * for status pending situations other than deferred interrupt		 *  conditions detected by s390_process_IRQ() itself we must not		 *  call the handler. This will synchronously be reported back		 *  to the caller instead, e.g. when detected during do_IO().		 */		if ( ioinfo[irq]->ui.flags.s_pend || ioinfo[irq]->ui.flags.unready )			allow4handler = 0;		/*		 * Call device action handler if applicable		 */		if ( allow4handler )		{			/*			 *  We only reset the busy condition when we are sure that no further			 *   interrupt is pending for the current I/O request (ending_status).			 */			if ( ending_status || !ioinfo[irq]->ui.flags.oper )			{				ioinfo[irq]->ui.flags.oper     = 1;  /* dev IS oper */				ioinfo[irq]->ui.flags.busy     = 0;				ioinfo[irq]->ui.flags.doio     = 0;				ioinfo[irq]->ui.flags.haltio   = 0;				ioinfo[irq]->ui.flags.fast     = 0;				ioinfo[irq]->ui.flags.repall   = 0;				ioinfo[irq]->ui.flags.w4final  = 0;				ioinfo[irq]->devstat.flag             |= DEVSTAT_FINAL_STATUS;				((devstat_t *)(action->dev_id))->flag |= DEVSTAT_FINAL_STATUS;				action->handler( irq, action->dev_id, &regs);				//				// reset intparm after final status or we will badly present unsolicited				//  interrupts with a intparm value possibly no longer valid.				//				ioinfo[irq]->devstat.intparm   = 0;				//				// Was there anything queued ? Start the pending channel program				//  if there is one.				//				if ( ioinfo[irq]->ui.flags.doio_q )				{					int ret;					ret = s390_start_IO( irq,							               ioinfo[irq]->qcpa,							               ioinfo[irq]->qintparm,							               ioinfo[irq]->qlpm,							               ioinfo[irq]->qflag);					ioinfo[irq]->ui.flags.doio_q = 0;					/*					 * If s390_start_IO() failed call the device's interrupt					 *  handler, the IRQ related devstat area was setup by					 *  s390_start_IO() accordingly already (status pending					 *  condition).					 */					if ( ret )					{						action->handler( irq, action->dev_id, &regs);					} /* endif */				} /* endif */			}			else			{				ioinfo[irq]->ui.flags.w4final = 1;				action->handler( irq, action->dev_id, &regs);			} /* endif */		} /* endif */		break;	case 3:      /* device not operational */		ioinfo[irq]->ui.flags.oper    = 0;		ioinfo[irq]->ui.flags.busy    = 0;		ioinfo[irq]->ui.flags.doio    = 0;		ioinfo[irq]->ui.flags.haltio  = 0;		ioinfo[irq]->devstat.cstat    = 0;		ioinfo[irq]->devstat.dstat    = 0;		ioinfo[irq]->devstat.flag    |= DEVSTAT_NOT_OPER;		ioinfo[irq]->devstat.flag    |= DEVSTAT_FINAL_STATUS;		/*		 * When we find a device "not oper" we save the status		 *  information into the device status area and call the		 *  device specific interrupt handler.		 *		 * Note: currently we don't have any way to reenable		 *       the device unless an unsolicited interrupt		 *       is presented. We don't check for spurious		 *       interrupts on "not oper" conditions.		 */		if (    ( ioinfo[irq]->ui.flags.fast    )		     && ( ioinfo[irq]->ui.flags.w4final ) )		{			/*			 * If a new request was queued already, we have			 *  to simulate the "not oper" status for the			 *  queued request by switching the "intparm" value			 *  and notify the interrupt handler.			 */			if ( ioinfo[irq]->ui.flags.doio_q )			{				ioinfo[irq]->devstat.intparm = ioinfo[irq]->qintparm;			} /* endif */		} /* endif */		ioinfo[irq]->ui.flags.fast    = 0;		ioinfo[irq]->ui.flags.repall  = 0;		ioinfo[irq]->ui.flags.w4final = 0;		memcpy( action->dev_id, &(ioinfo[irq]->devstat), sdevstat );		ioinfo[irq]->devstat.intparm  = 0;		if ( !ioinfo[irq]->ui.flags.s_pend )			action->handler( irq, action->dev_id, &regs);		ending_status    = 1;		break;	} /* endswitch */	return( ending_status );}/* * Set the special i/o-interruption sublass 7 for the *  device specified by parameter irq. There can only *  be a single device been operated on this special *  isc. This function is aimed being able to check *  on special device interrupts in disabled state, *  without having to delay I/O processing (by queueing) *  for non-console devices. * * Setting of this isc is done by set_cons_dev(), while *  reset_cons_dev() resets this isc and re-enables the *  default isc3 for this device. wait_cons_dev() allows *  to actively wait on an interrupt for this device in *  disabed state. When the interrupt condition is *  encountered, wait_cons_dev(9 calls do_IRQ() to have *  the console device driver processing the interrupt. */int set_cons_dev( int irq ){	int           ccode;	unsigned long cr6 __attribute__ ((aligned (8)));	int           rc = 0;	if ( cons_dev != -1  )	{		rc = -EBUSY;	}	else if ( (irq > highest_subchannel) || (irq < 0) )	{		rc = -ENODEV;	}	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )	{		return( -ENODEV);   }	else	{		/*		 * modify the indicated console device to operate		 *  on special console interrupt sublass 7		 */		ccode = stsch( irq, &(ioinfo[irq]->schib) );		if (ccode)		{			rc                         = -ENODEV;			ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER;		}		else		{			ioinfo[irq]->schib.pmcw.isc = 7;			ccode = msch( irq, &(ioinfo[irq]->schib) );			if (ccode)			{				rc = -EIO;			}			else			{				cons_dev = irq;				/*				 * enable console I/O-interrupt sublass 7				 */				asm volatile ("STCTL 6,6,%0": "=m" (cr6));				cr6 |= 0x01000000;				asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory");			} /* endif */		} /* endif */	} /* endif */	return( rc);}int reset_cons_dev( int irq){	int     rc = 0;	int     ccode;	long    cr6 __attribute__ ((aligned (8)));	if ( cons_dev != -1  )	{		rc = -EBUSY;	}	else if ( (irq > highest_subchannel) || (irq < 0) )	{		rc = -ENODEV;	}	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )	{		return( -ENODEV);   }	else	{		/*		 * reset the indicated console device to operate		 *  on default console interrupt sublass 3		 */		ccode = stsch( irq, &(ioinfo[irq]->schib) );		if (ccode)		{			rc                         = -ENODEV;			ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER;		}		else		{			ioinfo[irq]->schib.pmcw.isc = 3;			ccode = msch( irq, &(ioinfo[irq]->schib) );			if (ccode)			{				rc = -EIO;			}			else			{				cons_dev = -1;				/*				 * disable special console I/O-interrupt sublass 7				 */				asm volatile ("STCTL 6,6,%0": "=m" (cr6));				cr6 &= 0xFEFFFFFF;				asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory");			} /* endif */		} /* endif */	} /* endif */	return( rc);}int wait_cons_dev( int irq ){	int              rc = 0;	long             save_cr6;	if ( irq == cons_dev )	{		/*		 * before entering the spinlock we may already have		 *  processed the interrupt on a different CPU ...		 */		if ( ioinfo[irq]->ui.flags.busy == 1 )		{			long cr6 __attribute__ ((aligned (8)));			/*			 * disable all, but isc 7 (console device)			 */			asm volatile ("STCTL 6,6,%0": "=m" (cr6));			save_cr6  = cr6;			cr6      &= 0x01FFFFFF;			asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory");			do {				tpi_info_t tpi_info;				if (tpi(&tpi_info) == 1) {					s390_process_IRQ( tpi_info.irq );				} else {					s390irq_spin_unlock(irq);					tod_wait(100);					s390irq_spin_lock(irq);				}				eieio();			} while (ioinfo[irq]->ui.flags.busy == 1);			/*			 * restore previous isc value			 */			asm volatile ("STCTL 6,6,%0": "=m" (cr6));			cr6 = save_cr6;			asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory");		} /* endif */	}	else	{		rc = EINVAL;	} /* endif */	return(rc);}int enable_cpu_sync_isc( int irq ){	int             ccode;	long            cr6 __attribute__ ((aligned (8)));	int             count = 0;	int             rc    = 0;	if ( irq <= highest_subchannel && ioinfo[irq] != INVALID_STORAGE_AREA )	{		ccode = stsch( irq, &(ioinfo[irq]->schib) );		if ( !ccode )		{

⌨️ 快捷键说明

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