1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#include <linux/module.h>
34#include <linux/slab.h>
35#include <linux/errno.h>
36#include <asm/io.h>
37#include <asm/system.h>
38#include <asm/string.h>
39#include <asm/uaccess.h>
40
41#include <linux/termios.h>
42#include <linux/serial.h>
43
44#include <linux/generic_serial.h>
45
46
47#include "linux_compat.h"
48#include "rio_linux.h"
49#include "pkt.h"
50#include "daemon.h"
51#include "rio.h"
52#include "riospace.h"
53#include "cmdpkt.h"
54#include "map.h"
55#include "rup.h"
56#include "port.h"
57#include "riodrvr.h"
58#include "rioinfo.h"
59#include "func.h"
60#include "errors.h"
61#include "pci.h"
62
63#include "parmmap.h"
64#include "unixrup.h"
65#include "board.h"
66#include "host.h"
67#include "phb.h"
68#include "link.h"
69#include "cmdblk.h"
70#include "route.h"
71#include "cirrus.h"
72#include "rioioctl.h"
73#include "param.h"
74
75static int RIOCheckIsolated(struct rio_info *, struct Host *, unsigned int);
76static int RIOIsolate(struct rio_info *, struct Host *, unsigned int);
77static int RIOCheck(struct Host *, unsigned int);
78static void RIOConCon(struct rio_info *, struct Host *, unsigned int, unsigned int, unsigned int, unsigned int, int);
79
80
81
82
83
84
85int RIORouteRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT __iomem * PacketP)
86{
87 struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *) PacketP->data;
88 struct PktCmd_M *PktReplyP;
89 struct CmdBlk *CmdBlkP;
90 struct Port *PortP;
91 struct Map *MapP;
92 struct Top *TopP;
93 int ThisLink, ThisLinkMin, ThisLinkMax;
94 int port;
95 int Mod, Mod1, Mod2;
96 unsigned short RtaType;
97 unsigned int RtaUniq;
98 unsigned int ThisUnit, ThisUnit2;
99 unsigned int OldUnit, NewUnit, OldLink, NewLink;
100 char *MyType, *MyName;
101 int Lies;
102 unsigned long flags;
103
104
105
106
107 if (readb(&PktCmdP->Command) == ROUTE_TOPOLOGY) {
108 MapP = HostP->Mapping;
109
110
111
112
113
114
115
116
117 if (Rup >= (unsigned short) MAX_RUP) {
118 ThisUnit = HOST_ID;
119 TopP = HostP->Topology;
120 MyType = "Host";
121 MyName = HostP->Name;
122 ThisLinkMin = ThisLinkMax = Rup - MAX_RUP;
123 } else {
124 ThisUnit = Rup + 1;
125 TopP = HostP->Mapping[Rup].Topology;
126 MyType = "RTA";
127 MyName = HostP->Mapping[Rup].Name;
128 ThisLinkMin = 0;
129 ThisLinkMax = LINKS_PER_UNIT - 1;
130 }
131
132
133
134
135
136
137 Lies = 0;
138 for (ThisLink = ThisLinkMin + 1; ThisLink <= ThisLinkMax; ThisLink++) {
139
140
141
142
143 if (readb(&PktCmdP->RouteTopology[ThisLink].Unit) > (unsigned short) MAX_RUP)
144 continue;
145
146 for (NewLink = ThisLinkMin; NewLink < ThisLink; NewLink++) {
147 if ((readb(&PktCmdP->RouteTopology[ThisLink].Unit) == readb(&PktCmdP->RouteTopology[NewLink].Unit)) && (readb(&PktCmdP->RouteTopology[ThisLink].Link) == readb(&PktCmdP->RouteTopology[NewLink].Link))) {
148 Lies++;
149 }
150 }
151 }
152
153 if (Lies) {
154 rio_dprintk(RIO_DEBUG_ROUTE, "LIES! DAMN LIES! %d LIES!\n", Lies);
155 rio_dprintk(RIO_DEBUG_ROUTE, "%d:%c %d:%c %d:%c %d:%c\n",
156 readb(&PktCmdP->RouteTopology[0].Unit),
157 'A' + readb(&PktCmdP->RouteTopology[0].Link),
158 readb(&PktCmdP->RouteTopology[1].Unit),
159 'A' + readb(&PktCmdP->RouteTopology[1].Link), readb(&PktCmdP->RouteTopology[2].Unit), 'A' + readb(&PktCmdP->RouteTopology[2].Link), readb(&PktCmdP->RouteTopology[3].Unit), 'A' + readb(&PktCmdP->RouteTopology[3].Link));
160 return 1;
161 }
162
163
164
165
166 for (ThisLink = ThisLinkMin; ThisLink <= ThisLinkMax; ThisLink++) {
167
168
169
170 OldUnit = TopP[ThisLink].Unit;
171 OldLink = TopP[ThisLink].Link;
172
173
174
175
176 NewUnit = readb(&PktCmdP->RouteTopology[ThisLink].Unit);
177 NewLink = readb(&PktCmdP->RouteTopology[ThisLink].Link);
178
179 if (OldUnit != NewUnit || OldLink != NewLink) {
180
181
182
183
184 if (NewUnit > MAX_RUP && NewUnit != ROUTE_DISCONNECT && NewUnit != ROUTE_NO_ID && NewUnit != ROUTE_INTERCONNECT) {
185 rio_dprintk(RIO_DEBUG_ROUTE, "I have a link from %s %s to unit %d:%d - I don't like it.\n", MyType, MyName, NewUnit, NewLink);
186 } else {
187
188
189
190 TopP[ThisLink].Unit = NewUnit;
191 TopP[ThisLink].Link = NewLink;
192
193 RIOSetChange(p);
194
195 if (OldUnit <= MAX_RUP) {
196
197
198
199 if (!p->RIONoMessage)
200 RIOConCon(p, HostP, ThisUnit, ThisLink, OldUnit, OldLink, DISCONNECT);
201 }
202
203 if ((NewUnit <= MAX_RUP) && !p->RIONoMessage)
204 RIOConCon(p, HostP, ThisUnit, ThisLink, NewUnit, NewLink, CONNECT);
205
206 if (NewUnit == ROUTE_NO_ID)
207 rio_dprintk(RIO_DEBUG_ROUTE, "%s %s (%c) is connected to an unconfigured unit.\n", MyType, MyName, 'A' + ThisLink);
208
209 if (NewUnit == ROUTE_INTERCONNECT) {
210 if (!p->RIONoMessage)
211 printk(KERN_DEBUG "rio: %s '%s' (%c) is connected to another network.\n", MyType, MyName, 'A' + ThisLink);
212 }
213
214
215
216
217
218
219 if (OldUnit == HOST_ID) {
220 if (HostP->Topology[OldLink].Unit == ThisUnit && HostP->Topology[OldLink].Link == ThisLink) {
221 rio_dprintk(RIO_DEBUG_ROUTE, "SETTING HOST (%c) TO DISCONNECTED!\n", OldLink + 'A');
222 HostP->Topology[OldLink].Unit = ROUTE_DISCONNECT;
223 HostP->Topology[OldLink].Link = NO_LINK;
224 } else {
225 rio_dprintk(RIO_DEBUG_ROUTE, "HOST(%c) WAS NOT CONNECTED TO %s (%c)!\n", OldLink + 'A', HostP->Mapping[ThisUnit - 1].Name, ThisLink + 'A');
226 }
227 } else if (OldUnit <= MAX_RUP) {
228 if (HostP->Mapping[OldUnit - 1].Topology[OldLink].Unit == ThisUnit && HostP->Mapping[OldUnit - 1].Topology[OldLink].Link == ThisLink) {
229 rio_dprintk(RIO_DEBUG_ROUTE, "SETTING RTA %s (%c) TO DISCONNECTED!\n", HostP->Mapping[OldUnit - 1].Name, OldLink + 'A');
230 HostP->Mapping[OldUnit - 1].Topology[OldLink].Unit = ROUTE_DISCONNECT;
231 HostP->Mapping[OldUnit - 1].Topology[OldLink].Link = NO_LINK;
232 } else {
233 rio_dprintk(RIO_DEBUG_ROUTE, "RTA %s (%c) WAS NOT CONNECTED TO %s (%c)\n", HostP->Mapping[OldUnit - 1].Name, OldLink + 'A', HostP->Mapping[ThisUnit - 1].Name, ThisLink + 'A');
234 }
235 }
236 if (NewUnit == HOST_ID) {
237 rio_dprintk(RIO_DEBUG_ROUTE, "MARKING HOST (%c) CONNECTED TO %s (%c)\n", NewLink + 'A', MyName, ThisLink + 'A');
238 HostP->Topology[NewLink].Unit = ThisUnit;
239 HostP->Topology[NewLink].Link = ThisLink;
240 } else if (NewUnit <= MAX_RUP) {
241 rio_dprintk(RIO_DEBUG_ROUTE, "MARKING RTA %s (%c) CONNECTED TO %s (%c)\n", HostP->Mapping[NewUnit - 1].Name, NewLink + 'A', MyName, ThisLink + 'A');
242 HostP->Mapping[NewUnit - 1].Topology[NewLink].Unit = ThisUnit;
243 HostP->Mapping[NewUnit - 1].Topology[NewLink].Link = ThisLink;
244 }
245 }
246 RIOSetChange(p);
247 RIOCheckIsolated(p, HostP, OldUnit);
248 }
249 }
250 return 1;
251 }
252
253
254
255
256 if (readb(&PktCmdP->Command) != ROUTE_REQUEST) {
257 rio_dprintk(RIO_DEBUG_ROUTE, "Unknown command %d received on rup %d host %p ROUTE_RUP\n", readb(&PktCmdP->Command), Rup, HostP);
258 return 1;
259 }
260
261 RtaUniq = (readb(&PktCmdP->UniqNum[0])) + (readb(&PktCmdP->UniqNum[1]) << 8) + (readb(&PktCmdP->UniqNum[2]) << 16) + (readb(&PktCmdP->UniqNum[3]) << 24);
262
263
264
265
266 RtaType = GetUnitType(RtaUniq);
267
268 rio_dprintk(RIO_DEBUG_ROUTE, "Received a request for an ID for serial number %x\n", RtaUniq);
269
270 Mod = readb(&PktCmdP->ModuleTypes);
271 Mod1 = LONYBLE(Mod);
272 if (RtaType == TYPE_RTA16) {
273
274
275
276
277 Mod2 = Mod1;
278 rio_dprintk(RIO_DEBUG_ROUTE, "Backplane type is %s (all ports)\n", p->RIOModuleTypes[Mod1].Name);
279 } else {
280 Mod2 = HINYBLE(Mod);
281 rio_dprintk(RIO_DEBUG_ROUTE, "Module types are %s (ports 0-3) and %s (ports 4-7)\n", p->RIOModuleTypes[Mod1].Name, p->RIOModuleTypes[Mod2].Name);
282 }
283
284
285
286
287 if (!(CmdBlkP = RIOGetCmdBlk())) {
288 rio_dprintk(RIO_DEBUG_ROUTE, "No command blocks to route RTA! come back later.\n");
289 return 0;
290 }
291
292
293
294
295 CmdBlkP->Packet.dest_unit = Rup;
296 CmdBlkP->Packet.dest_port = ROUTE_RUP;
297 CmdBlkP->Packet.src_unit = HOST_ID;
298 CmdBlkP->Packet.src_port = ROUTE_RUP;
299 CmdBlkP->Packet.len = PKT_CMD_BIT | 1;
300 CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;
301 PktReplyP = (struct PktCmd_M *) CmdBlkP->Packet.data;
302
303 if (!RIOBootOk(p, HostP, RtaUniq)) {
304 rio_dprintk(RIO_DEBUG_ROUTE, "RTA %x tried to get an ID, but does not belong - FOAD it!\n", RtaUniq);
305 PktReplyP->Command = ROUTE_FOAD;
306 memcpy(PktReplyP->CommandText, "RT_FOAD", 7);
307 RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
308 return 1;
309 }
310
311
312
313
314 for (ThisUnit = 0; ThisUnit < MAX_RUP; ThisUnit++) {
315 rio_dprintk(RIO_DEBUG_ROUTE, "Entry %d Flags=%s %s UniqueNum=0x%x\n",
316 ThisUnit, HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE ? "Slot-In-Use" : "Not In Use", HostP->Mapping[ThisUnit].Flags & SLOT_TENTATIVE ? "Slot-Tentative" : "Not Tentative", HostP->Mapping[ThisUnit].RtaUniqueNum);
317
318
319
320
321 if ((HostP->Mapping[ThisUnit].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && (HostP->Mapping[ThisUnit].RtaUniqueNum == RtaUniq)) {
322 if (RtaType == TYPE_RTA16) {
323 ThisUnit2 = HostP->Mapping[ThisUnit].ID2 - 1;
324 rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slots %d+%d\n", RtaUniq, ThisUnit, ThisUnit2);
325 } else
326 rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slot %d\n", RtaUniq, ThisUnit);
327
328
329
330
331
332
333 if ((HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) && !(HostP->Mapping[ThisUnit].Flags & RTA_BOOTED)) {
334 if (!(HostP->Mapping[ThisUnit].Flags & MSG_DONE)) {
335 if (!p->RIONoMessage)
336 printk(KERN_DEBUG "rio: RTA '%s' is being updated.\n", HostP->Mapping[ThisUnit].Name);
337 HostP->Mapping[ThisUnit].Flags |= MSG_DONE;
338 }
339 PktReplyP->Command = ROUTE_FOAD;
340 memcpy(PktReplyP->CommandText, "RT_FOAD", 7);
341 RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
342 return 1;
343 }
344
345
346
347
348
349
350
351 PktReplyP->Command = ROUTE_ALLOCATE;
352 PktReplyP->IDNum = ThisUnit + 1;
353 if (RtaType == TYPE_RTA16) {
354 if (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE)
355
356
357
358
359 RIOFixPhbs(p, HostP, ThisUnit2);
360 PktReplyP->IDNum2 = ThisUnit2 + 1;
361 rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated IDs %d+%d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum, PktReplyP->IDNum2);
362 } else {
363 PktReplyP->IDNum2 = ROUTE_NO_ID;
364 rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated ID %d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum);
365 }
366 memcpy(PktReplyP->CommandText, "RT_ALLOCAT", 10);
367
368 RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
369
370
371
372
373
374
375 if ((HostP->Mapping[ThisUnit].Flags & RTA_NEWBOOT) && (HostP->Mapping[ThisUnit].SysPort != NO_PORT)) {
376
377
378
379
380
381 for (port = 0; port < PORTS_PER_RTA; port++) {
382 PortP = p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort];
383 if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
384 rio_dprintk(RIO_DEBUG_ROUTE, "Re-opened this port\n");
385 rio_spin_lock_irqsave(&PortP->portSem, flags);
386 PortP->MagicFlags |= MAGIC_REBOOT;
387 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
388 }
389 }
390 if (RtaType == TYPE_RTA16) {
391 for (port = 0; port < PORTS_PER_RTA; port++) {
392 PortP = p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort];
393 if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
394 rio_dprintk(RIO_DEBUG_ROUTE, "Re-opened this port\n");
395 rio_spin_lock_irqsave(&PortP->portSem, flags);
396 PortP->MagicFlags |= MAGIC_REBOOT;
397 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
398 }
399 }
400 }
401 }
402
403
404
405
406 HostP->UnixRups[ThisUnit].ModTypes = Mod;
407 if (RtaType == TYPE_RTA16)
408 HostP->UnixRups[ThisUnit2].ModTypes = Mod;
409
410
411
412
413
414
415 if (HostP->Mapping[ThisUnit].SysPort != NO_PORT) {
416 for (port = 0; port < PORTS_PER_MODULE; port++) {
417 p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
418 p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port];
419 p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
420 p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
421 }
422 if (RtaType == TYPE_RTA16) {
423 for (port = 0; port < PORTS_PER_MODULE; port++) {
424 p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
425 p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port];
426 p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
427 p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
428 }
429 }
430 }
431
432
433
434
435 return 1;
436 }
437 }
438
439
440
441
442
443
444
445 for (ThisUnit = 0; ThisUnit < HostP->NumExtraBooted; ThisUnit++)
446 if (HostP->ExtraUnits[ThisUnit] == RtaUniq)
447 break;
448 if (ThisUnit == HostP->NumExtraBooted && ThisUnit != MAX_EXTRA_UNITS) {
449
450
451
452
453
454
455
456
457
458
459 static int UnknownMesgDone = 0;
460
461 if (!UnknownMesgDone) {
462 if (!p->RIONoMessage)
463 printk(KERN_DEBUG "rio: One or more unknown RTAs are being updated.\n");
464 UnknownMesgDone = 1;
465 }
466
467 PktReplyP->Command = ROUTE_FOAD;
468 memcpy(PktReplyP->CommandText, "RT_FOAD", 7);
469 } else {
470
471
472
473
474
475
476 if (RtaType == TYPE_RTA16) {
477 if (RIOFindFreeID(p, HostP, &ThisUnit, &ThisUnit2) == 0) {
478 RIODefaultName(p, HostP, ThisUnit);
479 rio_fill_host_slot(ThisUnit, ThisUnit2, RtaUniq, HostP);
480 }
481 } else {
482 if (RIOFindFreeID(p, HostP, &ThisUnit, NULL) == 0) {
483 RIODefaultName(p, HostP, ThisUnit);
484 rio_fill_host_slot(ThisUnit, 0, RtaUniq, HostP);
485 }
486 }
487 PktReplyP->Command = ROUTE_USED;
488 memcpy(PktReplyP->CommandText, "RT_USED", 7);
489 }
490 RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
491 return 1;
492}
493
494
495void RIOFixPhbs(struct rio_info *p, struct Host *HostP, unsigned int unit)
496{
497 unsigned short link, port;
498 struct Port *PortP;
499 unsigned long flags;
500 int PortN = HostP->Mapping[unit].SysPort;
501
502 rio_dprintk(RIO_DEBUG_ROUTE, "RIOFixPhbs unit %d sysport %d\n", unit, PortN);
503
504 if (PortN != -1) {
505 unsigned short dest_unit = HostP->Mapping[unit].ID2;
506
507
508
509
510 PortP = p->RIOPortp[HostP->Mapping[dest_unit - 1].SysPort];
511
512 link = readw(&PortP->PhbP->link);
513
514 for (port = 0; port < PORTS_PER_RTA; port++, PortN++) {
515 unsigned short dest_port = port + 8;
516 u16 __iomem *TxPktP;
517 struct PKT __iomem *Pkt;
518
519 PortP = p->RIOPortp[PortN];
520
521 rio_spin_lock_irqsave(&PortP->portSem, flags);
522
523
524
525
526 if (!PortP->TxStart) {
527 rio_dprintk(RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n");
528 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
529 break;
530 }
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548 for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) {
549
550
551
552
553
554 Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(TxPktP));
555
556
557
558
559 Pkt = (struct PKT __iomem *) ((unsigned long) Pkt & ~PKT_IN_USE);
560 writeb(dest_unit, &Pkt->dest_unit);
561 writeb(dest_port, &Pkt->dest_port);
562 }
563 rio_dprintk(RIO_DEBUG_ROUTE, "phb dest: Old %x:%x New %x:%x\n", readw(&PortP->PhbP->destination) & 0xff, (readw(&PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port);
564 writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination);
565 writew(link, &PortP->PhbP->link);
566
567 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
568 }
569
570
571
572
573 if (link > 3)
574 return;
575 if (((unit * 8) + 7) > readw(&HostP->LinkStrP[link].last_port)) {
576 rio_dprintk(RIO_DEBUG_ROUTE, "last port on host link %d: %d\n", link, (unit * 8) + 7);
577 writew((unit * 8) + 7, &HostP->LinkStrP[link].last_port);
578 }
579 }
580}
581
582
583
584
585
586
587
588static int RIOCheckIsolated(struct rio_info *p, struct Host *HostP, unsigned int UnitId)
589{
590 unsigned long flags;
591 rio_spin_lock_irqsave(&HostP->HostLock, flags);
592
593 if (RIOCheck(HostP, UnitId)) {
594 rio_dprintk(RIO_DEBUG_ROUTE, "Unit %d is NOT isolated\n", UnitId);
595 rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
596 return (0);
597 }
598
599 RIOIsolate(p, HostP, UnitId);
600 RIOSetChange(p);
601 rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
602 return 1;
603}
604
605
606
607
608
609
610static int RIOIsolate(struct rio_info *p, struct Host *HostP, unsigned int UnitId)
611{
612 unsigned int link, unit;
613
614 UnitId--;
615
616 if (UnitId >= MAX_RUP)
617 return (0);
618
619 if (HostP->Mapping[UnitId].Flags & BEEN_HERE)
620 return (0);
621
622 HostP->Mapping[UnitId].Flags |= BEEN_HERE;
623
624 if (p->RIOPrintDisabled == DO_PRINT)
625 rio_dprintk(RIO_DEBUG_ROUTE, "RIOMesgIsolated %s", HostP->Mapping[UnitId].Name);
626
627 for (link = 0; link < LINKS_PER_UNIT; link++) {
628 unit = HostP->Mapping[UnitId].Topology[link].Unit;
629 HostP->Mapping[UnitId].Topology[link].Unit = ROUTE_DISCONNECT;
630 HostP->Mapping[UnitId].Topology[link].Link = NO_LINK;
631 RIOIsolate(p, HostP, unit);
632 }
633 HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
634 return 1;
635}
636
637static int RIOCheck(struct Host *HostP, unsigned int UnitId)
638{
639 unsigned char link;
640
641
642 rio_dprintk(RIO_DEBUG_ROUTE, "RIOCheck : UnitID = %d\n", UnitId);
643
644 if (UnitId == HOST_ID) {
645
646 return 1;
647 }
648
649 UnitId--;
650
651 if (UnitId >= MAX_RUP) {
652
653 return 0;
654 }
655
656 for (link = 0; link < LINKS_PER_UNIT; link++) {
657 if (HostP->Mapping[UnitId].Topology[link].Unit == HOST_ID) {
658
659
660 return 1;
661 }
662 }
663
664 if (HostP->Mapping[UnitId].Flags & BEEN_HERE) {
665
666 return 0;
667 }
668
669 HostP->Mapping[UnitId].Flags |= BEEN_HERE;
670
671 for (link = 0; link < LINKS_PER_UNIT; link++) {
672
673 if (RIOCheck(HostP, HostP->Mapping[UnitId].Topology[link].Unit)) {
674
675 HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
676 return 1;
677 }
678 }
679
680 HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
681
682
683
684 return 0;
685}
686
687
688
689
690
691unsigned int GetUnitType(unsigned int Uniq)
692{
693 switch ((Uniq >> 28) & 0xf) {
694 case RIO_AT:
695 case RIO_MCA:
696 case RIO_EISA:
697 case RIO_PCI:
698 rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: Host\n");
699 return (TYPE_HOST);
700 case RIO_RTA_16:
701 rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: 16 port RTA\n");
702 return (TYPE_RTA16);
703 case RIO_RTA:
704 rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: 8 port RTA\n");
705 return (TYPE_RTA8);
706 default:
707 rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: Unrecognised\n");
708 return (99);
709 }
710}
711
712int RIOSetChange(struct rio_info *p)
713{
714 if (p->RIOQuickCheck != NOT_CHANGED)
715 return (0);
716 p->RIOQuickCheck = CHANGED;
717 if (p->RIOSignalProcess) {
718 rio_dprintk(RIO_DEBUG_ROUTE, "Send SIG-HUP");
719
720
721
722 }
723 return (0);
724}
725
726static void RIOConCon(struct rio_info *p,
727 struct Host *HostP,
728 unsigned int FromId,
729 unsigned int FromLink,
730 unsigned int ToId,
731 unsigned int ToLink,
732 int Change)
733{
734 char *FromName;
735 char *FromType;
736 char *ToName;
737 char *ToType;
738 unsigned int tp;
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767 if (Change == CONNECT) {
768 if (p->RIORtaDisCons)
769 p->RIORtaDisCons--;
770 } else {
771 p->RIORtaDisCons++;
772 }
773
774 if (p->RIOPrintDisabled == DONT_PRINT)
775 return;
776
777 if (FromId > ToId) {
778 tp = FromId;
779 FromId = ToId;
780 ToId = tp;
781 tp = FromLink;
782 FromLink = ToLink;
783 ToLink = tp;
784 }
785
786 FromName = FromId ? HostP->Mapping[FromId - 1].Name : HostP->Name;
787 FromType = FromId ? "RTA" : "HOST";
788 ToName = ToId ? HostP->Mapping[ToId - 1].Name : HostP->Name;
789 ToType = ToId ? "RTA" : "HOST";
790
791 rio_dprintk(RIO_DEBUG_ROUTE, "Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected");
792 printk(KERN_DEBUG "rio: Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected");
793}
794
795
796
797
798
799
800
801static int RIORemoveFromSavedTable(struct rio_info *p, struct Map *pMap)
802{
803 int entry;
804
805
806
807
808
809
810 for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
811 if (p->RIOSavedTable[entry].RtaUniqueNum == pMap->RtaUniqueNum) {
812 memset(&p->RIOSavedTable[entry], 0, sizeof(struct Map));
813 }
814 }
815 return 0;
816}
817
818
819
820
821
822
823
824
825static int RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit)
826{
827 int link;
828
829
830 rio_dprintk(RIO_DEBUG_ROUTE, "RIOFreeDisconnect unit %d\n", unit);
831
832
833
834
835
836 for (link = 0; link < LINKS_PER_UNIT; link++) {
837 if (HostP->Mapping[unit].Topology[link].Unit != ROUTE_DISCONNECT)
838 break;
839 }
840
841
842
843
844 if (link < LINKS_PER_UNIT)
845 return 1;
846
847#ifdef NEED_TO_FIX_THIS
848
849
850
851
852 rio_dprintk(RIO_DEBUG_ROUTE, "Just about to check LBOLT on entry %d\n", unit);
853 if (drv_getparm(LBOLT, (ulong_t *) & current_time))
854 rio_dprintk(RIO_DEBUG_ROUTE, "drv_getparm(LBOLT,....) Failed.\n");
855
856 elapse_time = current_time - TentTime[unit];
857 rio_dprintk(RIO_DEBUG_ROUTE, "elapse %d = current %d - tent %d (%d usec)\n", elapse_time, current_time, TentTime[unit], drv_hztousec(elapse_time));
858 if (drv_hztousec(elapse_time) < WAIT_TO_FINISH) {
859 rio_dprintk(RIO_DEBUG_ROUTE, "Skipping slot %d, not timed out yet %d\n", unit, drv_hztousec(elapse_time));
860 return 1;
861 }
862#endif
863
864
865
866
867
868 if (HostP->Mapping[unit].ID2 != 0) {
869 int nOther = (HostP->Mapping[unit].ID2) - 1;
870
871 rio_dprintk(RIO_DEBUG_ROUTE, "RioFreedis second slot %d.\n", nOther);
872 memset(&HostP->Mapping[nOther], 0, sizeof(struct Map));
873 }
874 RIORemoveFromSavedTable(p, &HostP->Mapping[unit]);
875
876 return 0;
877}
878
879
880
881
882
883
884
885
886
887int RIOFindFreeID(struct rio_info *p, struct Host *HostP, unsigned int * pID1, unsigned int * pID2)
888{
889 int unit, tempID;
890
891
892
893
894
895
896 *pID1 = MAX_RUP;
897 if (pID2 != NULL)
898 *pID2 = MAX_RUP;
899
900
901
902
903
904
905 for (unit = 0; unit < MAX_RUP; unit++) {
906 rio_dprintk(RIO_DEBUG_ROUTE, "Scanning unit %d\n", unit);
907
908
909
910 if (HostP->Mapping[unit].Flags == 0) {
911 rio_dprintk(RIO_DEBUG_ROUTE, " This slot is empty.\n");
912
913
914
915 if (*pID1 == MAX_RUP) {
916 rio_dprintk(RIO_DEBUG_ROUTE, "Make tentative entry for first unit %d\n", unit);
917 *pID1 = unit;
918
919
920
921
922
923 if (pID2 == NULL)
924 return 0;
925 } else {
926
927
928
929 rio_dprintk(RIO_DEBUG_ROUTE, "Make tentative entry for second unit %d\n", unit);
930 *pID2 = unit;
931 return 0;
932 }
933 }
934 }
935
936
937
938
939
940
941 rio_dprintk(RIO_DEBUG_ROUTE, "Starting to scan for tentative slots\n");
942 for (unit = 0; unit < MAX_RUP; unit++) {
943 if (((HostP->Mapping[unit].Flags & SLOT_TENTATIVE) || (HostP->Mapping[unit].Flags == 0)) && !(HostP->Mapping[unit].Flags & RTA16_SECOND_SLOT)) {
944 rio_dprintk(RIO_DEBUG_ROUTE, " Slot %d looks promising.\n", unit);
945
946 if (unit == *pID1) {
947 rio_dprintk(RIO_DEBUG_ROUTE, " No it isn't, its the 1st half\n");
948 continue;
949 }
950
951
952
953
954
955
956
957
958
959 if (HostP->Mapping[unit].Flags != 0)
960 if (RIOFreeDisconnected(p, HostP, unit) != 0)
961 continue;
962
963
964
965 if (*pID1 == MAX_RUP) {
966 rio_dprintk(RIO_DEBUG_ROUTE, "Grab tentative entry for first unit %d\n", unit);
967 *pID1 = unit;
968
969
970
971
972 memset(&HostP->Mapping[unit], 0, sizeof(struct Map));
973
974
975
976
977
978 if (pID2 == NULL)
979 return 0;
980 } else {
981
982
983
984 rio_dprintk(RIO_DEBUG_ROUTE, "Grab tentative/empty entry for second unit %d\n", unit);
985 *pID2 = unit;
986
987
988
989
990 memset(&HostP->Mapping[unit], 0, sizeof(struct Map));
991
992
993
994
995
996
997
998
999 if (*pID1 > *pID2) {
1000 rio_dprintk(RIO_DEBUG_ROUTE, "Swapping IDS %d %d\n", *pID1, *pID2);
1001 tempID = *pID1;
1002 *pID1 = *pID2;
1003 *pID2 = tempID;
1004 }
1005 return 0;
1006 }
1007 }
1008 }
1009
1010
1011
1012
1013
1014 return 1;
1015}
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040