diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/char/rio/rioctrl.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/char/rio/rioctrl.c')
-rw-r--r-- | drivers/char/rio/rioctrl.c | 1869 |
1 files changed, 1869 insertions, 0 deletions
diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c new file mode 100644 index 000000000000..b4d1a23e27e4 --- /dev/null +++ b/drivers/char/rio/rioctrl.c | |||
@@ -0,0 +1,1869 @@ | |||
1 | /* | ||
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 | ||
33 | static 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" | ||
54 | #include "typdef.h" | ||
55 | #include "pkt.h" | ||
56 | #include "daemon.h" | ||
57 | #include "rio.h" | ||
58 | #include "riospace.h" | ||
59 | #include "top.h" | ||
60 | #include "cmdpkt.h" | ||
61 | #include "map.h" | ||
62 | #include "riotypes.h" | ||
63 | #include "rup.h" | ||
64 | #include "port.h" | ||
65 | #include "riodrvr.h" | ||
66 | #include "rioinfo.h" | ||
67 | #include "func.h" | ||
68 | #include "errors.h" | ||
69 | #include "pci.h" | ||
70 | |||
71 | #include "parmmap.h" | ||
72 | #include "unixrup.h" | ||
73 | #include "board.h" | ||
74 | #include "host.h" | ||
75 | #include "error.h" | ||
76 | #include "phb.h" | ||
77 | #include "link.h" | ||
78 | #include "cmdblk.h" | ||
79 | #include "route.h" | ||
80 | #include "control.h" | ||
81 | #include "cirrus.h" | ||
82 | #include "rioioctl.h" | ||
83 | |||
84 | |||
85 | static struct LpbReq LpbReq; | ||
86 | static struct RupReq RupReq; | ||
87 | static struct PortReq PortReq; | ||
88 | static struct HostReq HostReq; | ||
89 | static struct HostDpRam HostDpRam; | ||
90 | static struct DebugCtrl DebugCtrl; | ||
91 | static struct Map MapEnt; | ||
92 | static struct PortSetup PortSetup; | ||
93 | static struct DownLoad DownLoad; | ||
94 | static struct SendPack SendPack; | ||
95 | /* static struct StreamInfo StreamInfo; */ | ||
96 | /* static char modemtable[RIO_PORTS]; */ | ||
97 | static struct SpecialRupCmd SpecialRupCmd; | ||
98 | static struct PortParams PortParams; | ||
99 | static struct portStats portStats; | ||
100 | |||
101 | static struct SubCmdStruct { | ||
102 | ushort Host; | ||
103 | ushort Rup; | ||
104 | ushort Port; | ||
105 | ushort Addr; | ||
106 | } SubCmd; | ||
107 | |||
108 | struct PortTty { | ||
109 | uint port; | ||
110 | struct ttystatics Tty; | ||
111 | }; | ||
112 | |||
113 | static struct PortTty PortTty; | ||
114 | typedef struct ttystatics TERMIO; | ||
115 | |||
116 | /* | ||
117 | ** This table is used when the config.rio downloads bin code to the | ||
118 | ** driver. We index the table using the product code, 0-F, and call | ||
119 | ** the function pointed to by the entry, passing the information | ||
120 | ** about the boot. | ||
121 | ** The RIOBootCodeUNKNOWN entry is there to politely tell the calling | ||
122 | ** process to bog off. | ||
123 | */ | ||
124 | static int | ||
125 | (*RIOBootTable[MAX_PRODUCT])(struct rio_info *, struct DownLoad *) = | ||
126 | { | ||
127 | /* 0 */ RIOBootCodeHOST, /* Host Card */ | ||
128 | /* 1 */ RIOBootCodeRTA, /* RTA */ | ||
129 | }; | ||
130 | |||
131 | #define drv_makedev(maj, min) ((((uint) maj & 0xff) << 8) | ((uint) min & 0xff)) | ||
132 | |||
133 | int copyin (int arg, caddr_t dp, int siz) | ||
134 | { | ||
135 | int rv; | ||
136 | |||
137 | rio_dprintk (RIO_DEBUG_CTRL, "Copying %d bytes from user %p to %p.\n", siz, (void *)arg, dp); | ||
138 | rv = copy_from_user (dp, (void *)arg, siz); | ||
139 | if (rv) return COPYFAIL; | ||
140 | else return rv; | ||
141 | } | ||
142 | |||
143 | static int copyout (caddr_t dp, int arg, int siz) | ||
144 | { | ||
145 | int rv; | ||
146 | |||
147 | rio_dprintk (RIO_DEBUG_CTRL, "Copying %d bytes to user %p from %p.\n", siz, (void *)arg, dp); | ||
148 | rv = copy_to_user ((void *)arg, dp, siz); | ||
149 | if (rv) return COPYFAIL; | ||
150 | else return rv; | ||
151 | } | ||
152 | |||
153 | int | ||
154 | riocontrol(p, dev, cmd, arg, su) | ||
155 | struct rio_info * p; | ||
156 | dev_t dev; | ||
157 | int cmd; | ||
158 | caddr_t arg; | ||
159 | int su; | ||
160 | { | ||
161 | uint Host; /* leave me unsigned! */ | ||
162 | uint port; /* and me! */ | ||
163 | struct Host *HostP; | ||
164 | ushort loop; | ||
165 | int Entry; | ||
166 | struct Port *PortP; | ||
167 | PKT *PacketP; | ||
168 | int retval = 0; | ||
169 | unsigned long flags; | ||
170 | |||
171 | func_enter (); | ||
172 | |||
173 | /* Confuse the compiler to think that we've initialized these */ | ||
174 | Host=0; | ||
175 | PortP = NULL; | ||
176 | |||
177 | rio_dprintk (RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: 0x%x\n", cmd, (int)arg); | ||
178 | |||
179 | switch (cmd) { | ||
180 | /* | ||
181 | ** RIO_SET_TIMER | ||
182 | ** | ||
183 | ** Change the value of the host card interrupt timer. | ||
184 | ** If the host card number is -1 then all host cards are changed | ||
185 | ** otherwise just the specified host card will be changed. | ||
186 | */ | ||
187 | case RIO_SET_TIMER: | ||
188 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_TIMER to %dms\n", (uint)arg); | ||
189 | { | ||
190 | int host, value; | ||
191 | host = (uint)arg >> 16; | ||
192 | value = (uint)arg & 0x0000ffff; | ||
193 | if (host == -1) { | ||
194 | for (host = 0; host < p->RIONumHosts; host++) { | ||
195 | if (p->RIOHosts[host].Flags == RC_RUNNING) { | ||
196 | WWORD(p->RIOHosts[host].ParmMapP->timer , value); | ||
197 | } | ||
198 | } | ||
199 | } else if (host >= p->RIONumHosts) { | ||
200 | return -EINVAL; | ||
201 | } else { | ||
202 | if ( p->RIOHosts[host].Flags == RC_RUNNING ) { | ||
203 | WWORD(p->RIOHosts[host].ParmMapP->timer , value); | ||
204 | } | ||
205 | } | ||
206 | } | ||
207 | return 0; | ||
208 | |||
209 | case RIO_IDENTIFY_DRIVER: | ||
210 | /* | ||
211 | ** 15.10.1998 ARG - ESIL 0760 part fix | ||
212 | ** Added driver ident string output. | ||
213 | ** | ||
214 | #ifndef __THIS_RELEASE__ | ||
215 | #warning Driver Version string not defined ! | ||
216 | #endif | ||
217 | cprintf("%s %s %s %s\n", | ||
218 | RIO_DRV_STR, | ||
219 | __THIS_RELEASE__, | ||
220 | __DATE__, __TIME__ ); | ||
221 | |||
222 | return 0; | ||
223 | |||
224 | case RIO_DISPLAY_HOST_CFG: | ||
225 | ** | ||
226 | ** 15.10.1998 ARG - ESIL 0760 part fix | ||
227 | ** Added driver host card ident string output. | ||
228 | ** | ||
229 | ** Note that the only types currently supported | ||
230 | ** are ISA and PCI. Also this driver does not | ||
231 | ** (yet) distinguish between the Old PCI card | ||
232 | ** and the Jet PCI card. In fact I think this | ||
233 | ** driver only supports JET PCI ! | ||
234 | ** | ||
235 | |||
236 | for (Host = 0; Host < p->RIONumHosts; Host++) | ||
237 | { | ||
238 | HostP = &(p->RIOHosts[Host]); | ||
239 | |||
240 | switch ( HostP->Type ) | ||
241 | { | ||
242 | case RIO_AT : | ||
243 | strcpy( host_type, RIO_AT_HOST_STR ); | ||
244 | break; | ||
245 | |||
246 | case RIO_PCI : | ||
247 | strcpy( host_type, RIO_PCI_HOST_STR ); | ||
248 | break; | ||
249 | |||
250 | default : | ||
251 | strcpy( host_type, "Unknown" ); | ||
252 | break; | ||
253 | } | ||
254 | |||
255 | cprintf( | ||
256 | "RIO Host %d - Type:%s Addr:%X IRQ:%d\n", | ||
257 | Host, host_type, | ||
258 | (uint)HostP->PaddrP, | ||
259 | (int)HostP->Ivec - 32 ); | ||
260 | } | ||
261 | return 0; | ||
262 | ** | ||
263 | */ | ||
264 | |||
265 | case RIO_FOAD_RTA: | ||
266 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_FOAD_RTA\n"); | ||
267 | return RIOCommandRta(p, (uint)arg, RIOFoadRta); | ||
268 | |||
269 | case RIO_ZOMBIE_RTA: | ||
270 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_ZOMBIE_RTA\n"); | ||
271 | return RIOCommandRta(p, (uint)arg, RIOZombieRta); | ||
272 | |||
273 | case RIO_IDENTIFY_RTA: | ||
274 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_IDENTIFY_RTA\n"); | ||
275 | return RIOIdentifyRta(p, arg); | ||
276 | |||
277 | case RIO_KILL_NEIGHBOUR: | ||
278 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_KILL_NEIGHBOUR\n"); | ||
279 | return RIOKillNeighbour(p, arg); | ||
280 | |||
281 | case SPECIAL_RUP_CMD: | ||
282 | { | ||
283 | struct CmdBlk *CmdBlkP; | ||
284 | |||
285 | rio_dprintk (RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD\n"); | ||
286 | if (copyin((int)arg, (caddr_t)&SpecialRupCmd, | ||
287 | sizeof(SpecialRupCmd)) == COPYFAIL ) { | ||
288 | rio_dprintk (RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD copy failed\n"); | ||
289 | p->RIOError.Error = COPYIN_FAILED; | ||
290 | return -EFAULT; | ||
291 | } | ||
292 | CmdBlkP = RIOGetCmdBlk(); | ||
293 | if ( !CmdBlkP ) { | ||
294 | rio_dprintk (RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD GetCmdBlk failed\n"); | ||
295 | return -ENXIO; | ||
296 | } | ||
297 | CmdBlkP->Packet = SpecialRupCmd.Packet; | ||
298 | if ( SpecialRupCmd.Host >= p->RIONumHosts ) | ||
299 | SpecialRupCmd.Host = 0; | ||
300 | rio_dprintk (RIO_DEBUG_CTRL, "Queue special rup command for host %d rup %d\n", | ||
301 | SpecialRupCmd.Host, SpecialRupCmd.RupNum); | ||
302 | if (RIOQueueCmdBlk(&p->RIOHosts[SpecialRupCmd.Host], | ||
303 | SpecialRupCmd.RupNum, CmdBlkP) == RIO_FAIL) { | ||
304 | cprintf("FAILED TO QUEUE SPECIAL RUP COMMAND\n"); | ||
305 | } | ||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | case RIO_DEBUG_MEM: | ||
310 | #ifdef DEBUG_MEM_SUPPORT | ||
311 | RIO_DEBUG_CTRL, if (su) | ||
312 | return rio_RIODebugMemory(RIO_DEBUG_CTRL, arg); | ||
313 | else | ||
314 | #endif | ||
315 | return -EPERM; | ||
316 | |||
317 | case RIO_ALL_MODEM: | ||
318 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_ALL_MODEM\n"); | ||
319 | p->RIOError.Error = IOCTL_COMMAND_UNKNOWN; | ||
320 | return -EINVAL; | ||
321 | |||
322 | case RIO_GET_TABLE: | ||
323 | /* | ||
324 | ** Read the routing table from the device driver to user space | ||
325 | */ | ||
326 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_TABLE\n"); | ||
327 | |||
328 | if ((retval = RIOApel(p)) != 0) | ||
329 | return retval; | ||
330 | |||
331 | if (copyout((caddr_t)p->RIOConnectTable, (int)arg, | ||
332 | TOTAL_MAP_ENTRIES*sizeof(struct Map)) == COPYFAIL) { | ||
333 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_TABLE copy failed\n"); | ||
334 | p->RIOError.Error = COPYOUT_FAILED; | ||
335 | return -EFAULT; | ||
336 | } | ||
337 | |||
338 | { | ||
339 | int entry; | ||
340 | rio_dprintk (RIO_DEBUG_CTRL, "*****\nMAP ENTRIES\n"); | ||
341 | for ( entry=0; entry<TOTAL_MAP_ENTRIES; entry++ ) | ||
342 | { | ||
343 | if ((p->RIOConnectTable[entry].ID == 0) && | ||
344 | (p->RIOConnectTable[entry].HostUniqueNum == 0) && | ||
345 | (p->RIOConnectTable[entry].RtaUniqueNum == 0)) continue; | ||
346 | |||
347 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum ); | ||
348 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum ); | ||
349 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID ); | ||
350 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2 ); | ||
351 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Flags = 0x%x\n", entry, (int)p->RIOConnectTable[entry].Flags ); | ||
352 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.SysPort = 0x%x\n", entry, (int)p->RIOConnectTable[entry].SysPort ); | ||
353 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[0].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Unit ); | ||
354 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[0].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Link ); | ||
355 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[1].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Unit ); | ||
356 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[1].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Link ); | ||
357 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[2].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Unit ); | ||
358 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[2].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Link ); | ||
359 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[3].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Unit ); | ||
360 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[4].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Link ); | ||
361 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name ); | ||
362 | } | ||
363 | rio_dprintk (RIO_DEBUG_CTRL, "*****\nEND MAP ENTRIES\n"); | ||
364 | } | ||
365 | p->RIOQuickCheck = NOT_CHANGED; /* a table has been gotten */ | ||
366 | return 0; | ||
367 | |||
368 | case RIO_PUT_TABLE: | ||
369 | /* | ||
370 | ** Write the routing table to the device driver from user space | ||
371 | */ | ||
372 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_TABLE\n"); | ||
373 | |||
374 | if ( !su ) { | ||
375 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_TABLE !Root\n"); | ||
376 | p->RIOError.Error = NOT_SUPER_USER; | ||
377 | return -EPERM; | ||
378 | } | ||
379 | if ( copyin((int)arg, (caddr_t)&p->RIOConnectTable[0], | ||
380 | TOTAL_MAP_ENTRIES*sizeof(struct Map) ) == COPYFAIL ) { | ||
381 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_TABLE copy failed\n"); | ||
382 | p->RIOError.Error = COPYIN_FAILED; | ||
383 | return -EFAULT; | ||
384 | } | ||
385 | /* | ||
386 | *********************************** | ||
387 | { | ||
388 | int entry; | ||
389 | rio_dprint(RIO_DEBUG_CTRL, ("*****\nMAP ENTRIES\n") ); | ||
390 | for ( entry=0; entry<TOTAL_MAP_ENTRIES; entry++ ) | ||
391 | { | ||
392 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum ) ); | ||
393 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum ) ); | ||
394 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID ) ); | ||
395 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2 ) ); | ||
396 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Flags = 0x%x\n", entry, p->RIOConnectTable[entry].Flags ) ); | ||
397 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.SysPort = 0x%x\n", entry, p->RIOConnectTable[entry].SysPort ) ); | ||
398 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[0].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Unit ) ); | ||
399 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[0].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Link ) ); | ||
400 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[1].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Unit ) ); | ||
401 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[1].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Link ) ); | ||
402 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[2].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Unit ) ); | ||
403 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[2].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Link ) ); | ||
404 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[3].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Unit ) ); | ||
405 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[4].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Link ) ); | ||
406 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name ) ); | ||
407 | } | ||
408 | rio_dprint(RIO_DEBUG_CTRL, ("*****\nEND MAP ENTRIES\n") ); | ||
409 | } | ||
410 | *********************************** | ||
411 | */ | ||
412 | return RIONewTable(p); | ||
413 | |||
414 | case RIO_GET_BINDINGS : | ||
415 | /* | ||
416 | ** Send bindings table, containing unique numbers of RTAs owned | ||
417 | ** by this system to user space | ||
418 | */ | ||
419 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_BINDINGS\n"); | ||
420 | |||
421 | if ( !su ) | ||
422 | { | ||
423 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_BINDINGS !Root\n"); | ||
424 | p->RIOError.Error = NOT_SUPER_USER; | ||
425 | return -EPERM; | ||
426 | } | ||
427 | if (copyout((caddr_t) p->RIOBindTab, (int)arg, | ||
428 | (sizeof(ulong) * MAX_RTA_BINDINGS)) == COPYFAIL ) { | ||
429 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_BINDINGS copy failed\n"); | ||
430 | p->RIOError.Error = COPYOUT_FAILED; | ||
431 | return -EFAULT; | ||
432 | } | ||
433 | return 0; | ||
434 | |||
435 | case RIO_PUT_BINDINGS : | ||
436 | /* | ||
437 | ** Receive a bindings table, containing unique numbers of RTAs owned | ||
438 | ** by this system | ||
439 | */ | ||
440 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS\n"); | ||
441 | |||
442 | if ( !su ) | ||
443 | { | ||
444 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS !Root\n"); | ||
445 | p->RIOError.Error = NOT_SUPER_USER; | ||
446 | return -EPERM; | ||
447 | } | ||
448 | if (copyin((int)arg, (caddr_t)&p->RIOBindTab[0], | ||
449 | (sizeof(ulong) * MAX_RTA_BINDINGS))==COPYFAIL ) { | ||
450 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS copy failed\n"); | ||
451 | p->RIOError.Error = COPYIN_FAILED; | ||
452 | return -EFAULT; | ||
453 | } | ||
454 | return 0; | ||
455 | |||
456 | case RIO_BIND_RTA : | ||
457 | { | ||
458 | int EmptySlot = -1; | ||
459 | /* | ||
460 | ** Bind this RTA to host, so that it will be booted by | ||
461 | ** host in 'boot owned RTAs' mode. | ||
462 | */ | ||
463 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_BIND_RTA\n"); | ||
464 | |||
465 | if ( !su ) { | ||
466 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_BIND_RTA !Root\n"); | ||
467 | p->RIOError.Error = NOT_SUPER_USER; | ||
468 | return -EPERM; | ||
469 | } | ||
470 | for (Entry = 0; Entry < MAX_RTA_BINDINGS; Entry++) { | ||
471 | if ((EmptySlot == -1) && (p->RIOBindTab[Entry] == 0L)) | ||
472 | EmptySlot = Entry; | ||
473 | else if (p->RIOBindTab[Entry] == (int) arg) { | ||
474 | /* | ||
475 | ** Already exists - delete | ||
476 | */ | ||
477 | p->RIOBindTab[Entry] = 0L; | ||
478 | rio_dprintk (RIO_DEBUG_CTRL, "Removing Rta %x from p->RIOBindTab\n", | ||
479 | (int) arg); | ||
480 | return 0; | ||
481 | } | ||
482 | } | ||
483 | /* | ||
484 | ** Dosen't exist - add | ||
485 | */ | ||
486 | if (EmptySlot != -1) { | ||
487 | p->RIOBindTab[EmptySlot] = (int) arg; | ||
488 | rio_dprintk (RIO_DEBUG_CTRL, "Adding Rta %x to p->RIOBindTab\n", | ||
489 | (int) arg); | ||
490 | } | ||
491 | else { | ||
492 | rio_dprintk (RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %x not added\n", | ||
493 | (int) arg); | ||
494 | return -ENOMEM; | ||
495 | } | ||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | case RIO_RESUME : | ||
500 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME\n"); | ||
501 | port = (uint) arg; | ||
502 | if ((port < 0) || (port > 511)) { | ||
503 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Bad port number %d\n", port); | ||
504 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
505 | return -EINVAL; | ||
506 | } | ||
507 | PortP = p->RIOPortp[port]; | ||
508 | if (!PortP->Mapped) { | ||
509 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not mapped\n", port); | ||
510 | p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM; | ||
511 | return -EINVAL; | ||
512 | } | ||
513 | if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) { | ||
514 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not open\n", port); | ||
515 | return -EINVAL; | ||
516 | } | ||
517 | |||
518 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
519 | if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RESUME) == | ||
520 | RIO_FAIL) { | ||
521 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME failed\n"); | ||
522 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
523 | return -EBUSY; | ||
524 | } | ||
525 | else { | ||
526 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Port %d resumed\n", port); | ||
527 | PortP->State |= RIO_BUSY; | ||
528 | } | ||
529 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
530 | return retval; | ||
531 | |||
532 | case RIO_ASSIGN_RTA: | ||
533 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA\n"); | ||
534 | if ( !su ) { | ||
535 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA !Root\n"); | ||
536 | p->RIOError.Error = NOT_SUPER_USER; | ||
537 | return -EPERM; | ||
538 | } | ||
539 | if (copyin((int)arg, (caddr_t)&MapEnt, sizeof(MapEnt)) | ||
540 | == COPYFAIL) { | ||
541 | rio_dprintk (RIO_DEBUG_CTRL, "Copy from user space failed\n"); | ||
542 | p->RIOError.Error = COPYIN_FAILED; | ||
543 | return -EFAULT; | ||
544 | } | ||
545 | return RIOAssignRta(p, &MapEnt); | ||
546 | |||
547 | case RIO_CHANGE_NAME: | ||
548 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_CHANGE_NAME\n"); | ||
549 | if ( !su ) { | ||
550 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_CHANGE_NAME !Root\n"); | ||
551 | p->RIOError.Error = NOT_SUPER_USER; | ||
552 | return -EPERM; | ||
553 | } | ||
554 | if (copyin((int)arg, (caddr_t)&MapEnt, sizeof(MapEnt)) | ||
555 | == COPYFAIL) { | ||
556 | rio_dprintk (RIO_DEBUG_CTRL, "Copy from user space failed\n"); | ||
557 | p->RIOError.Error = COPYIN_FAILED; | ||
558 | return -EFAULT; | ||
559 | } | ||
560 | return RIOChangeName(p, &MapEnt); | ||
561 | |||
562 | case RIO_DELETE_RTA: | ||
563 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_DELETE_RTA\n"); | ||
564 | if ( !su ) { | ||
565 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_DELETE_RTA !Root\n"); | ||
566 | p->RIOError.Error = NOT_SUPER_USER; | ||
567 | return -EPERM; | ||
568 | } | ||
569 | if (copyin((int)arg, (caddr_t)&MapEnt, sizeof(MapEnt)) | ||
570 | == COPYFAIL ) { | ||
571 | rio_dprintk (RIO_DEBUG_CTRL, "Copy from data space failed\n"); | ||
572 | p->RIOError.Error = COPYIN_FAILED; | ||
573 | return -EFAULT; | ||
574 | } | ||
575 | return RIODeleteRta(p, &MapEnt); | ||
576 | |||
577 | case RIO_QUICK_CHECK: | ||
578 | /* | ||
579 | ** 09.12.1998 ARG - ESIL 0776 part fix | ||
580 | ** A customer was using this to get the RTAs | ||
581 | ** connect/disconnect status. | ||
582 | ** RIOConCon() had been botched use RIOHalted | ||
583 | ** to keep track of RTA connections and | ||
584 | ** disconnections. That has been changed and | ||
585 | ** RIORtaDisCons in the rio_info struct now | ||
586 | ** does the job. So we need to return the value | ||
587 | ** of RIORtaCons instead of RIOHalted. | ||
588 | ** | ||
589 | if (copyout((caddr_t)&p->RIOHalted,(int)arg, | ||
590 | sizeof(uint))==COPYFAIL) { | ||
591 | ** | ||
592 | */ | ||
593 | |||
594 | if (copyout((caddr_t)&p->RIORtaDisCons,(int)arg, | ||
595 | sizeof(uint))==COPYFAIL) { | ||
596 | p->RIOError.Error = COPYOUT_FAILED; | ||
597 | return -EFAULT; | ||
598 | } | ||
599 | return 0; | ||
600 | |||
601 | case RIO_LAST_ERROR: | ||
602 | if (copyout((caddr_t)&p->RIOError, (int)arg, | ||
603 | sizeof(struct Error)) ==COPYFAIL ) | ||
604 | return -EFAULT; | ||
605 | return 0; | ||
606 | |||
607 | case RIO_GET_LOG: | ||
608 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_LOG\n"); | ||
609 | #ifdef LOGGING | ||
610 | RIOGetLog(arg); | ||
611 | return 0; | ||
612 | #else | ||
613 | return -EINVAL; | ||
614 | #endif | ||
615 | |||
616 | case RIO_GET_MODTYPE: | ||
617 | if ( copyin( (int)arg, (caddr_t)&port, | ||
618 | sizeof(uint)) == COPYFAIL ) | ||
619 | { | ||
620 | p->RIOError.Error = COPYIN_FAILED; | ||
621 | return -EFAULT; | ||
622 | } | ||
623 | rio_dprintk (RIO_DEBUG_CTRL, "Get module type for port %d\n", port); | ||
624 | if ( port < 0 || port > 511 ) | ||
625 | { | ||
626 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Bad port number %d\n", port); | ||
627 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
628 | return -EINVAL; | ||
629 | } | ||
630 | PortP = (p->RIOPortp[port]); | ||
631 | if (!PortP->Mapped) | ||
632 | { | ||
633 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Port %d not mapped\n", port); | ||
634 | p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM; | ||
635 | return -EINVAL; | ||
636 | } | ||
637 | /* | ||
638 | ** Return module type of port | ||
639 | */ | ||
640 | port = PortP->HostP->UnixRups[PortP->RupNum].ModTypes; | ||
641 | if (copyout((caddr_t)&port, (int)arg, | ||
642 | sizeof(uint)) == COPYFAIL) { | ||
643 | p->RIOError.Error = COPYOUT_FAILED; | ||
644 | return -EFAULT; | ||
645 | } | ||
646 | return(0); | ||
647 | /* | ||
648 | ** 02.03.1999 ARG - ESIL 0820 fix | ||
649 | ** We are no longer using "Boot Mode", so these ioctls | ||
650 | ** are not required : | ||
651 | ** | ||
652 | case RIO_GET_BOOT_MODE : | ||
653 | rio_dprint(RIO_DEBUG_CTRL, ("Get boot mode - %x\n", p->RIOBootMode)); | ||
654 | ** | ||
655 | ** Return boot state of system - BOOT_ALL, BOOT_OWN or BOOT_NONE | ||
656 | ** | ||
657 | if (copyout((caddr_t)&p->RIOBootMode, (int)arg, | ||
658 | sizeof(p->RIOBootMode)) == COPYFAIL) { | ||
659 | p->RIOError.Error = COPYOUT_FAILED; | ||
660 | return -EFAULT; | ||
661 | } | ||
662 | return(0); | ||
663 | |||
664 | case RIO_SET_BOOT_MODE : | ||
665 | p->RIOBootMode = (uint) arg; | ||
666 | rio_dprint(RIO_DEBUG_CTRL, ("Set boot mode to 0x%x\n", p->RIOBootMode)); | ||
667 | return(0); | ||
668 | ** | ||
669 | ** End ESIL 0820 fix | ||
670 | */ | ||
671 | |||
672 | case RIO_BLOCK_OPENS: | ||
673 | rio_dprintk (RIO_DEBUG_CTRL, "Opens block until booted\n"); | ||
674 | for ( Entry=0; Entry < RIO_PORTS; Entry++ ) { | ||
675 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
676 | p->RIOPortp[Entry]->WaitUntilBooted = 1; | ||
677 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
678 | } | ||
679 | return 0; | ||
680 | |||
681 | case RIO_SETUP_PORTS: | ||
682 | rio_dprintk (RIO_DEBUG_CTRL, "Setup ports\n"); | ||
683 | if (copyin((int)arg, (caddr_t)&PortSetup, sizeof(PortSetup)) | ||
684 | == COPYFAIL ) { | ||
685 | p->RIOError.Error = COPYIN_FAILED; | ||
686 | rio_dprintk (RIO_DEBUG_CTRL, "EFAULT"); | ||
687 | return -EFAULT; | ||
688 | } | ||
689 | if ( PortSetup.From > PortSetup.To || | ||
690 | PortSetup.To >= RIO_PORTS ) { | ||
691 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
692 | rio_dprintk (RIO_DEBUG_CTRL, "ENXIO"); | ||
693 | return -ENXIO; | ||
694 | } | ||
695 | if ( PortSetup.XpCps > p->RIOConf.MaxXpCps || | ||
696 | PortSetup.XpCps < p->RIOConf.MinXpCps ) { | ||
697 | p->RIOError.Error = XPRINT_CPS_OUT_OF_RANGE; | ||
698 | rio_dprintk (RIO_DEBUG_CTRL, "EINVAL"); | ||
699 | return -EINVAL; | ||
700 | } | ||
701 | if ( !p->RIOPortp ) { | ||
702 | cprintf("No p->RIOPortp array!\n"); | ||
703 | rio_dprintk (RIO_DEBUG_CTRL, "No p->RIOPortp array!\n"); | ||
704 | return -EIO; | ||
705 | } | ||
706 | rio_dprintk (RIO_DEBUG_CTRL, "entering loop (%d %d)!\n", PortSetup.From, PortSetup.To); | ||
707 | for (loop=PortSetup.From; loop<=PortSetup.To; loop++) { | ||
708 | rio_dprintk (RIO_DEBUG_CTRL, "in loop (%d)!\n", loop); | ||
709 | #if 0 | ||
710 | PortP = p->RIOPortp[loop]; | ||
711 | if ( !PortP->TtyP ) | ||
712 | PortP->TtyP = &p->channel[loop]; | ||
713 | |||
714 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
715 | if ( PortSetup.IxAny ) | ||
716 | PortP->Config |= RIO_IXANY; | ||
717 | else | ||
718 | PortP->Config &= ~RIO_IXANY; | ||
719 | if ( PortSetup.IxOn ) | ||
720 | PortP->Config |= RIO_IXON; | ||
721 | else | ||
722 | PortP->Config &= ~RIO_IXON; | ||
723 | |||
724 | /* | ||
725 | ** If the port needs to wait for all a processes output | ||
726 | ** to drain before closing then this flag will be set. | ||
727 | */ | ||
728 | if (PortSetup.Drain) { | ||
729 | PortP->Config |= RIO_WAITDRAIN; | ||
730 | } else { | ||
731 | PortP->Config &= ~RIO_WAITDRAIN; | ||
732 | } | ||
733 | /* | ||
734 | ** Store settings if locking or unlocking port or if the | ||
735 | ** port is not locked, when setting the store option. | ||
736 | */ | ||
737 | if (PortP->Mapped && | ||
738 | ((PortSetup.Lock && !PortP->Lock) || | ||
739 | (!PortP->Lock && | ||
740 | (PortSetup.Store && !PortP->Store)))) { | ||
741 | PortP->StoredTty.iflag = PortP->TtyP->tm.c_iflag; | ||
742 | PortP->StoredTty.oflag = PortP->TtyP->tm.c_oflag; | ||
743 | PortP->StoredTty.cflag = PortP->TtyP->tm.c_cflag; | ||
744 | PortP->StoredTty.lflag = PortP->TtyP->tm.c_lflag; | ||
745 | PortP->StoredTty.line = PortP->TtyP->tm.c_line; | ||
746 | bcopy(PortP->TtyP->tm.c_cc, PortP->StoredTty.cc, | ||
747 | NCC + 5); | ||
748 | } | ||
749 | PortP->Lock = PortSetup.Lock; | ||
750 | PortP->Store = PortSetup.Store; | ||
751 | PortP->Xprint.XpCps = PortSetup.XpCps; | ||
752 | bcopy(PortSetup.XpOn,PortP->Xprint.XpOn,MAX_XP_CTRL_LEN); | ||
753 | bcopy(PortSetup.XpOff,PortP->Xprint.XpOff,MAX_XP_CTRL_LEN); | ||
754 | PortP->Xprint.XpOn[MAX_XP_CTRL_LEN-1] = '\0'; | ||
755 | PortP->Xprint.XpOff[MAX_XP_CTRL_LEN-1] = '\0'; | ||
756 | PortP->Xprint.XpLen = RIOStrlen(PortP->Xprint.XpOn)+ | ||
757 | RIOStrlen(PortP->Xprint.XpOff); | ||
758 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
759 | #endif | ||
760 | } | ||
761 | rio_dprintk (RIO_DEBUG_CTRL, "after loop (%d)!\n", loop); | ||
762 | rio_dprintk (RIO_DEBUG_CTRL, "Retval:%x\n", retval); | ||
763 | return retval; | ||
764 | |||
765 | case RIO_GET_PORT_SETUP : | ||
766 | rio_dprintk (RIO_DEBUG_CTRL, "Get port setup\n"); | ||
767 | if (copyin((int)arg, (caddr_t)&PortSetup, sizeof(PortSetup)) | ||
768 | == COPYFAIL ) { | ||
769 | p->RIOError.Error = COPYIN_FAILED; | ||
770 | return -EFAULT; | ||
771 | } | ||
772 | if ( PortSetup.From >= RIO_PORTS ) { | ||
773 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
774 | return -ENXIO; | ||
775 | } | ||
776 | |||
777 | port = PortSetup.To = PortSetup.From; | ||
778 | PortSetup.IxAny = (p->RIOPortp[port]->Config & RIO_IXANY) ? | ||
779 | 1 : 0; | ||
780 | PortSetup.IxOn = (p->RIOPortp[port]->Config & RIO_IXON) ? | ||
781 | 1 : 0; | ||
782 | PortSetup.Drain = (p->RIOPortp[port]->Config & RIO_WAITDRAIN) ? | ||
783 | 1 : 0; | ||
784 | PortSetup.Store = p->RIOPortp[port]->Store; | ||
785 | PortSetup.Lock = p->RIOPortp[port]->Lock; | ||
786 | PortSetup.XpCps = p->RIOPortp[port]->Xprint.XpCps; | ||
787 | bcopy(p->RIOPortp[port]->Xprint.XpOn, PortSetup.XpOn, | ||
788 | MAX_XP_CTRL_LEN); | ||
789 | bcopy(p->RIOPortp[port]->Xprint.XpOff, PortSetup.XpOff, | ||
790 | MAX_XP_CTRL_LEN); | ||
791 | PortSetup.XpOn[MAX_XP_CTRL_LEN-1] = '\0'; | ||
792 | PortSetup.XpOff[MAX_XP_CTRL_LEN-1] = '\0'; | ||
793 | |||
794 | if ( copyout((caddr_t)&PortSetup,(int)arg,sizeof(PortSetup)) | ||
795 | ==COPYFAIL ) { | ||
796 | p->RIOError.Error = COPYOUT_FAILED; | ||
797 | return -EFAULT; | ||
798 | } | ||
799 | return retval; | ||
800 | |||
801 | case RIO_GET_PORT_PARAMS : | ||
802 | rio_dprintk (RIO_DEBUG_CTRL, "Get port params\n"); | ||
803 | if (copyin( (int)arg, (caddr_t)&PortParams, | ||
804 | sizeof(struct PortParams)) == COPYFAIL) { | ||
805 | p->RIOError.Error = COPYIN_FAILED; | ||
806 | return -EFAULT; | ||
807 | } | ||
808 | if (PortParams.Port >= RIO_PORTS) { | ||
809 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
810 | return -ENXIO; | ||
811 | } | ||
812 | PortP = (p->RIOPortp[PortParams.Port]); | ||
813 | PortParams.Config = PortP->Config; | ||
814 | PortParams.State = PortP->State; | ||
815 | rio_dprintk (RIO_DEBUG_CTRL, "Port %d\n", PortParams.Port); | ||
816 | |||
817 | if (copyout((caddr_t)&PortParams, (int)arg, | ||
818 | sizeof(struct PortParams)) == COPYFAIL ) { | ||
819 | p->RIOError.Error = COPYOUT_FAILED; | ||
820 | return -EFAULT; | ||
821 | } | ||
822 | return retval; | ||
823 | |||
824 | case RIO_GET_PORT_TTY : | ||
825 | rio_dprintk (RIO_DEBUG_CTRL, "Get port tty\n"); | ||
826 | if (copyin((int)arg, (caddr_t)&PortTty, sizeof(struct PortTty)) | ||
827 | == COPYFAIL) { | ||
828 | p->RIOError.Error = COPYIN_FAILED; | ||
829 | return -EFAULT; | ||
830 | } | ||
831 | if ( PortTty.port >= RIO_PORTS ) { | ||
832 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
833 | return -ENXIO; | ||
834 | } | ||
835 | |||
836 | rio_dprintk (RIO_DEBUG_CTRL, "Port %d\n", PortTty.port); | ||
837 | PortP = (p->RIOPortp[PortTty.port]); | ||
838 | #if 0 | ||
839 | PortTty.Tty.tm.c_iflag = PortP->TtyP->tm.c_iflag; | ||
840 | PortTty.Tty.tm.c_oflag = PortP->TtyP->tm.c_oflag; | ||
841 | PortTty.Tty.tm.c_cflag = PortP->TtyP->tm.c_cflag; | ||
842 | PortTty.Tty.tm.c_lflag = PortP->TtyP->tm.c_lflag; | ||
843 | #endif | ||
844 | if (copyout((caddr_t)&PortTty, (int)arg, | ||
845 | sizeof(struct PortTty)) == COPYFAIL) { | ||
846 | p->RIOError.Error = COPYOUT_FAILED; | ||
847 | return -EFAULT; | ||
848 | } | ||
849 | return retval; | ||
850 | |||
851 | case RIO_SET_PORT_TTY : | ||
852 | if (copyin((int)arg, (caddr_t)&PortTty, | ||
853 | sizeof(struct PortTty)) == COPYFAIL) { | ||
854 | p->RIOError.Error = COPYIN_FAILED; | ||
855 | return -EFAULT; | ||
856 | } | ||
857 | rio_dprintk (RIO_DEBUG_CTRL, "Set port %d tty\n", PortTty.port); | ||
858 | if (PortTty.port >= (ushort) RIO_PORTS) { | ||
859 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
860 | return -ENXIO; | ||
861 | } | ||
862 | PortP = (p->RIOPortp[PortTty.port]); | ||
863 | #if 0 | ||
864 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
865 | PortP->TtyP->tm.c_iflag = PortTty.Tty.tm.c_iflag; | ||
866 | PortP->TtyP->tm.c_oflag = PortTty.Tty.tm.c_oflag; | ||
867 | PortP->TtyP->tm.c_cflag = PortTty.Tty.tm.c_cflag; | ||
868 | PortP->TtyP->tm.c_lflag = PortTty.Tty.tm.c_lflag; | ||
869 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
870 | #endif | ||
871 | |||
872 | RIOParam(PortP, CONFIG, PortP->State & RIO_MODEM, OK_TO_SLEEP); | ||
873 | return retval; | ||
874 | |||
875 | case RIO_SET_PORT_PARAMS : | ||
876 | rio_dprintk (RIO_DEBUG_CTRL, "Set port params\n"); | ||
877 | if ( copyin((int)arg, (caddr_t)&PortParams, sizeof(PortParams)) | ||
878 | == COPYFAIL ) { | ||
879 | p->RIOError.Error = COPYIN_FAILED; | ||
880 | return -EFAULT; | ||
881 | } | ||
882 | if (PortParams.Port >= (ushort) RIO_PORTS) { | ||
883 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
884 | return -ENXIO; | ||
885 | } | ||
886 | PortP = (p->RIOPortp[PortParams.Port]); | ||
887 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
888 | PortP->Config = PortParams.Config; | ||
889 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
890 | return retval; | ||
891 | |||
892 | case RIO_GET_PORT_STATS : | ||
893 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_PORT_STATS\n"); | ||
894 | if ( copyin((int)arg, (caddr_t)&portStats, | ||
895 | sizeof(struct portStats)) == COPYFAIL ) { | ||
896 | p->RIOError.Error = COPYIN_FAILED; | ||
897 | return -EFAULT; | ||
898 | } | ||
899 | if ( portStats.port >= RIO_PORTS ) { | ||
900 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
901 | return -ENXIO; | ||
902 | } | ||
903 | PortP = (p->RIOPortp[portStats.port]); | ||
904 | portStats.gather = PortP->statsGather; | ||
905 | portStats.txchars = PortP->txchars; | ||
906 | portStats.rxchars = PortP->rxchars; | ||
907 | portStats.opens = PortP->opens; | ||
908 | portStats.closes = PortP->closes; | ||
909 | portStats.ioctls = PortP->ioctls; | ||
910 | if ( copyout((caddr_t)&portStats, (int)arg, | ||
911 | sizeof(struct portStats)) == COPYFAIL ) { | ||
912 | p->RIOError.Error = COPYOUT_FAILED; | ||
913 | return -EFAULT; | ||
914 | } | ||
915 | return retval; | ||
916 | |||
917 | case RIO_RESET_PORT_STATS : | ||
918 | port = (uint) arg; | ||
919 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESET_PORT_STATS\n"); | ||
920 | if ( port >= RIO_PORTS ) { | ||
921 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
922 | return -ENXIO; | ||
923 | } | ||
924 | PortP = (p->RIOPortp[port]); | ||
925 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
926 | PortP->txchars = 0; | ||
927 | PortP->rxchars = 0; | ||
928 | PortP->opens = 0; | ||
929 | PortP->closes = 0; | ||
930 | PortP->ioctls = 0; | ||
931 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
932 | return retval; | ||
933 | |||
934 | case RIO_GATHER_PORT_STATS : | ||
935 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GATHER_PORT_STATS\n"); | ||
936 | if ( copyin( (int)arg, (caddr_t)&portStats, | ||
937 | sizeof(struct portStats)) == COPYFAIL ) { | ||
938 | p->RIOError.Error = COPYIN_FAILED; | ||
939 | return -EFAULT; | ||
940 | } | ||
941 | if ( portStats.port >= RIO_PORTS ) { | ||
942 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
943 | return -ENXIO; | ||
944 | } | ||
945 | PortP = (p->RIOPortp[portStats.port]); | ||
946 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
947 | PortP->statsGather = portStats.gather; | ||
948 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
949 | return retval; | ||
950 | |||
951 | #ifdef DEBUG_SUPPORTED | ||
952 | case RIO_READ_LEVELS: | ||
953 | { | ||
954 | int num; | ||
955 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_LEVELS\n"); | ||
956 | for ( num=0; RIODbInf[num].Flag; num++ ) ; | ||
957 | rio_dprintk (RIO_DEBUG_CTRL, "%d levels to copy\n",num); | ||
958 | if (copyout((caddr_t)RIODbInf,(int)arg, | ||
959 | sizeof(struct DbInf)*(num+1))==COPYFAIL) { | ||
960 | rio_dprintk (RIO_DEBUG_CTRL, "ReadLevels Copy failed\n"); | ||
961 | p->RIOError.Error = COPYOUT_FAILED; | ||
962 | return -EFAULT; | ||
963 | } | ||
964 | rio_dprintk (RIO_DEBUG_CTRL, "%d levels to copied\n",num); | ||
965 | return retval; | ||
966 | } | ||
967 | #endif | ||
968 | |||
969 | case RIO_READ_CONFIG: | ||
970 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n"); | ||
971 | if (copyout((caddr_t)&p->RIOConf, (int)arg, | ||
972 | sizeof(struct Conf)) ==COPYFAIL ) { | ||
973 | p->RIOError.Error = COPYOUT_FAILED; | ||
974 | return -EFAULT; | ||
975 | } | ||
976 | return retval; | ||
977 | |||
978 | case RIO_SET_CONFIG: | ||
979 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_CONFIG\n"); | ||
980 | if ( !su ) { | ||
981 | p->RIOError.Error = NOT_SUPER_USER; | ||
982 | return -EPERM; | ||
983 | } | ||
984 | if ( copyin((int)arg, (caddr_t)&p->RIOConf, sizeof(struct Conf) ) | ||
985 | ==COPYFAIL ) { | ||
986 | p->RIOError.Error = COPYIN_FAILED; | ||
987 | return -EFAULT; | ||
988 | } | ||
989 | /* | ||
990 | ** move a few value around | ||
991 | */ | ||
992 | for (Host=0; Host < p->RIONumHosts; Host++) | ||
993 | if ( (p->RIOHosts[Host].Flags & RUN_STATE) == RC_RUNNING ) | ||
994 | WWORD(p->RIOHosts[Host].ParmMapP->timer , | ||
995 | p->RIOConf.Timer); | ||
996 | return retval; | ||
997 | |||
998 | case RIO_START_POLLER: | ||
999 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_START_POLLER\n"); | ||
1000 | return -EINVAL; | ||
1001 | |||
1002 | case RIO_STOP_POLLER: | ||
1003 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_STOP_POLLER\n"); | ||
1004 | if ( !su ) { | ||
1005 | p->RIOError.Error = NOT_SUPER_USER; | ||
1006 | return -EPERM; | ||
1007 | } | ||
1008 | p->RIOPolling = NOT_POLLING; | ||
1009 | return retval; | ||
1010 | |||
1011 | case RIO_SETDEBUG: | ||
1012 | case RIO_GETDEBUG: | ||
1013 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SETDEBUG/RIO_GETDEBUG\n"); | ||
1014 | if ( copyin( (int)arg, (caddr_t)&DebugCtrl, sizeof(DebugCtrl) ) | ||
1015 | ==COPYFAIL ) { | ||
1016 | p->RIOError.Error = COPYIN_FAILED; | ||
1017 | return -EFAULT; | ||
1018 | } | ||
1019 | if ( DebugCtrl.SysPort == NO_PORT ) { | ||
1020 | if ( cmd == RIO_SETDEBUG ) { | ||
1021 | if ( !su ) { | ||
1022 | p->RIOError.Error = NOT_SUPER_USER; | ||
1023 | return -EPERM; | ||
1024 | } | ||
1025 | p->rio_debug = DebugCtrl.Debug; | ||
1026 | p->RIODebugWait = DebugCtrl.Wait; | ||
1027 | rio_dprintk (RIO_DEBUG_CTRL, "Set global debug to 0x%x set wait to 0x%x\n", | ||
1028 | p->rio_debug,p->RIODebugWait); | ||
1029 | } | ||
1030 | else { | ||
1031 | rio_dprintk (RIO_DEBUG_CTRL, "Get global debug 0x%x wait 0x%x\n", | ||
1032 | p->rio_debug,p->RIODebugWait); | ||
1033 | DebugCtrl.Debug = p->rio_debug; | ||
1034 | DebugCtrl.Wait = p->RIODebugWait; | ||
1035 | if ( copyout((caddr_t)&DebugCtrl,(int)arg, | ||
1036 | sizeof(DebugCtrl)) == COPYFAIL ) { | ||
1037 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", | ||
1038 | DebugCtrl.SysPort); | ||
1039 | p->RIOError.Error = COPYOUT_FAILED; | ||
1040 | return -EFAULT; | ||
1041 | } | ||
1042 | } | ||
1043 | } | ||
1044 | else if ( DebugCtrl.SysPort >= RIO_PORTS && | ||
1045 | DebugCtrl.SysPort != NO_PORT ) { | ||
1046 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", | ||
1047 | DebugCtrl.SysPort); | ||
1048 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
1049 | return -ENXIO; | ||
1050 | } | ||
1051 | else if ( cmd == RIO_SETDEBUG ) { | ||
1052 | if ( !su ) { | ||
1053 | p->RIOError.Error = NOT_SUPER_USER; | ||
1054 | return -EPERM; | ||
1055 | } | ||
1056 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
1057 | p->RIOPortp[DebugCtrl.SysPort]->Debug = DebugCtrl.Debug; | ||
1058 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
1059 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SETDEBUG 0x%x\n", | ||
1060 | p->RIOPortp[DebugCtrl.SysPort]->Debug); | ||
1061 | } | ||
1062 | else { | ||
1063 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GETDEBUG 0x%x\n", | ||
1064 | p->RIOPortp[DebugCtrl.SysPort]->Debug); | ||
1065 | DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug; | ||
1066 | if ( copyout((caddr_t)&DebugCtrl,(int)arg, | ||
1067 | sizeof(DebugCtrl))==COPYFAIL ) { | ||
1068 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n"); | ||
1069 | p->RIOError.Error = COPYOUT_FAILED; | ||
1070 | return -EFAULT; | ||
1071 | } | ||
1072 | } | ||
1073 | return retval; | ||
1074 | |||
1075 | case RIO_VERSID: | ||
1076 | /* | ||
1077 | ** Enquire about the release and version. | ||
1078 | ** We return MAX_VERSION_LEN bytes, being a | ||
1079 | ** textual null terminated string. | ||
1080 | */ | ||
1081 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_VERSID\n"); | ||
1082 | if ( copyout( (caddr_t)RIOVersid(), | ||
1083 | (int)arg, | ||
1084 | sizeof(struct rioVersion) ) == COPYFAIL ) | ||
1085 | { | ||
1086 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_VERSID: Bad copy to user space (host=%d)\n", Host); | ||
1087 | p->RIOError.Error = COPYOUT_FAILED; | ||
1088 | return -EFAULT; | ||
1089 | } | ||
1090 | return retval; | ||
1091 | |||
1092 | /* | ||
1093 | ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
1094 | ** !! commented out previous 'RIO_VERSID' functionality !! | ||
1095 | ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
1096 | ** | ||
1097 | case RIO_VERSID: | ||
1098 | ** | ||
1099 | ** Enquire about the release and version. | ||
1100 | ** We return MAX_VERSION_LEN bytes, being a textual null | ||
1101 | ** terminated string. | ||
1102 | ** | ||
1103 | rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID\n")); | ||
1104 | if (copyout((caddr_t)RIOVersid(), | ||
1105 | (int)arg, MAX_VERSION_LEN ) == COPYFAIL ) { | ||
1106 | rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID: Bad copy to user space\n",Host)); | ||
1107 | p->RIOError.Error = COPYOUT_FAILED; | ||
1108 | return -EFAULT; | ||
1109 | } | ||
1110 | return retval; | ||
1111 | ** | ||
1112 | ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
1113 | */ | ||
1114 | |||
1115 | case RIO_NUM_HOSTS: | ||
1116 | /* | ||
1117 | ** Enquire as to the number of hosts located | ||
1118 | ** at init time. | ||
1119 | */ | ||
1120 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n"); | ||
1121 | if (copyout((caddr_t)&p->RIONumHosts, (int)arg, | ||
1122 | sizeof(p->RIONumHosts) )==COPYFAIL ) { | ||
1123 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n"); | ||
1124 | p->RIOError.Error = COPYOUT_FAILED; | ||
1125 | return -EFAULT; | ||
1126 | } | ||
1127 | return retval; | ||
1128 | |||
1129 | case RIO_HOST_FOAD: | ||
1130 | /* | ||
1131 | ** Kill host. This may not be in the final version... | ||
1132 | */ | ||
1133 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_FOAD %d\n", (int)arg); | ||
1134 | if ( !su ) { | ||
1135 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n"); | ||
1136 | p->RIOError.Error = NOT_SUPER_USER; | ||
1137 | return -EPERM; | ||
1138 | } | ||
1139 | p->RIOHalted = 1; | ||
1140 | p->RIOSystemUp = 0; | ||
1141 | |||
1142 | for ( Host=0; Host<p->RIONumHosts; Host++ ) { | ||
1143 | (void)RIOBoardTest( p->RIOHosts[Host].PaddrP, | ||
1144 | p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type, | ||
1145 | p->RIOHosts[Host].Slot ); | ||
1146 | bzero( (caddr_t)&p->RIOHosts[Host].Flags, | ||
1147 | ((int)&p->RIOHosts[Host].____end_marker____) - | ||
1148 | ((int)&p->RIOHosts[Host].Flags) ); | ||
1149 | p->RIOHosts[Host].Flags = RC_WAITING; | ||
1150 | #if 0 | ||
1151 | RIOSetupDataStructs(p); | ||
1152 | #endif | ||
1153 | } | ||
1154 | RIOFoadWakeup(p); | ||
1155 | p->RIONumBootPkts = 0; | ||
1156 | p->RIOBooting = 0; | ||
1157 | |||
1158 | #ifdef RINGBUFFER_SUPPORT | ||
1159 | for( loop=0; loop<RIO_PORTS; loop++ ) | ||
1160 | if ( p->RIOPortp[loop]->TxRingBuffer ) | ||
1161 | sysfree((void *)p->RIOPortp[loop]->TxRingBuffer, | ||
1162 | RIOBufferSize ); | ||
1163 | #endif | ||
1164 | #if 0 | ||
1165 | bzero((caddr_t)&p->RIOPortp[0],RIO_PORTS*sizeof(struct Port)); | ||
1166 | #else | ||
1167 | printk ("HEEEEELP!\n"); | ||
1168 | #endif | ||
1169 | |||
1170 | for( loop=0; loop<RIO_PORTS; loop++ ) { | ||
1171 | #if 0 | ||
1172 | p->RIOPortp[loop]->TtyP = &p->channel[loop]; | ||
1173 | #endif | ||
1174 | |||
1175 | spin_lock_init(&p->RIOPortp[loop]->portSem); | ||
1176 | p->RIOPortp[loop]->InUse = NOT_INUSE; | ||
1177 | } | ||
1178 | |||
1179 | p->RIOSystemUp = 0; | ||
1180 | return retval; | ||
1181 | |||
1182 | case RIO_DOWNLOAD: | ||
1183 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD\n"); | ||
1184 | if ( !su ) { | ||
1185 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Not super user\n"); | ||
1186 | p->RIOError.Error = NOT_SUPER_USER; | ||
1187 | return -EPERM; | ||
1188 | } | ||
1189 | if ( copyin((int)arg, (caddr_t)&DownLoad, | ||
1190 | sizeof(DownLoad) )==COPYFAIL ) { | ||
1191 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n"); | ||
1192 | p->RIOError.Error = COPYIN_FAILED; | ||
1193 | return -EFAULT; | ||
1194 | } | ||
1195 | rio_dprintk (RIO_DEBUG_CTRL, "Copied in download code for product code 0x%x\n", | ||
1196 | DownLoad.ProductCode); | ||
1197 | |||
1198 | /* | ||
1199 | ** It is important that the product code is an unsigned object! | ||
1200 | */ | ||
1201 | if ( DownLoad.ProductCode > MAX_PRODUCT ) { | ||
1202 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Bad product code %d passed\n", | ||
1203 | DownLoad.ProductCode); | ||
1204 | p->RIOError.Error = NO_SUCH_PRODUCT; | ||
1205 | return -ENXIO; | ||
1206 | } | ||
1207 | /* | ||
1208 | ** do something! | ||
1209 | */ | ||
1210 | retval = (*(RIOBootTable[DownLoad.ProductCode]))(p, &DownLoad); | ||
1211 | /* <-- Panic */ | ||
1212 | p->RIOHalted = 0; | ||
1213 | /* | ||
1214 | ** and go back, content with a job well completed. | ||
1215 | */ | ||
1216 | return retval; | ||
1217 | |||
1218 | case RIO_PARMS: | ||
1219 | { | ||
1220 | uint host; | ||
1221 | |||
1222 | if (copyin((int)arg, (caddr_t)&host, | ||
1223 | sizeof(host) ) == COPYFAIL ) { | ||
1224 | rio_dprintk (RIO_DEBUG_CTRL, | ||
1225 | "RIO_HOST_REQ: Copy in from user space failed\n"); | ||
1226 | p->RIOError.Error = COPYIN_FAILED; | ||
1227 | return -EFAULT; | ||
1228 | } | ||
1229 | /* | ||
1230 | ** Fetch the parmmap | ||
1231 | */ | ||
1232 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_PARMS\n"); | ||
1233 | if ( copyout( (caddr_t)p->RIOHosts[host].ParmMapP, | ||
1234 | (int)arg, sizeof(PARM_MAP) )==COPYFAIL ) { | ||
1235 | p->RIOError.Error = COPYOUT_FAILED; | ||
1236 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n"); | ||
1237 | return -EFAULT; | ||
1238 | } | ||
1239 | } | ||
1240 | return retval; | ||
1241 | |||
1242 | case RIO_HOST_REQ: | ||
1243 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ\n"); | ||
1244 | if (copyin((int)arg, (caddr_t)&HostReq, | ||
1245 | sizeof(HostReq) )==COPYFAIL ) { | ||
1246 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n"); | ||
1247 | p->RIOError.Error = COPYIN_FAILED; | ||
1248 | return -EFAULT; | ||
1249 | } | ||
1250 | if ( HostReq.HostNum >= p->RIONumHosts ) { | ||
1251 | p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; | ||
1252 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ: Illegal host number %d\n", | ||
1253 | HostReq.HostNum); | ||
1254 | return -ENXIO; | ||
1255 | } | ||
1256 | rio_dprintk (RIO_DEBUG_CTRL, "Request for host %d\n", HostReq.HostNum); | ||
1257 | |||
1258 | if (copyout((caddr_t)&p->RIOHosts[HostReq.HostNum], | ||
1259 | (int)HostReq.HostP,sizeof(struct Host) ) == COPYFAIL) { | ||
1260 | p->RIOError.Error = COPYOUT_FAILED; | ||
1261 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ: Bad copy to user space\n"); | ||
1262 | return -EFAULT; | ||
1263 | } | ||
1264 | return retval; | ||
1265 | |||
1266 | case RIO_HOST_DPRAM: | ||
1267 | rio_dprintk (RIO_DEBUG_CTRL, "Request for DPRAM\n"); | ||
1268 | if ( copyin( (int)arg, (caddr_t)&HostDpRam, | ||
1269 | sizeof(HostDpRam) )==COPYFAIL ) { | ||
1270 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Copy in from user space failed\n"); | ||
1271 | p->RIOError.Error = COPYIN_FAILED; | ||
1272 | return -EFAULT; | ||
1273 | } | ||
1274 | if ( HostDpRam.HostNum >= p->RIONumHosts ) { | ||
1275 | p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; | ||
1276 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Illegal host number %d\n", | ||
1277 | HostDpRam.HostNum); | ||
1278 | return -ENXIO; | ||
1279 | } | ||
1280 | rio_dprintk (RIO_DEBUG_CTRL, "Request for host %d\n", HostDpRam.HostNum); | ||
1281 | |||
1282 | if (p->RIOHosts[HostDpRam.HostNum].Type == RIO_PCI) { | ||
1283 | int off; | ||
1284 | /* It's hardware like this that really gets on my tits. */ | ||
1285 | static unsigned char copy[sizeof(struct DpRam)]; | ||
1286 | for ( off=0; off<sizeof(struct DpRam); off++ ) | ||
1287 | copy[off] = p->RIOHosts[HostDpRam.HostNum].Caddr[off]; | ||
1288 | if ( copyout( (caddr_t)copy, (int)HostDpRam.DpRamP, | ||
1289 | sizeof(struct DpRam) ) == COPYFAIL ) { | ||
1290 | p->RIOError.Error = COPYOUT_FAILED; | ||
1291 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n"); | ||
1292 | return -EFAULT; | ||
1293 | } | ||
1294 | } | ||
1295 | else if (copyout((caddr_t)p->RIOHosts[HostDpRam.HostNum].Caddr, | ||
1296 | (int)HostDpRam.DpRamP, | ||
1297 | sizeof(struct DpRam) ) == COPYFAIL ) { | ||
1298 | p->RIOError.Error = COPYOUT_FAILED; | ||
1299 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n"); | ||
1300 | return -EFAULT; | ||
1301 | } | ||
1302 | return retval; | ||
1303 | |||
1304 | case RIO_SET_BUSY: | ||
1305 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_BUSY\n"); | ||
1306 | if ( (int)arg < 0 || (int)arg > 511 ) { | ||
1307 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %d\n",(int)arg); | ||
1308 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
1309 | return -EINVAL; | ||
1310 | } | ||
1311 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
1312 | p->RIOPortp[(int)arg]->State |= RIO_BUSY; | ||
1313 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
1314 | return retval; | ||
1315 | |||
1316 | case RIO_HOST_PORT: | ||
1317 | /* | ||
1318 | ** The daemon want port information | ||
1319 | ** (probably for debug reasons) | ||
1320 | */ | ||
1321 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT\n"); | ||
1322 | if ( copyin((int)arg, (caddr_t)&PortReq, | ||
1323 | sizeof(PortReq) )==COPYFAIL ) { | ||
1324 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT: Copy in from user space failed\n"); | ||
1325 | p->RIOError.Error = COPYIN_FAILED; | ||
1326 | return -EFAULT; | ||
1327 | } | ||
1328 | |||
1329 | if (PortReq.SysPort >= RIO_PORTS) { /* SysPort is unsigned */ | ||
1330 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT: Illegal port number %d\n", | ||
1331 | PortReq.SysPort); | ||
1332 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
1333 | return -ENXIO; | ||
1334 | } | ||
1335 | rio_dprintk (RIO_DEBUG_CTRL, "Request for port %d\n", PortReq.SysPort); | ||
1336 | if (copyout((caddr_t)p->RIOPortp[PortReq.SysPort], | ||
1337 | (int)PortReq.PortP, | ||
1338 | sizeof(struct Port) ) == COPYFAIL) { | ||
1339 | p->RIOError.Error = COPYOUT_FAILED; | ||
1340 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT: Bad copy to user space\n"); | ||
1341 | return -EFAULT; | ||
1342 | } | ||
1343 | return retval; | ||
1344 | |||
1345 | case RIO_HOST_RUP: | ||
1346 | /* | ||
1347 | ** The daemon want rup information | ||
1348 | ** (probably for debug reasons) | ||
1349 | */ | ||
1350 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP\n"); | ||
1351 | if (copyin((int)arg, (caddr_t)&RupReq, | ||
1352 | sizeof(RupReq) )==COPYFAIL ) { | ||
1353 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Copy in from user space failed\n"); | ||
1354 | p->RIOError.Error = COPYIN_FAILED; | ||
1355 | return -EFAULT; | ||
1356 | } | ||
1357 | if (RupReq.HostNum >= p->RIONumHosts) { /* host is unsigned */ | ||
1358 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal host number %d\n", | ||
1359 | RupReq.HostNum); | ||
1360 | p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; | ||
1361 | return -ENXIO; | ||
1362 | } | ||
1363 | if ( RupReq.RupNum >= MAX_RUP+LINKS_PER_UNIT ) { /* eek! */ | ||
1364 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal rup number %d\n", | ||
1365 | RupReq.RupNum); | ||
1366 | p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE; | ||
1367 | return -EINVAL; | ||
1368 | } | ||
1369 | HostP = &p->RIOHosts[RupReq.HostNum]; | ||
1370 | |||
1371 | if ((HostP->Flags & RUN_STATE) != RC_RUNNING) { | ||
1372 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Host %d not running\n", | ||
1373 | RupReq.HostNum); | ||
1374 | p->RIOError.Error = HOST_NOT_RUNNING; | ||
1375 | return -EIO; | ||
1376 | } | ||
1377 | rio_dprintk (RIO_DEBUG_CTRL, "Request for rup %d from host %d\n", | ||
1378 | RupReq.RupNum,RupReq.HostNum); | ||
1379 | |||
1380 | if (copyout((caddr_t)HostP->UnixRups[RupReq.RupNum].RupP, | ||
1381 | (int)RupReq.RupP,sizeof(struct RUP) ) == COPYFAIL) { | ||
1382 | p->RIOError.Error = COPYOUT_FAILED; | ||
1383 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n"); | ||
1384 | return -EFAULT; | ||
1385 | } | ||
1386 | return retval; | ||
1387 | |||
1388 | case RIO_HOST_LPB: | ||
1389 | /* | ||
1390 | ** The daemon want lpb information | ||
1391 | ** (probably for debug reasons) | ||
1392 | */ | ||
1393 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB\n"); | ||
1394 | if (copyin((int)arg, (caddr_t)&LpbReq, | ||
1395 | sizeof(LpbReq) )==COPYFAIL ) { | ||
1396 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy from user space\n"); | ||
1397 | p->RIOError.Error = COPYIN_FAILED; | ||
1398 | return -EFAULT; | ||
1399 | } | ||
1400 | if (LpbReq.Host >= p->RIONumHosts) { /* host is unsigned */ | ||
1401 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal host number %d\n", | ||
1402 | LpbReq.Host); | ||
1403 | p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; | ||
1404 | return -ENXIO; | ||
1405 | } | ||
1406 | if ( LpbReq.Link >= LINKS_PER_UNIT ) { /* eek! */ | ||
1407 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal link number %d\n", | ||
1408 | LpbReq.Link); | ||
1409 | p->RIOError.Error = LINK_NUMBER_OUT_OF_RANGE; | ||
1410 | return -EINVAL; | ||
1411 | } | ||
1412 | HostP = &p->RIOHosts[LpbReq.Host]; | ||
1413 | |||
1414 | if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) { | ||
1415 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Host %d not running\n", | ||
1416 | LpbReq.Host ); | ||
1417 | p->RIOError.Error = HOST_NOT_RUNNING; | ||
1418 | return -EIO; | ||
1419 | } | ||
1420 | rio_dprintk (RIO_DEBUG_CTRL, "Request for lpb %d from host %d\n", | ||
1421 | LpbReq.Link, LpbReq.Host); | ||
1422 | |||
1423 | if (copyout((caddr_t)&HostP->LinkStrP[LpbReq.Link], | ||
1424 | (int)LpbReq.LpbP,sizeof(struct LPB) ) == COPYFAIL) { | ||
1425 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n"); | ||
1426 | p->RIOError.Error = COPYOUT_FAILED; | ||
1427 | return -EFAULT; | ||
1428 | } | ||
1429 | return retval; | ||
1430 | |||
1431 | /* | ||
1432 | ** Here 3 IOCTL's that allow us to change the way in which | ||
1433 | ** rio logs errors. send them just to syslog or send them | ||
1434 | ** to both syslog and console or send them to just the console. | ||
1435 | ** | ||
1436 | ** See RioStrBuf() in util.c for the other half. | ||
1437 | */ | ||
1438 | case RIO_SYSLOG_ONLY: | ||
1439 | p->RIOPrintLogState = PRINT_TO_LOG; /* Just syslog */ | ||
1440 | return 0; | ||
1441 | |||
1442 | case RIO_SYSLOG_CONS: | ||
1443 | p->RIOPrintLogState = PRINT_TO_LOG_CONS;/* syslog and console */ | ||
1444 | return 0; | ||
1445 | |||
1446 | case RIO_CONS_ONLY: | ||
1447 | p->RIOPrintLogState = PRINT_TO_CONS; /* Just console */ | ||
1448 | return 0; | ||
1449 | |||
1450 | case RIO_SIGNALS_ON: | ||
1451 | if ( p->RIOSignalProcess ) { | ||
1452 | p->RIOError.Error = SIGNALS_ALREADY_SET; | ||
1453 | return -EBUSY; | ||
1454 | } | ||
1455 | p->RIOSignalProcess = getpid(); | ||
1456 | p->RIOPrintDisabled = DONT_PRINT; | ||
1457 | return retval; | ||
1458 | |||
1459 | case RIO_SIGNALS_OFF: | ||
1460 | if ( p->RIOSignalProcess != getpid() ) { | ||
1461 | p->RIOError.Error = NOT_RECEIVING_PROCESS; | ||
1462 | return -EPERM; | ||
1463 | } | ||
1464 | rio_dprintk (RIO_DEBUG_CTRL, "Clear signal process to zero\n"); | ||
1465 | p->RIOSignalProcess = 0; | ||
1466 | return retval; | ||
1467 | |||
1468 | case RIO_SET_BYTE_MODE: | ||
1469 | for ( Host=0; Host<p->RIONumHosts; Host++ ) | ||
1470 | if ( p->RIOHosts[Host].Type == RIO_AT ) | ||
1471 | p->RIOHosts[Host].Mode &= ~WORD_OPERATION; | ||
1472 | return retval; | ||
1473 | |||
1474 | case RIO_SET_WORD_MODE: | ||
1475 | for ( Host=0; Host<p->RIONumHosts; Host++ ) | ||
1476 | if ( p->RIOHosts[Host].Type == RIO_AT ) | ||
1477 | p->RIOHosts[Host].Mode |= WORD_OPERATION; | ||
1478 | return retval; | ||
1479 | |||
1480 | case RIO_SET_FAST_BUS: | ||
1481 | for ( Host=0; Host<p->RIONumHosts; Host++ ) | ||
1482 | if ( p->RIOHosts[Host].Type == RIO_AT ) | ||
1483 | p->RIOHosts[Host].Mode |= FAST_AT_BUS; | ||
1484 | return retval; | ||
1485 | |||
1486 | case RIO_SET_SLOW_BUS: | ||
1487 | for ( Host=0; Host<p->RIONumHosts; Host++ ) | ||
1488 | if ( p->RIOHosts[Host].Type == RIO_AT ) | ||
1489 | p->RIOHosts[Host].Mode &= ~FAST_AT_BUS; | ||
1490 | return retval; | ||
1491 | |||
1492 | case RIO_MAP_B50_TO_50: | ||
1493 | case RIO_MAP_B50_TO_57600: | ||
1494 | case RIO_MAP_B110_TO_110: | ||
1495 | case RIO_MAP_B110_TO_115200: | ||
1496 | rio_dprintk (RIO_DEBUG_CTRL, "Baud rate mapping\n"); | ||
1497 | port = (uint) arg; | ||
1498 | if ( port < 0 || port > 511 ) { | ||
1499 | rio_dprintk (RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port); | ||
1500 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
1501 | return -EINVAL; | ||
1502 | } | ||
1503 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
1504 | switch( cmd ) | ||
1505 | { | ||
1506 | case RIO_MAP_B50_TO_50 : | ||
1507 | p->RIOPortp[port]->Config |= RIO_MAP_50_TO_50; | ||
1508 | break; | ||
1509 | case RIO_MAP_B50_TO_57600 : | ||
1510 | p->RIOPortp[port]->Config &= ~RIO_MAP_50_TO_50; | ||
1511 | break; | ||
1512 | case RIO_MAP_B110_TO_110 : | ||
1513 | p->RIOPortp[port]->Config |= RIO_MAP_110_TO_110; | ||
1514 | break; | ||
1515 | case RIO_MAP_B110_TO_115200 : | ||
1516 | p->RIOPortp[port]->Config &= ~RIO_MAP_110_TO_110; | ||
1517 | break; | ||
1518 | } | ||
1519 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
1520 | return retval; | ||
1521 | |||
1522 | case RIO_STREAM_INFO: | ||
1523 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_STREAM_INFO\n"); | ||
1524 | return -EINVAL; | ||
1525 | |||
1526 | case RIO_SEND_PACKET: | ||
1527 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n"); | ||
1528 | if ( copyin( (int)arg, (caddr_t)&SendPack, | ||
1529 | sizeof(SendPack) )==COPYFAIL ) { | ||
1530 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n"); | ||
1531 | p->RIOError.Error = COPYIN_FAILED; | ||
1532 | return -EFAULT; | ||
1533 | } | ||
1534 | if ( SendPack.PortNum >= 128 ) { | ||
1535 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
1536 | return -ENXIO; | ||
1537 | } | ||
1538 | |||
1539 | PortP = p->RIOPortp[SendPack.PortNum]; | ||
1540 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
1541 | |||
1542 | if ( !can_add_transmit(&PacketP,PortP) ) { | ||
1543 | p->RIOError.Error = UNIT_IS_IN_USE; | ||
1544 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
1545 | return -ENOSPC; | ||
1546 | } | ||
1547 | |||
1548 | for ( loop=0; loop<(ushort)(SendPack.Len & 127); loop++ ) | ||
1549 | WBYTE(PacketP->data[loop], SendPack.Data[loop] ); | ||
1550 | |||
1551 | WBYTE(PacketP->len, SendPack.Len); | ||
1552 | |||
1553 | add_transmit( PortP ); | ||
1554 | /* | ||
1555 | ** Count characters transmitted for port statistics reporting | ||
1556 | */ | ||
1557 | if (PortP->statsGather) | ||
1558 | PortP->txchars += (SendPack.Len & 127); | ||
1559 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
1560 | return retval; | ||
1561 | |||
1562 | case RIO_NO_MESG: | ||
1563 | if ( su ) | ||
1564 | p->RIONoMessage = 1; | ||
1565 | return su ? 0 : -EPERM; | ||
1566 | |||
1567 | case RIO_MESG: | ||
1568 | if ( su ) | ||
1569 | p->RIONoMessage = 0; | ||
1570 | return su ? 0 : -EPERM; | ||
1571 | |||
1572 | case RIO_WHAT_MESG: | ||
1573 | if ( copyout( (caddr_t)&p->RIONoMessage, (int)arg, | ||
1574 | sizeof(p->RIONoMessage) )==COPYFAIL ) { | ||
1575 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n"); | ||
1576 | p->RIOError.Error = COPYOUT_FAILED; | ||
1577 | return -EFAULT; | ||
1578 | } | ||
1579 | return 0; | ||
1580 | |||
1581 | case RIO_MEM_DUMP : | ||
1582 | if (copyin((int)arg, (caddr_t)&SubCmd, | ||
1583 | sizeof(struct SubCmdStruct)) == COPYFAIL) { | ||
1584 | p->RIOError.Error = COPYIN_FAILED; | ||
1585 | return -EFAULT; | ||
1586 | } | ||
1587 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_MEM_DUMP host %d rup %d addr %x\n", | ||
1588 | SubCmd.Host, SubCmd.Rup, SubCmd.Addr); | ||
1589 | |||
1590 | if (SubCmd.Rup >= MAX_RUP+LINKS_PER_UNIT ) { | ||
1591 | p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE; | ||
1592 | return -EINVAL; | ||
1593 | } | ||
1594 | |||
1595 | if (SubCmd.Host >= p->RIONumHosts ) { | ||
1596 | p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; | ||
1597 | return -EINVAL; | ||
1598 | } | ||
1599 | |||
1600 | port = p->RIOHosts[SubCmd.Host]. | ||
1601 | UnixRups[SubCmd.Rup].BaseSysPort; | ||
1602 | |||
1603 | PortP = p->RIOPortp[port]; | ||
1604 | |||
1605 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
1606 | |||
1607 | if ( RIOPreemptiveCmd(p, PortP, MEMDUMP ) == RIO_FAIL ) { | ||
1608 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_MEM_DUMP failed\n"); | ||
1609 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
1610 | return -EBUSY; | ||
1611 | } | ||
1612 | else | ||
1613 | PortP->State |= RIO_BUSY; | ||
1614 | |||
1615 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
1616 | if ( copyout( (caddr_t)p->RIOMemDump, (int)arg, | ||
1617 | MEMDUMP_SIZE) == COPYFAIL ) { | ||
1618 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n"); | ||
1619 | p->RIOError.Error = COPYOUT_FAILED; | ||
1620 | return -EFAULT; | ||
1621 | } | ||
1622 | return 0; | ||
1623 | |||
1624 | case RIO_TICK: | ||
1625 | if ((int)arg < 0 || (int)arg >= p->RIONumHosts) | ||
1626 | return -EINVAL; | ||
1627 | rio_dprintk (RIO_DEBUG_CTRL, "Set interrupt for host %d\n", (int)arg); | ||
1628 | WBYTE(p->RIOHosts[(int)arg].SetInt , 0xff); | ||
1629 | return 0; | ||
1630 | |||
1631 | case RIO_TOCK: | ||
1632 | if ((int)arg < 0 || (int)arg >= p->RIONumHosts) | ||
1633 | return -EINVAL; | ||
1634 | rio_dprintk (RIO_DEBUG_CTRL, "Clear interrupt for host %d\n", (int)arg); | ||
1635 | WBYTE((p->RIOHosts[(int)arg].ResetInt) , 0xff); | ||
1636 | return 0; | ||
1637 | |||
1638 | case RIO_READ_CHECK: | ||
1639 | /* Check reads for pkts with data[0] the same */ | ||
1640 | p->RIOReadCheck = !p->RIOReadCheck; | ||
1641 | if (copyout((caddr_t)&p->RIOReadCheck,(int)arg, | ||
1642 | sizeof(uint))== COPYFAIL) { | ||
1643 | p->RIOError.Error = COPYOUT_FAILED; | ||
1644 | return -EFAULT; | ||
1645 | } | ||
1646 | return 0; | ||
1647 | |||
1648 | case RIO_READ_REGISTER : | ||
1649 | if (copyin((int)arg, (caddr_t)&SubCmd, | ||
1650 | sizeof(struct SubCmdStruct)) == COPYFAIL) { | ||
1651 | p->RIOError.Error = COPYIN_FAILED; | ||
1652 | return -EFAULT; | ||
1653 | } | ||
1654 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_REGISTER host %d rup %d port %d reg %x\n", | ||
1655 | SubCmd.Host, SubCmd.Rup, SubCmd.Port, SubCmd.Addr); | ||
1656 | |||
1657 | if (SubCmd.Port > 511) { | ||
1658 | rio_dprintk (RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", | ||
1659 | SubCmd.Port); | ||
1660 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
1661 | return -EINVAL; | ||
1662 | } | ||
1663 | |||
1664 | if (SubCmd.Rup >= MAX_RUP+LINKS_PER_UNIT ) { | ||
1665 | p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE; | ||
1666 | return -EINVAL; | ||
1667 | } | ||
1668 | |||
1669 | if (SubCmd.Host >= p->RIONumHosts ) { | ||
1670 | p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; | ||
1671 | return -EINVAL; | ||
1672 | } | ||
1673 | |||
1674 | port = p->RIOHosts[SubCmd.Host]. | ||
1675 | UnixRups[SubCmd.Rup].BaseSysPort + SubCmd.Port; | ||
1676 | PortP = p->RIOPortp[port]; | ||
1677 | |||
1678 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
1679 | |||
1680 | if (RIOPreemptiveCmd(p, PortP, READ_REGISTER) == RIO_FAIL) { | ||
1681 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_REGISTER failed\n"); | ||
1682 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
1683 | return -EBUSY; | ||
1684 | } | ||
1685 | else | ||
1686 | PortP->State |= RIO_BUSY; | ||
1687 | |||
1688 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
1689 | if (copyout((caddr_t)&p->CdRegister, (int)arg, | ||
1690 | sizeof(uint)) == COPYFAIL ) { | ||
1691 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n"); | ||
1692 | p->RIOError.Error = COPYOUT_FAILED; | ||
1693 | return -EFAULT; | ||
1694 | } | ||
1695 | return 0; | ||
1696 | /* | ||
1697 | ** rio_make_dev: given port number (0-511) ORed with port type | ||
1698 | ** (RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT) return dev_t | ||
1699 | ** value to pass to mknod to create the correct device node. | ||
1700 | */ | ||
1701 | case RIO_MAKE_DEV: | ||
1702 | { | ||
1703 | uint port = (uint)arg & RIO_MODEM_MASK; | ||
1704 | |||
1705 | switch ( (uint)arg & RIO_DEV_MASK ) { | ||
1706 | case RIO_DEV_DIRECT: | ||
1707 | arg = (caddr_t)drv_makedev(MAJOR(dev), port); | ||
1708 | rio_dprintk (RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n",port, (int)arg); | ||
1709 | return (int)arg; | ||
1710 | case RIO_DEV_MODEM: | ||
1711 | arg = (caddr_t)drv_makedev(MAJOR(dev), (port|RIO_MODEM_BIT) ); | ||
1712 | rio_dprintk (RIO_DEBUG_CTRL, "Makedev modem 0x%x is 0x%x\n",port, (int)arg); | ||
1713 | return (int)arg; | ||
1714 | case RIO_DEV_XPRINT: | ||
1715 | arg = (caddr_t)drv_makedev(MAJOR(dev), port); | ||
1716 | rio_dprintk (RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n",port, (int)arg); | ||
1717 | return (int)arg; | ||
1718 | } | ||
1719 | rio_dprintk (RIO_DEBUG_CTRL, "MAKE Device is called\n"); | ||
1720 | return -EINVAL; | ||
1721 | } | ||
1722 | /* | ||
1723 | ** rio_minor: given a dev_t from a stat() call, return | ||
1724 | ** the port number (0-511) ORed with the port type | ||
1725 | ** ( RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT ) | ||
1726 | */ | ||
1727 | case RIO_MINOR: | ||
1728 | { | ||
1729 | dev_t dv; | ||
1730 | int mino; | ||
1731 | |||
1732 | dv = (dev_t)((int)arg); | ||
1733 | mino = RIO_UNMODEM(dv); | ||
1734 | |||
1735 | if ( RIO_ISMODEM(dv) ) { | ||
1736 | rio_dprintk (RIO_DEBUG_CTRL, "Minor for device 0x%x: modem %d\n", dv, mino); | ||
1737 | arg = (caddr_t)(mino | RIO_DEV_MODEM); | ||
1738 | } | ||
1739 | else { | ||
1740 | rio_dprintk (RIO_DEBUG_CTRL, "Minor for device 0x%x: direct %d\n", dv, mino); | ||
1741 | arg = (caddr_t)(mino | RIO_DEV_DIRECT); | ||
1742 | } | ||
1743 | return (int)arg; | ||
1744 | } | ||
1745 | } | ||
1746 | rio_dprintk (RIO_DEBUG_CTRL, "INVALID DAEMON IOCTL 0x%x\n",cmd); | ||
1747 | p->RIOError.Error = IOCTL_COMMAND_UNKNOWN; | ||
1748 | |||
1749 | func_exit (); | ||
1750 | return -EINVAL; | ||
1751 | } | ||
1752 | |||
1753 | /* | ||
1754 | ** Pre-emptive commands go on RUPs and are only one byte long. | ||
1755 | */ | ||
1756 | int | ||
1757 | RIOPreemptiveCmd(p, PortP, Cmd) | ||
1758 | struct rio_info * p; | ||
1759 | struct Port *PortP; | ||
1760 | uchar Cmd; | ||
1761 | { | ||
1762 | struct CmdBlk *CmdBlkP; | ||
1763 | struct PktCmd_M *PktCmdP; | ||
1764 | int Ret; | ||
1765 | ushort rup; | ||
1766 | int port; | ||
1767 | |||
1768 | #ifdef CHECK | ||
1769 | CheckPortP( PortP ); | ||
1770 | #endif | ||
1771 | |||
1772 | if ( PortP->State & RIO_DELETED ) { | ||
1773 | rio_dprintk (RIO_DEBUG_CTRL, "Preemptive command to deleted RTA ignored\n"); | ||
1774 | return RIO_FAIL; | ||
1775 | } | ||
1776 | |||
1777 | if (((int)((char)PortP->InUse) == -1) || ! (CmdBlkP = RIOGetCmdBlk()) ) { | ||
1778 | rio_dprintk (RIO_DEBUG_CTRL, "Cannot allocate command block for command %d on port %d\n", | ||
1779 | Cmd, PortP->PortNum); | ||
1780 | return RIO_FAIL; | ||
1781 | } | ||
1782 | |||
1783 | rio_dprintk (RIO_DEBUG_CTRL, "Command blk 0x%x - InUse now %d\n", | ||
1784 | (int)CmdBlkP,PortP->InUse); | ||
1785 | |||
1786 | PktCmdP = (struct PktCmd_M *)&CmdBlkP->Packet.data[0]; | ||
1787 | |||
1788 | CmdBlkP->Packet.src_unit = 0; | ||
1789 | if (PortP->SecondBlock) | ||
1790 | rup = PortP->ID2; | ||
1791 | else | ||
1792 | rup = PortP->RupNum; | ||
1793 | CmdBlkP->Packet.dest_unit = rup; | ||
1794 | CmdBlkP->Packet.src_port = COMMAND_RUP; | ||
1795 | CmdBlkP->Packet.dest_port = COMMAND_RUP; | ||
1796 | CmdBlkP->Packet.len = PKT_CMD_BIT | 2; | ||
1797 | CmdBlkP->PostFuncP = RIOUnUse; | ||
1798 | CmdBlkP->PostArg = (int)PortP; | ||
1799 | PktCmdP->Command = Cmd; | ||
1800 | port = PortP->HostPort % (ushort)PORTS_PER_RTA; | ||
1801 | /* | ||
1802 | ** Index ports 8-15 for 2nd block of 16 port RTA. | ||
1803 | */ | ||
1804 | if (PortP->SecondBlock) | ||
1805 | port += (ushort) PORTS_PER_RTA; | ||
1806 | PktCmdP->PhbNum = port; | ||
1807 | |||
1808 | switch ( Cmd ) { | ||
1809 | case MEMDUMP: | ||
1810 | rio_dprintk (RIO_DEBUG_CTRL, "Queue MEMDUMP command blk 0x%x (addr 0x%x)\n", | ||
1811 | (int)CmdBlkP, (int)SubCmd.Addr); | ||
1812 | PktCmdP->SubCommand = MEMDUMP; | ||
1813 | PktCmdP->SubAddr = SubCmd.Addr; | ||
1814 | break; | ||
1815 | case FCLOSE: | ||
1816 | rio_dprintk (RIO_DEBUG_CTRL, "Queue FCLOSE command blk 0x%x\n",(int)CmdBlkP); | ||
1817 | break; | ||
1818 | case READ_REGISTER: | ||
1819 | rio_dprintk (RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) command blk 0x%x\n", | ||
1820 | (int)SubCmd.Addr, (int)CmdBlkP); | ||
1821 | PktCmdP->SubCommand = READ_REGISTER; | ||
1822 | PktCmdP->SubAddr = SubCmd.Addr; | ||
1823 | break; | ||
1824 | case RESUME: | ||
1825 | rio_dprintk (RIO_DEBUG_CTRL, "Queue RESUME command blk 0x%x\n",(int)CmdBlkP); | ||
1826 | break; | ||
1827 | case RFLUSH: | ||
1828 | rio_dprintk (RIO_DEBUG_CTRL, "Queue RFLUSH command blk 0x%x\n",(int)CmdBlkP); | ||
1829 | CmdBlkP->PostFuncP = RIORFlushEnable; | ||
1830 | break; | ||
1831 | case SUSPEND: | ||
1832 | rio_dprintk (RIO_DEBUG_CTRL, "Queue SUSPEND command blk 0x%x\n",(int)CmdBlkP); | ||
1833 | break; | ||
1834 | |||
1835 | case MGET : | ||
1836 | rio_dprintk (RIO_DEBUG_CTRL, "Queue MGET command blk 0x%x\n", (int)CmdBlkP); | ||
1837 | break; | ||
1838 | |||
1839 | case MSET : | ||
1840 | case MBIC : | ||
1841 | case MBIS : | ||
1842 | CmdBlkP->Packet.data[4] = (char) PortP->ModemLines; | ||
1843 | rio_dprintk (RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command blk 0x%x\n", (int)CmdBlkP); | ||
1844 | break; | ||
1845 | |||
1846 | case WFLUSH: | ||
1847 | /* | ||
1848 | ** If we have queued up the maximum number of Write flushes | ||
1849 | ** allowed then we should not bother sending any more to the | ||
1850 | ** RTA. | ||
1851 | */ | ||
1852 | if ((int)((char)PortP->WflushFlag) == (int)-1) { | ||
1853 | rio_dprintk (RIO_DEBUG_CTRL, "Trashed WFLUSH, WflushFlag about to wrap!"); | ||
1854 | RIOFreeCmdBlk(CmdBlkP); | ||
1855 | return(RIO_FAIL); | ||
1856 | } else { | ||
1857 | rio_dprintk (RIO_DEBUG_CTRL, "Queue WFLUSH command blk 0x%x\n", | ||
1858 | (int)CmdBlkP); | ||
1859 | CmdBlkP->PostFuncP = RIOWFlushMark; | ||
1860 | } | ||
1861 | break; | ||
1862 | } | ||
1863 | |||
1864 | PortP->InUse++; | ||
1865 | |||
1866 | Ret = RIOQueueCmdBlk( PortP->HostP, rup, CmdBlkP ); | ||
1867 | |||
1868 | return Ret; | ||
1869 | } | ||