rioctrl.c

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

C
1,498
字号
		return retval;	case RIO_SET_SLOW_BUS:		for (Host = 0; Host < p->RIONumHosts; Host++)			if (p->RIOHosts[Host].Type == RIO_AT)				p->RIOHosts[Host].Mode &= ~FAST_AT_BUS;		return retval;	case RIO_MAP_B50_TO_50:	case RIO_MAP_B50_TO_57600:	case RIO_MAP_B110_TO_110:	case RIO_MAP_B110_TO_115200:		rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping\n");		port = (unsigned long) arg;		if (port < 0 || port > 511) {			rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port);			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;			return -EINVAL;		}		rio_spin_lock_irqsave(&PortP->portSem, flags);		switch (cmd) {		case RIO_MAP_B50_TO_50:			p->RIOPortp[port]->Config |= RIO_MAP_50_TO_50;			break;		case RIO_MAP_B50_TO_57600:			p->RIOPortp[port]->Config &= ~RIO_MAP_50_TO_50;			break;		case RIO_MAP_B110_TO_110:			p->RIOPortp[port]->Config |= RIO_MAP_110_TO_110;			break;		case RIO_MAP_B110_TO_115200:			p->RIOPortp[port]->Config &= ~RIO_MAP_110_TO_110;			break;		}		rio_spin_unlock_irqrestore(&PortP->portSem, flags);		return retval;	case RIO_STREAM_INFO:		rio_dprintk(RIO_DEBUG_CTRL, "RIO_STREAM_INFO\n");		return -EINVAL;	case RIO_SEND_PACKET:		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n");		if (copy_from_user(&SendPack, arg, sizeof(SendPack))) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n");			p->RIOError.Error = COPYIN_FAILED;			return -EFAULT;		}		if (SendPack.PortNum >= 128) {			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;			return -ENXIO;		}		PortP = p->RIOPortp[SendPack.PortNum];		rio_spin_lock_irqsave(&PortP->portSem, flags);		if (!can_add_transmit(&PacketP, PortP)) {			p->RIOError.Error = UNIT_IS_IN_USE;			rio_spin_unlock_irqrestore(&PortP->portSem, flags);			return -ENOSPC;		}		for (loop = 0; loop < (ushort) (SendPack.Len & 127); loop++)			writeb(SendPack.Data[loop], &PacketP->data[loop]);		writeb(SendPack.Len, &PacketP->len);		add_transmit(PortP);		/*		 ** Count characters transmitted for port statistics reporting		 */		if (PortP->statsGather)			PortP->txchars += (SendPack.Len & 127);		rio_spin_unlock_irqrestore(&PortP->portSem, flags);		return retval;	case RIO_NO_MESG:		if (su)			p->RIONoMessage = 1;		return su ? 0 : -EPERM;	case RIO_MESG:		if (su)			p->RIONoMessage = 0;		return su ? 0 : -EPERM;	case RIO_WHAT_MESG:		if (copy_to_user(arg, &p->RIONoMessage, sizeof(p->RIONoMessage))) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n");			p->RIOError.Error = COPYOUT_FAILED;			return -EFAULT;		}		return 0;	case RIO_MEM_DUMP:		if (copy_from_user(&SubCmd, arg, sizeof(struct SubCmdStruct))) {			p->RIOError.Error = COPYIN_FAILED;			return -EFAULT;		}		rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP host %d rup %d addr %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Addr);		if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) {			p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;			return -EINVAL;		}		if (SubCmd.Host >= p->RIONumHosts) {			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;			return -EINVAL;		}		port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort;		PortP = p->RIOPortp[port];		rio_spin_lock_irqsave(&PortP->portSem, flags);		if (RIOPreemptiveCmd(p, PortP, MEMDUMP) == RIO_FAIL) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP failed\n");			rio_spin_unlock_irqrestore(&PortP->portSem, flags);			return -EBUSY;		} else			PortP->State |= RIO_BUSY;		rio_spin_unlock_irqrestore(&PortP->portSem, flags);		if (copy_to_user(arg, p->RIOMemDump, MEMDUMP_SIZE)) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n");			p->RIOError.Error = COPYOUT_FAILED;			return -EFAULT;		}		return 0;	case RIO_TICK:		if ((unsigned long) arg >= p->RIONumHosts)			return -EINVAL;		rio_dprintk(RIO_DEBUG_CTRL, "Set interrupt for host %ld\n", (unsigned long) arg);		writeb(0xFF, &p->RIOHosts[(unsigned long) arg].SetInt);		return 0;	case RIO_TOCK:		if ((unsigned long) arg >= p->RIONumHosts)			return -EINVAL;		rio_dprintk(RIO_DEBUG_CTRL, "Clear interrupt for host %ld\n", (unsigned long) arg);		writeb(0xFF, &p->RIOHosts[(unsigned long) arg].ResetInt);		return 0;	case RIO_READ_CHECK:		/* Check reads for pkts with data[0] the same */		p->RIOReadCheck = !p->RIOReadCheck;		if (copy_to_user(arg, &p->RIOReadCheck, sizeof(unsigned int))) {			p->RIOError.Error = COPYOUT_FAILED;			return -EFAULT;		}		return 0;	case RIO_READ_REGISTER:		if (copy_from_user(&SubCmd, arg, sizeof(struct SubCmdStruct))) {			p->RIOError.Error = COPYIN_FAILED;			return -EFAULT;		}		rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER host %d rup %d port %d reg %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Port, SubCmd.Addr);		if (SubCmd.Port > 511) {			rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", SubCmd.Port);			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;			return -EINVAL;		}		if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) {			p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;			return -EINVAL;		}		if (SubCmd.Host >= p->RIONumHosts) {			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;			return -EINVAL;		}		port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort + SubCmd.Port;		PortP = p->RIOPortp[port];		rio_spin_lock_irqsave(&PortP->portSem, flags);		if (RIOPreemptiveCmd(p, PortP, READ_REGISTER) == RIO_FAIL) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER failed\n");			rio_spin_unlock_irqrestore(&PortP->portSem, flags);			return -EBUSY;		} else			PortP->State |= RIO_BUSY;		rio_spin_unlock_irqrestore(&PortP->portSem, flags);		if (copy_to_user(arg, &p->CdRegister, sizeof(unsigned int))) {			rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n");			p->RIOError.Error = COPYOUT_FAILED;			return -EFAULT;		}		return 0;		/*		 ** rio_make_dev: given port number (0-511) ORed with port type		 ** (RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT) return dev_t		 ** value to pass to mknod to create the correct device node.		 */	case RIO_MAKE_DEV:		{			unsigned int port = (unsigned long) arg & RIO_MODEM_MASK;			unsigned int ret;			switch ((unsigned long) arg & RIO_DEV_MASK) {			case RIO_DEV_DIRECT:				ret = drv_makedev(MAJOR(dev), port);				rio_dprintk(RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n", port, ret);				return ret;			case RIO_DEV_MODEM:				ret = drv_makedev(MAJOR(dev), (port | RIO_MODEM_BIT));				rio_dprintk(RIO_DEBUG_CTRL, "Makedev modem 0x%x is 0x%x\n", port, ret);				return ret;			case RIO_DEV_XPRINT:				ret = drv_makedev(MAJOR(dev), port);				rio_dprintk(RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n", port, ret);				return ret;			}			rio_dprintk(RIO_DEBUG_CTRL, "MAKE Device is called\n");			return -EINVAL;		}		/*		 ** rio_minor: given a dev_t from a stat() call, return		 ** the port number (0-511) ORed with the port type		 ** ( RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT )		 */	case RIO_MINOR:		{			dev_t dv;			int mino;			unsigned long ret;			dv = (dev_t) ((unsigned long) arg);			mino = RIO_UNMODEM(dv);			if (RIO_ISMODEM(dv)) {				rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: modem %d\n", dv, mino);				ret = mino | RIO_DEV_MODEM;			} else {				rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: direct %d\n", dv, mino);				ret = mino | RIO_DEV_DIRECT;			}			return ret;		}	}	rio_dprintk(RIO_DEBUG_CTRL, "INVALID DAEMON IOCTL 0x%x\n", cmd);	p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;	func_exit();	return -EINVAL;}/*** Pre-emptive commands go on RUPs and are only one byte long.*/int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd){	struct CmdBlk *CmdBlkP;	struct PktCmd_M *PktCmdP;	int Ret;	ushort rup;	int port;	if (PortP->State & RIO_DELETED) {		rio_dprintk(RIO_DEBUG_CTRL, "Preemptive command to deleted RTA ignored\n");		return RIO_FAIL;	}	if ((PortP->InUse == (typeof(PortP->InUse))-1) ||			!(CmdBlkP = RIOGetCmdBlk())) {		rio_dprintk(RIO_DEBUG_CTRL, "Cannot allocate command block "			"for command %d on port %d\n", Cmd, PortP->PortNum);		return RIO_FAIL;	}	rio_dprintk(RIO_DEBUG_CTRL, "Command blk %p - InUse now %d\n",			CmdBlkP, PortP->InUse);	PktCmdP = (struct PktCmd_M *)&CmdBlkP->Packet.data[0];	CmdBlkP->Packet.src_unit = 0;	if (PortP->SecondBlock)		rup = PortP->ID2;	else		rup = PortP->RupNum;	CmdBlkP->Packet.dest_unit = rup;	CmdBlkP->Packet.src_port = COMMAND_RUP;	CmdBlkP->Packet.dest_port = COMMAND_RUP;	CmdBlkP->Packet.len = PKT_CMD_BIT | 2;	CmdBlkP->PostFuncP = RIOUnUse;	CmdBlkP->PostArg = (unsigned long) PortP;	PktCmdP->Command = Cmd;	port = PortP->HostPort % (ushort) PORTS_PER_RTA;	/*	 ** Index ports 8-15 for 2nd block of 16 port RTA.	 */	if (PortP->SecondBlock)		port += (ushort) PORTS_PER_RTA;	PktCmdP->PhbNum = port;	switch (Cmd) {	case MEMDUMP:		rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk %p "				"(addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr);		PktCmdP->SubCommand = MEMDUMP;		PktCmdP->SubAddr = SubCmd.Addr;		break;	case FCLOSE:		rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk %p\n",				CmdBlkP);		break;	case READ_REGISTER:		rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) "				"command blk %p\n", (int) SubCmd.Addr, CmdBlkP);		PktCmdP->SubCommand = READ_REGISTER;		PktCmdP->SubAddr = SubCmd.Addr;		break;	case RESUME:		rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk %p\n",				CmdBlkP);		break;	case RFLUSH:		rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk %p\n",				CmdBlkP);		CmdBlkP->PostFuncP = RIORFlushEnable;		break;	case SUSPEND:		rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk %p\n",				CmdBlkP);		break;	case MGET:		rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk %p\n",				CmdBlkP);		break;	case MSET:	case MBIC:	case MBIS:		CmdBlkP->Packet.data[4] = (char) PortP->ModemLines;		rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command "				"blk %p\n", CmdBlkP);		break;	case WFLUSH:		/*		 ** If we have queued up the maximum number of Write flushes		 ** allowed then we should not bother sending any more to the		 ** RTA.		 */		if (PortP->WflushFlag == (typeof(PortP->WflushFlag))-1) {			rio_dprintk(RIO_DEBUG_CTRL, "Trashed WFLUSH, "					"WflushFlag about to wrap!");			RIOFreeCmdBlk(CmdBlkP);			return (RIO_FAIL);		} else {			rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command "					"blk %p\n", CmdBlkP);			CmdBlkP->PostFuncP = RIOWFlushMark;		}		break;	}	PortP->InUse++;	Ret = RIOQueueCmdBlk(PortP->HostP, rup, CmdBlkP);	return Ret;}

⌨️ 快捷键说明

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