2 ** -----------------------------------------------------------------------------
4 ** Perle Specialix driver for Linux
5 ** Ported from existing RIO Driver for SCO sources.
7 * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
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.
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.
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.
25 ** Last Modified : 11/6/98 10:33:36
26 ** Retrieved : 11/6/98 10:33:48
28 ** ident @(#)rioboot.c 1.3
30 ** -----------------------------------------------------------------------------
34 static char *_rioboot_c_sccs_
= "@(#)rioboot.c 1.3";
37 #include <linux/module.h>
38 #include <linux/slab.h>
39 #include <linux/errno.h>
40 #include <linux/interrupt.h>
42 #include <asm/system.h>
43 #include <asm/string.h>
44 #include <asm/semaphore.h>
47 #include <linux/termios.h>
48 #include <linux/serial.h>
50 #include <linux/generic_serial.h>
54 #include "linux_compat.h"
55 #include "rio_linux.h"
83 static int RIOBootComplete( struct rio_info
*p
, struct Host
*HostP
, uint Rup
, struct PktCmd
*PktCmdP
);
88 /* 0 */ INTERRUPT_DISABLE
,
89 /* 1 */ INTERRUPT_DISABLE
,
90 /* 2 */ INTERRUPT_DISABLE
,
91 /* 3 */ INTERRUPT_DISABLE
,
92 /* 4 */ INTERRUPT_DISABLE
,
93 /* 5 */ INTERRUPT_DISABLE
,
94 /* 6 */ INTERRUPT_DISABLE
,
95 /* 7 */ INTERRUPT_DISABLE
,
96 /* 8 */ INTERRUPT_DISABLE
,
97 /* 9 */ IRQ_9
|INTERRUPT_ENABLE
,
98 /* 10 */ INTERRUPT_DISABLE
,
99 /* 11 */ IRQ_11
|INTERRUPT_ENABLE
,
100 /* 12 */ IRQ_12
|INTERRUPT_ENABLE
,
101 /* 13 */ INTERRUPT_DISABLE
,
102 /* 14 */ INTERRUPT_DISABLE
,
103 /* 15 */ IRQ_15
|INTERRUPT_ENABLE
107 ** Load in the RTA boot code.
110 RIOBootCodeRTA(p
, rbp
)
112 struct DownLoad
* rbp
;
118 /* Linux doesn't allow you to disable interrupts during a
119 "copyin". (Crash when a pagefault occurs). */
120 /* disable(oldspl); */
122 rio_dprintk (RIO_DEBUG_BOOT
, "Data at user address 0x%x\n",(int)rbp
->DataP
);
125 ** Check that we have set asside enough memory for this
127 if ( rbp
->Count
> SIXTY_FOUR_K
) {
128 rio_dprintk (RIO_DEBUG_BOOT
, "RTA Boot Code Too Large!\n");
129 p
->RIOError
.Error
= HOST_FILE_TOO_LARGE
;
130 /* restore(oldspl); */
135 if ( p
->RIOBooting
) {
136 rio_dprintk (RIO_DEBUG_BOOT
, "RTA Boot Code : BUSY BUSY BUSY!\n");
137 p
->RIOError
.Error
= BOOT_IN_PROGRESS
;
138 /* restore(oldspl); */
144 ** The data we load in must end on a (RTA_BOOT_DATA_SIZE) byte boundary,
145 ** so calculate how far we have to move the data up the buffer
148 offset
= (RTA_BOOT_DATA_SIZE
- (rbp
->Count
% RTA_BOOT_DATA_SIZE
)) %
152 ** Be clean, and clear the 'unused' portion of the boot buffer,
153 ** because it will (eventually) be part of the Rta run time environment
154 ** and so should be zeroed.
156 bzero( (caddr_t
)p
->RIOBootPackets
, offset
);
159 ** Copy the data from user space.
162 if ( copyin((int)rbp
->DataP
,((caddr_t
)(p
->RIOBootPackets
))+offset
,
163 rbp
->Count
) ==COPYFAIL
) {
164 rio_dprintk (RIO_DEBUG_BOOT
, "Bad data copy from user space\n");
165 p
->RIOError
.Error
= COPYIN_FAILED
;
166 /* restore(oldspl); */
172 ** Make sure that our copy of the size includes that offset we discussed
175 p
->RIONumBootPkts
= (rbp
->Count
+offset
)/RTA_BOOT_DATA_SIZE
;
176 p
->RIOBootCount
= rbp
->Count
;
178 /* restore(oldspl); */
183 void rio_start_card_running (struct Host
* HostP
)
187 switch ( HostP
->Type
) {
189 rio_dprintk (RIO_DEBUG_BOOT
, "Start ISA card running\n");
190 WBYTE(HostP
->Control
,
191 BOOT_FROM_RAM
| EXTERNAL_BUS_ON
193 | RIOAtVec2Ctrl
[HostP
->Ivec
& 0xF] );
196 #ifdef FUTURE_RELEASE
199 ** MCA handles IRQ vectors differently, so we don't write
200 ** them to this register.
202 rio_dprintk (RIO_DEBUG_BOOT
, "Start MCA card running\n");
203 WBYTE(HostP
->Control
, McaTpBootFromRam
| McaTpBusEnable
| HostP
->Mode
);
208 ** EISA is totally different and expects OUTBZs to turn it on.
210 rio_dprintk (RIO_DEBUG_BOOT
, "Start EISA card running\n");
211 OUTBZ( HostP
->Slot
, EISA_CONTROL_PORT
, HostP
->Mode
| RIOEisaVec2Ctrl
[HostP
->Ivec
] | EISA_TP_RUN
| EISA_TP_BUS_ENABLE
| EISA_TP_BOOT_FROM_RAM
);
217 ** PCI is much the same as MCA. Everything is once again memory
218 ** mapped, so we are writing to memory registers instead of io
221 rio_dprintk (RIO_DEBUG_BOOT
, "Start PCI card running\n");
222 WBYTE(HostP
->Control
, PCITpBootFromRam
| PCITpBusEnable
| HostP
->Mode
);
225 rio_dprintk (RIO_DEBUG_BOOT
, "Unknown host type %d\n", HostP
->Type
);
229 printk (KERN_INFO "Done with starting the card\n");
236 ** Load in the host boot code - load it directly onto all halted hosts
237 ** of the correct type.
239 ** Put your rubber pants on before messing with this code - even the magic
240 ** numbers have trouble understanding what they are doing here.
243 RIOBootCodeHOST(p
, rbp
)
245 register struct DownLoad
*rbp
;
247 register struct Host
*HostP
;
248 register caddr_t Cad
;
249 register PARM_MAP
*ParmMapP
;
257 ushort offset
; /* It is very important that this is a ushort */
259 caddr_t DownCode
= NULL
;
262 HostP
= NULL
; /* Assure the compiler we've initialized it */
263 for ( host
=0; host
<p
->RIONumHosts
; host
++ ) {
264 rio_dprintk (RIO_DEBUG_BOOT
, "Attempt to boot host %d\n",host
);
265 HostP
= &p
->RIOHosts
[host
];
267 rio_dprintk (RIO_DEBUG_BOOT
, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n",
268 HostP
->Type
, HostP
->Mode
, HostP
->Ivec
);
271 if ( (HostP
->Flags
& RUN_STATE
) != RC_WAITING
) {
272 rio_dprintk (RIO_DEBUG_BOOT
, "%s %d already running\n","Host",host
);
277 ** Grab a 32 bit pointer to the card.
282 ** We are going to (try) and load in rbp->Count bytes.
283 ** The last byte will reside at p->RIOConf.HostLoadBase-1;
284 ** Therefore, we need to start copying at address
285 ** (caddr+p->RIOConf.HostLoadBase-rbp->Count)
287 StartP
= (caddr_t
)&Cad
[p
->RIOConf
.HostLoadBase
-rbp
->Count
];
289 rio_dprintk (RIO_DEBUG_BOOT
, "kernel virtual address for host is 0x%x\n", (int)Cad
);
290 rio_dprintk (RIO_DEBUG_BOOT
, "kernel virtual address for download is 0x%x\n", (int)StartP
);
291 rio_dprintk (RIO_DEBUG_BOOT
, "host loadbase is 0x%x\n",p
->RIOConf
.HostLoadBase
);
292 rio_dprintk (RIO_DEBUG_BOOT
, "size of download is 0x%x\n", rbp
->Count
);
294 if ( p
->RIOConf
.HostLoadBase
< rbp
->Count
) {
295 rio_dprintk (RIO_DEBUG_BOOT
, "Bin too large\n");
296 p
->RIOError
.Error
= HOST_FILE_TOO_LARGE
;
301 ** Ensure that the host really is stopped.
302 ** Disable it's external bus & twang its reset line.
304 RIOHostReset( HostP
->Type
, (struct DpRam
*)HostP
->CardP
, HostP
->Slot
);
307 ** Copy the data directly from user space to the SRAM.
308 ** This ain't going to be none too clever if the download
309 ** code is bigger than this segment.
311 rio_dprintk (RIO_DEBUG_BOOT
, "Copy in code\n");
314 ** PCI hostcard can't cope with 32 bit accesses and so need to copy
315 ** data to a local buffer, and then dripfeed the card.
317 if ( HostP
->Type
== RIO_PCI
) {
320 DownCode
= sysbrk(rbp
->Count
);
322 rio_dprintk (RIO_DEBUG_BOOT
, "No system memory available\n");
323 p
->RIOError
.Error
= NOT_ENOUGH_CORE_FOR_PCI_COPY
;
327 bzero(DownCode
, rbp
->Count
);
329 if ( copyin((int)rbp
->DataP
,DownCode
,rbp
->Count
)==COPYFAIL
) {
330 rio_dprintk (RIO_DEBUG_BOOT
, "Bad copyin of host data\n");
331 sysfree( DownCode
, rbp
->Count
);
332 p
->RIOError
.Error
= COPYIN_FAILED
;
337 HostP
->Copy( DownCode
, StartP
, rbp
->Count
);
339 sysfree( DownCode
, rbp
->Count
);
341 else if ( copyin((int)rbp
->DataP
,StartP
,rbp
->Count
)==COPYFAIL
) {
342 rio_dprintk (RIO_DEBUG_BOOT
, "Bad copyin of host data\n");
343 p
->RIOError
.Error
= COPYIN_FAILED
;
348 rio_dprintk (RIO_DEBUG_BOOT
, "Copy completed\n");
353 ** Upto this point the code has been fairly rational, and possibly
354 ** even straight forward. What follows is a pile of crud that will
355 ** magically turn into six bytes of transputer assembler. Normally
356 ** you would expect an array or something, but, being me, I have
357 ** chosen [been told] to use a technique whereby the startup code
358 ** will be correct if we change the loadbase for the code. Which
359 ** brings us onto another issue - the loadbase is the *end* of the
360 ** code, not the start.
362 ** If I were you I wouldn't start from here.
366 ** We now need to insert a short boot section into
367 ** the memory at the end of Sram2. This is normally (de)composed
368 ** of the last eight bytes of the download code. The
369 ** download has been assembled/compiled to expect to be
370 ** loaded from 0x7FFF downwards. We have loaded it
371 ** at some other address. The startup code goes into the small
372 ** ram window at Sram2, in the last 8 bytes, which are really
373 ** at addresses 0x7FF8-0x7FFF.
375 ** If the loadbase is, say, 0x7C00, then we need to branch to
376 ** address 0x7BFE to run the host.bin startup code. We assemble
377 ** this jump manually.
379 ** The two byte sequence 60 08 is loaded into memory at address
380 ** 0x7FFE,F. This is a local branch to location 0x7FF8 (60 is nfix 0,
381 ** which adds '0' to the .O register, complements .O, and then shifts
382 ** it left by 4 bit positions, 08 is a jump .O+8 instruction. This will
383 ** add 8 to .O (which was 0xFFF0), and will branch RELATIVE to the new
384 ** location. Now, the branch starts from the value of .PC (or .IP or
385 ** whatever the bloody register is called on this chip), and the .PC
386 ** will be pointing to the location AFTER the branch, in this case
387 ** .PC == 0x8000, so the branch will be to 0x8000+0xFFF8 = 0x7FF8.
389 ** A long branch is coded at 0x7FF8. This consists of loading a four
390 ** byte offset into .O using nfix (as above) and pfix operators. The
391 ** pfix operates in exactly the same way as the nfix operator, but
392 ** without the complement operation. The offset, of course, must be
393 ** relative to the address of the byte AFTER the branch instruction,
394 ** which will be (urm) 0x7FFC, so, our final destination of the branch
395 ** (loadbase-2), has to be reached from here. Imagine that the loadbase
396 ** is 0x7C00 (which it is), then we will need to branch to 0x7BFE (which
397 ** is the first byte of the initial two byte short local branch of the
400 ** To code a jump from 0x7FFC (which is where the branch will start
401 ** from) to 0x7BFE, we will need to branch 0xFC02 bytes (0x7FFC+0xFC02)=
403 ** This will be coded as four bytes:
410 ** The nfix operator is used, so that the startup code will be
411 ** compatible with the whole Tp family. (lies, damn lies, it'll never
412 ** work in a month of Sundays).
414 ** The nfix nyble is the 1s complement of the nyble value you
415 ** want to load - in this case we wanted 'F' so we nfix loaded '0'.
420 ** Dest points to the top 8 bytes of Sram2. The Tp jumps
421 ** to 0x7FFE at reset time, and starts executing. This is
422 ** a short branch to 0x7FF8, where a long branch is coded.
425 DestP
= (BYTE
*)&Cad
[0x7FF8]; /* <<<---- READ THE ABOVE COMMENTS */
427 #define NFIX(N) (0x60 | (N)) /* .O = (~(.O + N))<<4 */
428 #define PFIX(N) (0x20 | (N)) /* .O = (.O + N)<<4 */
429 #define JUMP(N) (0x00 | (N)) /* .PC = .PC + .O */
432 ** 0x7FFC is the address of the location following the last byte of
433 ** the four byte jump instruction.
434 ** READ THE ABOVE COMMENTS
436 ** offset is (TO-FROM) % MEMSIZE, but with compound buggering about.
437 ** Memsize is 64K for this range of Tp, so offset is a short (unsigned,
438 ** cos I don't understand 2's complement).
440 offset
= (p
->RIOConf
.HostLoadBase
-2)-0x7FFC;
441 WBYTE( DestP
[0] , NFIX(((ushort
)(~offset
) >> (ushort
)12) & 0xF) );
442 WBYTE( DestP
[1] , PFIX(( offset
>> 8) & 0xF) );
443 WBYTE( DestP
[2] , PFIX(( offset
>> 4) & 0xF) );
444 WBYTE( DestP
[3] , JUMP( offset
& 0xF) );
446 WBYTE( DestP
[6] , NFIX(0) );
447 WBYTE( DestP
[7] , JUMP(8) );
449 rio_dprintk (RIO_DEBUG_BOOT
, "host loadbase is 0x%x\n",p
->RIOConf
.HostLoadBase
);
450 rio_dprintk (RIO_DEBUG_BOOT
, "startup offset is 0x%x\n",offset
);
453 ** Flag what is going on
455 HostP
->Flags
&= ~RUN_STATE
;
456 HostP
->Flags
|= RC_STARTUP
;
459 ** Grab a copy of the current ParmMap pointer, so we
460 ** can tell when it has changed.
462 OldParmMap
= RWORD(HostP
->__ParmMapR
);
464 rio_dprintk (RIO_DEBUG_BOOT
, "Original parmmap is 0x%x\n",OldParmMap
);
467 ** And start it running (I hope).
468 ** As there is nothing dodgy or obscure about the
469 ** above code, this is guaranteed to work every time.
471 rio_dprintk (RIO_DEBUG_BOOT
, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n",
472 HostP
->Type
, HostP
->Mode
, HostP
->Ivec
);
474 rio_start_card_running(HostP
);
476 rio_dprintk (RIO_DEBUG_BOOT
, "Set control port\n");
479 ** Now, wait for upto five seconds for the Tp to setup the parmmap
482 for ( wait_count
=0; (wait_count
<p
->RIOConf
.StartupTime
)&&
483 (RWORD(HostP
->__ParmMapR
)==OldParmMap
); wait_count
++ ) {
484 rio_dprintk (RIO_DEBUG_BOOT
, "Checkout %d, 0x%x\n",wait_count
,RWORD(HostP
->__ParmMapR
));
485 delay(HostP
, HUNDRED_MS
);
490 ** If the parmmap pointer is unchanged, then the host code
491 ** has crashed & burned in a really spectacular way
493 if ( RWORD(HostP
->__ParmMapR
) == OldParmMap
) {
494 rio_dprintk (RIO_DEBUG_BOOT
, "parmmap 0x%x\n", RWORD(HostP
->__ParmMapR
));
495 rio_dprintk (RIO_DEBUG_BOOT
, "RIO Mesg Run Fail\n");
497 #define HOST_DISABLE \
498 HostP->Flags &= ~RUN_STATE; \
499 HostP->Flags |= RC_STUFFED; \
500 RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot );\
506 rio_dprintk (RIO_DEBUG_BOOT
, "Running 0x%x\n", RWORD(HostP
->__ParmMapR
));
509 ** Well, the board thought it was OK, and setup its parmmap
510 ** pointer. For the time being, we will pretend that this
511 ** board is running, and check out what the error flag says.
515 ** Grab a 32 bit pointer to the parmmap structure
517 ParmMapP
= (PARM_MAP
*)RIO_PTR(Cad
,RWORD(HostP
->__ParmMapR
));
518 rio_dprintk (RIO_DEBUG_BOOT
, "ParmMapP : %x\n", (int)ParmMapP
);
519 ParmMapP
= (PARM_MAP
*)((unsigned long)Cad
+
520 (unsigned long)((RWORD((HostP
->__ParmMapR
))) & 0xFFFF));
521 rio_dprintk (RIO_DEBUG_BOOT
, "ParmMapP : %x\n", (int)ParmMapP
);
524 ** The links entry should be 0xFFFF; we set it up
525 ** with a mask to say how many PHBs to use, and
526 ** which links to use.
528 if ( (RWORD(ParmMapP
->links
) & 0xFFFF) != 0xFFFF ) {
529 rio_dprintk (RIO_DEBUG_BOOT
, "RIO Mesg Run Fail %s\n", HostP
->Name
);
530 rio_dprintk (RIO_DEBUG_BOOT
, "Links = 0x%x\n",RWORD(ParmMapP
->links
));
534 WWORD(ParmMapP
->links
, RIO_LINK_ENABLE
);
537 ** now wait for the card to set all the parmmap->XXX stuff
538 ** this is a wait of upto two seconds....
540 rio_dprintk (RIO_DEBUG_BOOT
, "Looking for init_done - %d ticks\n",p
->RIOConf
.StartupTime
);
541 HostP
->timeout_id
= 0;
542 for ( wait_count
=0; (wait_count
<p
->RIOConf
.StartupTime
) &&
543 !RWORD(ParmMapP
->init_done
); wait_count
++ ) {
544 rio_dprintk (RIO_DEBUG_BOOT
, "Waiting for init_done\n");
545 delay(HostP
, HUNDRED_MS
);
547 rio_dprintk (RIO_DEBUG_BOOT
, "OK! init_done!\n");
549 if (RWORD(ParmMapP
->error
) != E_NO_ERROR
||
550 !RWORD(ParmMapP
->init_done
) ) {
551 rio_dprintk (RIO_DEBUG_BOOT
, "RIO Mesg Run Fail %s\n", HostP
->Name
);
552 rio_dprintk (RIO_DEBUG_BOOT
, "Timedout waiting for init_done\n");
556 rio_dprintk (RIO_DEBUG_BOOT
, "Got init_done\n");
561 rio_dprintk (RIO_DEBUG_BOOT
, "Host ID %x Running\n",HostP
->UniqueNum
);
564 ** set the time period between interrupts.
566 WWORD(ParmMapP
->timer
, (short)p
->RIOConf
.Timer
);
569 ** Translate all the 16 bit pointers in the __ParmMapR into
570 ** 32 bit pointers for the driver.
572 HostP
->ParmMapP
= ParmMapP
;
573 HostP
->PhbP
= (PHB
*)RIO_PTR(Cad
,RWORD(ParmMapP
->phb_ptr
));
574 HostP
->RupP
= (RUP
*)RIO_PTR(Cad
,RWORD(ParmMapP
->rups
));
575 HostP
->PhbNumP
= (ushort
*)RIO_PTR(Cad
,RWORD(ParmMapP
->phb_num_ptr
));
576 HostP
->LinkStrP
= (LPB
*)RIO_PTR(Cad
,RWORD(ParmMapP
->link_str_ptr
));
579 ** point the UnixRups at the real Rups
581 for ( RupN
= 0; RupN
<MAX_RUP
; RupN
++ ) {
582 HostP
->UnixRups
[RupN
].RupP
= &HostP
->RupP
[RupN
];
583 HostP
->UnixRups
[RupN
].Id
= RupN
+1;
584 HostP
->UnixRups
[RupN
].BaseSysPort
= NO_PORT
;
585 spin_lock_init(&HostP
->UnixRups
[RupN
].RupLock
);
588 for ( RupN
= 0; RupN
<LINKS_PER_UNIT
; RupN
++ ) {
589 HostP
->UnixRups
[RupN
+MAX_RUP
].RupP
= &HostP
->LinkStrP
[RupN
].rup
;
590 HostP
->UnixRups
[RupN
+MAX_RUP
].Id
= 0;
591 HostP
->UnixRups
[RupN
+MAX_RUP
].BaseSysPort
= NO_PORT
;
592 spin_lock_init(&HostP
->UnixRups
[RupN
+MAX_RUP
].RupLock
);
596 ** point the PortP->Phbs at the real Phbs
598 for ( PortN
=p
->RIOFirstPortsMapped
;
599 PortN
<p
->RIOLastPortsMapped
+PORTS_PER_RTA
; PortN
++ ) {
600 if ( p
->RIOPortp
[PortN
]->HostP
== HostP
) {
601 struct Port
*PortP
= p
->RIOPortp
[PortN
];
605 if ( !PortP
->Mapped
)
608 PhbP
= &HostP
->PhbP
[PortP
->HostPort
];
609 rio_spin_lock_irqsave(&PortP
->portSem
, flags
);
613 PortP
->TxAdd
= (WORD
*)RIO_PTR(Cad
,RWORD(PhbP
->tx_add
));
614 PortP
->TxStart
= (WORD
*)RIO_PTR(Cad
,RWORD(PhbP
->tx_start
));
615 PortP
->TxEnd
= (WORD
*)RIO_PTR(Cad
,RWORD(PhbP
->tx_end
));
616 PortP
->RxRemove
= (WORD
*)RIO_PTR(Cad
,RWORD(PhbP
->rx_remove
));
617 PortP
->RxStart
= (WORD
*)RIO_PTR(Cad
,RWORD(PhbP
->rx_start
));
618 PortP
->RxEnd
= (WORD
*)RIO_PTR(Cad
,RWORD(PhbP
->rx_end
));
620 rio_spin_unlock_irqrestore(&PortP
->portSem
, flags
);
622 ** point the UnixRup at the base SysPort
624 if ( !(PortN
% PORTS_PER_RTA
) )
625 HostP
->UnixRups
[PortP
->RupNum
].BaseSysPort
= PortN
;
629 rio_dprintk (RIO_DEBUG_BOOT
, "Set the card running... \n");
631 ** last thing - show the world that everything is in place
633 HostP
->Flags
&= ~RUN_STATE
;
634 HostP
->Flags
|= RC_RUNNING
;
637 ** MPX always uses a poller. This is actually patched into the system
638 ** configuration and called directly from each clock tick.
645 rio_dprintk (RIO_DEBUG_BOOT
, "Done everything %x\n", HostP
->Ivec
);
653 ** Boot an RTA. If we have successfully processed this boot, then
654 ** return 1. If we havent, then return 0.
657 RIOBootRup( p
, Rup
, HostP
, PacketP
)
663 struct PktCmd
*PktCmdP
= (struct PktCmd
*)PacketP
->data
;
664 struct PktCmd_M
*PktReplyP
;
665 struct CmdBlk
*CmdBlkP
;
669 ** If we haven't been told what to boot, we can't boot it.
671 if ( p
->RIONumBootPkts
== 0 ) {
672 rio_dprintk (RIO_DEBUG_BOOT
, "No RTA code to download yet\n");
676 /* rio_dprint(RIO_DEBUG_BOOT, NULL,DBG_BOOT,"Incoming command packet\n"); */
677 /* ShowPacket( DBG_BOOT, PacketP ); */
680 ** Special case of boot completed - if we get one of these then we
681 ** don't need a command block. For all other cases we do, so handle
682 ** this first and then get a command block, then handle every other
683 ** case, relinquishing the command block if disaster strikes!
685 if ( (RBYTE(PacketP
->len
) & PKT_CMD_BIT
) &&
686 (RBYTE(PktCmdP
->Command
)==BOOT_COMPLETED
) )
687 return RIOBootComplete(p
, HostP
, Rup
, PktCmdP
);
690 ** try to unhook a command block from the command free list.
692 if ( !(CmdBlkP
= RIOGetCmdBlk()) ) {
693 rio_dprintk (RIO_DEBUG_BOOT
, "No command blocks to boot RTA! come back later.\n");
698 ** Fill in the default info on the command block
700 CmdBlkP
->Packet
.dest_unit
= Rup
< (ushort
)MAX_RUP
? Rup
: 0;
701 CmdBlkP
->Packet
.dest_port
= BOOT_RUP
;
702 CmdBlkP
->Packet
.src_unit
= 0;
703 CmdBlkP
->Packet
.src_port
= BOOT_RUP
;
705 CmdBlkP
->PreFuncP
= CmdBlkP
->PostFuncP
= NULL
;
706 PktReplyP
= (struct PktCmd_M
*)CmdBlkP
->Packet
.data
;
709 ** process COMMANDS on the boot rup!
711 if ( RBYTE(PacketP
->len
) & PKT_CMD_BIT
) {
713 ** We only expect one type of command - a BOOT_REQUEST!
715 if ( RBYTE(PktCmdP
->Command
) != BOOT_REQUEST
) {
716 rio_dprintk (RIO_DEBUG_BOOT
, "Unexpected command %d on BOOT RUP %d of host %d\n",
717 PktCmdP
->Command
,Rup
,HostP
-p
->RIOHosts
);
718 ShowPacket( DBG_BOOT
, PacketP
);
719 RIOFreeCmdBlk( CmdBlkP
);
724 ** Build a Boot Sequence command block
726 ** 02.03.1999 ARG - ESIL 0820 fix
727 ** We no longer need to use "Boot Mode", we'll always allow
728 ** boot requests - the boot will not complete if the device
729 ** appears in the bindings table.
730 ** So, this conditional is not required ...
732 if (p->RIOBootMode == RC_BOOT_NONE)
734 ** If the system is in slave mode, and a boot request is
735 ** received, set command to BOOT_ABORT so that the boot
736 ** will not complete.
738 PktReplyP->Command = BOOT_ABORT;
741 ** We'll just (always) set the command field in packet reply
742 ** to allow an attempted boot sequence :
744 PktReplyP
->Command
= BOOT_SEQUENCE
;
746 PktReplyP
->BootSequence
.NumPackets
= p
->RIONumBootPkts
;
747 PktReplyP
->BootSequence
.LoadBase
= p
->RIOConf
.RtaLoadBase
;
748 PktReplyP
->BootSequence
.CodeSize
= p
->RIOBootCount
;
750 CmdBlkP
->Packet
.len
= BOOT_SEQUENCE_LEN
| PKT_CMD_BIT
;
752 bcopy("BOOT",(void *)&CmdBlkP
->Packet
.data
[BOOT_SEQUENCE_LEN
],4);
754 rio_dprintk (RIO_DEBUG_BOOT
, "Boot RTA on Host %d Rup %d - %d (0x%x) packets to 0x%x\n",
755 HostP
-p
->RIOHosts
, Rup
, p
->RIONumBootPkts
, p
->RIONumBootPkts
,
756 p
->RIOConf
.RtaLoadBase
);
759 ** If this host is in slave mode, send the RTA an invalid boot
760 ** sequence command block to force it to kill the boot. We wait
761 ** for half a second before sending this packet to prevent the RTA
762 ** attempting to boot too often. The master host should then grab
763 ** the RTA and make it its own.
766 RIOQueueCmdBlk( HostP
, Rup
, CmdBlkP
);
771 ** It is a request for boot data.
773 sequence
= RWORD(PktCmdP
->Sequence
);
775 rio_dprintk (RIO_DEBUG_BOOT
, "Boot block %d on Host %d Rup%d\n",sequence
,HostP
-p
->RIOHosts
,Rup
);
777 if ( sequence
>= p
->RIONumBootPkts
) {
778 rio_dprintk (RIO_DEBUG_BOOT
, "Got a request for packet %d, max is %d\n", sequence
,
780 ShowPacket( DBG_BOOT
, PacketP
);
783 PktReplyP
->Sequence
= sequence
;
785 bcopy( p
->RIOBootPackets
[ p
->RIONumBootPkts
- sequence
- 1 ],
786 PktReplyP
->BootData
, RTA_BOOT_DATA_SIZE
);
788 CmdBlkP
->Packet
.len
= PKT_MAX_DATA_LEN
;
789 ShowPacket( DBG_BOOT
, &CmdBlkP
->Packet
);
790 RIOQueueCmdBlk( HostP
, Rup
, CmdBlkP
);
795 ** This function is called when an RTA been booted.
796 ** If booted by a host, HostP->HostUniqueNum is the booting host.
797 ** If booted by an RTA, HostP->Mapping[Rup].RtaUniqueNum is the booting RTA.
798 ** RtaUniq is the booted RTA.
800 static int RIOBootComplete( struct rio_info
*p
, struct Host
*HostP
, uint Rup
, struct PktCmd
*PktCmdP
)
802 struct Map
*MapP
= NULL
;
803 struct Map
*MapP2
= NULL
;
809 char *MyType
, *MyName
;
812 uint RtaUniq
= (RBYTE(PktCmdP
->UniqNum
[0])) +
813 (RBYTE(PktCmdP
->UniqNum
[1]) << 8) +
814 (RBYTE(PktCmdP
->UniqNum
[2]) << 16) +
815 (RBYTE(PktCmdP
->UniqNum
[3]) << 24);
817 /* Was RIOBooting-- . That's bad. If an RTA sends two of them, the
818 driver will never think that the RTA has booted... -- REW */
821 rio_dprintk (RIO_DEBUG_BOOT
, "RTA Boot completed - BootInProgress now %d\n", p
->RIOBooting
);
824 ** Determine type of unit (16/8 port RTA).
826 RtaType
= GetUnitType(RtaUniq
);
827 if ( Rup
>= (ushort
)MAX_RUP
) {
828 rio_dprintk (RIO_DEBUG_BOOT
, "RIO: Host %s has booted an RTA(%d) on link %c\n",
829 HostP
->Name
, 8 * RtaType
, RBYTE(PktCmdP
->LinkNum
)+'A');
831 rio_dprintk (RIO_DEBUG_BOOT
, "RIO: RTA %s has booted an RTA(%d) on link %c\n",
832 HostP
->Mapping
[Rup
].Name
, 8 * RtaType
,
833 RBYTE(PktCmdP
->LinkNum
)+'A');
836 rio_dprintk (RIO_DEBUG_BOOT
, "UniqNum is 0x%x\n",RtaUniq
);
838 if ( ( RtaUniq
== 0x00000000 ) || ( RtaUniq
== 0xffffffff ) )
840 rio_dprintk (RIO_DEBUG_BOOT
, "Illegal RTA Uniq Number\n");
845 ** If this RTA has just booted an RTA which doesn't belong to this
846 ** system, or the system is in slave mode, do not attempt to create
847 ** a new table entry for it.
849 if (!RIOBootOk(p
, HostP
, RtaUniq
))
851 MyLink
= RBYTE(PktCmdP
->LinkNum
);
852 if (Rup
< (ushort
) MAX_RUP
)
855 ** RtaUniq was clone booted (by this RTA). Instruct this RTA
856 ** to hold off further attempts to boot on this link for 30
859 if (RIOSuspendBootRta(HostP
, HostP
->Mapping
[Rup
].ID
, MyLink
))
861 rio_dprintk (RIO_DEBUG_BOOT
, "RTA failed to suspend booting on link %c\n",
868 ** RtaUniq was booted by this host. Set the booting link
869 ** to hold off for 30 seconds to give another unit a
870 ** chance to boot it.
872 WWORD(HostP
->LinkStrP
[MyLink
].WaitNoBoot
, 30);
874 rio_dprintk (RIO_DEBUG_BOOT
, "RTA %x not owned - suspend booting down link %c on unit %x\n",
875 RtaUniq
, 'A' + MyLink
, HostP
->Mapping
[Rup
].RtaUniqueNum
);
880 ** Check for a SLOT_IN_USE entry for this RTA attached to the
881 ** current host card in the driver table.
883 ** If it exists, make a note that we have booted it. Other parts of
884 ** the driver are interested in this information at a later date,
885 ** in particular when the booting RTA asks for an ID for this unit,
886 ** we must have set the BOOTED flag, and the NEWBOOT flag is used
887 ** to force an open on any ports that where previously open on this
890 for ( entry
=0; entry
<MAX_RUP
; entry
++ )
894 if ((HostP
->Mapping
[entry
].Flags
& SLOT_IN_USE
) &&
895 (HostP
->Mapping
[entry
].RtaUniqueNum
==RtaUniq
))
897 HostP
->Mapping
[entry
].Flags
|= RTA_BOOTED
|RTA_NEWBOOT
;
899 RIO_SV_BROADCAST(HostP
->svFlags
[entry
]);
901 if ( (sysport
=HostP
->Mapping
[entry
].SysPort
) != NO_PORT
)
903 if ( sysport
< p
->RIOFirstPortsBooted
)
904 p
->RIOFirstPortsBooted
= sysport
;
905 if ( sysport
> p
->RIOLastPortsBooted
)
906 p
->RIOLastPortsBooted
= sysport
;
908 ** For a 16 port RTA, check the second bank of 8 ports
910 if (RtaType
== TYPE_RTA16
)
912 entry2
= HostP
->Mapping
[entry
].ID2
- 1;
913 HostP
->Mapping
[entry2
].Flags
|= RTA_BOOTED
|RTA_NEWBOOT
;
915 RIO_SV_BROADCAST(HostP
->svFlags
[entry2
]);
917 sysport
= HostP
->Mapping
[entry2
].SysPort
;
918 if ( sysport
< p
->RIOFirstPortsBooted
)
919 p
->RIOFirstPortsBooted
= sysport
;
920 if ( sysport
> p
->RIOLastPortsBooted
)
921 p
->RIOLastPortsBooted
= sysport
;
924 if (RtaType
== TYPE_RTA16
) {
925 rio_dprintk (RIO_DEBUG_BOOT
, "RTA will be given IDs %d+%d\n",
928 rio_dprintk (RIO_DEBUG_BOOT
, "RTA will be given ID %d\n",entry
+1);
934 rio_dprintk (RIO_DEBUG_BOOT
, "RTA not configured for this host\n");
936 if ( Rup
>= (ushort
)MAX_RUP
)
939 ** It was a host that did the booting
942 MyName
= HostP
->Name
;
947 ** It was an RTA that did the booting
950 MyName
= HostP
->Mapping
[Rup
].Name
;
952 MyLink
= RBYTE(PktCmdP
->LinkNum
);
955 ** There is no SLOT_IN_USE entry for this RTA attached to the current
956 ** host card in the driver table.
958 ** Check for a SLOT_TENTATIVE entry for this RTA attached to the
959 ** current host card in the driver table.
961 ** If we find one, then we re-use that slot.
963 for ( entry
=0; entry
<MAX_RUP
; entry
++ )
965 if ( (HostP
->Mapping
[entry
].Flags
& SLOT_TENTATIVE
) &&
966 (HostP
->Mapping
[entry
].RtaUniqueNum
== RtaUniq
) )
968 if (RtaType
== TYPE_RTA16
)
970 entry2
= HostP
->Mapping
[entry
].ID2
- 1;
971 if ( (HostP
->Mapping
[entry2
].Flags
& SLOT_TENTATIVE
) &&
972 (HostP
->Mapping
[entry2
].RtaUniqueNum
== RtaUniq
) )
973 rio_dprintk (RIO_DEBUG_BOOT
, "Found previous tentative slots (%d+%d)\n",
979 rio_dprintk (RIO_DEBUG_BOOT
, "Found previous tentative slot (%d)\n",entry
);
980 if (! p
->RIONoMessage
)
981 cprintf("RTA connected to %s '%s' (%c) not configured.\n",MyType
,MyName
,MyLink
+'A');
987 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
988 ** attached to the current host card in the driver table.
990 ** Check if there is a SLOT_IN_USE or SLOT_TENTATIVE entry on another
991 ** host for this RTA in the driver table.
993 ** For a SLOT_IN_USE entry on another host, we need to delete the RTA
994 ** entry from the other host and add it to this host (using some of
995 ** the functions from table.c which do this).
996 ** For a SLOT_TENTATIVE entry on another host, we must cope with the
997 ** following scenario:
999 ** + Plug 8 port RTA into host A. (This creates SLOT_TENTATIVE entry
1001 ** + Unplug RTA and plug into host B. (We now have 2 SLOT_TENTATIVE
1003 ** + Configure RTA on host B. (This slot now becomes SLOT_IN_USE)
1004 ** + Unplug RTA and plug back into host A.
1005 ** + Configure RTA on host A. We now have the same RTA configured
1006 ** with different ports on two different hosts.
1008 rio_dprintk (RIO_DEBUG_BOOT
, "Have we seen RTA %x before?\n", RtaUniq
);
1010 Flag
= 0; /* Convince the compiler this variable is initialized */
1011 for ( host
= 0; !found
&& (host
< p
->RIONumHosts
); host
++ )
1013 for ( rta
=0; rta
<MAX_RUP
; rta
++ )
1015 if ((p
->RIOHosts
[host
].Mapping
[rta
].Flags
&
1016 (SLOT_IN_USE
| SLOT_TENTATIVE
)) &&
1017 (p
->RIOHosts
[host
].Mapping
[rta
].RtaUniqueNum
==RtaUniq
))
1019 Flag
= p
->RIOHosts
[host
].Mapping
[rta
].Flags
;
1020 MapP
= &p
->RIOHosts
[host
].Mapping
[rta
];
1021 if (RtaType
== TYPE_RTA16
)
1023 MapP2
= &p
->RIOHosts
[host
].Mapping
[MapP
->ID2
- 1];
1024 rio_dprintk (RIO_DEBUG_BOOT
, "This RTA is units %d+%d from host %s\n",
1025 rta
+1, MapP
->ID2
, p
->RIOHosts
[host
].Name
);
1028 rio_dprintk (RIO_DEBUG_BOOT
, "This RTA is unit %d from host %s\n",
1029 rta
+1, p
->RIOHosts
[host
].Name
);
1037 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
1038 ** attached to the current host card in the driver table.
1040 ** If we have not found a SLOT_IN_USE or SLOT_TENTATIVE entry on
1041 ** another host for this RTA in the driver table...
1043 ** Check for a SLOT_IN_USE entry for this RTA in the config table.
1047 rio_dprintk (RIO_DEBUG_BOOT
, "Look for RTA %x in RIOSavedTable\n",RtaUniq
);
1048 for ( rta
=0; rta
< TOTAL_MAP_ENTRIES
; rta
++ )
1050 rio_dprintk (RIO_DEBUG_BOOT
, "Check table entry %d (%x)",
1052 p
->RIOSavedTable
[rta
].RtaUniqueNum
);
1054 if ( (p
->RIOSavedTable
[rta
].Flags
& SLOT_IN_USE
) &&
1055 (p
->RIOSavedTable
[rta
].RtaUniqueNum
== RtaUniq
) )
1057 MapP
= &p
->RIOSavedTable
[rta
];
1058 Flag
= p
->RIOSavedTable
[rta
].Flags
;
1059 if (RtaType
== TYPE_RTA16
)
1061 for (entry2
= rta
+ 1; entry2
< TOTAL_MAP_ENTRIES
;
1064 if (p
->RIOSavedTable
[entry2
].RtaUniqueNum
== RtaUniq
)
1067 MapP2
= &p
->RIOSavedTable
[entry2
];
1068 rio_dprintk (RIO_DEBUG_BOOT
, "This RTA is from table entries %d+%d\n",
1072 rio_dprintk (RIO_DEBUG_BOOT
, "This RTA is from table entry %d\n", rta
);
1079 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
1080 ** attached to the current host card in the driver table.
1082 ** We may have found a SLOT_IN_USE entry on another host for this
1083 ** RTA in the config table, or a SLOT_IN_USE or SLOT_TENTATIVE entry
1084 ** on another host for this RTA in the driver table.
1086 ** Check the driver table for room to fit this newly discovered RTA.
1087 ** RIOFindFreeID() first looks for free slots and if it does not
1088 ** find any free slots it will then attempt to oust any
1089 ** tentative entry in the table.
1092 if (RtaType
== TYPE_RTA16
)
1094 if (RIOFindFreeID(p
, HostP
, &entry
, &entry2
) == 0)
1096 RIODefaultName(p
, HostP
, entry
);
1097 FillSlot(entry
, entry2
, RtaUniq
, HostP
);
1103 if (RIOFindFreeID(p
, HostP
, &entry
, NULL
) == 0)
1105 RIODefaultName(p
, HostP
, entry
);
1106 FillSlot(entry
, 0, RtaUniq
, HostP
);
1112 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
1113 ** attached to the current host card in the driver table.
1115 ** If we found a SLOT_IN_USE entry on another host for this
1116 ** RTA in the config or driver table, and there are enough free
1117 ** slots in the driver table, then we need to move it over and
1118 ** delete it from the other host.
1119 ** If we found a SLOT_TENTATIVE entry on another host for this
1120 ** RTA in the driver table, just delete the other host entry.
1126 if (Flag
& SLOT_IN_USE
)
1128 rio_dprintk (RIO_DEBUG_BOOT
,
1129 "This RTA configured on another host - move entry to current host (1)\n");
1130 HostP
->Mapping
[entry
].SysPort
= MapP
->SysPort
;
1131 CCOPY( MapP
->Name
, HostP
->Mapping
[entry
].Name
, MAX_NAME_LEN
);
1132 HostP
->Mapping
[entry
].Flags
=
1133 SLOT_IN_USE
| RTA_BOOTED
| RTA_NEWBOOT
;
1135 RIO_SV_BROADCAST(HostP
->svFlags
[entry
]);
1137 RIOReMapPorts( p
, HostP
, &HostP
->Mapping
[entry
] );
1138 if ( HostP
->Mapping
[entry
].SysPort
< p
->RIOFirstPortsBooted
)
1139 p
->RIOFirstPortsBooted
= HostP
->Mapping
[entry
].SysPort
;
1140 if ( HostP
->Mapping
[entry
].SysPort
> p
->RIOLastPortsBooted
)
1141 p
->RIOLastPortsBooted
= HostP
->Mapping
[entry
].SysPort
;
1142 rio_dprintk (RIO_DEBUG_BOOT
, "SysPort %d, Name %s\n",(int)MapP
->SysPort
,MapP
->Name
);
1146 rio_dprintk (RIO_DEBUG_BOOT
,
1147 "This RTA has a tentative entry on another host - delete that entry (1)\n");
1148 HostP
->Mapping
[entry
].Flags
=
1149 SLOT_TENTATIVE
| RTA_BOOTED
| RTA_NEWBOOT
;
1151 RIO_SV_BROADCAST(HostP
->svFlags
[entry
]);
1154 if (RtaType
== TYPE_RTA16
)
1156 if (Flag
& SLOT_IN_USE
)
1158 HostP
->Mapping
[entry2
].Flags
= SLOT_IN_USE
|
1159 RTA_BOOTED
| RTA_NEWBOOT
| RTA16_SECOND_SLOT
;
1161 RIO_SV_BROADCAST(HostP
->svFlags
[entry2
]);
1163 HostP
->Mapping
[entry2
].SysPort
= MapP2
->SysPort
;
1165 ** Map second block of ttys for 16 port RTA
1167 RIOReMapPorts( p
, HostP
, &HostP
->Mapping
[entry2
] );
1168 if (HostP
->Mapping
[entry2
].SysPort
< p
->RIOFirstPortsBooted
)
1169 p
->RIOFirstPortsBooted
= HostP
->Mapping
[entry2
].SysPort
;
1170 if (HostP
->Mapping
[entry2
].SysPort
> p
->RIOLastPortsBooted
)
1171 p
->RIOLastPortsBooted
= HostP
->Mapping
[entry2
].SysPort
;
1172 rio_dprintk (RIO_DEBUG_BOOT
, "SysPort %d, Name %s\n",
1173 (int)HostP
->Mapping
[entry2
].SysPort
,
1174 HostP
->Mapping
[entry
].Name
);
1177 HostP
->Mapping
[entry2
].Flags
= SLOT_TENTATIVE
|
1178 RTA_BOOTED
| RTA_NEWBOOT
| RTA16_SECOND_SLOT
;
1180 RIO_SV_BROADCAST(HostP
->svFlags
[entry2
]);
1182 bzero( (caddr_t
)MapP2
, sizeof(struct Map
) );
1184 bzero( (caddr_t
)MapP
, sizeof(struct Map
) );
1185 if (! p
->RIONoMessage
)
1186 cprintf("An orphaned RTA has been adopted by %s '%s' (%c).\n",MyType
,MyName
,MyLink
+'A');
1188 else if (! p
->RIONoMessage
)
1189 cprintf("RTA connected to %s '%s' (%c) not configured.\n",MyType
,MyName
,MyLink
+'A');
1195 ** There is no room in the driver table to make an entry for the
1196 ** booted RTA. Keep a note of its Uniq Num in the overflow table,
1197 ** so we can ignore it's ID requests.
1199 if (! p
->RIONoMessage
)
1200 cprintf("The RTA connected to %s '%s' (%c) cannot be configured. You cannot configure more than 128 ports to one host card.\n",MyType
,MyName
,MyLink
+'A');
1201 for ( entry
=0; entry
<HostP
->NumExtraBooted
; entry
++ )
1203 if ( HostP
->ExtraUnits
[entry
] == RtaUniq
)
1212 ** If there is room, add the unit to the list of extras
1214 if ( HostP
->NumExtraBooted
< MAX_EXTRA_UNITS
)
1215 HostP
->ExtraUnits
[HostP
->NumExtraBooted
++] = RtaUniq
;
1221 ** If the RTA or its host appears in the RIOBindTab[] structure then
1222 ** we mustn't boot the RTA and should return FALSE.
1223 ** This operation is slightly different from the other drivers for RIO
1224 ** in that this is designed to work with the new utilities
1225 ** not config.rio and is FAR SIMPLER.
1226 ** We no longer support the RIOBootMode variable. It is all done from the
1227 ** "boot/noboot" field in the rio.cf file.
1230 RIOBootOk(p
, HostP
, RtaUniq
)
1231 struct rio_info
* p
;
1232 struct Host
* HostP
;
1236 uint HostUniq
= HostP
->UniqueNum
;
1239 ** Search bindings table for RTA or its parent.
1240 ** If it exists, return 0, else 1.
1243 ( Entry
< MAX_RTA_BINDINGS
) && ( p
->RIOBindTab
[Entry
] != 0 );
1246 if ( (p
->RIOBindTab
[Entry
] == HostUniq
) ||
1247 (p
->RIOBindTab
[Entry
] == RtaUniq
) )
1254 ** Make an empty slot tentative. If this is a 16 port RTA, make both
1255 ** slots tentative, and the second one RTA_SECOND_SLOT as well.
1259 FillSlot(entry
, entry2
, RtaUniq
, HostP
)
1267 rio_dprintk (RIO_DEBUG_BOOT
, "FillSlot(%d, %d, 0x%x...)\n", entry
, entry2
, RtaUniq
);
1269 HostP
->Mapping
[entry
].Flags
= (RTA_BOOTED
| RTA_NEWBOOT
| SLOT_TENTATIVE
);
1270 HostP
->Mapping
[entry
].SysPort
= NO_PORT
;
1271 HostP
->Mapping
[entry
].RtaUniqueNum
= RtaUniq
;
1272 HostP
->Mapping
[entry
].HostUniqueNum
= HostP
->UniqueNum
;
1273 HostP
->Mapping
[entry
].ID
= entry
+ 1;
1274 HostP
->Mapping
[entry
].ID2
= 0;
1276 HostP
->Mapping
[entry2
].Flags
= (RTA_BOOTED
| RTA_NEWBOOT
|
1277 SLOT_TENTATIVE
| RTA16_SECOND_SLOT
);
1278 HostP
->Mapping
[entry2
].SysPort
= NO_PORT
;
1279 HostP
->Mapping
[entry2
].RtaUniqueNum
= RtaUniq
;
1280 HostP
->Mapping
[entry2
].HostUniqueNum
= HostP
->UniqueNum
;
1281 HostP
->Mapping
[entry2
].Name
[0] = '\0';
1282 HostP
->Mapping
[entry2
].ID
= entry2
+ 1;
1283 HostP
->Mapping
[entry2
].ID2
= entry
+ 1;
1284 HostP
->Mapping
[entry
].ID2
= entry2
+ 1;
1287 ** Must set these up, so that utilities show
1288 ** topology of 16 port RTAs correctly
1290 for ( link
=0; link
<LINKS_PER_UNIT
; link
++ ) {
1291 HostP
->Mapping
[entry
].Topology
[link
].Unit
= ROUTE_DISCONNECT
;
1292 HostP
->Mapping
[entry
].Topology
[link
].Link
= NO_LINK
;
1294 HostP
->Mapping
[entry2
].Topology
[link
].Unit
= ROUTE_DISCONNECT
;
1295 HostP
->Mapping
[entry2
].Topology
[link
].Link
= NO_LINK
;