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
;
672 CheckPacketP(PacketP
);
676 ** If we haven't been told what to boot, we can't boot it.
678 if ( p
->RIONumBootPkts
== 0 ) {
679 rio_dprintk (RIO_DEBUG_BOOT
, "No RTA code to download yet\n");
683 /* rio_dprint(RIO_DEBUG_BOOT, NULL,DBG_BOOT,"Incoming command packet\n"); */
684 /* ShowPacket( DBG_BOOT, PacketP ); */
687 ** Special case of boot completed - if we get one of these then we
688 ** don't need a command block. For all other cases we do, so handle
689 ** this first and then get a command block, then handle every other
690 ** case, relinquishing the command block if disaster strikes!
692 if ( (RBYTE(PacketP
->len
) & PKT_CMD_BIT
) &&
693 (RBYTE(PktCmdP
->Command
)==BOOT_COMPLETED
) )
694 return RIOBootComplete(p
, HostP
, Rup
, PktCmdP
);
697 ** try to unhook a command block from the command free list.
699 if ( !(CmdBlkP
= RIOGetCmdBlk()) ) {
700 rio_dprintk (RIO_DEBUG_BOOT
, "No command blocks to boot RTA! come back later.\n");
705 ** Fill in the default info on the command block
707 CmdBlkP
->Packet
.dest_unit
= Rup
< (ushort
)MAX_RUP
? Rup
: 0;
708 CmdBlkP
->Packet
.dest_port
= BOOT_RUP
;
709 CmdBlkP
->Packet
.src_unit
= 0;
710 CmdBlkP
->Packet
.src_port
= BOOT_RUP
;
712 CmdBlkP
->PreFuncP
= CmdBlkP
->PostFuncP
= NULL
;
713 PktReplyP
= (struct PktCmd_M
*)CmdBlkP
->Packet
.data
;
716 ** process COMMANDS on the boot rup!
718 if ( RBYTE(PacketP
->len
) & PKT_CMD_BIT
) {
720 ** We only expect one type of command - a BOOT_REQUEST!
722 if ( RBYTE(PktCmdP
->Command
) != BOOT_REQUEST
) {
723 rio_dprintk (RIO_DEBUG_BOOT
, "Unexpected command %d on BOOT RUP %d of host %d\n",
724 PktCmdP
->Command
,Rup
,HostP
-p
->RIOHosts
);
725 ShowPacket( DBG_BOOT
, PacketP
);
726 RIOFreeCmdBlk( CmdBlkP
);
731 ** Build a Boot Sequence command block
733 ** 02.03.1999 ARG - ESIL 0820 fix
734 ** We no longer need to use "Boot Mode", we'll always allow
735 ** boot requests - the boot will not complete if the device
736 ** appears in the bindings table.
737 ** So, this conditional is not required ...
739 if (p->RIOBootMode == RC_BOOT_NONE)
741 ** If the system is in slave mode, and a boot request is
742 ** received, set command to BOOT_ABORT so that the boot
743 ** will not complete.
745 PktReplyP->Command = BOOT_ABORT;
748 ** We'll just (always) set the command field in packet reply
749 ** to allow an attempted boot sequence :
751 PktReplyP
->Command
= BOOT_SEQUENCE
;
753 PktReplyP
->BootSequence
.NumPackets
= p
->RIONumBootPkts
;
754 PktReplyP
->BootSequence
.LoadBase
= p
->RIOConf
.RtaLoadBase
;
755 PktReplyP
->BootSequence
.CodeSize
= p
->RIOBootCount
;
757 CmdBlkP
->Packet
.len
= BOOT_SEQUENCE_LEN
| PKT_CMD_BIT
;
759 bcopy("BOOT",(void *)&CmdBlkP
->Packet
.data
[BOOT_SEQUENCE_LEN
],4);
761 rio_dprintk (RIO_DEBUG_BOOT
, "Boot RTA on Host %d Rup %d - %d (0x%x) packets to 0x%x\n",
762 HostP
-p
->RIOHosts
, Rup
, p
->RIONumBootPkts
, p
->RIONumBootPkts
,
763 p
->RIOConf
.RtaLoadBase
);
766 ** If this host is in slave mode, send the RTA an invalid boot
767 ** sequence command block to force it to kill the boot. We wait
768 ** for half a second before sending this packet to prevent the RTA
769 ** attempting to boot too often. The master host should then grab
770 ** the RTA and make it its own.
773 RIOQueueCmdBlk( HostP
, Rup
, CmdBlkP
);
778 ** It is a request for boot data.
780 sequence
= RWORD(PktCmdP
->Sequence
);
782 rio_dprintk (RIO_DEBUG_BOOT
, "Boot block %d on Host %d Rup%d\n",sequence
,HostP
-p
->RIOHosts
,Rup
);
784 if ( sequence
>= p
->RIONumBootPkts
) {
785 rio_dprintk (RIO_DEBUG_BOOT
, "Got a request for packet %d, max is %d\n", sequence
,
787 ShowPacket( DBG_BOOT
, PacketP
);
790 PktReplyP
->Sequence
= sequence
;
792 bcopy( p
->RIOBootPackets
[ p
->RIONumBootPkts
- sequence
- 1 ],
793 PktReplyP
->BootData
, RTA_BOOT_DATA_SIZE
);
795 CmdBlkP
->Packet
.len
= PKT_MAX_DATA_LEN
;
796 ShowPacket( DBG_BOOT
, &CmdBlkP
->Packet
);
797 RIOQueueCmdBlk( HostP
, Rup
, CmdBlkP
);
802 ** This function is called when an RTA been booted.
803 ** If booted by a host, HostP->HostUniqueNum is the booting host.
804 ** If booted by an RTA, HostP->Mapping[Rup].RtaUniqueNum is the booting RTA.
805 ** RtaUniq is the booted RTA.
807 static int RIOBootComplete( struct rio_info
*p
, struct Host
*HostP
, uint Rup
, struct PktCmd
*PktCmdP
)
809 struct Map
*MapP
= NULL
;
810 struct Map
*MapP2
= NULL
;
816 char *MyType
, *MyName
;
819 uint RtaUniq
= (RBYTE(PktCmdP
->UniqNum
[0])) +
820 (RBYTE(PktCmdP
->UniqNum
[1]) << 8) +
821 (RBYTE(PktCmdP
->UniqNum
[2]) << 16) +
822 (RBYTE(PktCmdP
->UniqNum
[3]) << 24);
824 /* Was RIOBooting-- . That's bad. If an RTA sends two of them, the
825 driver will never think that the RTA has booted... -- REW */
828 rio_dprintk (RIO_DEBUG_BOOT
, "RTA Boot completed - BootInProgress now %d\n", p
->RIOBooting
);
831 ** Determine type of unit (16/8 port RTA).
833 RtaType
= GetUnitType(RtaUniq
);
834 if ( Rup
>= (ushort
)MAX_RUP
) {
835 rio_dprintk (RIO_DEBUG_BOOT
, "RIO: Host %s has booted an RTA(%d) on link %c\n",
836 HostP
->Name
, 8 * RtaType
, RBYTE(PktCmdP
->LinkNum
)+'A');
838 rio_dprintk (RIO_DEBUG_BOOT
, "RIO: RTA %s has booted an RTA(%d) on link %c\n",
839 HostP
->Mapping
[Rup
].Name
, 8 * RtaType
,
840 RBYTE(PktCmdP
->LinkNum
)+'A');
843 rio_dprintk (RIO_DEBUG_BOOT
, "UniqNum is 0x%x\n",RtaUniq
);
845 if ( ( RtaUniq
== 0x00000000 ) || ( RtaUniq
== 0xffffffff ) )
847 rio_dprintk (RIO_DEBUG_BOOT
, "Illegal RTA Uniq Number\n");
852 ** If this RTA has just booted an RTA which doesn't belong to this
853 ** system, or the system is in slave mode, do not attempt to create
854 ** a new table entry for it.
856 if (!RIOBootOk(p
, HostP
, RtaUniq
))
858 MyLink
= RBYTE(PktCmdP
->LinkNum
);
859 if (Rup
< (ushort
) MAX_RUP
)
862 ** RtaUniq was clone booted (by this RTA). Instruct this RTA
863 ** to hold off further attempts to boot on this link for 30
866 if (RIOSuspendBootRta(HostP
, HostP
->Mapping
[Rup
].ID
, MyLink
))
868 rio_dprintk (RIO_DEBUG_BOOT
, "RTA failed to suspend booting on link %c\n",
875 ** RtaUniq was booted by this host. Set the booting link
876 ** to hold off for 30 seconds to give another unit a
877 ** chance to boot it.
879 WWORD(HostP
->LinkStrP
[MyLink
].WaitNoBoot
, 30);
881 rio_dprintk (RIO_DEBUG_BOOT
, "RTA %x not owned - suspend booting down link %c on unit %x\n",
882 RtaUniq
, 'A' + MyLink
, HostP
->Mapping
[Rup
].RtaUniqueNum
);
887 ** Check for a SLOT_IN_USE entry for this RTA attached to the
888 ** current host card in the driver table.
890 ** If it exists, make a note that we have booted it. Other parts of
891 ** the driver are interested in this information at a later date,
892 ** in particular when the booting RTA asks for an ID for this unit,
893 ** we must have set the BOOTED flag, and the NEWBOOT flag is used
894 ** to force an open on any ports that where previously open on this
897 for ( entry
=0; entry
<MAX_RUP
; entry
++ )
901 if ((HostP
->Mapping
[entry
].Flags
& SLOT_IN_USE
) &&
902 (HostP
->Mapping
[entry
].RtaUniqueNum
==RtaUniq
))
904 HostP
->Mapping
[entry
].Flags
|= RTA_BOOTED
|RTA_NEWBOOT
;
906 RIO_SV_BROADCAST(HostP
->svFlags
[entry
]);
908 if ( (sysport
=HostP
->Mapping
[entry
].SysPort
) != NO_PORT
)
910 if ( sysport
< p
->RIOFirstPortsBooted
)
911 p
->RIOFirstPortsBooted
= sysport
;
912 if ( sysport
> p
->RIOLastPortsBooted
)
913 p
->RIOLastPortsBooted
= sysport
;
915 ** For a 16 port RTA, check the second bank of 8 ports
917 if (RtaType
== TYPE_RTA16
)
919 entry2
= HostP
->Mapping
[entry
].ID2
- 1;
920 HostP
->Mapping
[entry2
].Flags
|= RTA_BOOTED
|RTA_NEWBOOT
;
922 RIO_SV_BROADCAST(HostP
->svFlags
[entry2
]);
924 sysport
= HostP
->Mapping
[entry2
].SysPort
;
925 if ( sysport
< p
->RIOFirstPortsBooted
)
926 p
->RIOFirstPortsBooted
= sysport
;
927 if ( sysport
> p
->RIOLastPortsBooted
)
928 p
->RIOLastPortsBooted
= sysport
;
931 if (RtaType
== TYPE_RTA16
) {
932 rio_dprintk (RIO_DEBUG_BOOT
, "RTA will be given IDs %d+%d\n",
935 rio_dprintk (RIO_DEBUG_BOOT
, "RTA will be given ID %d\n",entry
+1);
941 rio_dprintk (RIO_DEBUG_BOOT
, "RTA not configured for this host\n");
943 if ( Rup
>= (ushort
)MAX_RUP
)
946 ** It was a host that did the booting
949 MyName
= HostP
->Name
;
954 ** It was an RTA that did the booting
957 MyName
= HostP
->Mapping
[Rup
].Name
;
964 MyLink
= RBYTE(PktCmdP
->LinkNum
);
967 ** There is no SLOT_IN_USE entry for this RTA attached to the current
968 ** host card in the driver table.
970 ** Check for a SLOT_TENTATIVE entry for this RTA attached to the
971 ** current host card in the driver table.
973 ** If we find one, then we re-use that slot.
975 for ( entry
=0; entry
<MAX_RUP
; entry
++ )
977 if ( (HostP
->Mapping
[entry
].Flags
& SLOT_TENTATIVE
) &&
978 (HostP
->Mapping
[entry
].RtaUniqueNum
== RtaUniq
) )
980 if (RtaType
== TYPE_RTA16
)
982 entry2
= HostP
->Mapping
[entry
].ID2
- 1;
983 if ( (HostP
->Mapping
[entry2
].Flags
& SLOT_TENTATIVE
) &&
984 (HostP
->Mapping
[entry2
].RtaUniqueNum
== RtaUniq
) )
985 rio_dprintk (RIO_DEBUG_BOOT
, "Found previous tentative slots (%d+%d)\n",
991 rio_dprintk (RIO_DEBUG_BOOT
, "Found previous tentative slot (%d)\n",entry
);
992 if (! p
->RIONoMessage
)
993 cprintf("RTA connected to %s '%s' (%c) not configured.\n",MyType
,MyName
,MyLink
+'A');
999 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
1000 ** attached to the current host card in the driver table.
1002 ** Check if there is a SLOT_IN_USE or SLOT_TENTATIVE entry on another
1003 ** host for this RTA in the driver table.
1005 ** For a SLOT_IN_USE entry on another host, we need to delete the RTA
1006 ** entry from the other host and add it to this host (using some of
1007 ** the functions from table.c which do this).
1008 ** For a SLOT_TENTATIVE entry on another host, we must cope with the
1009 ** following scenario:
1011 ** + Plug 8 port RTA into host A. (This creates SLOT_TENTATIVE entry
1013 ** + Unplug RTA and plug into host B. (We now have 2 SLOT_TENTATIVE
1015 ** + Configure RTA on host B. (This slot now becomes SLOT_IN_USE)
1016 ** + Unplug RTA and plug back into host A.
1017 ** + Configure RTA on host A. We now have the same RTA configured
1018 ** with different ports on two different hosts.
1020 rio_dprintk (RIO_DEBUG_BOOT
, "Have we seen RTA %x before?\n", RtaUniq
);
1022 Flag
= 0; /* Convince the compiler this variable is initialized */
1023 for ( host
= 0; !found
&& (host
< p
->RIONumHosts
); host
++ )
1025 for ( rta
=0; rta
<MAX_RUP
; rta
++ )
1027 if ((p
->RIOHosts
[host
].Mapping
[rta
].Flags
&
1028 (SLOT_IN_USE
| SLOT_TENTATIVE
)) &&
1029 (p
->RIOHosts
[host
].Mapping
[rta
].RtaUniqueNum
==RtaUniq
))
1031 Flag
= p
->RIOHosts
[host
].Mapping
[rta
].Flags
;
1032 MapP
= &p
->RIOHosts
[host
].Mapping
[rta
];
1033 if (RtaType
== TYPE_RTA16
)
1035 MapP2
= &p
->RIOHosts
[host
].Mapping
[MapP
->ID2
- 1];
1036 rio_dprintk (RIO_DEBUG_BOOT
, "This RTA is units %d+%d from host %s\n",
1037 rta
+1, MapP
->ID2
, p
->RIOHosts
[host
].Name
);
1040 rio_dprintk (RIO_DEBUG_BOOT
, "This RTA is unit %d from host %s\n",
1041 rta
+1, p
->RIOHosts
[host
].Name
);
1049 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
1050 ** attached to the current host card in the driver table.
1052 ** If we have not found a SLOT_IN_USE or SLOT_TENTATIVE entry on
1053 ** another host for this RTA in the driver table...
1055 ** Check for a SLOT_IN_USE entry for this RTA in the config table.
1059 rio_dprintk (RIO_DEBUG_BOOT
, "Look for RTA %x in RIOSavedTable\n",RtaUniq
);
1060 for ( rta
=0; rta
< TOTAL_MAP_ENTRIES
; rta
++ )
1062 rio_dprintk (RIO_DEBUG_BOOT
, "Check table entry %d (%x)",
1064 p
->RIOSavedTable
[rta
].RtaUniqueNum
);
1066 if ( (p
->RIOSavedTable
[rta
].Flags
& SLOT_IN_USE
) &&
1067 (p
->RIOSavedTable
[rta
].RtaUniqueNum
== RtaUniq
) )
1069 MapP
= &p
->RIOSavedTable
[rta
];
1070 Flag
= p
->RIOSavedTable
[rta
].Flags
;
1071 if (RtaType
== TYPE_RTA16
)
1073 for (entry2
= rta
+ 1; entry2
< TOTAL_MAP_ENTRIES
;
1076 if (p
->RIOSavedTable
[entry2
].RtaUniqueNum
== RtaUniq
)
1079 MapP2
= &p
->RIOSavedTable
[entry2
];
1080 rio_dprintk (RIO_DEBUG_BOOT
, "This RTA is from table entries %d+%d\n",
1084 rio_dprintk (RIO_DEBUG_BOOT
, "This RTA is from table entry %d\n", rta
);
1091 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
1092 ** attached to the current host card in the driver table.
1094 ** We may have found a SLOT_IN_USE entry on another host for this
1095 ** RTA in the config table, or a SLOT_IN_USE or SLOT_TENTATIVE entry
1096 ** on another host for this RTA in the driver table.
1098 ** Check the driver table for room to fit this newly discovered RTA.
1099 ** RIOFindFreeID() first looks for free slots and if it does not
1100 ** find any free slots it will then attempt to oust any
1101 ** tentative entry in the table.
1104 if (RtaType
== TYPE_RTA16
)
1106 if (RIOFindFreeID(p
, HostP
, &entry
, &entry2
) == 0)
1108 RIODefaultName(p
, HostP
, entry
);
1109 FillSlot(entry
, entry2
, RtaUniq
, HostP
);
1115 if (RIOFindFreeID(p
, HostP
, &entry
, NULL
) == 0)
1117 RIODefaultName(p
, HostP
, entry
);
1118 FillSlot(entry
, 0, RtaUniq
, HostP
);
1124 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
1125 ** attached to the current host card in the driver table.
1127 ** If we found a SLOT_IN_USE entry on another host for this
1128 ** RTA in the config or driver table, and there are enough free
1129 ** slots in the driver table, then we need to move it over and
1130 ** delete it from the other host.
1131 ** If we found a SLOT_TENTATIVE entry on another host for this
1132 ** RTA in the driver table, just delete the other host entry.
1138 if (Flag
& SLOT_IN_USE
)
1140 rio_dprintk (RIO_DEBUG_BOOT
,
1141 "This RTA configured on another host - move entry to current host (1)\n");
1142 HostP
->Mapping
[entry
].SysPort
= MapP
->SysPort
;
1143 CCOPY( MapP
->Name
, HostP
->Mapping
[entry
].Name
, MAX_NAME_LEN
);
1144 HostP
->Mapping
[entry
].Flags
=
1145 SLOT_IN_USE
| RTA_BOOTED
| RTA_NEWBOOT
;
1147 RIO_SV_BROADCAST(HostP
->svFlags
[entry
]);
1149 RIOReMapPorts( p
, HostP
, &HostP
->Mapping
[entry
] );
1150 if ( HostP
->Mapping
[entry
].SysPort
< p
->RIOFirstPortsBooted
)
1151 p
->RIOFirstPortsBooted
= HostP
->Mapping
[entry
].SysPort
;
1152 if ( HostP
->Mapping
[entry
].SysPort
> p
->RIOLastPortsBooted
)
1153 p
->RIOLastPortsBooted
= HostP
->Mapping
[entry
].SysPort
;
1154 rio_dprintk (RIO_DEBUG_BOOT
, "SysPort %d, Name %s\n",(int)MapP
->SysPort
,MapP
->Name
);
1158 rio_dprintk (RIO_DEBUG_BOOT
,
1159 "This RTA has a tentative entry on another host - delete that entry (1)\n");
1160 HostP
->Mapping
[entry
].Flags
=
1161 SLOT_TENTATIVE
| RTA_BOOTED
| RTA_NEWBOOT
;
1163 RIO_SV_BROADCAST(HostP
->svFlags
[entry
]);
1166 if (RtaType
== TYPE_RTA16
)
1168 if (Flag
& SLOT_IN_USE
)
1170 HostP
->Mapping
[entry2
].Flags
= SLOT_IN_USE
|
1171 RTA_BOOTED
| RTA_NEWBOOT
| RTA16_SECOND_SLOT
;
1173 RIO_SV_BROADCAST(HostP
->svFlags
[entry2
]);
1175 HostP
->Mapping
[entry2
].SysPort
= MapP2
->SysPort
;
1177 ** Map second block of ttys for 16 port RTA
1179 RIOReMapPorts( p
, HostP
, &HostP
->Mapping
[entry2
] );
1180 if (HostP
->Mapping
[entry2
].SysPort
< p
->RIOFirstPortsBooted
)
1181 p
->RIOFirstPortsBooted
= HostP
->Mapping
[entry2
].SysPort
;
1182 if (HostP
->Mapping
[entry2
].SysPort
> p
->RIOLastPortsBooted
)
1183 p
->RIOLastPortsBooted
= HostP
->Mapping
[entry2
].SysPort
;
1184 rio_dprintk (RIO_DEBUG_BOOT
, "SysPort %d, Name %s\n",
1185 (int)HostP
->Mapping
[entry2
].SysPort
,
1186 HostP
->Mapping
[entry
].Name
);
1189 HostP
->Mapping
[entry2
].Flags
= SLOT_TENTATIVE
|
1190 RTA_BOOTED
| RTA_NEWBOOT
| RTA16_SECOND_SLOT
;
1192 RIO_SV_BROADCAST(HostP
->svFlags
[entry2
]);
1194 bzero( (caddr_t
)MapP2
, sizeof(struct Map
) );
1196 bzero( (caddr_t
)MapP
, sizeof(struct Map
) );
1197 if (! p
->RIONoMessage
)
1198 cprintf("An orphaned RTA has been adopted by %s '%s' (%c).\n",MyType
,MyName
,MyLink
+'A');
1200 else if (! p
->RIONoMessage
)
1201 cprintf("RTA connected to %s '%s' (%c) not configured.\n",MyType
,MyName
,MyLink
+'A');
1207 ** There is no room in the driver table to make an entry for the
1208 ** booted RTA. Keep a note of its Uniq Num in the overflow table,
1209 ** so we can ignore it's ID requests.
1211 if (! p
->RIONoMessage
)
1212 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');
1213 for ( entry
=0; entry
<HostP
->NumExtraBooted
; entry
++ )
1215 if ( HostP
->ExtraUnits
[entry
] == RtaUniq
)
1224 ** If there is room, add the unit to the list of extras
1226 if ( HostP
->NumExtraBooted
< MAX_EXTRA_UNITS
)
1227 HostP
->ExtraUnits
[HostP
->NumExtraBooted
++] = RtaUniq
;
1233 ** If the RTA or its host appears in the RIOBindTab[] structure then
1234 ** we mustn't boot the RTA and should return FALSE.
1235 ** This operation is slightly different from the other drivers for RIO
1236 ** in that this is designed to work with the new utilities
1237 ** not config.rio and is FAR SIMPLER.
1238 ** We no longer support the RIOBootMode variable. It is all done from the
1239 ** "boot/noboot" field in the rio.cf file.
1242 RIOBootOk(p
, HostP
, RtaUniq
)
1243 struct rio_info
* p
;
1244 struct Host
* HostP
;
1248 uint HostUniq
= HostP
->UniqueNum
;
1251 ** Search bindings table for RTA or its parent.
1252 ** If it exists, return 0, else 1.
1255 ( Entry
< MAX_RTA_BINDINGS
) && ( p
->RIOBindTab
[Entry
] != 0 );
1258 if ( (p
->RIOBindTab
[Entry
] == HostUniq
) ||
1259 (p
->RIOBindTab
[Entry
] == RtaUniq
) )
1266 ** Make an empty slot tentative. If this is a 16 port RTA, make both
1267 ** slots tentative, and the second one RTA_SECOND_SLOT as well.
1271 FillSlot(entry
, entry2
, RtaUniq
, HostP
)
1279 rio_dprintk (RIO_DEBUG_BOOT
, "FillSlot(%d, %d, 0x%x...)\n", entry
, entry2
, RtaUniq
);
1281 HostP
->Mapping
[entry
].Flags
= (RTA_BOOTED
| RTA_NEWBOOT
| SLOT_TENTATIVE
);
1282 HostP
->Mapping
[entry
].SysPort
= NO_PORT
;
1283 HostP
->Mapping
[entry
].RtaUniqueNum
= RtaUniq
;
1284 HostP
->Mapping
[entry
].HostUniqueNum
= HostP
->UniqueNum
;
1285 HostP
->Mapping
[entry
].ID
= entry
+ 1;
1286 HostP
->Mapping
[entry
].ID2
= 0;
1288 HostP
->Mapping
[entry2
].Flags
= (RTA_BOOTED
| RTA_NEWBOOT
|
1289 SLOT_TENTATIVE
| RTA16_SECOND_SLOT
);
1290 HostP
->Mapping
[entry2
].SysPort
= NO_PORT
;
1291 HostP
->Mapping
[entry2
].RtaUniqueNum
= RtaUniq
;
1292 HostP
->Mapping
[entry2
].HostUniqueNum
= HostP
->UniqueNum
;
1293 HostP
->Mapping
[entry2
].Name
[0] = '\0';
1294 HostP
->Mapping
[entry2
].ID
= entry2
+ 1;
1295 HostP
->Mapping
[entry2
].ID2
= entry
+ 1;
1296 HostP
->Mapping
[entry
].ID2
= entry2
+ 1;
1299 ** Must set these up, so that utilities show
1300 ** topology of 16 port RTAs correctly
1302 for ( link
=0; link
<LINKS_PER_UNIT
; link
++ ) {
1303 HostP
->Mapping
[entry
].Topology
[link
].Unit
= ROUTE_DISCONNECT
;
1304 HostP
->Mapping
[entry
].Topology
[link
].Link
= NO_LINK
;
1306 HostP
->Mapping
[entry2
].Topology
[link
].Unit
= ROUTE_DISCONNECT
;
1307 HostP
->Mapping
[entry2
].Topology
[link
].Link
= NO_LINK
;
1314 Function: This function is to disable the disk interrupt
1318 disable_interrupt(vector
)
1326 val
= 1 << (vector
- 40);
1327 __outb(S8259
+1, __inb(S8259
+1) | val
);
1330 val
= 1 << (vector
- 32);
1331 __outb(M8259
+1, __inb(M8259
+1) | val
);
1337 Function: This function is to enable the disk interrupt
1341 enable_interrupt(vector
)
1349 val
= 1 << (vector
- 40);
1351 __outb(S8259
+1, __inb(S8259
+1) & val
);
1354 val
= 1 << (vector
- 32);
1356 __outb(M8259
+1, __inb(M8259
+1) & val
);