diff options
Diffstat (limited to 'drivers/char/rio/riocmd.c')
-rw-r--r-- | drivers/char/rio/riocmd.c | 1041 |
1 files changed, 1041 insertions, 0 deletions
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c new file mode 100644 index 000000000000..533085ec6f1b --- /dev/null +++ b/drivers/char/rio/riocmd.c | |||
@@ -0,0 +1,1041 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** ported from the existing SCO driver source | ||
6 | ** | ||
7 | * | ||
8 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | ** | ||
24 | ** Module : riocmd.c | ||
25 | ** SID : 1.2 | ||
26 | ** Last Modified : 11/6/98 10:33:41 | ||
27 | ** Retrieved : 11/6/98 10:33:49 | ||
28 | ** | ||
29 | ** ident @(#)riocmd.c 1.2 | ||
30 | ** | ||
31 | ** ----------------------------------------------------------------------------- | ||
32 | */ | ||
33 | #ifdef SCCS_LABELS | ||
34 | static char *_riocmd_c_sccs_ = "@(#)riocmd.c 1.2"; | ||
35 | #endif | ||
36 | |||
37 | #include <linux/module.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/errno.h> | ||
40 | #include <linux/tty.h> | ||
41 | #include <asm/io.h> | ||
42 | #include <asm/system.h> | ||
43 | #include <asm/string.h> | ||
44 | #include <asm/semaphore.h> | ||
45 | |||
46 | #include <linux/termios.h> | ||
47 | #include <linux/serial.h> | ||
48 | |||
49 | #include <linux/generic_serial.h> | ||
50 | |||
51 | #include "linux_compat.h" | ||
52 | #include "rio_linux.h" | ||
53 | #include "typdef.h" | ||
54 | #include "pkt.h" | ||
55 | #include "daemon.h" | ||
56 | #include "rio.h" | ||
57 | #include "riospace.h" | ||
58 | #include "top.h" | ||
59 | #include "cmdpkt.h" | ||
60 | #include "map.h" | ||
61 | #include "riotypes.h" | ||
62 | #include "rup.h" | ||
63 | #include "port.h" | ||
64 | #include "riodrvr.h" | ||
65 | #include "rioinfo.h" | ||
66 | #include "func.h" | ||
67 | #include "errors.h" | ||
68 | #include "pci.h" | ||
69 | |||
70 | #include "parmmap.h" | ||
71 | #include "unixrup.h" | ||
72 | #include "board.h" | ||
73 | #include "host.h" | ||
74 | #include "error.h" | ||
75 | #include "phb.h" | ||
76 | #include "link.h" | ||
77 | #include "cmdblk.h" | ||
78 | #include "route.h" | ||
79 | #include "control.h" | ||
80 | #include "cirrus.h" | ||
81 | |||
82 | |||
83 | static struct IdentifyRta IdRta; | ||
84 | static struct KillNeighbour KillUnit; | ||
85 | |||
86 | int | ||
87 | RIOFoadRta(struct Host *HostP, struct Map *MapP) | ||
88 | { | ||
89 | struct CmdBlk *CmdBlkP; | ||
90 | |||
91 | rio_dprintk (RIO_DEBUG_CMD, "FOAD RTA\n"); | ||
92 | |||
93 | CmdBlkP = RIOGetCmdBlk(); | ||
94 | |||
95 | if ( !CmdBlkP ) { | ||
96 | rio_dprintk (RIO_DEBUG_CMD, "FOAD RTA: GetCmdBlk failed\n"); | ||
97 | return -ENXIO; | ||
98 | } | ||
99 | |||
100 | CmdBlkP->Packet.dest_unit = MapP->ID; | ||
101 | CmdBlkP->Packet.dest_port = BOOT_RUP; | ||
102 | CmdBlkP->Packet.src_unit = 0; | ||
103 | CmdBlkP->Packet.src_port = BOOT_RUP; | ||
104 | CmdBlkP->Packet.len = 0x84; | ||
105 | CmdBlkP->Packet.data[0] = IFOAD; | ||
106 | CmdBlkP->Packet.data[1] = 0; | ||
107 | CmdBlkP->Packet.data[2] = IFOAD_MAGIC & 0xFF; | ||
108 | CmdBlkP->Packet.data[3] = (IFOAD_MAGIC >> 8) & 0xFF; | ||
109 | |||
110 | if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) { | ||
111 | rio_dprintk (RIO_DEBUG_CMD, "FOAD RTA: Failed to queue foad command\n"); | ||
112 | return -EIO; | ||
113 | } | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | int | ||
118 | RIOZombieRta(struct Host *HostP, struct Map *MapP) | ||
119 | { | ||
120 | struct CmdBlk *CmdBlkP; | ||
121 | |||
122 | rio_dprintk (RIO_DEBUG_CMD, "ZOMBIE RTA\n"); | ||
123 | |||
124 | CmdBlkP = RIOGetCmdBlk(); | ||
125 | |||
126 | if ( !CmdBlkP ) { | ||
127 | rio_dprintk (RIO_DEBUG_CMD, "ZOMBIE RTA: GetCmdBlk failed\n"); | ||
128 | return -ENXIO; | ||
129 | } | ||
130 | |||
131 | CmdBlkP->Packet.dest_unit = MapP->ID; | ||
132 | CmdBlkP->Packet.dest_port = BOOT_RUP; | ||
133 | CmdBlkP->Packet.src_unit = 0; | ||
134 | CmdBlkP->Packet.src_port = BOOT_RUP; | ||
135 | CmdBlkP->Packet.len = 0x84; | ||
136 | CmdBlkP->Packet.data[0] = ZOMBIE; | ||
137 | CmdBlkP->Packet.data[1] = 0; | ||
138 | CmdBlkP->Packet.data[2] = ZOMBIE_MAGIC & 0xFF; | ||
139 | CmdBlkP->Packet.data[3] = (ZOMBIE_MAGIC >> 8) & 0xFF; | ||
140 | |||
141 | if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) { | ||
142 | rio_dprintk (RIO_DEBUG_CMD, "ZOMBIE RTA: Failed to queue zombie command\n"); | ||
143 | return -EIO; | ||
144 | } | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | int | ||
149 | RIOCommandRta(struct rio_info *p, uint RtaUnique, | ||
150 | int (* func)(struct Host *HostP, struct Map *MapP)) | ||
151 | { | ||
152 | uint Host; | ||
153 | |||
154 | rio_dprintk (RIO_DEBUG_CMD, "Command RTA 0x%x func 0x%x\n", RtaUnique, (int)func); | ||
155 | |||
156 | if ( !RtaUnique ) | ||
157 | return(0); | ||
158 | |||
159 | for ( Host = 0; Host < p->RIONumHosts; Host++ ) { | ||
160 | uint Rta; | ||
161 | struct Host *HostP = &p->RIOHosts[Host]; | ||
162 | |||
163 | for ( Rta = 0; Rta < RTAS_PER_HOST; Rta++ ) { | ||
164 | struct Map *MapP = &HostP->Mapping[Rta]; | ||
165 | |||
166 | if ( MapP->RtaUniqueNum == RtaUnique ) { | ||
167 | uint Link; | ||
168 | |||
169 | /* | ||
170 | ** now, lets just check we have a route to it... | ||
171 | ** IF the routing stuff is working, then one of the | ||
172 | ** topology entries for this unit will have a legit | ||
173 | ** route *somewhere*. We care not where - if its got | ||
174 | ** any connections, we can get to it. | ||
175 | */ | ||
176 | for ( Link = 0; Link < LINKS_PER_UNIT; Link++ ) { | ||
177 | if ( MapP->Topology[Link].Unit <= (uchar)MAX_RUP ) { | ||
178 | /* | ||
179 | ** Its worth trying the operation... | ||
180 | */ | ||
181 | return (*func)( HostP, MapP ); | ||
182 | } | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | } | ||
187 | return -ENXIO; | ||
188 | } | ||
189 | |||
190 | |||
191 | int | ||
192 | RIOIdentifyRta(struct rio_info *p, caddr_t arg) | ||
193 | { | ||
194 | uint Host; | ||
195 | |||
196 | if ( copyin( (int)arg, (caddr_t)&IdRta, sizeof(IdRta) ) == COPYFAIL ) { | ||
197 | rio_dprintk (RIO_DEBUG_CMD, "RIO_IDENTIFY_RTA copy failed\n"); | ||
198 | p->RIOError.Error = COPYIN_FAILED; | ||
199 | return -EFAULT; | ||
200 | } | ||
201 | |||
202 | for ( Host = 0 ; Host < p->RIONumHosts; Host++ ) { | ||
203 | uint Rta; | ||
204 | struct Host *HostP = &p->RIOHosts[Host]; | ||
205 | |||
206 | for ( Rta = 0; Rta < RTAS_PER_HOST; Rta++ ) { | ||
207 | struct Map *MapP = &HostP->Mapping[Rta]; | ||
208 | |||
209 | if ( MapP->RtaUniqueNum == IdRta.RtaUnique ) { | ||
210 | uint Link; | ||
211 | /* | ||
212 | ** now, lets just check we have a route to it... | ||
213 | ** IF the routing stuff is working, then one of the | ||
214 | ** topology entries for this unit will have a legit | ||
215 | ** route *somewhere*. We care not where - if its got | ||
216 | ** any connections, we can get to it. | ||
217 | */ | ||
218 | for ( Link = 0; Link < LINKS_PER_UNIT; Link++ ) { | ||
219 | if ( MapP->Topology[Link].Unit <= (uchar)MAX_RUP ) { | ||
220 | /* | ||
221 | ** Its worth trying the operation... | ||
222 | */ | ||
223 | struct CmdBlk *CmdBlkP; | ||
224 | |||
225 | rio_dprintk (RIO_DEBUG_CMD, "IDENTIFY RTA\n"); | ||
226 | |||
227 | CmdBlkP = RIOGetCmdBlk(); | ||
228 | |||
229 | if ( !CmdBlkP ) { | ||
230 | rio_dprintk (RIO_DEBUG_CMD, "IDENTIFY RTA: GetCmdBlk failed\n"); | ||
231 | return -ENXIO; | ||
232 | } | ||
233 | |||
234 | CmdBlkP->Packet.dest_unit = MapP->ID; | ||
235 | CmdBlkP->Packet.dest_port = BOOT_RUP; | ||
236 | CmdBlkP->Packet.src_unit = 0; | ||
237 | CmdBlkP->Packet.src_port = BOOT_RUP; | ||
238 | CmdBlkP->Packet.len = 0x84; | ||
239 | CmdBlkP->Packet.data[0] = IDENTIFY; | ||
240 | CmdBlkP->Packet.data[1] = 0; | ||
241 | CmdBlkP->Packet.data[2] = IdRta.ID; | ||
242 | |||
243 | if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) { | ||
244 | rio_dprintk (RIO_DEBUG_CMD, "IDENTIFY RTA: Failed to queue command\n"); | ||
245 | return -EIO; | ||
246 | } | ||
247 | return 0; | ||
248 | } | ||
249 | } | ||
250 | } | ||
251 | } | ||
252 | } | ||
253 | return -ENOENT; | ||
254 | } | ||
255 | |||
256 | |||
257 | int | ||
258 | RIOKillNeighbour(struct rio_info *p, caddr_t arg) | ||
259 | { | ||
260 | uint Host; | ||
261 | uint ID; | ||
262 | struct Host *HostP; | ||
263 | struct CmdBlk *CmdBlkP; | ||
264 | |||
265 | rio_dprintk (RIO_DEBUG_CMD, "KILL HOST NEIGHBOUR\n"); | ||
266 | |||
267 | if ( copyin( (int)arg, (caddr_t)&KillUnit, sizeof(KillUnit) ) == COPYFAIL ) { | ||
268 | rio_dprintk (RIO_DEBUG_CMD, "RIO_KILL_NEIGHBOUR copy failed\n"); | ||
269 | p->RIOError.Error = COPYIN_FAILED; | ||
270 | return -EFAULT; | ||
271 | } | ||
272 | |||
273 | if ( KillUnit.Link > 3 ) | ||
274 | return -ENXIO; | ||
275 | |||
276 | CmdBlkP = RIOGetCmdBlk(); | ||
277 | |||
278 | if ( !CmdBlkP ) { | ||
279 | rio_dprintk (RIO_DEBUG_CMD, "UFOAD: GetCmdBlk failed\n"); | ||
280 | return -ENXIO; | ||
281 | } | ||
282 | |||
283 | CmdBlkP->Packet.dest_unit = 0; | ||
284 | CmdBlkP->Packet.src_unit = 0; | ||
285 | CmdBlkP->Packet.dest_port = BOOT_RUP; | ||
286 | CmdBlkP->Packet.src_port = BOOT_RUP; | ||
287 | CmdBlkP->Packet.len = 0x84; | ||
288 | CmdBlkP->Packet.data[0] = UFOAD; | ||
289 | CmdBlkP->Packet.data[1] = KillUnit.Link; | ||
290 | CmdBlkP->Packet.data[2] = UFOAD_MAGIC & 0xFF; | ||
291 | CmdBlkP->Packet.data[3] = (UFOAD_MAGIC >> 8) & 0xFF; | ||
292 | |||
293 | for ( Host = 0; Host < p->RIONumHosts; Host++ ) { | ||
294 | ID = 0; | ||
295 | HostP = &p->RIOHosts[Host]; | ||
296 | |||
297 | if ( HostP->UniqueNum == KillUnit.UniqueNum ) { | ||
298 | if ( RIOQueueCmdBlk( HostP, RTAS_PER_HOST+KillUnit.Link, | ||
299 | CmdBlkP) == RIO_FAIL ) { | ||
300 | rio_dprintk (RIO_DEBUG_CMD, "UFOAD: Failed queue command\n"); | ||
301 | return -EIO; | ||
302 | } | ||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | for ( ID=0; ID < RTAS_PER_HOST; ID++ ) { | ||
307 | if ( HostP->Mapping[ID].RtaUniqueNum == KillUnit.UniqueNum ) { | ||
308 | CmdBlkP->Packet.dest_unit = ID+1; | ||
309 | if ( RIOQueueCmdBlk( HostP, ID, CmdBlkP) == RIO_FAIL ) { | ||
310 | rio_dprintk (RIO_DEBUG_CMD, "UFOAD: Failed queue command\n"); | ||
311 | return -EIO; | ||
312 | } | ||
313 | return 0; | ||
314 | } | ||
315 | } | ||
316 | } | ||
317 | RIOFreeCmdBlk( CmdBlkP ); | ||
318 | return -ENXIO; | ||
319 | } | ||
320 | |||
321 | int | ||
322 | RIOSuspendBootRta(struct Host *HostP, int ID, int Link) | ||
323 | { | ||
324 | struct CmdBlk *CmdBlkP; | ||
325 | |||
326 | rio_dprintk (RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA ID %d, link %c\n", ID, 'A' + Link); | ||
327 | |||
328 | CmdBlkP = RIOGetCmdBlk(); | ||
329 | |||
330 | if ( !CmdBlkP ) { | ||
331 | rio_dprintk (RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: GetCmdBlk failed\n"); | ||
332 | return -ENXIO; | ||
333 | } | ||
334 | |||
335 | CmdBlkP->Packet.dest_unit = ID; | ||
336 | CmdBlkP->Packet.dest_port = BOOT_RUP; | ||
337 | CmdBlkP->Packet.src_unit = 0; | ||
338 | CmdBlkP->Packet.src_port = BOOT_RUP; | ||
339 | CmdBlkP->Packet.len = 0x84; | ||
340 | CmdBlkP->Packet.data[0] = IWAIT; | ||
341 | CmdBlkP->Packet.data[1] = Link; | ||
342 | CmdBlkP->Packet.data[2] = IWAIT_MAGIC & 0xFF; | ||
343 | CmdBlkP->Packet.data[3] = (IWAIT_MAGIC >> 8) & 0xFF; | ||
344 | |||
345 | if ( RIOQueueCmdBlk( HostP, ID - 1, CmdBlkP) == RIO_FAIL ) { | ||
346 | rio_dprintk (RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: Failed to queue iwait command\n"); | ||
347 | return -EIO; | ||
348 | } | ||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | int | ||
353 | RIOFoadWakeup(struct rio_info *p) | ||
354 | { | ||
355 | int port; | ||
356 | register struct Port *PortP; | ||
357 | unsigned long flags; | ||
358 | |||
359 | for ( port=0; port<RIO_PORTS; port++) { | ||
360 | PortP = p->RIOPortp[port]; | ||
361 | |||
362 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
363 | PortP->Config = 0; | ||
364 | PortP->State = 0; | ||
365 | PortP->InUse = NOT_INUSE; | ||
366 | PortP->PortState = 0; | ||
367 | PortP->FlushCmdBodge = 0; | ||
368 | PortP->ModemLines = 0; | ||
369 | PortP->ModemState = 0; | ||
370 | PortP->CookMode = 0; | ||
371 | PortP->ParamSem = 0; | ||
372 | PortP->Mapped = 0; | ||
373 | PortP->WflushFlag = 0; | ||
374 | PortP->MagicFlags = 0; | ||
375 | PortP->RxDataStart = 0; | ||
376 | PortP->TxBufferIn = 0; | ||
377 | PortP->TxBufferOut = 0; | ||
378 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
379 | } | ||
380 | return(0); | ||
381 | } | ||
382 | |||
383 | /* | ||
384 | ** Incoming command on the COMMAND_RUP to be processed. | ||
385 | */ | ||
386 | static int | ||
387 | RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP) | ||
388 | { | ||
389 | struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data; | ||
390 | struct Port *PortP; | ||
391 | struct UnixRup *UnixRupP; | ||
392 | ushort SysPort; | ||
393 | ushort ReportedModemStatus; | ||
394 | ushort rup; | ||
395 | ushort subCommand; | ||
396 | unsigned long flags; | ||
397 | |||
398 | func_enter (); | ||
399 | |||
400 | #ifdef CHECK | ||
401 | CheckHost( Host ); | ||
402 | CheckHostP( HostP ); | ||
403 | CheckPacketP( PacketP ); | ||
404 | #endif | ||
405 | |||
406 | /* | ||
407 | ** 16 port RTA note: | ||
408 | ** Command rup packets coming from the RTA will have pkt->data[1] (which | ||
409 | ** translates to PktCmdP->PhbNum) set to the host port number for the | ||
410 | ** particular unit. To access the correct BaseSysPort for a 16 port RTA, | ||
411 | ** we can use PhbNum to get the rup number for the appropriate 8 port | ||
412 | ** block (for the first block, this should be equal to 'Rup'). | ||
413 | */ | ||
414 | rup = RBYTE(PktCmdP->PhbNum) / (ushort)PORTS_PER_RTA; | ||
415 | UnixRupP = &HostP->UnixRups[rup]; | ||
416 | SysPort = UnixRupP->BaseSysPort + | ||
417 | (RBYTE(PktCmdP->PhbNum) % (ushort)PORTS_PER_RTA); | ||
418 | rio_dprintk (RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort); | ||
419 | |||
420 | #ifdef CHECK | ||
421 | CheckRup( rup ); | ||
422 | CheckUnixRupP( UnixRupP ); | ||
423 | #endif | ||
424 | if ( UnixRupP->BaseSysPort == NO_PORT ) { | ||
425 | rio_dprintk (RIO_DEBUG_CMD, "OBSCURE ERROR!\n"); | ||
426 | rio_dprintk (RIO_DEBUG_CMD, "Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n"); | ||
427 | rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: Host number %d, name ``%s''\n", | ||
428 | HostP-p->RIOHosts, HostP->Name ); | ||
429 | rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: Rup number 0x%x\n", rup); | ||
430 | |||
431 | if ( Rup >= (ushort)MAX_RUP ) { | ||
432 | rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", | ||
433 | HostP->Mapping[Rup].Name); | ||
434 | } else | ||
435 | rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", | ||
436 | ('A' + Rup - MAX_RUP), HostP->Name); | ||
437 | |||
438 | rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n", | ||
439 | PacketP->dest_unit, PacketP->dest_port ); | ||
440 | rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Source 0x%x:0x%x\n", | ||
441 | PacketP->src_unit, PacketP->src_port ); | ||
442 | rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Length 0x%x (%d)\n", PacketP->len,PacketP->len ); | ||
443 | rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Control 0x%x (%d)\n", PacketP->control, PacketP->control); | ||
444 | rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Check 0x%x (%d)\n", PacketP->csum, PacketP->csum ); | ||
445 | rio_dprintk (RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " | ||
446 | "Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command ); | ||
447 | return TRUE; | ||
448 | } | ||
449 | |||
450 | #ifdef CHECK | ||
451 | CheckSysPort( SysPort ); | ||
452 | #endif | ||
453 | PortP = p->RIOPortp[ SysPort ]; | ||
454 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
455 | switch( RBYTE(PktCmdP->Command) ) { | ||
456 | case BREAK_RECEIVED: | ||
457 | rio_dprintk (RIO_DEBUG_CMD, "Received a break!\n"); | ||
458 | /* If the current line disc. is not multi-threading and | ||
459 | the current processor is not the default, reset rup_intr | ||
460 | and return FALSE to ensure that the command packet is | ||
461 | not freed. */ | ||
462 | /* Call tmgr HANGUP HERE */ | ||
463 | /* Fix this later when every thing works !!!! RAMRAJ */ | ||
464 | gs_got_break (&PortP->gs); | ||
465 | break; | ||
466 | |||
467 | case COMPLETE: | ||
468 | rio_dprintk (RIO_DEBUG_CMD, "Command complete on phb %d host %d\n", | ||
469 | RBYTE(PktCmdP->PhbNum), HostP-p->RIOHosts); | ||
470 | subCommand = 1; | ||
471 | switch (RBYTE(PktCmdP->SubCommand)) { | ||
472 | case MEMDUMP : | ||
473 | rio_dprintk (RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n", | ||
474 | RBYTE(PktCmdP->SubCommand), RWORD(PktCmdP->SubAddr)); | ||
475 | break; | ||
476 | case READ_REGISTER : | ||
477 | rio_dprintk (RIO_DEBUG_CMD, "Read register (0x%x)\n", RWORD(PktCmdP->SubAddr)); | ||
478 | p->CdRegister = (RBYTE(PktCmdP->ModemStatus) & MSVR1_HOST); | ||
479 | break; | ||
480 | default : | ||
481 | subCommand = 0; | ||
482 | break; | ||
483 | } | ||
484 | if (subCommand) | ||
485 | break; | ||
486 | rio_dprintk (RIO_DEBUG_CMD, "New status is 0x%x was 0x%x\n", | ||
487 | RBYTE(PktCmdP->PortStatus),PortP->PortState); | ||
488 | if (PortP->PortState != RBYTE(PktCmdP->PortStatus)) { | ||
489 | rio_dprintk (RIO_DEBUG_CMD, "Mark status & wakeup\n"); | ||
490 | PortP->PortState = RBYTE(PktCmdP->PortStatus); | ||
491 | /* What should we do here ... | ||
492 | wakeup( &PortP->PortState ); | ||
493 | */ | ||
494 | } else | ||
495 | rio_dprintk (RIO_DEBUG_CMD, "No change\n"); | ||
496 | |||
497 | /* FALLTHROUGH */ | ||
498 | case MODEM_STATUS: | ||
499 | /* | ||
500 | ** Knock out the tbusy and tstop bits, as these are not relevant | ||
501 | ** to the check for modem status change (they're just there because | ||
502 | ** it's a convenient place to put them!). | ||
503 | */ | ||
504 | ReportedModemStatus = RBYTE(PktCmdP->ModemStatus); | ||
505 | if ((PortP->ModemState & MSVR1_HOST) == | ||
506 | (ReportedModemStatus & MSVR1_HOST)) { | ||
507 | rio_dprintk (RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState); | ||
508 | /* | ||
509 | ** Update ModemState just in case tbusy or tstop states have | ||
510 | ** changed. | ||
511 | */ | ||
512 | PortP->ModemState = ReportedModemStatus; | ||
513 | } | ||
514 | else { | ||
515 | rio_dprintk (RIO_DEBUG_CMD, "Modem status change from 0x%x to 0x%x\n", | ||
516 | PortP->ModemState, ReportedModemStatus); | ||
517 | PortP->ModemState = ReportedModemStatus; | ||
518 | #ifdef MODEM_SUPPORT | ||
519 | if ( PortP->Mapped ) { | ||
520 | /***********************************************************\ | ||
521 | ************************************************************* | ||
522 | *** *** | ||
523 | *** M O D E M S T A T E C H A N G E *** | ||
524 | *** *** | ||
525 | ************************************************************* | ||
526 | \***********************************************************/ | ||
527 | /* | ||
528 | ** If the device is a modem, then check the modem | ||
529 | ** carrier. | ||
530 | */ | ||
531 | if (PortP->gs.tty == NULL) | ||
532 | break; | ||
533 | if (PortP->gs.tty->termios == NULL) | ||
534 | break; | ||
535 | |||
536 | if (!(PortP->gs.tty->termios->c_cflag & CLOCAL) && | ||
537 | ((PortP->State & (RIO_MOPEN|RIO_WOPEN)))) { | ||
538 | |||
539 | rio_dprintk (RIO_DEBUG_CMD, "Is there a Carrier?\n"); | ||
540 | /* | ||
541 | ** Is there a carrier? | ||
542 | */ | ||
543 | if ( PortP->ModemState & MSVR1_CD ) { | ||
544 | /* | ||
545 | ** Has carrier just appeared? | ||
546 | */ | ||
547 | if (!(PortP->State & RIO_CARR_ON)) { | ||
548 | rio_dprintk (RIO_DEBUG_CMD, "Carrier just came up.\n"); | ||
549 | PortP->State |= RIO_CARR_ON; | ||
550 | /* | ||
551 | ** wakeup anyone in WOPEN | ||
552 | */ | ||
553 | if (PortP->State & (PORT_ISOPEN | RIO_WOPEN) ) | ||
554 | wake_up_interruptible (&PortP->gs.open_wait); | ||
555 | #ifdef STATS | ||
556 | PortP->Stat.ModemOnCnt++; | ||
557 | #endif | ||
558 | } | ||
559 | } else { | ||
560 | /* | ||
561 | ** Has carrier just dropped? | ||
562 | */ | ||
563 | if (PortP->State & RIO_CARR_ON) { | ||
564 | if (PortP->State & (PORT_ISOPEN|RIO_WOPEN|RIO_MOPEN)) | ||
565 | tty_hangup (PortP->gs.tty); | ||
566 | PortP->State &= ~RIO_CARR_ON; | ||
567 | rio_dprintk (RIO_DEBUG_CMD, "Carrirer just went down\n"); | ||
568 | #ifdef STATS | ||
569 | PortP->Stat.ModemOffCnt++; | ||
570 | #endif | ||
571 | } | ||
572 | } | ||
573 | } | ||
574 | } | ||
575 | #endif | ||
576 | } | ||
577 | break; | ||
578 | |||
579 | default: | ||
580 | rio_dprintk (RIO_DEBUG_CMD, "Unknown command %d on CMD_RUP of host %d\n", | ||
581 | RBYTE(PktCmdP->Command),HostP-p->RIOHosts); | ||
582 | break; | ||
583 | } | ||
584 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
585 | |||
586 | func_exit (); | ||
587 | |||
588 | return TRUE; | ||
589 | } | ||
590 | /* | ||
591 | ** The command mechanism: | ||
592 | ** Each rup has a chain of commands associated with it. | ||
593 | ** This chain is maintained by routines in this file. | ||
594 | ** Periodically we are called and we run a quick check of all the | ||
595 | ** active chains to determine if there is a command to be executed, | ||
596 | ** and if the rup is ready to accept it. | ||
597 | ** | ||
598 | */ | ||
599 | |||
600 | /* | ||
601 | ** Allocate an empty command block. | ||
602 | */ | ||
603 | struct CmdBlk * | ||
604 | RIOGetCmdBlk(void) | ||
605 | { | ||
606 | struct CmdBlk *CmdBlkP; | ||
607 | |||
608 | CmdBlkP = (struct CmdBlk *)sysbrk(sizeof(struct CmdBlk)); | ||
609 | if (CmdBlkP) | ||
610 | bzero(CmdBlkP, sizeof(struct CmdBlk)); | ||
611 | |||
612 | return CmdBlkP; | ||
613 | } | ||
614 | |||
615 | /* | ||
616 | ** Return a block to the head of the free list. | ||
617 | */ | ||
618 | void | ||
619 | RIOFreeCmdBlk(struct CmdBlk *CmdBlkP) | ||
620 | { | ||
621 | sysfree((void *)CmdBlkP, sizeof(struct CmdBlk)); | ||
622 | } | ||
623 | |||
624 | /* | ||
625 | ** attach a command block to the list of commands to be performed for | ||
626 | ** a given rup. | ||
627 | */ | ||
628 | int | ||
629 | RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP) | ||
630 | { | ||
631 | struct CmdBlk **Base; | ||
632 | struct UnixRup *UnixRupP; | ||
633 | unsigned long flags; | ||
634 | |||
635 | #ifdef CHECK | ||
636 | CheckHostP( HostP ); | ||
637 | CheckRup( Rup ); | ||
638 | CheckCmdBlkP( CmdBlkP ); | ||
639 | #endif | ||
640 | if ( Rup >= (ushort)(MAX_RUP+LINKS_PER_UNIT) ) { | ||
641 | rio_dprintk (RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n",Rup); | ||
642 | RIOFreeCmdBlk( CmdBlkP ); | ||
643 | return RIO_FAIL; | ||
644 | } | ||
645 | |||
646 | UnixRupP = &HostP->UnixRups[Rup]; | ||
647 | |||
648 | rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); | ||
649 | |||
650 | /* | ||
651 | ** If the RUP is currently inactive, then put the request | ||
652 | ** straight on the RUP.... | ||
653 | */ | ||
654 | if ( (UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) && | ||
655 | (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE ) && | ||
656 | (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP)(CmdBlkP->PreArg,CmdBlkP) | ||
657 | :TRUE)) { | ||
658 | rio_dprintk (RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n", | ||
659 | CmdBlkP->Packet.data[0]); | ||
660 | |||
661 | /* | ||
662 | ** Whammy! blat that pack! | ||
663 | */ | ||
664 | HostP->Copy( (caddr_t)&CmdBlkP->Packet, | ||
665 | RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt ), sizeof(PKT) ); | ||
666 | |||
667 | /* | ||
668 | ** place command packet on the pending position. | ||
669 | */ | ||
670 | UnixRupP->CmdPendingP = CmdBlkP; | ||
671 | |||
672 | /* | ||
673 | ** set the command register | ||
674 | */ | ||
675 | WWORD(UnixRupP->RupP->txcontrol , TX_PACKET_READY); | ||
676 | |||
677 | rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); | ||
678 | |||
679 | return RIO_SUCCESS; | ||
680 | } | ||
681 | rio_dprintk (RIO_DEBUG_CMD, "RUP active - en-queing\n"); | ||
682 | |||
683 | if ( UnixRupP->CmdsWaitingP != NULL) | ||
684 | rio_dprintk (RIO_DEBUG_CMD, "Rup active - command waiting\n"); | ||
685 | if ( UnixRupP->CmdPendingP != NULL ) | ||
686 | rio_dprintk (RIO_DEBUG_CMD, "Rup active - command pending\n"); | ||
687 | if ( RWORD(UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE ) | ||
688 | rio_dprintk (RIO_DEBUG_CMD, "Rup active - command rup not ready\n"); | ||
689 | |||
690 | Base = &UnixRupP->CmdsWaitingP; | ||
691 | |||
692 | rio_dprintk (RIO_DEBUG_CMD, "First try to queue cmdblk 0x%x at 0x%x\n", (int)CmdBlkP,(int)Base); | ||
693 | |||
694 | while ( *Base ) { | ||
695 | rio_dprintk (RIO_DEBUG_CMD, "Command cmdblk 0x%x here\n", (int)(*Base)); | ||
696 | Base = &((*Base)->NextP); | ||
697 | rio_dprintk (RIO_DEBUG_CMD, "Now try to queue cmd cmdblk 0x%x at 0x%x\n", | ||
698 | (int)CmdBlkP,(int)Base); | ||
699 | } | ||
700 | |||
701 | rio_dprintk (RIO_DEBUG_CMD, "Will queue cmdblk 0x%x at 0x%x\n",(int)CmdBlkP,(int)Base); | ||
702 | |||
703 | *Base = CmdBlkP; | ||
704 | |||
705 | CmdBlkP->NextP = NULL; | ||
706 | |||
707 | rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); | ||
708 | |||
709 | return RIO_SUCCESS; | ||
710 | } | ||
711 | |||
712 | /* | ||
713 | ** Here we go - if there is an empty rup, fill it! | ||
714 | ** must be called at splrio() or higher. | ||
715 | */ | ||
716 | void | ||
717 | RIOPollHostCommands(struct rio_info *p, struct Host *HostP) | ||
718 | { | ||
719 | register struct CmdBlk *CmdBlkP; | ||
720 | register struct UnixRup *UnixRupP; | ||
721 | struct PKT *PacketP; | ||
722 | ushort Rup; | ||
723 | unsigned long flags; | ||
724 | |||
725 | |||
726 | Rup = MAX_RUP+LINKS_PER_UNIT; | ||
727 | |||
728 | do { /* do this loop for each RUP */ | ||
729 | /* | ||
730 | ** locate the rup we are processing & lock it | ||
731 | */ | ||
732 | UnixRupP = &HostP->UnixRups[--Rup]; | ||
733 | |||
734 | spin_lock_irqsave(&UnixRupP->RupLock, flags); | ||
735 | |||
736 | /* | ||
737 | ** First check for incoming commands: | ||
738 | */ | ||
739 | if ( RWORD(UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE ) { | ||
740 | int FreeMe; | ||
741 | |||
742 | PacketP =(PKT *)RIO_PTR(HostP->Caddr,RWORD(UnixRupP->RupP->rxpkt)); | ||
743 | |||
744 | ShowPacket( DBG_CMD, PacketP ); | ||
745 | |||
746 | switch ( RBYTE(PacketP->dest_port) ) { | ||
747 | case BOOT_RUP: | ||
748 | rio_dprintk (RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n", | ||
749 | RBYTE(PacketP->len) & 0x80 ? "Command":"Data", | ||
750 | RBYTE(PacketP->data[0])); | ||
751 | rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); | ||
752 | FreeMe= RIOBootRup(p, Rup,HostP,PacketP); | ||
753 | rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); | ||
754 | break; | ||
755 | |||
756 | case COMMAND_RUP: | ||
757 | /* | ||
758 | ** Free the RUP lock as loss of carrier causes a | ||
759 | ** ttyflush which will (eventually) call another | ||
760 | ** routine that uses the RUP lock. | ||
761 | */ | ||
762 | rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); | ||
763 | FreeMe= RIOCommandRup(p, Rup,HostP,PacketP); | ||
764 | if (PacketP->data[5] == MEMDUMP) { | ||
765 | rio_dprintk (RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", | ||
766 | *(ushort *) &(PacketP->data[6])); | ||
767 | HostP->Copy( (caddr_t)&(PacketP->data[8]), | ||
768 | (caddr_t)p->RIOMemDump, 32 ); | ||
769 | } | ||
770 | rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); | ||
771 | break; | ||
772 | |||
773 | case ROUTE_RUP: | ||
774 | rio_spin_unlock_irqrestore( &UnixRupP->RupLock, flags); | ||
775 | FreeMe = RIORouteRup(p, Rup, HostP, PacketP ); | ||
776 | rio_spin_lock_irqsave( &UnixRupP->RupLock, flags ); | ||
777 | break; | ||
778 | |||
779 | default: | ||
780 | rio_dprintk (RIO_DEBUG_CMD, "Unknown RUP %d\n", RBYTE(PacketP->dest_port)); | ||
781 | FreeMe = 1; | ||
782 | break; | ||
783 | } | ||
784 | |||
785 | if ( FreeMe ) { | ||
786 | rio_dprintk (RIO_DEBUG_CMD, "Free processed incoming command packet\n"); | ||
787 | put_free_end(HostP,PacketP); | ||
788 | |||
789 | WWORD(UnixRupP->RupP->rxcontrol , RX_RUP_INACTIVE); | ||
790 | |||
791 | if ( RWORD(UnixRupP->RupP->handshake)==PHB_HANDSHAKE_SET ) { | ||
792 | rio_dprintk (RIO_DEBUG_CMD, "Handshake rup %d\n",Rup); | ||
793 | WWORD(UnixRupP->RupP->handshake, | ||
794 | PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET); | ||
795 | } | ||
796 | } | ||
797 | } | ||
798 | |||
799 | /* | ||
800 | ** IF a command was running on the port, | ||
801 | ** and it has completed, then tidy it up. | ||
802 | */ | ||
803 | if ( (CmdBlkP = UnixRupP->CmdPendingP) && /* ASSIGN! */ | ||
804 | (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) { | ||
805 | /* | ||
806 | ** we are idle. | ||
807 | ** there is a command in pending. | ||
808 | ** Therefore, this command has finished. | ||
809 | ** So, wakeup whoever is waiting for it (and tell them | ||
810 | ** what happened). | ||
811 | */ | ||
812 | if ( CmdBlkP->Packet.dest_port == BOOT_RUP ) | ||
813 | rio_dprintk (RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n", | ||
814 | CmdBlkP->Packet.len & 0x80 ? "Command":"Data", | ||
815 | CmdBlkP->Packet.data[0]); | ||
816 | |||
817 | rio_dprintk (RIO_DEBUG_CMD, "Command 0x%x completed\n",(int)CmdBlkP); | ||
818 | |||
819 | /* | ||
820 | ** Clear the Rup lock to prevent mutual exclusion. | ||
821 | */ | ||
822 | if ( CmdBlkP->PostFuncP ) { | ||
823 | rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); | ||
824 | (*CmdBlkP->PostFuncP) (CmdBlkP->PostArg,CmdBlkP); | ||
825 | rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); | ||
826 | } | ||
827 | |||
828 | /* | ||
829 | ** ....clear the pending flag.... | ||
830 | */ | ||
831 | UnixRupP->CmdPendingP = NULL; | ||
832 | |||
833 | /* | ||
834 | ** ....and return the command block to the freelist. | ||
835 | */ | ||
836 | RIOFreeCmdBlk( CmdBlkP ); | ||
837 | } | ||
838 | |||
839 | /* | ||
840 | ** If there is a command for this rup, and the rup | ||
841 | ** is idle, then process the command | ||
842 | */ | ||
843 | if ( (CmdBlkP = UnixRupP->CmdsWaitingP) && /* ASSIGN! */ | ||
844 | (UnixRupP->CmdPendingP == NULL) && | ||
845 | (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) { | ||
846 | /* | ||
847 | ** if the pre-function is non-zero, call it. | ||
848 | ** If it returns RIO_FAIL then don't | ||
849 | ** send this command yet! | ||
850 | */ | ||
851 | #ifdef CHECK | ||
852 | CheckCmdBlkP (CmdBlkP); | ||
853 | #endif | ||
854 | if ( !(CmdBlkP->PreFuncP ? | ||
855 | (*CmdBlkP->PreFuncP)(CmdBlkP->PreArg, CmdBlkP) : TRUE)) { | ||
856 | rio_dprintk (RIO_DEBUG_CMD, "Not ready to start command 0x%x\n",(int)CmdBlkP); | ||
857 | } | ||
858 | else { | ||
859 | rio_dprintk (RIO_DEBUG_CMD, "Start new command 0x%x Cmd byte is 0x%x\n", | ||
860 | (int)CmdBlkP, CmdBlkP->Packet.data[0]); | ||
861 | /* | ||
862 | ** Whammy! blat that pack! | ||
863 | */ | ||
864 | #ifdef CHECK | ||
865 | CheckPacketP ((PKT *)RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt)); | ||
866 | #endif | ||
867 | HostP->Copy( (caddr_t)&CmdBlkP->Packet, | ||
868 | RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(PKT)); | ||
869 | |||
870 | /* | ||
871 | ** remove the command from the rup command queue... | ||
872 | */ | ||
873 | UnixRupP->CmdsWaitingP = CmdBlkP->NextP; | ||
874 | |||
875 | /* | ||
876 | ** ...and place it on the pending position. | ||
877 | */ | ||
878 | UnixRupP->CmdPendingP = CmdBlkP; | ||
879 | |||
880 | /* | ||
881 | ** set the command register | ||
882 | */ | ||
883 | WWORD(UnixRupP->RupP->txcontrol,TX_PACKET_READY); | ||
884 | |||
885 | /* | ||
886 | ** the command block will be freed | ||
887 | ** when the command has been processed. | ||
888 | */ | ||
889 | } | ||
890 | } | ||
891 | spin_unlock_irqrestore(&UnixRupP->RupLock, flags); | ||
892 | } while ( Rup ); | ||
893 | } | ||
894 | |||
895 | int | ||
896 | RIOWFlushMark(int iPortP, struct CmdBlk *CmdBlkP) | ||
897 | { | ||
898 | struct Port * PortP = (struct Port *)iPortP; | ||
899 | unsigned long flags; | ||
900 | |||
901 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
902 | #ifdef CHECK | ||
903 | CheckPortP( PortP ); | ||
904 | #endif | ||
905 | PortP->WflushFlag++; | ||
906 | PortP->MagicFlags |= MAGIC_FLUSH; | ||
907 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
908 | return RIOUnUse( iPortP, CmdBlkP ); | ||
909 | } | ||
910 | |||
911 | int | ||
912 | RIORFlushEnable(int iPortP, struct CmdBlk *CmdBlkP) | ||
913 | { | ||
914 | struct Port * PortP = (struct Port *)iPortP; | ||
915 | PKT *PacketP; | ||
916 | unsigned long flags; | ||
917 | |||
918 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
919 | |||
920 | while ( can_remove_receive(&PacketP, PortP) ) { | ||
921 | remove_receive(PortP); | ||
922 | ShowPacket(DBG_PROC, PacketP ); | ||
923 | put_free_end( PortP->HostP, PacketP ); | ||
924 | } | ||
925 | |||
926 | if ( RWORD(PortP->PhbP->handshake)==PHB_HANDSHAKE_SET ) { | ||
927 | /* | ||
928 | ** MAGIC! (Basically, handshake the RX buffer, so that | ||
929 | ** the RTAs upstream can be re-enabled.) | ||
930 | */ | ||
931 | rio_dprintk (RIO_DEBUG_CMD, "Util: Set RX handshake bit\n"); | ||
932 | WWORD(PortP->PhbP->handshake, PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET); | ||
933 | } | ||
934 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
935 | return RIOUnUse( iPortP, CmdBlkP ); | ||
936 | } | ||
937 | |||
938 | int | ||
939 | RIOUnUse(int iPortP, struct CmdBlk *CmdBlkP) | ||
940 | { | ||
941 | struct Port * PortP = (struct Port *)iPortP; | ||
942 | unsigned long flags; | ||
943 | |||
944 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
945 | |||
946 | #ifdef CHECK | ||
947 | CheckPortP( PortP ); | ||
948 | #endif | ||
949 | rio_dprintk (RIO_DEBUG_CMD, "Decrement in use count for port\n"); | ||
950 | |||
951 | if (PortP->InUse) { | ||
952 | if ( --PortP->InUse != NOT_INUSE ) { | ||
953 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
954 | return 0; | ||
955 | } | ||
956 | } | ||
957 | /* | ||
958 | ** While PortP->InUse is set (i.e. a preemptive command has been sent to | ||
959 | ** the RTA and is awaiting completion), any transmit data is prevented from | ||
960 | ** being transferred from the write queue into the transmit packets | ||
961 | ** (add_transmit) and no furthur transmit interrupt will be sent for that | ||
962 | ** data. The next interrupt will occur up to 500ms later (RIOIntr is called | ||
963 | ** twice a second as a saftey measure). This was the case when kermit was | ||
964 | ** used to send data into a RIO port. After each packet was sent, TCFLSH | ||
965 | ** was called to flush the read queue preemptively. PortP->InUse was | ||
966 | ** incremented, thereby blocking the 6 byte acknowledgement packet | ||
967 | ** transmitted back. This acknowledgment hung around for 500ms before | ||
968 | ** being sent, thus reducing input performance substantially!. | ||
969 | ** When PortP->InUse becomes NOT_INUSE, we must ensure that any data | ||
970 | ** hanging around in the transmit buffer is sent immediately. | ||
971 | */ | ||
972 | WWORD(PortP->HostP->ParmMapP->tx_intr, 1); | ||
973 | /* What to do here .. | ||
974 | wakeup( (caddr_t)&(PortP->InUse) ); | ||
975 | */ | ||
976 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
977 | return 0; | ||
978 | } | ||
979 | |||
980 | void | ||
981 | ShowPacket(uint Flags, struct PKT *PacketP) | ||
982 | { | ||
983 | } | ||
984 | |||
985 | /* | ||
986 | ** | ||
987 | ** How to use this file: | ||
988 | ** | ||
989 | ** To send a command down a rup, you need to allocate a command block, fill | ||
990 | ** in the packet information, fill in the command number, fill in the pre- | ||
991 | ** and post- functions and arguments, and then add the command block to the | ||
992 | ** queue of command blocks for the port in question. When the port is idle, | ||
993 | ** then the pre-function will be called. If this returns RIO_FAIL then the | ||
994 | ** command will be re-queued and tried again at a later date (probably in one | ||
995 | ** clock tick). If the pre-function returns NOT RIO_FAIL, then the command | ||
996 | ** packet will be queued on the RUP, and the txcontrol field set to the | ||
997 | ** command number. When the txcontrol field has changed from being the | ||
998 | ** command number, then the post-function will be called, with the argument | ||
999 | ** specified earlier, a pointer to the command block, and the value of | ||
1000 | ** txcontrol. | ||
1001 | ** | ||
1002 | ** To allocate a command block, call RIOGetCmdBlk(). This returns a pointer | ||
1003 | ** to the command block structure allocated, or NULL if there aren't any. | ||
1004 | ** The block will have been zeroed for you. | ||
1005 | ** | ||
1006 | ** The structure has the following fields: | ||
1007 | ** | ||
1008 | ** struct CmdBlk | ||
1009 | ** { | ||
1010 | ** struct CmdBlk *NextP; ** Pointer to next command block ** | ||
1011 | ** struct PKT Packet; ** A packet, to copy to the rup ** | ||
1012 | ** int (*PreFuncP)(); ** The func to call to check if OK ** | ||
1013 | ** int PreArg; ** The arg for the func ** | ||
1014 | ** int (*PostFuncP)(); ** The func to call when completed ** | ||
1015 | ** int PostArg; ** The arg for the func ** | ||
1016 | ** }; | ||
1017 | ** | ||
1018 | ** You need to fill in ALL fields EXCEPT NextP, which is used to link the | ||
1019 | ** blocks together either on the free list or on the Rup list. | ||
1020 | ** | ||
1021 | ** Packet is an actual packet structure to be filled in with the packet | ||
1022 | ** information associated with the command. You need to fill in everything, | ||
1023 | ** as the command processore doesn't process the command packet in any way. | ||
1024 | ** | ||
1025 | ** The PreFuncP is called before the packet is enqueued on the host rup. | ||
1026 | ** PreFuncP is called as (*PreFuncP)(PreArg, CmdBlkP);. PreFuncP must | ||
1027 | ** return !RIO_FAIL to have the packet queued on the rup, and RIO_FAIL | ||
1028 | ** if the packet is NOT to be queued. | ||
1029 | ** | ||
1030 | ** The PostFuncP is called when the command has completed. It is called | ||
1031 | ** as (*PostFuncP)(PostArg, CmdBlkP, txcontrol);. PostFuncP is not expected | ||
1032 | ** to return a value. PostFuncP does NOT need to free the command block, | ||
1033 | ** as this happens automatically after PostFuncP returns. | ||
1034 | ** | ||
1035 | ** Once the command block has been filled in, it is attached to the correct | ||
1036 | ** queue by calling RIOQueueCmdBlk( HostP, Rup, CmdBlkP ) where HostP is | ||
1037 | ** a pointer to the struct Host, Rup is the NUMBER of the rup (NOT a pointer | ||
1038 | ** to it!), and CmdBlkP is the pointer to the command block allocated using | ||
1039 | ** RIOGetCmdBlk(). | ||
1040 | ** | ||
1041 | */ | ||