rioctrl.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 1,498 行 · 第 1/4 页

C
1,498
字号
			return -EFAULT;		}		if (DebugCtrl.SysPort == NO_PORT) {			if (cmd == RIO_SETDEBUG) {				if (!su) {					p->RIOError.Error = NOT_SUPER_USER;					return -EPERM;				}				p->rio_debug = DebugCtrl.Debug;				p->RIODebugWait = DebugCtrl.Wait;				rio_dprintk(RIO_DEBUG_CTRL, "Set global debug to 0x%x set wait to 0x%x\n", p->rio_debug, p->RIODebugWait);			} else {				rio_dprintk(RIO_DEBUG_CTRL, "Get global debug 0x%x wait 0x%x\n", p->rio_debug, p->RIODebugWait);				DebugCtrl.Debug = p->rio_debug;				DebugCtrl.Wait = p->RIODebugWait;				if (copy_to_user(arg, &DebugCtrl, sizeof(DebugCtrl))) {					rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort);					p->RIOError.Error = COPYOUT_FAILED;					return -EFAULT;				}			}		} else if (DebugCtrl.SysPort >= RIO_PORTS && DebugCtrl.SysPort != NO_PORT) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort);			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;			return -ENXIO;		} else if (cmd == RIO_SETDEBUG) {			if (!su) {				p->RIOError.Error = NOT_SUPER_USER;				return -EPERM;			}			rio_spin_lock_irqsave(&PortP->portSem, flags);			p->RIOPortp[DebugCtrl.SysPort]->Debug = DebugCtrl.Debug;			rio_spin_unlock_irqrestore(&PortP->portSem, flags);			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug);		} else {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug);			DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug;			if (copy_to_user(arg, &DebugCtrl, sizeof(DebugCtrl))) {				rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n");				p->RIOError.Error = COPYOUT_FAILED;				return -EFAULT;			}		}		return retval;	case RIO_VERSID:		/*		 ** Enquire about the release and version.		 ** We return MAX_VERSION_LEN bytes, being a		 ** textual null terminated string.		 */		rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID\n");		if (copy_to_user(arg, RIOVersid(), sizeof(struct rioVersion))) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID: Bad copy to user space (host=%d)\n", Host);			p->RIOError.Error = COPYOUT_FAILED;			return -EFAULT;		}		return retval;	case RIO_NUM_HOSTS:		/*		 ** Enquire as to the number of hosts located		 ** at init time.		 */		rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n");		if (copy_to_user(arg, &p->RIONumHosts, sizeof(p->RIONumHosts))) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n");			p->RIOError.Error = COPYOUT_FAILED;			return -EFAULT;		}		return retval;	case RIO_HOST_FOAD:		/*		 ** Kill host. This may not be in the final version...		 */		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD %ld\n", (unsigned long) arg);		if (!su) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n");			p->RIOError.Error = NOT_SUPER_USER;			return -EPERM;		}		p->RIOHalted = 1;		p->RIOSystemUp = 0;		for (Host = 0; Host < p->RIONumHosts; Host++) {			(void) RIOBoardTest(p->RIOHosts[Host].PaddrP, p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type, p->RIOHosts[Host].Slot);			memset(&p->RIOHosts[Host].Flags, 0, ((char *) &p->RIOHosts[Host].____end_marker____) - ((char *) &p->RIOHosts[Host].Flags));			p->RIOHosts[Host].Flags = RC_WAITING;		}		RIOFoadWakeup(p);		p->RIONumBootPkts = 0;		p->RIOBooting = 0;		printk("HEEEEELP!\n");		for (loop = 0; loop < RIO_PORTS; loop++) {			spin_lock_init(&p->RIOPortp[loop]->portSem);			p->RIOPortp[loop]->InUse = NOT_INUSE;		}		p->RIOSystemUp = 0;		return retval;	case RIO_DOWNLOAD:		rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD\n");		if (!su) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Not super user\n");			p->RIOError.Error = NOT_SUPER_USER;			return -EPERM;		}		if (copy_from_user(&DownLoad, arg, sizeof(DownLoad))) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n");			p->RIOError.Error = COPYIN_FAILED;			return -EFAULT;		}		rio_dprintk(RIO_DEBUG_CTRL, "Copied in download code for product code 0x%x\n", DownLoad.ProductCode);		/*		 ** It is important that the product code is an unsigned object!		 */		if (DownLoad.ProductCode > MAX_PRODUCT) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Bad product code %d passed\n", DownLoad.ProductCode);			p->RIOError.Error = NO_SUCH_PRODUCT;			return -ENXIO;		}		/*		 ** do something!		 */		retval = (*(RIOBootTable[DownLoad.ProductCode])) (p, &DownLoad);		/* <-- Panic */		p->RIOHalted = 0;		/*		 ** and go back, content with a job well completed.		 */		return retval;	case RIO_PARMS:		{			unsigned int host;			if (copy_from_user(&host, arg, sizeof(host))) {				rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");				p->RIOError.Error = COPYIN_FAILED;				return -EFAULT;			}			/*			 ** Fetch the parmmap			 */			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS\n");			if (copy_to_user(arg, p->RIOHosts[host].ParmMapP, sizeof(PARM_MAP))) {				p->RIOError.Error = COPYOUT_FAILED;				rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n");				return -EFAULT;			}		}		return retval;	case RIO_HOST_REQ:		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ\n");		if (copy_from_user(&HostReq, arg, sizeof(HostReq))) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");			p->RIOError.Error = COPYIN_FAILED;			return -EFAULT;		}		if (HostReq.HostNum >= p->RIONumHosts) {			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Illegal host number %d\n", HostReq.HostNum);			return -ENXIO;		}		rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostReq.HostNum);		if (copy_to_user(HostReq.HostP, &p->RIOHosts[HostReq.HostNum], sizeof(struct Host))) {			p->RIOError.Error = COPYOUT_FAILED;			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Bad copy to user space\n");			return -EFAULT;		}		return retval;	case RIO_HOST_DPRAM:		rio_dprintk(RIO_DEBUG_CTRL, "Request for DPRAM\n");		if (copy_from_user(&HostDpRam, arg, sizeof(HostDpRam))) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Copy in from user space failed\n");			p->RIOError.Error = COPYIN_FAILED;			return -EFAULT;		}		if (HostDpRam.HostNum >= p->RIONumHosts) {			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Illegal host number %d\n", HostDpRam.HostNum);			return -ENXIO;		}		rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostDpRam.HostNum);		if (p->RIOHosts[HostDpRam.HostNum].Type == RIO_PCI) {			int off;			/* It's hardware like this that really gets on my tits. */			static unsigned char copy[sizeof(struct DpRam)];			for (off = 0; off < sizeof(struct DpRam); off++)				copy[off] = readb(&p->RIOHosts[HostDpRam.HostNum].Caddr[off]);			if (copy_to_user(HostDpRam.DpRamP, copy, sizeof(struct DpRam))) {				p->RIOError.Error = COPYOUT_FAILED;				rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");				return -EFAULT;			}		} else if (copy_to_user(HostDpRam.DpRamP, p->RIOHosts[HostDpRam.HostNum].Caddr, sizeof(struct DpRam))) {			p->RIOError.Error = COPYOUT_FAILED;			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");			return -EFAULT;		}		return retval;	case RIO_SET_BUSY:		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY\n");		if ((unsigned long) arg > 511) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %ld\n", (unsigned long) arg);			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;			return -EINVAL;		}		rio_spin_lock_irqsave(&PortP->portSem, flags);		p->RIOPortp[(unsigned long) arg]->State |= RIO_BUSY;		rio_spin_unlock_irqrestore(&PortP->portSem, flags);		return retval;	case RIO_HOST_PORT:		/*		 ** The daemon want port information		 ** (probably for debug reasons)		 */		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT\n");		if (copy_from_user(&PortReq, arg, sizeof(PortReq))) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Copy in from user space failed\n");			p->RIOError.Error = COPYIN_FAILED;			return -EFAULT;		}		if (PortReq.SysPort >= RIO_PORTS) {	/* SysPort is unsigned */			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Illegal port number %d\n", PortReq.SysPort);			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;			return -ENXIO;		}		rio_dprintk(RIO_DEBUG_CTRL, "Request for port %d\n", PortReq.SysPort);		if (copy_to_user(PortReq.PortP, p->RIOPortp[PortReq.SysPort], sizeof(struct Port))) {			p->RIOError.Error = COPYOUT_FAILED;			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Bad copy to user space\n");			return -EFAULT;		}		return retval;	case RIO_HOST_RUP:		/*		 ** The daemon want rup information		 ** (probably for debug reasons)		 */		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP\n");		if (copy_from_user(&RupReq, arg, sizeof(RupReq))) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Copy in from user space failed\n");			p->RIOError.Error = COPYIN_FAILED;			return -EFAULT;		}		if (RupReq.HostNum >= p->RIONumHosts) {	/* host is unsigned */			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal host number %d\n", RupReq.HostNum);			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;			return -ENXIO;		}		if (RupReq.RupNum >= MAX_RUP + LINKS_PER_UNIT) {	/* eek! */			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal rup number %d\n", RupReq.RupNum);			p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;			return -EINVAL;		}		HostP = &p->RIOHosts[RupReq.HostNum];		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Host %d not running\n", RupReq.HostNum);			p->RIOError.Error = HOST_NOT_RUNNING;			return -EIO;		}		rio_dprintk(RIO_DEBUG_CTRL, "Request for rup %d from host %d\n", RupReq.RupNum, RupReq.HostNum);		if (copy_to_user(HostP->UnixRups[RupReq.RupNum].RupP, RupReq.RupP, sizeof(struct RUP))) {			p->RIOError.Error = COPYOUT_FAILED;			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n");			return -EFAULT;		}		return retval;	case RIO_HOST_LPB:		/*		 ** The daemon want lpb information		 ** (probably for debug reasons)		 */		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB\n");		if (copy_from_user(&LpbReq, arg, sizeof(LpbReq))) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy from user space\n");			p->RIOError.Error = COPYIN_FAILED;			return -EFAULT;		}		if (LpbReq.Host >= p->RIONumHosts) {	/* host is unsigned */			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal host number %d\n", LpbReq.Host);			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;			return -ENXIO;		}		if (LpbReq.Link >= LINKS_PER_UNIT) {	/* eek! */			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal link number %d\n", LpbReq.Link);			p->RIOError.Error = LINK_NUMBER_OUT_OF_RANGE;			return -EINVAL;		}		HostP = &p->RIOHosts[LpbReq.Host];		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Host %d not running\n", LpbReq.Host);			p->RIOError.Error = HOST_NOT_RUNNING;			return -EIO;		}		rio_dprintk(RIO_DEBUG_CTRL, "Request for lpb %d from host %d\n", LpbReq.Link, LpbReq.Host);		if (copy_to_user(LpbReq.LpbP, &HostP->LinkStrP[LpbReq.Link], sizeof(struct LPB))) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n");			p->RIOError.Error = COPYOUT_FAILED;			return -EFAULT;		}		return retval;		/*		 ** Here 3 IOCTL's that allow us to change the way in which		 ** rio logs errors. send them just to syslog or send them		 ** to both syslog and console or send them to just the console.		 **		 ** See RioStrBuf() in util.c for the other half.		 */	case RIO_SYSLOG_ONLY:		p->RIOPrintLogState = PRINT_TO_LOG;	/* Just syslog */		return 0;	case RIO_SYSLOG_CONS:		p->RIOPrintLogState = PRINT_TO_LOG_CONS;	/* syslog and console */		return 0;	case RIO_CONS_ONLY:		p->RIOPrintLogState = PRINT_TO_CONS;	/* Just console */		return 0;	case RIO_SIGNALS_ON:		if (p->RIOSignalProcess) {			p->RIOError.Error = SIGNALS_ALREADY_SET;			return -EBUSY;		}		/* FIXME: PID tracking */		p->RIOSignalProcess = current->pid;		p->RIOPrintDisabled = DONT_PRINT;		return retval;	case RIO_SIGNALS_OFF:		if (p->RIOSignalProcess != current->pid) {			p->RIOError.Error = NOT_RECEIVING_PROCESS;			return -EPERM;		}		rio_dprintk(RIO_DEBUG_CTRL, "Clear signal process to zero\n");		p->RIOSignalProcess = 0;		return retval;	case RIO_SET_BYTE_MODE:		for (Host = 0; Host < p->RIONumHosts; Host++)			if (p->RIOHosts[Host].Type == RIO_AT)				p->RIOHosts[Host].Mode &= ~WORD_OPERATION;		return retval;	case RIO_SET_WORD_MODE:		for (Host = 0; Host < p->RIONumHosts; Host++)			if (p->RIOHosts[Host].Type == RIO_AT)				p->RIOHosts[Host].Mode |= WORD_OPERATION;		return retval;	case RIO_SET_FAST_BUS:		for (Host = 0; Host < p->RIONumHosts; Host++)			if (p->RIOHosts[Host].Type == RIO_AT)				p->RIOHosts[Host].Mode |= FAST_AT_BUS;

⌨️ 快捷键说明

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