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 + -
显示快捷键?