blob: 732e7db5f717700e287c1cc1c93733586de2bbe1 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2** -----------------------------------------------------------------------------
3**
4** Perle Specialix driver for Linux
5** Ported from existing RIO Driver for SCO sources.
6 *
7 * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22**
23** Module : rioctrl.c
24** SID : 1.3
25** Last Modified : 11/6/98 10:33:42
26** Retrieved : 11/6/98 10:33:49
27**
28** ident @(#)rioctrl.c 1.3
29**
30** -----------------------------------------------------------------------------
31*/
32#ifdef SCCS_LABELS
33static char *_rioctrl_c_sccs_ = "@(#)rioctrl.c 1.3";
34#endif
35
36
37#include <linux/module.h>
38#include <linux/slab.h>
39#include <linux/errno.h>
40#include <asm/io.h>
41#include <asm/system.h>
42#include <asm/string.h>
43#include <asm/semaphore.h>
44#include <asm/uaccess.h>
45
46#include <linux/termios.h>
47#include <linux/serial.h>
48
49#include <linux/generic_serial.h>
50
51
52#include "linux_compat.h"
53#include "rio_linux.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070054#include "pkt.h"
55#include "daemon.h"
56#include "rio.h"
57#include "riospace.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070058#include "cmdpkt.h"
59#include "map.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070060#include "rup.h"
61#include "port.h"
62#include "riodrvr.h"
63#include "rioinfo.h"
64#include "func.h"
65#include "errors.h"
66#include "pci.h"
67
68#include "parmmap.h"
69#include "unixrup.h"
70#include "board.h"
71#include "host.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070072#include "phb.h"
73#include "link.h"
74#include "cmdblk.h"
75#include "route.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070076#include "cirrus.h"
77#include "rioioctl.h"
78
79
Andrew Morton8d8706e2006-01-11 12:17:49 -080080static struct LpbReq LpbReq;
81static struct RupReq RupReq;
82static struct PortReq PortReq;
Al Virod886cb52006-05-27 00:08:25 -040083static struct HostReq HostReq; /* oh really? global? and no locking? */
Linus Torvalds1da177e2005-04-16 15:20:36 -070084static struct HostDpRam HostDpRam;
85static struct DebugCtrl DebugCtrl;
Andrew Morton8d8706e2006-01-11 12:17:49 -080086static struct Map MapEnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -070087static struct PortSetup PortSetup;
Andrew Morton8d8706e2006-01-11 12:17:49 -080088static struct DownLoad DownLoad;
89static struct SendPack SendPack;
Linus Torvalds1da177e2005-04-16 15:20:36 -070090/* static struct StreamInfo StreamInfo; */
91/* static char modemtable[RIO_PORTS]; */
92static struct SpecialRupCmd SpecialRupCmd;
93static struct PortParams PortParams;
94static struct portStats portStats;
95
96static struct SubCmdStruct {
Andrew Morton8d8706e2006-01-11 12:17:49 -080097 ushort Host;
98 ushort Rup;
99 ushort Port;
100 ushort Addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101} SubCmd;
102
103struct PortTty {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800104 uint port;
105 struct ttystatics Tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106};
107
Andrew Morton8d8706e2006-01-11 12:17:49 -0800108static struct PortTty PortTty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109typedef struct ttystatics TERMIO;
110
111/*
112** This table is used when the config.rio downloads bin code to the
113** driver. We index the table using the product code, 0-F, and call
114** the function pointed to by the entry, passing the information
115** about the boot.
116** The RIOBootCodeUNKNOWN entry is there to politely tell the calling
117** process to bog off.
118*/
Andrew Morton8d8706e2006-01-11 12:17:49 -0800119static int
120 (*RIOBootTable[MAX_PRODUCT]) (struct rio_info *, struct DownLoad *) = {
121 /* 0 */ RIOBootCodeHOST,
122 /* Host Card */
123 /* 1 */ RIOBootCodeRTA,
124 /* RTA */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125};
126
127#define drv_makedev(maj, min) ((((uint) maj & 0xff) << 8) | ((uint) min & 0xff))
128
Al Virod886cb52006-05-27 00:08:25 -0400129int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130{
Andrew Morton8d8706e2006-01-11 12:17:49 -0800131 uint Host; /* leave me unsigned! */
132 uint port; /* and me! */
133 struct Host *HostP;
134 ushort loop;
135 int Entry;
136 struct Port *PortP;
Al Virod886cb52006-05-27 00:08:25 -0400137 struct PKT __iomem *PacketP;
Andrew Morton8d8706e2006-01-11 12:17:49 -0800138 int retval = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 unsigned long flags;
Al Virod886cb52006-05-27 00:08:25 -0400140 void __user *argp = (void __user *)arg;
Andrew Morton8d8706e2006-01-11 12:17:49 -0800141
142 func_enter();
143
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 /* Confuse the compiler to think that we've initialized these */
Andrew Morton8d8706e2006-01-11 12:17:49 -0800145 Host = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 PortP = NULL;
147
Al Virod886cb52006-05-27 00:08:25 -0400148 rio_dprintk(RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: %p\n", cmd, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
150 switch (cmd) {
151 /*
Andrew Morton8d8706e2006-01-11 12:17:49 -0800152 ** RIO_SET_TIMER
153 **
154 ** Change the value of the host card interrupt timer.
155 ** If the host card number is -1 then all host cards are changed
156 ** otherwise just the specified host card will be changed.
157 */
158 case RIO_SET_TIMER:
Al Virod886cb52006-05-27 00:08:25 -0400159 rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_TIMER to %ldms\n", arg);
Andrew Morton8d8706e2006-01-11 12:17:49 -0800160 {
161 int host, value;
Al Virod886cb52006-05-27 00:08:25 -0400162 host = (arg >> 16) & 0x0000FFFF;
163 value = arg & 0x0000ffff;
Andrew Morton8d8706e2006-01-11 12:17:49 -0800164 if (host == -1) {
165 for (host = 0; host < p->RIONumHosts; host++) {
166 if (p->RIOHosts[host].Flags == RC_RUNNING) {
Alan Cox3d336aa2006-03-24 03:18:29 -0800167 writew(value, &p->RIOHosts[host].ParmMapP->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 }
169 }
Andrew Morton8d8706e2006-01-11 12:17:49 -0800170 } else if (host >= p->RIONumHosts) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 return -EINVAL;
Andrew Morton8d8706e2006-01-11 12:17:49 -0800172 } else {
173 if (p->RIOHosts[host].Flags == RC_RUNNING) {
Alan Cox3d336aa2006-03-24 03:18:29 -0800174 writew(value, &p->RIOHosts[host].ParmMapP->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 }
Andrew Morton8d8706e2006-01-11 12:17:49 -0800176 }
177 }
178 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179
Andrew Morton8d8706e2006-01-11 12:17:49 -0800180 case RIO_FOAD_RTA:
181 rio_dprintk(RIO_DEBUG_CTRL, "RIO_FOAD_RTA\n");
Al Virod886cb52006-05-27 00:08:25 -0400182 return RIOCommandRta(p, arg, RIOFoadRta);
Andrew Morton8d8706e2006-01-11 12:17:49 -0800183
184 case RIO_ZOMBIE_RTA:
185 rio_dprintk(RIO_DEBUG_CTRL, "RIO_ZOMBIE_RTA\n");
Al Virod886cb52006-05-27 00:08:25 -0400186 return RIOCommandRta(p, arg, RIOZombieRta);
Andrew Morton8d8706e2006-01-11 12:17:49 -0800187
188 case RIO_IDENTIFY_RTA:
189 rio_dprintk(RIO_DEBUG_CTRL, "RIO_IDENTIFY_RTA\n");
Al Virod886cb52006-05-27 00:08:25 -0400190 return RIOIdentifyRta(p, argp);
Andrew Morton8d8706e2006-01-11 12:17:49 -0800191
192 case RIO_KILL_NEIGHBOUR:
193 rio_dprintk(RIO_DEBUG_CTRL, "RIO_KILL_NEIGHBOUR\n");
Al Virod886cb52006-05-27 00:08:25 -0400194 return RIOKillNeighbour(p, argp);
Andrew Morton8d8706e2006-01-11 12:17:49 -0800195
196 case SPECIAL_RUP_CMD:
197 {
198 struct CmdBlk *CmdBlkP;
199
200 rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD\n");
Al Virod886cb52006-05-27 00:08:25 -0400201 if (copy_from_user(&SpecialRupCmd, argp, sizeof(SpecialRupCmd))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800202 rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD copy failed\n");
203 p->RIOError.Error = COPYIN_FAILED;
204 return -EFAULT;
205 }
206 CmdBlkP = RIOGetCmdBlk();
207 if (!CmdBlkP) {
208 rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD GetCmdBlk failed\n");
209 return -ENXIO;
210 }
211 CmdBlkP->Packet = SpecialRupCmd.Packet;
212 if (SpecialRupCmd.Host >= p->RIONumHosts)
213 SpecialRupCmd.Host = 0;
214 rio_dprintk(RIO_DEBUG_CTRL, "Queue special rup command for host %d rup %d\n", SpecialRupCmd.Host, SpecialRupCmd.RupNum);
215 if (RIOQueueCmdBlk(&p->RIOHosts[SpecialRupCmd.Host], SpecialRupCmd.RupNum, CmdBlkP) == RIO_FAIL) {
Alan Cox3d336aa2006-03-24 03:18:29 -0800216 printk(KERN_WARNING "rio: FAILED TO QUEUE SPECIAL RUP COMMAND\n");
Andrew Morton8d8706e2006-01-11 12:17:49 -0800217 }
218 return 0;
219 }
220
221 case RIO_DEBUG_MEM:
Alan Coxf4caf162006-01-16 17:27:38 +0000222 return -EPERM;
Andrew Morton8d8706e2006-01-11 12:17:49 -0800223
224 case RIO_ALL_MODEM:
225 rio_dprintk(RIO_DEBUG_CTRL, "RIO_ALL_MODEM\n");
226 p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
227 return -EINVAL;
228
229 case RIO_GET_TABLE:
230 /*
231 ** Read the routing table from the device driver to user space
232 */
233 rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE\n");
234
235 if ((retval = RIOApel(p)) != 0)
236 return retval;
237
Al Virod886cb52006-05-27 00:08:25 -0400238 if (copy_to_user(argp, p->RIOConnectTable, TOTAL_MAP_ENTRIES * sizeof(struct Map))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800239 rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE copy failed\n");
240 p->RIOError.Error = COPYOUT_FAILED;
241 return -EFAULT;
242 }
243
244 {
245 int entry;
246 rio_dprintk(RIO_DEBUG_CTRL, "*****\nMAP ENTRIES\n");
247 for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
248 if ((p->RIOConnectTable[entry].ID == 0) && (p->RIOConnectTable[entry].HostUniqueNum == 0) && (p->RIOConnectTable[entry].RtaUniqueNum == 0))
249 continue;
250
251 rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum);
252 rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum);
253 rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID);
254 rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2);
255 rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Flags = 0x%x\n", entry, (int) p->RIOConnectTable[entry].Flags);
256 rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.SysPort = 0x%x\n", entry, (int) p->RIOConnectTable[entry].SysPort);
257 rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[0].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Unit);
258 rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[0].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Link);
259 rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[1].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Unit);
260 rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[1].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Link);
261 rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[2].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Unit);
262 rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[2].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Link);
263 rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[3].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Unit);
264 rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[4].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Link);
265 rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name);
266 }
267 rio_dprintk(RIO_DEBUG_CTRL, "*****\nEND MAP ENTRIES\n");
268 }
269 p->RIOQuickCheck = NOT_CHANGED; /* a table has been gotten */
270 return 0;
271
272 case RIO_PUT_TABLE:
273 /*
274 ** Write the routing table to the device driver from user space
275 */
276 rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE\n");
277
278 if (!su) {
279 rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE !Root\n");
280 p->RIOError.Error = NOT_SUPER_USER;
281 return -EPERM;
282 }
Al Virod886cb52006-05-27 00:08:25 -0400283 if (copy_from_user(&p->RIOConnectTable[0], argp, TOTAL_MAP_ENTRIES * sizeof(struct Map))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800284 rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE copy failed\n");
285 p->RIOError.Error = COPYIN_FAILED;
286 return -EFAULT;
287 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288/*
289***********************************
290 {
291 int entry;
292 rio_dprint(RIO_DEBUG_CTRL, ("*****\nMAP ENTRIES\n") );
293 for ( entry=0; entry<TOTAL_MAP_ENTRIES; entry++ )
294 {
295 rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum ) );
296 rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum ) );
297 rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID ) );
298 rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2 ) );
299 rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Flags = 0x%x\n", entry, p->RIOConnectTable[entry].Flags ) );
300 rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.SysPort = 0x%x\n", entry, p->RIOConnectTable[entry].SysPort ) );
301 rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[0].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Unit ) );
302 rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[0].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Link ) );
303 rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[1].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Unit ) );
304 rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[1].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Link ) );
305 rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[2].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Unit ) );
306 rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[2].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Link ) );
307 rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[3].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Unit ) );
308 rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[4].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Link ) );
309 rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name ) );
310 }
311 rio_dprint(RIO_DEBUG_CTRL, ("*****\nEND MAP ENTRIES\n") );
312 }
313***********************************
314*/
Andrew Morton8d8706e2006-01-11 12:17:49 -0800315 return RIONewTable(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316
Andrew Morton8d8706e2006-01-11 12:17:49 -0800317 case RIO_GET_BINDINGS:
318 /*
319 ** Send bindings table, containing unique numbers of RTAs owned
320 ** by this system to user space
321 */
322 rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323
Andrew Morton8d8706e2006-01-11 12:17:49 -0800324 if (!su) {
325 rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS !Root\n");
326 p->RIOError.Error = NOT_SUPER_USER;
327 return -EPERM;
328 }
Al Virod886cb52006-05-27 00:08:25 -0400329 if (copy_to_user(argp, p->RIOBindTab, (sizeof(ulong) * MAX_RTA_BINDINGS))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800330 rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS copy failed\n");
331 p->RIOError.Error = COPYOUT_FAILED;
332 return -EFAULT;
333 }
334 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335
Andrew Morton8d8706e2006-01-11 12:17:49 -0800336 case RIO_PUT_BINDINGS:
337 /*
338 ** Receive a bindings table, containing unique numbers of RTAs owned
339 ** by this system
340 */
341 rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS\n");
342
343 if (!su) {
344 rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS !Root\n");
345 p->RIOError.Error = NOT_SUPER_USER;
346 return -EPERM;
347 }
Al Virod886cb52006-05-27 00:08:25 -0400348 if (copy_from_user(&p->RIOBindTab[0], argp, (sizeof(ulong) * MAX_RTA_BINDINGS))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800349 rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS copy failed\n");
350 p->RIOError.Error = COPYIN_FAILED;
351 return -EFAULT;
352 }
353 return 0;
354
355 case RIO_BIND_RTA:
356 {
357 int EmptySlot = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 /*
Andrew Morton8d8706e2006-01-11 12:17:49 -0800359 ** Bind this RTA to host, so that it will be booted by
360 ** host in 'boot owned RTAs' mode.
361 */
362 rio_dprintk(RIO_DEBUG_CTRL, "RIO_BIND_RTA\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363
Andrew Morton8d8706e2006-01-11 12:17:49 -0800364 if (!su) {
365 rio_dprintk(RIO_DEBUG_CTRL, "RIO_BIND_RTA !Root\n");
366 p->RIOError.Error = NOT_SUPER_USER;
367 return -EPERM;
368 }
369 for (Entry = 0; Entry < MAX_RTA_BINDINGS; Entry++) {
370 if ((EmptySlot == -1) && (p->RIOBindTab[Entry] == 0L))
371 EmptySlot = Entry;
Al Virod886cb52006-05-27 00:08:25 -0400372 else if (p->RIOBindTab[Entry] == arg) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 /*
Andrew Morton8d8706e2006-01-11 12:17:49 -0800374 ** Already exists - delete
375 */
376 p->RIOBindTab[Entry] = 0L;
Al Virod886cb52006-05-27 00:08:25 -0400377 rio_dprintk(RIO_DEBUG_CTRL, "Removing Rta %ld from p->RIOBindTab\n", arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 return 0;
379 }
Andrew Morton8d8706e2006-01-11 12:17:49 -0800380 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 /*
Andrew Morton8d8706e2006-01-11 12:17:49 -0800382 ** Dosen't exist - add
383 */
384 if (EmptySlot != -1) {
Al Virod886cb52006-05-27 00:08:25 -0400385 p->RIOBindTab[EmptySlot] = arg;
386 rio_dprintk(RIO_DEBUG_CTRL, "Adding Rta %lx to p->RIOBindTab\n", arg);
Andrew Morton8d8706e2006-01-11 12:17:49 -0800387 } else {
Al Virod886cb52006-05-27 00:08:25 -0400388 rio_dprintk(RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %lx not added\n", arg);
Andrew Morton8d8706e2006-01-11 12:17:49 -0800389 return -ENOMEM;
390 }
391 return 0;
392 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393
Andrew Morton8d8706e2006-01-11 12:17:49 -0800394 case RIO_RESUME:
395 rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME\n");
Al Virod886cb52006-05-27 00:08:25 -0400396 port = arg;
Andrew Morton8d8706e2006-01-11 12:17:49 -0800397 if ((port < 0) || (port > 511)) {
398 rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Bad port number %d\n", port);
399 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
400 return -EINVAL;
401 }
402 PortP = p->RIOPortp[port];
403 if (!PortP->Mapped) {
404 rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not mapped\n", port);
405 p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
406 return -EINVAL;
407 }
408 if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
409 rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not open\n", port);
410 return -EINVAL;
411 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412
Andrew Morton8d8706e2006-01-11 12:17:49 -0800413 rio_spin_lock_irqsave(&PortP->portSem, flags);
414 if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RESUME) == RIO_FAIL) {
415 rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME failed\n");
416 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
417 return -EBUSY;
418 } else {
419 rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d resumed\n", port);
420 PortP->State |= RIO_BUSY;
421 }
422 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
423 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424
Andrew Morton8d8706e2006-01-11 12:17:49 -0800425 case RIO_ASSIGN_RTA:
426 rio_dprintk(RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA\n");
427 if (!su) {
428 rio_dprintk(RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA !Root\n");
429 p->RIOError.Error = NOT_SUPER_USER;
430 return -EPERM;
431 }
Al Virod886cb52006-05-27 00:08:25 -0400432 if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800433 rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n");
434 p->RIOError.Error = COPYIN_FAILED;
435 return -EFAULT;
436 }
437 return RIOAssignRta(p, &MapEnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438
Andrew Morton8d8706e2006-01-11 12:17:49 -0800439 case RIO_CHANGE_NAME:
440 rio_dprintk(RIO_DEBUG_CTRL, "RIO_CHANGE_NAME\n");
441 if (!su) {
442 rio_dprintk(RIO_DEBUG_CTRL, "RIO_CHANGE_NAME !Root\n");
443 p->RIOError.Error = NOT_SUPER_USER;
444 return -EPERM;
445 }
Al Virod886cb52006-05-27 00:08:25 -0400446 if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800447 rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n");
448 p->RIOError.Error = COPYIN_FAILED;
449 return -EFAULT;
450 }
451 return RIOChangeName(p, &MapEnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
Andrew Morton8d8706e2006-01-11 12:17:49 -0800453 case RIO_DELETE_RTA:
454 rio_dprintk(RIO_DEBUG_CTRL, "RIO_DELETE_RTA\n");
455 if (!su) {
456 rio_dprintk(RIO_DEBUG_CTRL, "RIO_DELETE_RTA !Root\n");
457 p->RIOError.Error = NOT_SUPER_USER;
458 return -EPERM;
459 }
Al Virod886cb52006-05-27 00:08:25 -0400460 if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800461 rio_dprintk(RIO_DEBUG_CTRL, "Copy from data space failed\n");
462 p->RIOError.Error = COPYIN_FAILED;
463 return -EFAULT;
464 }
465 return RIODeleteRta(p, &MapEnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466
Andrew Morton8d8706e2006-01-11 12:17:49 -0800467 case RIO_QUICK_CHECK:
Al Virod886cb52006-05-27 00:08:25 -0400468 if (copy_to_user(argp, &p->RIORtaDisCons, sizeof(unsigned int))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800469 p->RIOError.Error = COPYOUT_FAILED;
470 return -EFAULT;
471 }
472 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473
Andrew Morton8d8706e2006-01-11 12:17:49 -0800474 case RIO_LAST_ERROR:
Al Virod886cb52006-05-27 00:08:25 -0400475 if (copy_to_user(argp, &p->RIOError, sizeof(struct Error)))
Andrew Morton8d8706e2006-01-11 12:17:49 -0800476 return -EFAULT;
477 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
Andrew Morton8d8706e2006-01-11 12:17:49 -0800479 case RIO_GET_LOG:
480 rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_LOG\n");
Andrew Morton8d8706e2006-01-11 12:17:49 -0800481 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482
Andrew Morton8d8706e2006-01-11 12:17:49 -0800483 case RIO_GET_MODTYPE:
Al Virod886cb52006-05-27 00:08:25 -0400484 if (copy_from_user(&port, argp, sizeof(unsigned int))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800485 p->RIOError.Error = COPYIN_FAILED;
486 return -EFAULT;
487 }
488 rio_dprintk(RIO_DEBUG_CTRL, "Get module type for port %d\n", port);
489 if (port < 0 || port > 511) {
490 rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Bad port number %d\n", port);
491 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
492 return -EINVAL;
493 }
494 PortP = (p->RIOPortp[port]);
495 if (!PortP->Mapped) {
496 rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Port %d not mapped\n", port);
497 p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
498 return -EINVAL;
499 }
500 /*
501 ** Return module type of port
502 */
503 port = PortP->HostP->UnixRups[PortP->RupNum].ModTypes;
Al Virod886cb52006-05-27 00:08:25 -0400504 if (copy_to_user(argp, &port, sizeof(unsigned int))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800505 p->RIOError.Error = COPYOUT_FAILED;
506 return -EFAULT;
507 }
508 return (0);
Andrew Morton8d8706e2006-01-11 12:17:49 -0800509 case RIO_BLOCK_OPENS:
510 rio_dprintk(RIO_DEBUG_CTRL, "Opens block until booted\n");
511 for (Entry = 0; Entry < RIO_PORTS; Entry++) {
512 rio_spin_lock_irqsave(&PortP->portSem, flags);
513 p->RIOPortp[Entry]->WaitUntilBooted = 1;
514 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
515 }
516 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517
Andrew Morton8d8706e2006-01-11 12:17:49 -0800518 case RIO_SETUP_PORTS:
519 rio_dprintk(RIO_DEBUG_CTRL, "Setup ports\n");
Al Virod886cb52006-05-27 00:08:25 -0400520 if (copy_from_user(&PortSetup, argp, sizeof(PortSetup))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800521 p->RIOError.Error = COPYIN_FAILED;
522 rio_dprintk(RIO_DEBUG_CTRL, "EFAULT");
523 return -EFAULT;
524 }
525 if (PortSetup.From > PortSetup.To || PortSetup.To >= RIO_PORTS) {
526 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
527 rio_dprintk(RIO_DEBUG_CTRL, "ENXIO");
528 return -ENXIO;
529 }
530 if (PortSetup.XpCps > p->RIOConf.MaxXpCps || PortSetup.XpCps < p->RIOConf.MinXpCps) {
531 p->RIOError.Error = XPRINT_CPS_OUT_OF_RANGE;
532 rio_dprintk(RIO_DEBUG_CTRL, "EINVAL");
533 return -EINVAL;
534 }
535 if (!p->RIOPortp) {
Alan Cox3d336aa2006-03-24 03:18:29 -0800536 printk(KERN_ERR "rio: No p->RIOPortp array!\n");
Andrew Morton8d8706e2006-01-11 12:17:49 -0800537 rio_dprintk(RIO_DEBUG_CTRL, "No p->RIOPortp array!\n");
538 return -EIO;
539 }
540 rio_dprintk(RIO_DEBUG_CTRL, "entering loop (%d %d)!\n", PortSetup.From, PortSetup.To);
541 for (loop = PortSetup.From; loop <= PortSetup.To; loop++) {
542 rio_dprintk(RIO_DEBUG_CTRL, "in loop (%d)!\n", loop);
Andrew Morton8d8706e2006-01-11 12:17:49 -0800543 }
544 rio_dprintk(RIO_DEBUG_CTRL, "after loop (%d)!\n", loop);
545 rio_dprintk(RIO_DEBUG_CTRL, "Retval:%x\n", retval);
546 return retval;
547
548 case RIO_GET_PORT_SETUP:
549 rio_dprintk(RIO_DEBUG_CTRL, "Get port setup\n");
Al Virod886cb52006-05-27 00:08:25 -0400550 if (copy_from_user(&PortSetup, argp, sizeof(PortSetup))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800551 p->RIOError.Error = COPYIN_FAILED;
552 return -EFAULT;
553 }
554 if (PortSetup.From >= RIO_PORTS) {
555 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
556 return -ENXIO;
557 }
558
559 port = PortSetup.To = PortSetup.From;
560 PortSetup.IxAny = (p->RIOPortp[port]->Config & RIO_IXANY) ? 1 : 0;
561 PortSetup.IxOn = (p->RIOPortp[port]->Config & RIO_IXON) ? 1 : 0;
562 PortSetup.Drain = (p->RIOPortp[port]->Config & RIO_WAITDRAIN) ? 1 : 0;
563 PortSetup.Store = p->RIOPortp[port]->Store;
564 PortSetup.Lock = p->RIOPortp[port]->Lock;
565 PortSetup.XpCps = p->RIOPortp[port]->Xprint.XpCps;
Alan Cox554b7c82006-03-24 03:18:32 -0800566 memcpy(PortSetup.XpOn, p->RIOPortp[port]->Xprint.XpOn, MAX_XP_CTRL_LEN);
567 memcpy(PortSetup.XpOff, p->RIOPortp[port]->Xprint.XpOff, MAX_XP_CTRL_LEN);
Andrew Morton8d8706e2006-01-11 12:17:49 -0800568 PortSetup.XpOn[MAX_XP_CTRL_LEN - 1] = '\0';
569 PortSetup.XpOff[MAX_XP_CTRL_LEN - 1] = '\0';
570
Al Virod886cb52006-05-27 00:08:25 -0400571 if (copy_to_user(argp, &PortSetup, sizeof(PortSetup))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800572 p->RIOError.Error = COPYOUT_FAILED;
573 return -EFAULT;
574 }
575 return retval;
576
577 case RIO_GET_PORT_PARAMS:
578 rio_dprintk(RIO_DEBUG_CTRL, "Get port params\n");
Al Virod886cb52006-05-27 00:08:25 -0400579 if (copy_from_user(&PortParams, argp, sizeof(struct PortParams))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800580 p->RIOError.Error = COPYIN_FAILED;
581 return -EFAULT;
582 }
583 if (PortParams.Port >= RIO_PORTS) {
584 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
585 return -ENXIO;
586 }
587 PortP = (p->RIOPortp[PortParams.Port]);
588 PortParams.Config = PortP->Config;
589 PortParams.State = PortP->State;
590 rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortParams.Port);
591
Al Virod886cb52006-05-27 00:08:25 -0400592 if (copy_to_user(argp, &PortParams, sizeof(struct PortParams))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800593 p->RIOError.Error = COPYOUT_FAILED;
594 return -EFAULT;
595 }
596 return retval;
597
598 case RIO_GET_PORT_TTY:
599 rio_dprintk(RIO_DEBUG_CTRL, "Get port tty\n");
Al Virod886cb52006-05-27 00:08:25 -0400600 if (copy_from_user(&PortTty, argp, sizeof(struct PortTty))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800601 p->RIOError.Error = COPYIN_FAILED;
602 return -EFAULT;
603 }
604 if (PortTty.port >= RIO_PORTS) {
605 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
606 return -ENXIO;
607 }
608
609 rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortTty.port);
610 PortP = (p->RIOPortp[PortTty.port]);
Al Virod886cb52006-05-27 00:08:25 -0400611 if (copy_to_user(argp, &PortTty, sizeof(struct PortTty))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800612 p->RIOError.Error = COPYOUT_FAILED;
613 return -EFAULT;
614 }
615 return retval;
616
617 case RIO_SET_PORT_TTY:
Al Virod886cb52006-05-27 00:08:25 -0400618 if (copy_from_user(&PortTty, argp, sizeof(struct PortTty))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800619 p->RIOError.Error = COPYIN_FAILED;
620 return -EFAULT;
621 }
622 rio_dprintk(RIO_DEBUG_CTRL, "Set port %d tty\n", PortTty.port);
623 if (PortTty.port >= (ushort) RIO_PORTS) {
624 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
625 return -ENXIO;
626 }
627 PortP = (p->RIOPortp[PortTty.port]);
Andrew Morton8d8706e2006-01-11 12:17:49 -0800628 RIOParam(PortP, CONFIG, PortP->State & RIO_MODEM, OK_TO_SLEEP);
629 return retval;
630
631 case RIO_SET_PORT_PARAMS:
632 rio_dprintk(RIO_DEBUG_CTRL, "Set port params\n");
Al Virod886cb52006-05-27 00:08:25 -0400633 if (copy_from_user(&PortParams, argp, sizeof(PortParams))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800634 p->RIOError.Error = COPYIN_FAILED;
635 return -EFAULT;
636 }
637 if (PortParams.Port >= (ushort) RIO_PORTS) {
638 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
639 return -ENXIO;
640 }
641 PortP = (p->RIOPortp[PortParams.Port]);
642 rio_spin_lock_irqsave(&PortP->portSem, flags);
643 PortP->Config = PortParams.Config;
644 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
645 return retval;
646
647 case RIO_GET_PORT_STATS:
648 rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_PORT_STATS\n");
Al Virod886cb52006-05-27 00:08:25 -0400649 if (copy_from_user(&portStats, argp, sizeof(struct portStats))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800650 p->RIOError.Error = COPYIN_FAILED;
651 return -EFAULT;
652 }
653 if (portStats.port >= RIO_PORTS) {
654 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
655 return -ENXIO;
656 }
657 PortP = (p->RIOPortp[portStats.port]);
658 portStats.gather = PortP->statsGather;
659 portStats.txchars = PortP->txchars;
660 portStats.rxchars = PortP->rxchars;
661 portStats.opens = PortP->opens;
662 portStats.closes = PortP->closes;
663 portStats.ioctls = PortP->ioctls;
Al Virod886cb52006-05-27 00:08:25 -0400664 if (copy_to_user(argp, &portStats, sizeof(struct portStats))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800665 p->RIOError.Error = COPYOUT_FAILED;
666 return -EFAULT;
667 }
668 return retval;
669
670 case RIO_RESET_PORT_STATS:
Al Virod886cb52006-05-27 00:08:25 -0400671 port = arg;
Andrew Morton8d8706e2006-01-11 12:17:49 -0800672 rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESET_PORT_STATS\n");
673 if (port >= RIO_PORTS) {
674 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
675 return -ENXIO;
676 }
677 PortP = (p->RIOPortp[port]);
678 rio_spin_lock_irqsave(&PortP->portSem, flags);
679 PortP->txchars = 0;
680 PortP->rxchars = 0;
681 PortP->opens = 0;
682 PortP->closes = 0;
683 PortP->ioctls = 0;
684 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
685 return retval;
686
687 case RIO_GATHER_PORT_STATS:
688 rio_dprintk(RIO_DEBUG_CTRL, "RIO_GATHER_PORT_STATS\n");
Al Virod886cb52006-05-27 00:08:25 -0400689 if (copy_from_user(&portStats, argp, sizeof(struct portStats))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800690 p->RIOError.Error = COPYIN_FAILED;
691 return -EFAULT;
692 }
693 if (portStats.port >= RIO_PORTS) {
694 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
695 return -ENXIO;
696 }
697 PortP = (p->RIOPortp[portStats.port]);
698 rio_spin_lock_irqsave(&PortP->portSem, flags);
699 PortP->statsGather = portStats.gather;
700 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
701 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702
Andrew Morton8d8706e2006-01-11 12:17:49 -0800703 case RIO_READ_CONFIG:
704 rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n");
Al Virod886cb52006-05-27 00:08:25 -0400705 if (copy_to_user(argp, &p->RIOConf, sizeof(struct Conf))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800706 p->RIOError.Error = COPYOUT_FAILED;
707 return -EFAULT;
708 }
709 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
Andrew Morton8d8706e2006-01-11 12:17:49 -0800711 case RIO_SET_CONFIG:
712 rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_CONFIG\n");
713 if (!su) {
714 p->RIOError.Error = NOT_SUPER_USER;
715 return -EPERM;
716 }
Al Virod886cb52006-05-27 00:08:25 -0400717 if (copy_from_user(&p->RIOConf, argp, sizeof(struct Conf))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800718 p->RIOError.Error = COPYIN_FAILED;
719 return -EFAULT;
720 }
721 /*
722 ** move a few value around
723 */
724 for (Host = 0; Host < p->RIONumHosts; Host++)
725 if ((p->RIOHosts[Host].Flags & RUN_STATE) == RC_RUNNING)
Alan Cox3d336aa2006-03-24 03:18:29 -0800726 writew(p->RIOConf.Timer, &p->RIOHosts[Host].ParmMapP->timer);
Andrew Morton8d8706e2006-01-11 12:17:49 -0800727 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728
Andrew Morton8d8706e2006-01-11 12:17:49 -0800729 case RIO_START_POLLER:
730 rio_dprintk(RIO_DEBUG_CTRL, "RIO_START_POLLER\n");
731 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732
Andrew Morton8d8706e2006-01-11 12:17:49 -0800733 case RIO_STOP_POLLER:
734 rio_dprintk(RIO_DEBUG_CTRL, "RIO_STOP_POLLER\n");
735 if (!su) {
736 p->RIOError.Error = NOT_SUPER_USER;
737 return -EPERM;
738 }
739 p->RIOPolling = NOT_POLLING;
740 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741
Andrew Morton8d8706e2006-01-11 12:17:49 -0800742 case RIO_SETDEBUG:
743 case RIO_GETDEBUG:
744 rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG/RIO_GETDEBUG\n");
Al Virod886cb52006-05-27 00:08:25 -0400745 if (copy_from_user(&DebugCtrl, argp, sizeof(DebugCtrl))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800746 p->RIOError.Error = COPYIN_FAILED;
747 return -EFAULT;
748 }
749 if (DebugCtrl.SysPort == NO_PORT) {
750 if (cmd == RIO_SETDEBUG) {
751 if (!su) {
752 p->RIOError.Error = NOT_SUPER_USER;
753 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 }
Andrew Morton8d8706e2006-01-11 12:17:49 -0800755 p->rio_debug = DebugCtrl.Debug;
756 p->RIODebugWait = DebugCtrl.Wait;
757 rio_dprintk(RIO_DEBUG_CTRL, "Set global debug to 0x%x set wait to 0x%x\n", p->rio_debug, p->RIODebugWait);
758 } else {
759 rio_dprintk(RIO_DEBUG_CTRL, "Get global debug 0x%x wait 0x%x\n", p->rio_debug, p->RIODebugWait);
760 DebugCtrl.Debug = p->rio_debug;
761 DebugCtrl.Wait = p->RIODebugWait;
Al Virod886cb52006-05-27 00:08:25 -0400762 if (copy_to_user(argp, &DebugCtrl, sizeof(DebugCtrl))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800763 rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort);
764 p->RIOError.Error = COPYOUT_FAILED;
765 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 }
Andrew Morton8d8706e2006-01-11 12:17:49 -0800767 }
768 } else if (DebugCtrl.SysPort >= RIO_PORTS && DebugCtrl.SysPort != NO_PORT) {
769 rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort);
770 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
771 return -ENXIO;
772 } else if (cmd == RIO_SETDEBUG) {
773 if (!su) {
774 p->RIOError.Error = NOT_SUPER_USER;
775 return -EPERM;
776 }
777 rio_spin_lock_irqsave(&PortP->portSem, flags);
778 p->RIOPortp[DebugCtrl.SysPort]->Debug = DebugCtrl.Debug;
779 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
780 rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug);
781 } else {
782 rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug);
783 DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug;
Al Virod886cb52006-05-27 00:08:25 -0400784 if (copy_to_user(argp, &DebugCtrl, sizeof(DebugCtrl))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800785 rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n");
786 p->RIOError.Error = COPYOUT_FAILED;
787 return -EFAULT;
788 }
789 }
790 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
Andrew Morton8d8706e2006-01-11 12:17:49 -0800792 case RIO_VERSID:
793 /*
794 ** Enquire about the release and version.
795 ** We return MAX_VERSION_LEN bytes, being a
796 ** textual null terminated string.
797 */
798 rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID\n");
Al Virod886cb52006-05-27 00:08:25 -0400799 if (copy_to_user(argp, RIOVersid(), sizeof(struct rioVersion))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800800 rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID: Bad copy to user space (host=%d)\n", Host);
801 p->RIOError.Error = COPYOUT_FAILED;
802 return -EFAULT;
803 }
804 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805
Andrew Morton8d8706e2006-01-11 12:17:49 -0800806 case RIO_NUM_HOSTS:
807 /*
808 ** Enquire as to the number of hosts located
809 ** at init time.
810 */
811 rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n");
Al Virod886cb52006-05-27 00:08:25 -0400812 if (copy_to_user(argp, &p->RIONumHosts, sizeof(p->RIONumHosts))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800813 rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n");
814 p->RIOError.Error = COPYOUT_FAILED;
815 return -EFAULT;
816 }
817 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818
Andrew Morton8d8706e2006-01-11 12:17:49 -0800819 case RIO_HOST_FOAD:
820 /*
821 ** Kill host. This may not be in the final version...
822 */
Al Virod886cb52006-05-27 00:08:25 -0400823 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD %ld\n", arg);
Andrew Morton8d8706e2006-01-11 12:17:49 -0800824 if (!su) {
825 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n");
826 p->RIOError.Error = NOT_SUPER_USER;
827 return -EPERM;
828 }
829 p->RIOHalted = 1;
830 p->RIOSystemUp = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831
Andrew Morton8d8706e2006-01-11 12:17:49 -0800832 for (Host = 0; Host < p->RIONumHosts; Host++) {
833 (void) RIOBoardTest(p->RIOHosts[Host].PaddrP, p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type, p->RIOHosts[Host].Slot);
Alan Cox3d336aa2006-03-24 03:18:29 -0800834 memset(&p->RIOHosts[Host].Flags, 0, ((char *) &p->RIOHosts[Host].____end_marker____) - ((char *) &p->RIOHosts[Host].Flags));
Andrew Morton8d8706e2006-01-11 12:17:49 -0800835 p->RIOHosts[Host].Flags = RC_WAITING;
Andrew Morton8d8706e2006-01-11 12:17:49 -0800836 }
837 RIOFoadWakeup(p);
838 p->RIONumBootPkts = 0;
839 p->RIOBooting = 0;
Andrew Morton8d8706e2006-01-11 12:17:49 -0800840 printk("HEEEEELP!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841
Andrew Morton8d8706e2006-01-11 12:17:49 -0800842 for (loop = 0; loop < RIO_PORTS; loop++) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800843 spin_lock_init(&p->RIOPortp[loop]->portSem);
844 p->RIOPortp[loop]->InUse = NOT_INUSE;
845 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
Andrew Morton8d8706e2006-01-11 12:17:49 -0800847 p->RIOSystemUp = 0;
848 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849
Andrew Morton8d8706e2006-01-11 12:17:49 -0800850 case RIO_DOWNLOAD:
851 rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD\n");
852 if (!su) {
853 rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Not super user\n");
854 p->RIOError.Error = NOT_SUPER_USER;
855 return -EPERM;
856 }
Al Virod886cb52006-05-27 00:08:25 -0400857 if (copy_from_user(&DownLoad, argp, sizeof(DownLoad))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800858 rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n");
859 p->RIOError.Error = COPYIN_FAILED;
860 return -EFAULT;
861 }
862 rio_dprintk(RIO_DEBUG_CTRL, "Copied in download code for product code 0x%x\n", DownLoad.ProductCode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
Andrew Morton8d8706e2006-01-11 12:17:49 -0800864 /*
865 ** It is important that the product code is an unsigned object!
866 */
867 if (DownLoad.ProductCode > MAX_PRODUCT) {
868 rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Bad product code %d passed\n", DownLoad.ProductCode);
869 p->RIOError.Error = NO_SUCH_PRODUCT;
870 return -ENXIO;
871 }
872 /*
873 ** do something!
874 */
875 retval = (*(RIOBootTable[DownLoad.ProductCode])) (p, &DownLoad);
876 /* <-- Panic */
877 p->RIOHalted = 0;
878 /*
879 ** and go back, content with a job well completed.
880 */
881 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882
Andrew Morton8d8706e2006-01-11 12:17:49 -0800883 case RIO_PARMS:
884 {
Alan Cox3d336aa2006-03-24 03:18:29 -0800885 unsigned int host;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
Al Virod886cb52006-05-27 00:08:25 -0400887 if (copy_from_user(&host, argp, sizeof(host))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800888 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
889 p->RIOError.Error = COPYIN_FAILED;
890 return -EFAULT;
891 }
892 /*
893 ** Fetch the parmmap
894 */
895 rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS\n");
Al Virod886cb52006-05-27 00:08:25 -0400896 if (copy_to_user(argp, p->RIOHosts[host].ParmMapP, sizeof(PARM_MAP))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800897 p->RIOError.Error = COPYOUT_FAILED;
898 rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n");
899 return -EFAULT;
900 }
901 }
902 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903
Andrew Morton8d8706e2006-01-11 12:17:49 -0800904 case RIO_HOST_REQ:
905 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ\n");
Al Virod886cb52006-05-27 00:08:25 -0400906 if (copy_from_user(&HostReq, argp, sizeof(HostReq))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800907 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
908 p->RIOError.Error = COPYIN_FAILED;
909 return -EFAULT;
910 }
911 if (HostReq.HostNum >= p->RIONumHosts) {
912 p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
913 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Illegal host number %d\n", HostReq.HostNum);
914 return -ENXIO;
915 }
916 rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostReq.HostNum);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917
Alan Cox3d336aa2006-03-24 03:18:29 -0800918 if (copy_to_user(HostReq.HostP, &p->RIOHosts[HostReq.HostNum], sizeof(struct Host))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800919 p->RIOError.Error = COPYOUT_FAILED;
920 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Bad copy to user space\n");
921 return -EFAULT;
922 }
923 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924
Andrew Morton8d8706e2006-01-11 12:17:49 -0800925 case RIO_HOST_DPRAM:
926 rio_dprintk(RIO_DEBUG_CTRL, "Request for DPRAM\n");
Al Virod886cb52006-05-27 00:08:25 -0400927 if (copy_from_user(&HostDpRam, argp, sizeof(HostDpRam))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800928 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Copy in from user space failed\n");
929 p->RIOError.Error = COPYIN_FAILED;
930 return -EFAULT;
931 }
932 if (HostDpRam.HostNum >= p->RIONumHosts) {
933 p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
934 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Illegal host number %d\n", HostDpRam.HostNum);
935 return -ENXIO;
936 }
937 rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostDpRam.HostNum);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938
Andrew Morton8d8706e2006-01-11 12:17:49 -0800939 if (p->RIOHosts[HostDpRam.HostNum].Type == RIO_PCI) {
940 int off;
941 /* It's hardware like this that really gets on my tits. */
942 static unsigned char copy[sizeof(struct DpRam)];
943 for (off = 0; off < sizeof(struct DpRam); off++)
Al Virod886cb52006-05-27 00:08:25 -0400944 copy[off] = readb(p->RIOHosts[HostDpRam.HostNum].Caddr + off);
Alan Cox3d336aa2006-03-24 03:18:29 -0800945 if (copy_to_user(HostDpRam.DpRamP, copy, sizeof(struct DpRam))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800946 p->RIOError.Error = COPYOUT_FAILED;
947 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
948 return -EFAULT;
949 }
Alan Cox3d336aa2006-03-24 03:18:29 -0800950 } else if (copy_to_user(HostDpRam.DpRamP, p->RIOHosts[HostDpRam.HostNum].Caddr, sizeof(struct DpRam))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800951 p->RIOError.Error = COPYOUT_FAILED;
952 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
953 return -EFAULT;
954 }
955 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956
Andrew Morton8d8706e2006-01-11 12:17:49 -0800957 case RIO_SET_BUSY:
958 rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY\n");
Al Virod886cb52006-05-27 00:08:25 -0400959 if (arg > 511) {
960 rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %ld\n", arg);
Andrew Morton8d8706e2006-01-11 12:17:49 -0800961 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
962 return -EINVAL;
963 }
964 rio_spin_lock_irqsave(&PortP->portSem, flags);
Al Virod886cb52006-05-27 00:08:25 -0400965 p->RIOPortp[arg]->State |= RIO_BUSY;
Andrew Morton8d8706e2006-01-11 12:17:49 -0800966 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
967 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968
Andrew Morton8d8706e2006-01-11 12:17:49 -0800969 case RIO_HOST_PORT:
970 /*
971 ** The daemon want port information
972 ** (probably for debug reasons)
973 */
974 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT\n");
Al Virod886cb52006-05-27 00:08:25 -0400975 if (copy_from_user(&PortReq, argp, sizeof(PortReq))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800976 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Copy in from user space failed\n");
977 p->RIOError.Error = COPYIN_FAILED;
978 return -EFAULT;
979 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980
Andrew Morton8d8706e2006-01-11 12:17:49 -0800981 if (PortReq.SysPort >= RIO_PORTS) { /* SysPort is unsigned */
982 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Illegal port number %d\n", PortReq.SysPort);
983 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
984 return -ENXIO;
985 }
986 rio_dprintk(RIO_DEBUG_CTRL, "Request for port %d\n", PortReq.SysPort);
Alan Cox3d336aa2006-03-24 03:18:29 -0800987 if (copy_to_user(PortReq.PortP, p->RIOPortp[PortReq.SysPort], sizeof(struct Port))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -0800988 p->RIOError.Error = COPYOUT_FAILED;
989 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Bad copy to user space\n");
990 return -EFAULT;
991 }
992 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993
Andrew Morton8d8706e2006-01-11 12:17:49 -0800994 case RIO_HOST_RUP:
995 /*
996 ** The daemon want rup information
997 ** (probably for debug reasons)
998 */
999 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP\n");
Al Virod886cb52006-05-27 00:08:25 -04001000 if (copy_from_user(&RupReq, argp, sizeof(RupReq))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -08001001 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Copy in from user space failed\n");
1002 p->RIOError.Error = COPYIN_FAILED;
1003 return -EFAULT;
1004 }
1005 if (RupReq.HostNum >= p->RIONumHosts) { /* host is unsigned */
1006 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal host number %d\n", RupReq.HostNum);
1007 p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
1008 return -ENXIO;
1009 }
1010 if (RupReq.RupNum >= MAX_RUP + LINKS_PER_UNIT) { /* eek! */
1011 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal rup number %d\n", RupReq.RupNum);
1012 p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
1013 return -EINVAL;
1014 }
1015 HostP = &p->RIOHosts[RupReq.HostNum];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016
Andrew Morton8d8706e2006-01-11 12:17:49 -08001017 if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
1018 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Host %d not running\n", RupReq.HostNum);
1019 p->RIOError.Error = HOST_NOT_RUNNING;
1020 return -EIO;
1021 }
1022 rio_dprintk(RIO_DEBUG_CTRL, "Request for rup %d from host %d\n", RupReq.RupNum, RupReq.HostNum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023
Alan Cox3d336aa2006-03-24 03:18:29 -08001024 if (copy_to_user(HostP->UnixRups[RupReq.RupNum].RupP, RupReq.RupP, sizeof(struct RUP))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -08001025 p->RIOError.Error = COPYOUT_FAILED;
1026 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n");
1027 return -EFAULT;
1028 }
1029 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030
Andrew Morton8d8706e2006-01-11 12:17:49 -08001031 case RIO_HOST_LPB:
1032 /*
1033 ** The daemon want lpb information
1034 ** (probably for debug reasons)
1035 */
1036 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB\n");
Al Virod886cb52006-05-27 00:08:25 -04001037 if (copy_from_user(&LpbReq, argp, sizeof(LpbReq))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -08001038 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy from user space\n");
1039 p->RIOError.Error = COPYIN_FAILED;
1040 return -EFAULT;
1041 }
1042 if (LpbReq.Host >= p->RIONumHosts) { /* host is unsigned */
1043 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal host number %d\n", LpbReq.Host);
1044 p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
1045 return -ENXIO;
1046 }
1047 if (LpbReq.Link >= LINKS_PER_UNIT) { /* eek! */
1048 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal link number %d\n", LpbReq.Link);
1049 p->RIOError.Error = LINK_NUMBER_OUT_OF_RANGE;
1050 return -EINVAL;
1051 }
1052 HostP = &p->RIOHosts[LpbReq.Host];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053
Andrew Morton8d8706e2006-01-11 12:17:49 -08001054 if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
1055 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Host %d not running\n", LpbReq.Host);
1056 p->RIOError.Error = HOST_NOT_RUNNING;
1057 return -EIO;
1058 }
1059 rio_dprintk(RIO_DEBUG_CTRL, "Request for lpb %d from host %d\n", LpbReq.Link, LpbReq.Host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060
Alan Cox3d336aa2006-03-24 03:18:29 -08001061 if (copy_to_user(LpbReq.LpbP, &HostP->LinkStrP[LpbReq.Link], sizeof(struct LPB))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -08001062 rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n");
1063 p->RIOError.Error = COPYOUT_FAILED;
1064 return -EFAULT;
1065 }
1066 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
Andrew Morton8d8706e2006-01-11 12:17:49 -08001068 /*
1069 ** Here 3 IOCTL's that allow us to change the way in which
1070 ** rio logs errors. send them just to syslog or send them
1071 ** to both syslog and console or send them to just the console.
1072 **
1073 ** See RioStrBuf() in util.c for the other half.
1074 */
1075 case RIO_SYSLOG_ONLY:
1076 p->RIOPrintLogState = PRINT_TO_LOG; /* Just syslog */
1077 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078
Andrew Morton8d8706e2006-01-11 12:17:49 -08001079 case RIO_SYSLOG_CONS:
1080 p->RIOPrintLogState = PRINT_TO_LOG_CONS; /* syslog and console */
1081 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082
Andrew Morton8d8706e2006-01-11 12:17:49 -08001083 case RIO_CONS_ONLY:
1084 p->RIOPrintLogState = PRINT_TO_CONS; /* Just console */
1085 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086
Andrew Morton8d8706e2006-01-11 12:17:49 -08001087 case RIO_SIGNALS_ON:
1088 if (p->RIOSignalProcess) {
1089 p->RIOError.Error = SIGNALS_ALREADY_SET;
1090 return -EBUSY;
1091 }
Alan Cox3d336aa2006-03-24 03:18:29 -08001092 /* FIXME: PID tracking */
1093 p->RIOSignalProcess = current->pid;
Andrew Morton8d8706e2006-01-11 12:17:49 -08001094 p->RIOPrintDisabled = DONT_PRINT;
1095 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096
Andrew Morton8d8706e2006-01-11 12:17:49 -08001097 case RIO_SIGNALS_OFF:
Alan Cox3d336aa2006-03-24 03:18:29 -08001098 if (p->RIOSignalProcess != current->pid) {
Andrew Morton8d8706e2006-01-11 12:17:49 -08001099 p->RIOError.Error = NOT_RECEIVING_PROCESS;
1100 return -EPERM;
1101 }
1102 rio_dprintk(RIO_DEBUG_CTRL, "Clear signal process to zero\n");
1103 p->RIOSignalProcess = 0;
1104 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105
Andrew Morton8d8706e2006-01-11 12:17:49 -08001106 case RIO_SET_BYTE_MODE:
1107 for (Host = 0; Host < p->RIONumHosts; Host++)
1108 if (p->RIOHosts[Host].Type == RIO_AT)
1109 p->RIOHosts[Host].Mode &= ~WORD_OPERATION;
1110 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111
Andrew Morton8d8706e2006-01-11 12:17:49 -08001112 case RIO_SET_WORD_MODE:
1113 for (Host = 0; Host < p->RIONumHosts; Host++)
1114 if (p->RIOHosts[Host].Type == RIO_AT)
1115 p->RIOHosts[Host].Mode |= WORD_OPERATION;
1116 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
Andrew Morton8d8706e2006-01-11 12:17:49 -08001118 case RIO_SET_FAST_BUS:
1119 for (Host = 0; Host < p->RIONumHosts; Host++)
1120 if (p->RIOHosts[Host].Type == RIO_AT)
1121 p->RIOHosts[Host].Mode |= FAST_AT_BUS;
1122 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123
Andrew Morton8d8706e2006-01-11 12:17:49 -08001124 case RIO_SET_SLOW_BUS:
1125 for (Host = 0; Host < p->RIONumHosts; Host++)
1126 if (p->RIOHosts[Host].Type == RIO_AT)
1127 p->RIOHosts[Host].Mode &= ~FAST_AT_BUS;
1128 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129
Andrew Morton8d8706e2006-01-11 12:17:49 -08001130 case RIO_MAP_B50_TO_50:
1131 case RIO_MAP_B50_TO_57600:
1132 case RIO_MAP_B110_TO_110:
1133 case RIO_MAP_B110_TO_115200:
1134 rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping\n");
Al Virod886cb52006-05-27 00:08:25 -04001135 port = arg;
Andrew Morton8d8706e2006-01-11 12:17:49 -08001136 if (port < 0 || port > 511) {
1137 rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port);
1138 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
1139 return -EINVAL;
1140 }
1141 rio_spin_lock_irqsave(&PortP->portSem, flags);
1142 switch (cmd) {
1143 case RIO_MAP_B50_TO_50:
1144 p->RIOPortp[port]->Config |= RIO_MAP_50_TO_50;
1145 break;
1146 case RIO_MAP_B50_TO_57600:
1147 p->RIOPortp[port]->Config &= ~RIO_MAP_50_TO_50;
1148 break;
1149 case RIO_MAP_B110_TO_110:
1150 p->RIOPortp[port]->Config |= RIO_MAP_110_TO_110;
1151 break;
1152 case RIO_MAP_B110_TO_115200:
1153 p->RIOPortp[port]->Config &= ~RIO_MAP_110_TO_110;
1154 break;
1155 }
1156 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
1157 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158
Andrew Morton8d8706e2006-01-11 12:17:49 -08001159 case RIO_STREAM_INFO:
1160 rio_dprintk(RIO_DEBUG_CTRL, "RIO_STREAM_INFO\n");
1161 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162
Andrew Morton8d8706e2006-01-11 12:17:49 -08001163 case RIO_SEND_PACKET:
1164 rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n");
Al Virod886cb52006-05-27 00:08:25 -04001165 if (copy_from_user(&SendPack, argp, sizeof(SendPack))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -08001166 rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n");
1167 p->RIOError.Error = COPYIN_FAILED;
1168 return -EFAULT;
1169 }
1170 if (SendPack.PortNum >= 128) {
1171 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
1172 return -ENXIO;
1173 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
Andrew Morton8d8706e2006-01-11 12:17:49 -08001175 PortP = p->RIOPortp[SendPack.PortNum];
1176 rio_spin_lock_irqsave(&PortP->portSem, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177
Andrew Morton8d8706e2006-01-11 12:17:49 -08001178 if (!can_add_transmit(&PacketP, PortP)) {
1179 p->RIOError.Error = UNIT_IS_IN_USE;
1180 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
1181 return -ENOSPC;
1182 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183
Andrew Morton8d8706e2006-01-11 12:17:49 -08001184 for (loop = 0; loop < (ushort) (SendPack.Len & 127); loop++)
Alan Cox3d336aa2006-03-24 03:18:29 -08001185 writeb(SendPack.Data[loop], &PacketP->data[loop]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186
Alan Cox3d336aa2006-03-24 03:18:29 -08001187 writeb(SendPack.Len, &PacketP->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188
Andrew Morton8d8706e2006-01-11 12:17:49 -08001189 add_transmit(PortP);
1190 /*
1191 ** Count characters transmitted for port statistics reporting
1192 */
1193 if (PortP->statsGather)
1194 PortP->txchars += (SendPack.Len & 127);
1195 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
1196 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197
Andrew Morton8d8706e2006-01-11 12:17:49 -08001198 case RIO_NO_MESG:
1199 if (su)
1200 p->RIONoMessage = 1;
1201 return su ? 0 : -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202
Andrew Morton8d8706e2006-01-11 12:17:49 -08001203 case RIO_MESG:
1204 if (su)
1205 p->RIONoMessage = 0;
1206 return su ? 0 : -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207
Andrew Morton8d8706e2006-01-11 12:17:49 -08001208 case RIO_WHAT_MESG:
Al Virod886cb52006-05-27 00:08:25 -04001209 if (copy_to_user(argp, &p->RIONoMessage, sizeof(p->RIONoMessage))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -08001210 rio_dprintk(RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n");
1211 p->RIOError.Error = COPYOUT_FAILED;
1212 return -EFAULT;
1213 }
1214 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
Andrew Morton8d8706e2006-01-11 12:17:49 -08001216 case RIO_MEM_DUMP:
Al Virod886cb52006-05-27 00:08:25 -04001217 if (copy_from_user(&SubCmd, argp, sizeof(struct SubCmdStruct))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -08001218 p->RIOError.Error = COPYIN_FAILED;
1219 return -EFAULT;
1220 }
1221 rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP host %d rup %d addr %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222
Andrew Morton8d8706e2006-01-11 12:17:49 -08001223 if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) {
1224 p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
1225 return -EINVAL;
1226 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227
Andrew Morton8d8706e2006-01-11 12:17:49 -08001228 if (SubCmd.Host >= p->RIONumHosts) {
1229 p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
1230 return -EINVAL;
1231 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232
Andrew Morton8d8706e2006-01-11 12:17:49 -08001233 port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234
Andrew Morton8d8706e2006-01-11 12:17:49 -08001235 PortP = p->RIOPortp[port];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236
Andrew Morton8d8706e2006-01-11 12:17:49 -08001237 rio_spin_lock_irqsave(&PortP->portSem, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238
Andrew Morton8d8706e2006-01-11 12:17:49 -08001239 if (RIOPreemptiveCmd(p, PortP, MEMDUMP) == RIO_FAIL) {
1240 rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP failed\n");
1241 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
1242 return -EBUSY;
1243 } else
1244 PortP->State |= RIO_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245
Andrew Morton8d8706e2006-01-11 12:17:49 -08001246 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
Al Virod886cb52006-05-27 00:08:25 -04001247 if (copy_to_user(argp, p->RIOMemDump, MEMDUMP_SIZE)) {
Andrew Morton8d8706e2006-01-11 12:17:49 -08001248 rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n");
1249 p->RIOError.Error = COPYOUT_FAILED;
1250 return -EFAULT;
1251 }
1252 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253
Andrew Morton8d8706e2006-01-11 12:17:49 -08001254 case RIO_TICK:
Al Virod886cb52006-05-27 00:08:25 -04001255 if (arg >= p->RIONumHosts)
Andrew Morton8d8706e2006-01-11 12:17:49 -08001256 return -EINVAL;
Al Virod886cb52006-05-27 00:08:25 -04001257 rio_dprintk(RIO_DEBUG_CTRL, "Set interrupt for host %ld\n", arg);
1258 writeb(0xFF, &p->RIOHosts[arg].SetInt);
Andrew Morton8d8706e2006-01-11 12:17:49 -08001259 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260
Andrew Morton8d8706e2006-01-11 12:17:49 -08001261 case RIO_TOCK:
Al Virod886cb52006-05-27 00:08:25 -04001262 if (arg >= p->RIONumHosts)
Andrew Morton8d8706e2006-01-11 12:17:49 -08001263 return -EINVAL;
Al Virod886cb52006-05-27 00:08:25 -04001264 rio_dprintk(RIO_DEBUG_CTRL, "Clear interrupt for host %ld\n", arg);
1265 writeb(0xFF, &p->RIOHosts[arg].ResetInt);
Andrew Morton8d8706e2006-01-11 12:17:49 -08001266 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267
Andrew Morton8d8706e2006-01-11 12:17:49 -08001268 case RIO_READ_CHECK:
1269 /* Check reads for pkts with data[0] the same */
1270 p->RIOReadCheck = !p->RIOReadCheck;
Al Virod886cb52006-05-27 00:08:25 -04001271 if (copy_to_user(argp, &p->RIOReadCheck, sizeof(unsigned int))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -08001272 p->RIOError.Error = COPYOUT_FAILED;
1273 return -EFAULT;
1274 }
1275 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
Andrew Morton8d8706e2006-01-11 12:17:49 -08001277 case RIO_READ_REGISTER:
Al Virod886cb52006-05-27 00:08:25 -04001278 if (copy_from_user(&SubCmd, argp, sizeof(struct SubCmdStruct))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -08001279 p->RIOError.Error = COPYIN_FAILED;
1280 return -EFAULT;
1281 }
1282 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283
Andrew Morton8d8706e2006-01-11 12:17:49 -08001284 if (SubCmd.Port > 511) {
1285 rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", SubCmd.Port);
1286 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
1287 return -EINVAL;
1288 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289
Andrew Morton8d8706e2006-01-11 12:17:49 -08001290 if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) {
1291 p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
1292 return -EINVAL;
1293 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294
Andrew Morton8d8706e2006-01-11 12:17:49 -08001295 if (SubCmd.Host >= p->RIONumHosts) {
1296 p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
1297 return -EINVAL;
1298 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299
Andrew Morton8d8706e2006-01-11 12:17:49 -08001300 port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort + SubCmd.Port;
1301 PortP = p->RIOPortp[port];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302
Andrew Morton8d8706e2006-01-11 12:17:49 -08001303 rio_spin_lock_irqsave(&PortP->portSem, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304
Andrew Morton8d8706e2006-01-11 12:17:49 -08001305 if (RIOPreemptiveCmd(p, PortP, READ_REGISTER) == RIO_FAIL) {
1306 rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER failed\n");
1307 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
1308 return -EBUSY;
1309 } else
1310 PortP->State |= RIO_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311
Andrew Morton8d8706e2006-01-11 12:17:49 -08001312 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
Al Virod886cb52006-05-27 00:08:25 -04001313 if (copy_to_user(argp, &p->CdRegister, sizeof(unsigned int))) {
Andrew Morton8d8706e2006-01-11 12:17:49 -08001314 rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n");
1315 p->RIOError.Error = COPYOUT_FAILED;
1316 return -EFAULT;
1317 }
1318 return 0;
1319 /*
1320 ** rio_make_dev: given port number (0-511) ORed with port type
1321 ** (RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT) return dev_t
1322 ** value to pass to mknod to create the correct device node.
1323 */
1324 case RIO_MAKE_DEV:
1325 {
Al Virod886cb52006-05-27 00:08:25 -04001326 unsigned int port = arg & RIO_MODEM_MASK;
Alan Cox3d336aa2006-03-24 03:18:29 -08001327 unsigned int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328
Al Virod886cb52006-05-27 00:08:25 -04001329 switch (arg & RIO_DEV_MASK) {
Andrew Morton8d8706e2006-01-11 12:17:49 -08001330 case RIO_DEV_DIRECT:
Alan Cox3d336aa2006-03-24 03:18:29 -08001331 ret = drv_makedev(MAJOR(dev), port);
1332 rio_dprintk(RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n", port, ret);
1333 return ret;
Andrew Morton8d8706e2006-01-11 12:17:49 -08001334 case RIO_DEV_MODEM:
Alan Cox3d336aa2006-03-24 03:18:29 -08001335 ret = drv_makedev(MAJOR(dev), (port | RIO_MODEM_BIT));
1336 rio_dprintk(RIO_DEBUG_CTRL, "Makedev modem 0x%x is 0x%x\n", port, ret);
1337 return ret;
Andrew Morton8d8706e2006-01-11 12:17:49 -08001338 case RIO_DEV_XPRINT:
Alan Cox3d336aa2006-03-24 03:18:29 -08001339 ret = drv_makedev(MAJOR(dev), port);
1340 rio_dprintk(RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n", port, ret);
1341 return ret;
Andrew Morton8d8706e2006-01-11 12:17:49 -08001342 }
1343 rio_dprintk(RIO_DEBUG_CTRL, "MAKE Device is called\n");
1344 return -EINVAL;
1345 }
1346 /*
1347 ** rio_minor: given a dev_t from a stat() call, return
1348 ** the port number (0-511) ORed with the port type
1349 ** ( RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT )
1350 */
1351 case RIO_MINOR:
1352 {
1353 dev_t dv;
1354 int mino;
Alan Cox3d336aa2006-03-24 03:18:29 -08001355 unsigned long ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
Al Virod886cb52006-05-27 00:08:25 -04001357 dv = (dev_t) (arg);
Andrew Morton8d8706e2006-01-11 12:17:49 -08001358 mino = RIO_UNMODEM(dv);
1359
1360 if (RIO_ISMODEM(dv)) {
1361 rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: modem %d\n", dv, mino);
Alan Cox3d336aa2006-03-24 03:18:29 -08001362 ret = mino | RIO_DEV_MODEM;
Andrew Morton8d8706e2006-01-11 12:17:49 -08001363 } else {
1364 rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: direct %d\n", dv, mino);
Alan Cox3d336aa2006-03-24 03:18:29 -08001365 ret = mino | RIO_DEV_DIRECT;
Andrew Morton8d8706e2006-01-11 12:17:49 -08001366 }
Alan Cox3d336aa2006-03-24 03:18:29 -08001367 return ret;
Andrew Morton8d8706e2006-01-11 12:17:49 -08001368 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 }
Andrew Morton8d8706e2006-01-11 12:17:49 -08001370 rio_dprintk(RIO_DEBUG_CTRL, "INVALID DAEMON IOCTL 0x%x\n", cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
1372
Andrew Morton8d8706e2006-01-11 12:17:49 -08001373 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 return -EINVAL;
1375}
1376
1377/*
1378** Pre-emptive commands go on RUPs and are only one byte long.
1379*/
Alan Cox3d336aa2006-03-24 03:18:29 -08001380int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381{
1382 struct CmdBlk *CmdBlkP;
1383 struct PktCmd_M *PktCmdP;
1384 int Ret;
1385 ushort rup;
1386 int port;
1387
Andrew Morton8d8706e2006-01-11 12:17:49 -08001388 if (PortP->State & RIO_DELETED) {
1389 rio_dprintk(RIO_DEBUG_CTRL, "Preemptive command to deleted RTA ignored\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 return RIO_FAIL;
1391 }
1392
Alan Cox655fdea2006-05-15 09:44:26 -07001393 if ((PortP->InUse == (typeof(PortP->InUse))-1) ||
1394 !(CmdBlkP = RIOGetCmdBlk())) {
1395 rio_dprintk(RIO_DEBUG_CTRL, "Cannot allocate command block "
1396 "for command %d on port %d\n", Cmd, PortP->PortNum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 return RIO_FAIL;
1398 }
1399
Alan Cox655fdea2006-05-15 09:44:26 -07001400 rio_dprintk(RIO_DEBUG_CTRL, "Command blk %p - InUse now %d\n",
1401 CmdBlkP, PortP->InUse);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402
Alan Cox655fdea2006-05-15 09:44:26 -07001403 PktCmdP = (struct PktCmd_M *)&CmdBlkP->Packet.data[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404
Andrew Morton8d8706e2006-01-11 12:17:49 -08001405 CmdBlkP->Packet.src_unit = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 if (PortP->SecondBlock)
1407 rup = PortP->ID2;
1408 else
1409 rup = PortP->RupNum;
1410 CmdBlkP->Packet.dest_unit = rup;
Andrew Morton8d8706e2006-01-11 12:17:49 -08001411 CmdBlkP->Packet.src_port = COMMAND_RUP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 CmdBlkP->Packet.dest_port = COMMAND_RUP;
Andrew Morton8d8706e2006-01-11 12:17:49 -08001413 CmdBlkP->Packet.len = PKT_CMD_BIT | 2;
1414 CmdBlkP->PostFuncP = RIOUnUse;
Alan Cox3d336aa2006-03-24 03:18:29 -08001415 CmdBlkP->PostArg = (unsigned long) PortP;
Andrew Morton8d8706e2006-01-11 12:17:49 -08001416 PktCmdP->Command = Cmd;
1417 port = PortP->HostPort % (ushort) PORTS_PER_RTA;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 /*
Andrew Morton8d8706e2006-01-11 12:17:49 -08001419 ** Index ports 8-15 for 2nd block of 16 port RTA.
1420 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 if (PortP->SecondBlock)
1422 port += (ushort) PORTS_PER_RTA;
Andrew Morton8d8706e2006-01-11 12:17:49 -08001423 PktCmdP->PhbNum = port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424
Andrew Morton8d8706e2006-01-11 12:17:49 -08001425 switch (Cmd) {
1426 case MEMDUMP:
Alan Cox655fdea2006-05-15 09:44:26 -07001427 rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk %p "
1428 "(addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr);
Andrew Morton8d8706e2006-01-11 12:17:49 -08001429 PktCmdP->SubCommand = MEMDUMP;
1430 PktCmdP->SubAddr = SubCmd.Addr;
1431 break;
1432 case FCLOSE:
Alan Cox655fdea2006-05-15 09:44:26 -07001433 rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk %p\n",
1434 CmdBlkP);
Andrew Morton8d8706e2006-01-11 12:17:49 -08001435 break;
1436 case READ_REGISTER:
Alan Cox655fdea2006-05-15 09:44:26 -07001437 rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) "
1438 "command blk %p\n", (int) SubCmd.Addr, CmdBlkP);
Andrew Morton8d8706e2006-01-11 12:17:49 -08001439 PktCmdP->SubCommand = READ_REGISTER;
1440 PktCmdP->SubAddr = SubCmd.Addr;
1441 break;
1442 case RESUME:
Alan Cox655fdea2006-05-15 09:44:26 -07001443 rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk %p\n",
1444 CmdBlkP);
Andrew Morton8d8706e2006-01-11 12:17:49 -08001445 break;
1446 case RFLUSH:
Alan Cox655fdea2006-05-15 09:44:26 -07001447 rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk %p\n",
1448 CmdBlkP);
Andrew Morton8d8706e2006-01-11 12:17:49 -08001449 CmdBlkP->PostFuncP = RIORFlushEnable;
1450 break;
1451 case SUSPEND:
Alan Cox655fdea2006-05-15 09:44:26 -07001452 rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk %p\n",
1453 CmdBlkP);
Andrew Morton8d8706e2006-01-11 12:17:49 -08001454 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455
Andrew Morton8d8706e2006-01-11 12:17:49 -08001456 case MGET:
Alan Cox655fdea2006-05-15 09:44:26 -07001457 rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk %p\n",
1458 CmdBlkP);
Andrew Morton8d8706e2006-01-11 12:17:49 -08001459 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460
Andrew Morton8d8706e2006-01-11 12:17:49 -08001461 case MSET:
1462 case MBIC:
1463 case MBIS:
1464 CmdBlkP->Packet.data[4] = (char) PortP->ModemLines;
Alan Cox655fdea2006-05-15 09:44:26 -07001465 rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command "
1466 "blk %p\n", CmdBlkP);
Andrew Morton8d8706e2006-01-11 12:17:49 -08001467 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
Andrew Morton8d8706e2006-01-11 12:17:49 -08001469 case WFLUSH:
1470 /*
1471 ** If we have queued up the maximum number of Write flushes
1472 ** allowed then we should not bother sending any more to the
1473 ** RTA.
1474 */
Alan Cox655fdea2006-05-15 09:44:26 -07001475 if (PortP->WflushFlag == (typeof(PortP->WflushFlag))-1) {
1476 rio_dprintk(RIO_DEBUG_CTRL, "Trashed WFLUSH, "
1477 "WflushFlag about to wrap!");
Andrew Morton8d8706e2006-01-11 12:17:49 -08001478 RIOFreeCmdBlk(CmdBlkP);
1479 return (RIO_FAIL);
1480 } else {
Alan Cox655fdea2006-05-15 09:44:26 -07001481 rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command "
1482 "blk %p\n", CmdBlkP);
Andrew Morton8d8706e2006-01-11 12:17:49 -08001483 CmdBlkP->PostFuncP = RIOWFlushMark;
1484 }
1485 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 }
1487
1488 PortP->InUse++;
1489
Andrew Morton8d8706e2006-01-11 12:17:49 -08001490 Ret = RIOQueueCmdBlk(PortP->HostP, rup, CmdBlkP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491
1492 return Ret;
1493}