rioboot.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:40k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2. ** -----------------------------------------------------------------------------
  3. **
  4. **  Perle Specialix driver for Linux
  5. **  Ported from existing RIO Driver for SCO sources.
  6.  *
  7.  *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
  8.  *
  9.  *      This program is free software; you can redistribute it and/or modify
  10.  *      it under the terms of the GNU General Public License as published by
  11.  *      the Free Software Foundation; either version 2 of the License, or
  12.  *      (at your option) any later version.
  13.  *
  14.  *      This program is distributed in the hope that it will be useful,
  15.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  *      GNU General Public License for more details.
  18.  *
  19.  *      You should have received a copy of the GNU General Public License
  20.  *      along with this program; if not, write to the Free Software
  21.  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22. **
  23. ** Module : rioboot.c
  24. ** SID : 1.3
  25. ** Last Modified : 11/6/98 10:33:36
  26. ** Retrieved : 11/6/98 10:33:48
  27. **
  28. **  ident @(#)rioboot.c 1.3
  29. **
  30. ** -----------------------------------------------------------------------------
  31. */
  32. #ifdef SCCS_LABELS
  33. static char *_rioboot_c_sccs_ = "@(#)rioboot.c 1.3";
  34. #endif
  35. #define __NO_VERSION__
  36. #include <linux/module.h>
  37. #include <linux/slab.h>
  38. #include <linux/errno.h>
  39. #include <linux/interrupt.h>
  40. #include <asm/io.h>
  41. #include <asm/system.h>
  42. #include <asm/string.h>
  43. #include <asm/semaphore.h>
  44. #include <linux/termios.h>
  45. #include <linux/serial.h>
  46. #include <linux/compatmac.h>
  47. #include <linux/generic_serial.h>
  48. #include "linux_compat.h"
  49. #include "rio_linux.h"
  50. #include "typdef.h"
  51. #include "pkt.h"
  52. #include "daemon.h"
  53. #include "rio.h"
  54. #include "riospace.h"
  55. #include "top.h"
  56. #include "cmdpkt.h"
  57. #include "map.h"
  58. #include "riotypes.h"
  59. #include "rup.h"
  60. #include "port.h"
  61. #include "riodrvr.h"
  62. #include "rioinfo.h"
  63. #include "func.h"
  64. #include "errors.h"
  65. #include "pci.h"
  66. #include "parmmap.h"
  67. #include "unixrup.h"
  68. #include "board.h"
  69. #include "host.h"
  70. #include "error.h"
  71. #include "phb.h"
  72. #include "link.h"
  73. #include "cmdblk.h"
  74. #include "route.h"
  75. static uchar
  76. RIOAtVec2Ctrl[] =
  77. {
  78. /* 0 */  INTERRUPT_DISABLE,
  79. /* 1 */  INTERRUPT_DISABLE,
  80. /* 2 */  INTERRUPT_DISABLE,
  81. /* 3 */  INTERRUPT_DISABLE,
  82. /* 4 */  INTERRUPT_DISABLE,
  83. /* 5 */  INTERRUPT_DISABLE,
  84. /* 6 */  INTERRUPT_DISABLE,
  85. /* 7 */  INTERRUPT_DISABLE,
  86. /* 8 */  INTERRUPT_DISABLE,
  87. /* 9 */  IRQ_9|INTERRUPT_ENABLE,
  88. /* 10 */ INTERRUPT_DISABLE,
  89. /* 11 */ IRQ_11|INTERRUPT_ENABLE,
  90. /* 12 */ IRQ_12|INTERRUPT_ENABLE,
  91. /* 13 */ INTERRUPT_DISABLE,
  92. /* 14 */ INTERRUPT_DISABLE,
  93. /* 15 */ IRQ_15|INTERRUPT_ENABLE
  94. };
  95. /*
  96. ** Load in the RTA boot code.
  97. */
  98. int
  99. RIOBootCodeRTA(p, rbp)
  100. struct rio_info * p;
  101. struct DownLoad * rbp; 
  102. {
  103. int offset;
  104. func_enter ();
  105. /* Linux doesn't allow you to disable interrupts during a
  106.    "copyin". (Crash when a pagefault occurs). */
  107. /* disable(oldspl); */
  108. rio_dprintk (RIO_DEBUG_BOOT, "Data at user address 0x%xn",(int)rbp->DataP);
  109. /*
  110. ** Check that we have set asside enough memory for this
  111. */
  112. if ( rbp->Count > SIXTY_FOUR_K ) {
  113. rio_dprintk (RIO_DEBUG_BOOT, "RTA Boot Code Too Large!n");
  114. p->RIOError.Error = HOST_FILE_TOO_LARGE;
  115. /* restore(oldspl); */
  116. func_exit ();
  117. return ENOMEM;
  118. }
  119. if ( p->RIOBooting ) {
  120. rio_dprintk (RIO_DEBUG_BOOT, "RTA Boot Code : BUSY BUSY BUSY!n");
  121. p->RIOError.Error = BOOT_IN_PROGRESS;
  122. /* restore(oldspl); */
  123. func_exit ();
  124. return EBUSY;
  125. }
  126. /*
  127. ** The data we load in must end on a (RTA_BOOT_DATA_SIZE) byte boundary,
  128. ** so calculate how far we have to move the data up the buffer
  129. ** to achieve this.
  130. */
  131. offset = (RTA_BOOT_DATA_SIZE - (rbp->Count % RTA_BOOT_DATA_SIZE)) % 
  132. RTA_BOOT_DATA_SIZE;
  133. /*
  134. ** Be clean, and clear the 'unused' portion of the boot buffer,
  135. ** because it will (eventually) be part of the Rta run time environment
  136. ** and so should be zeroed.
  137. */
  138. bzero( (caddr_t)p->RIOBootPackets, offset );
  139. /*
  140. ** Copy the data from user space.
  141. */
  142. if ( copyin((int)rbp->DataP,((caddr_t)(p->RIOBootPackets))+offset,
  143. rbp->Count) ==COPYFAIL ) {
  144. rio_dprintk (RIO_DEBUG_BOOT, "Bad data copy from user spacen");
  145. p->RIOError.Error = COPYIN_FAILED;
  146. /* restore(oldspl); */
  147. func_exit ();
  148. return EFAULT;
  149. }
  150. /*
  151. ** Make sure that our copy of the size includes that offset we discussed
  152. ** earlier.
  153. */
  154. p->RIONumBootPkts = (rbp->Count+offset)/RTA_BOOT_DATA_SIZE;
  155. p->RIOBootCount   = rbp->Count;
  156. /* restore(oldspl); */
  157. func_exit();
  158. return 0;
  159. }
  160. void rio_start_card_running (struct Host * HostP)
  161. {
  162. func_enter ();
  163. switch ( HostP->Type ) {
  164. case RIO_AT:
  165. rio_dprintk (RIO_DEBUG_BOOT, "Start ISA card runningn");
  166. WBYTE(HostP->Control, 
  167.       BOOT_FROM_RAM | EXTERNAL_BUS_ON
  168.       | HostP->Mode
  169.       | RIOAtVec2Ctrl[HostP->Ivec & 0xF] );
  170. break;
  171. #ifdef FUTURE_RELEASE
  172. case RIO_MCA:
  173. /*
  174. ** MCA handles IRQ vectors differently, so we don't write 
  175. ** them to this register.
  176. */
  177. rio_dprintk (RIO_DEBUG_BOOT, "Start MCA card runningn");
  178. WBYTE(HostP->Control, McaTpBootFromRam | McaTpBusEnable | HostP->Mode);
  179. break;
  180. case RIO_EISA:
  181. /*
  182. ** EISA is totally different and expects OUTBZs to turn it on.
  183. */
  184. rio_dprintk (RIO_DEBUG_BOOT, "Start EISA card runningn");
  185. OUTBZ( HostP->Slot, EISA_CONTROL_PORT, HostP->Mode | RIOEisaVec2Ctrl[HostP->Ivec] | EISA_TP_RUN | EISA_TP_BUS_ENABLE | EISA_TP_BOOT_FROM_RAM );
  186. break;
  187. #endif
  188. case RIO_PCI:
  189. /*
  190. ** PCI is much the same as MCA. Everything is once again memory
  191. ** mapped, so we are writing to memory registers instead of io
  192. ** ports.
  193. */
  194. rio_dprintk (RIO_DEBUG_BOOT, "Start PCI card runningn");
  195. WBYTE(HostP->Control, PCITpBootFromRam | PCITpBusEnable | HostP->Mode);
  196. break;
  197. default:
  198. rio_dprintk (RIO_DEBUG_BOOT, "Unknown host type %dn", HostP->Type);
  199. break;
  200. }
  201. /* 
  202. printk (KERN_INFO "Done with starting the cardn");
  203. func_exit ();
  204. */
  205. return;
  206. }
  207. /*
  208. ** Load in the host boot code - load it directly onto all halted hosts
  209. ** of the correct type.
  210. **
  211. ** Put your rubber pants on before messing with this code - even the magic
  212. ** numbers have trouble understanding what they are doing here.
  213. */
  214. int
  215. RIOBootCodeHOST(p, rbp)
  216. struct rio_info * p;
  217. register struct DownLoad *rbp;
  218. {
  219. register struct Host *HostP;
  220. register caddr_t Cad;
  221. register PARM_MAP *ParmMapP;
  222. register int RupN;
  223. int PortN;
  224. uint host;
  225. caddr_t StartP;
  226. BYTE *DestP;
  227. int wait_count;
  228. ushort OldParmMap;
  229. ushort offset; /* It is very important that this is a ushort */
  230. /* uint byte; */
  231. caddr_t DownCode = NULL;
  232. unsigned long flags;
  233. HostP = NULL; /* Assure the compiler we've initialized it */
  234. for ( host=0; host<p->RIONumHosts; host++ ) {
  235. rio_dprintk (RIO_DEBUG_BOOT, "Attempt to boot host %dn",host);
  236. HostP = &p->RIOHosts[host];
  237. rio_dprintk (RIO_DEBUG_BOOT,  "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%xn",
  238.     HostP->Type, HostP->Mode, HostP->Ivec);
  239. if ( (HostP->Flags & RUN_STATE) != RC_WAITING ) {
  240. rio_dprintk (RIO_DEBUG_BOOT, "%s %d already runningn","Host",host);
  241. continue;
  242. }
  243. /*
  244. ** Grab a 32 bit pointer to the card.
  245. */
  246. Cad = HostP->Caddr;
  247. /*
  248. ** We are going to (try) and load in rbp->Count bytes.
  249. ** The last byte will reside at p->RIOConf.HostLoadBase-1;
  250. ** Therefore, we need to start copying at address
  251. ** (caddr+p->RIOConf.HostLoadBase-rbp->Count)
  252. */
  253. StartP = (caddr_t)&Cad[p->RIOConf.HostLoadBase-rbp->Count];
  254. rio_dprintk (RIO_DEBUG_BOOT, "kernel virtual address for host is 0x%xn", (int)Cad );
  255. rio_dprintk (RIO_DEBUG_BOOT, "kernel virtual address for download is 0x%xn", (int)StartP);
  256. rio_dprintk (RIO_DEBUG_BOOT, "host loadbase is 0x%xn",p->RIOConf.HostLoadBase);
  257. rio_dprintk (RIO_DEBUG_BOOT, "size of download is 0x%xn", rbp->Count);
  258. if ( p->RIOConf.HostLoadBase < rbp->Count ) {
  259. rio_dprintk (RIO_DEBUG_BOOT, "Bin too largen");
  260. p->RIOError.Error = HOST_FILE_TOO_LARGE;
  261. func_exit ();
  262. return EFBIG;
  263. }
  264. /*
  265. ** Ensure that the host really is stopped.
  266. ** Disable it's external bus & twang its reset line.
  267. */
  268. RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot );
  269. /*
  270. ** Copy the data directly from user space to the SRAM.
  271. ** This ain't going to be none too clever if the download
  272. ** code is bigger than this segment.
  273. */
  274. rio_dprintk (RIO_DEBUG_BOOT, "Copy in coden");
  275. /*
  276. ** PCI hostcard can't cope with 32 bit accesses and so need to copy 
  277. ** data to a local buffer, and then dripfeed the card.
  278. */
  279. if ( HostP->Type == RIO_PCI ) {
  280.   /* int offset; */
  281. DownCode = sysbrk(rbp->Count);
  282. if ( !DownCode ) {
  283. rio_dprintk (RIO_DEBUG_BOOT, "No system memory availablen");
  284. p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY;
  285. func_exit ();
  286. return ENOMEM;
  287. }
  288. bzero(DownCode, rbp->Count);
  289. if ( copyin((int)rbp->DataP,DownCode,rbp->Count)==COPYFAIL ) {
  290. rio_dprintk (RIO_DEBUG_BOOT, "Bad copyin of host datan");
  291. p->RIOError.Error = COPYIN_FAILED;
  292. func_exit ();
  293. return EFAULT;
  294. }
  295. HostP->Copy( DownCode, StartP, rbp->Count );
  296. sysfree( DownCode, rbp->Count );
  297. }
  298. else if ( copyin((int)rbp->DataP,StartP,rbp->Count)==COPYFAIL ) {
  299. rio_dprintk (RIO_DEBUG_BOOT, "Bad copyin of host datan");
  300. p->RIOError.Error = COPYIN_FAILED;
  301. func_exit ();
  302. return EFAULT;
  303. }
  304. rio_dprintk (RIO_DEBUG_BOOT, "Copy completedn");
  305. /*
  306. ** S T O P !
  307. **
  308. ** Upto this point the code has been fairly rational, and possibly
  309. ** even straight forward. What follows is a pile of crud that will
  310. ** magically turn into six bytes of transputer assembler. Normally
  311. ** you would expect an array or something, but, being me, I have
  312. ** chosen [been told] to use a technique whereby the startup code
  313. ** will be correct if we change the loadbase for the code. Which
  314. ** brings us onto another issue - the loadbase is the *end* of the
  315. ** code, not the start.
  316. **
  317. ** If I were you I wouldn't start from here.
  318. */
  319. /*
  320. ** We now need to insert a short boot section into
  321. ** the memory at the end of Sram2. This is normally (de)composed
  322. ** of the last eight bytes of the download code. The
  323. ** download has been assembled/compiled to expect to be
  324. ** loaded from 0x7FFF downwards. We have loaded it
  325. ** at some other address. The startup code goes into the small
  326. ** ram window at Sram2, in the last 8 bytes, which are really
  327. ** at addresses 0x7FF8-0x7FFF.
  328. **
  329. ** If the loadbase is, say, 0x7C00, then we need to branch to
  330. ** address 0x7BFE to run the host.bin startup code. We assemble
  331. ** this jump manually.
  332. **
  333. ** The two byte sequence 60 08 is loaded into memory at address
  334. ** 0x7FFE,F. This is a local branch to location 0x7FF8 (60 is nfix 0,
  335. ** which adds '0' to the .O register, complements .O, and then shifts
  336. ** it left by 4 bit positions, 08 is a jump .O+8 instruction. This will
  337. ** add 8 to .O (which was 0xFFF0), and will branch RELATIVE to the new
  338. ** location. Now, the branch starts from the value of .PC (or .IP or
  339. ** whatever the bloody register is called on this chip), and the .PC
  340. ** will be pointing to the location AFTER the branch, in this case
  341. ** .PC == 0x8000, so the branch will be to 0x8000+0xFFF8 = 0x7FF8.
  342. **
  343. ** A long branch is coded at 0x7FF8. This consists of loading a four
  344. ** byte offset into .O using nfix (as above) and pfix operators. The
  345. ** pfix operates in exactly the same way as the nfix operator, but
  346. ** without the complement operation. The offset, of course, must be
  347. ** relative to the address of the byte AFTER the branch instruction,
  348. ** which will be (urm) 0x7FFC, so, our final destination of the branch
  349. ** (loadbase-2), has to be reached from here. Imagine that the loadbase
  350. ** is 0x7C00 (which it is), then we will need to branch to 0x7BFE (which
  351. ** is the first byte of the initial two byte short local branch of the
  352. ** download code).
  353. **
  354. ** To code a jump from 0x7FFC (which is where the branch will start
  355. ** from) to 0x7BFE, we will need to branch 0xFC02 bytes (0x7FFC+0xFC02)=
  356. ** 0x7BFE.
  357. ** This will be coded as four bytes:
  358. ** 60 2C 20 02
  359. ** being nfix .O+0
  360. **    pfix .O+C
  361. **    pfix .O+0
  362. **    jump .O+2
  363. **
  364. ** The nfix operator is used, so that the startup code will be
  365. ** compatible with the whole Tp family. (lies, damn lies, it'll never
  366. ** work in a month of Sundays).
  367. **
  368. ** The nfix nyble is the 1s compliment of the nyble value you
  369. ** want to load - in this case we wanted 'F' so we nfix loaded '0'.
  370. */
  371. /*
  372. ** Dest points to the top 8 bytes of Sram2. The Tp jumps
  373. ** to 0x7FFE at reset time, and starts executing. This is
  374. ** a short branch to 0x7FF8, where a long branch is coded.
  375. */
  376. DestP = (BYTE *)&Cad[0x7FF8]; /* <<<---- READ THE ABOVE COMMENTS */
  377. #define NFIX(N) (0x60 | (N)) /* .O  = (~(.O + N))<<4 */
  378. #define PFIX(N) (0x20 | (N)) /* .O  =   (.O + N)<<4  */
  379. #define JUMP(N) (0x00 | (N)) /* .PC =   .PC + .O  */
  380. /*
  381. ** 0x7FFC is the address of the location following the last byte of
  382. ** the four byte jump instruction.
  383. ** READ THE ABOVE COMMENTS
  384. **
  385. ** offset is (TO-FROM) % MEMSIZE, but with compound buggering about.
  386. ** Memsize is 64K for this range of Tp, so offset is a short (unsigned,
  387. ** cos I don't understand 2's complement).
  388. */
  389. offset = (p->RIOConf.HostLoadBase-2)-0x7FFC;
  390. WBYTE( DestP[0] , NFIX(((ushort)(~offset) >> (ushort)12) & 0xF) );
  391. WBYTE( DestP[1] , PFIX(( offset >> 8) & 0xF) );
  392. WBYTE( DestP[2] , PFIX(( offset >> 4) & 0xF) );
  393. WBYTE( DestP[3] , JUMP( offset & 0xF) );
  394. WBYTE( DestP[6] , NFIX(0) );
  395. WBYTE( DestP[7] , JUMP(8) );
  396. rio_dprintk (RIO_DEBUG_BOOT, "host loadbase is 0x%xn",p->RIOConf.HostLoadBase);
  397. rio_dprintk (RIO_DEBUG_BOOT, "startup offset is 0x%xn",offset);
  398. /*
  399. ** Flag what is going on
  400. */
  401. HostP->Flags &= ~RUN_STATE;
  402. HostP->Flags |= RC_STARTUP;
  403. /*
  404. ** Grab a copy of the current ParmMap pointer, so we
  405. ** can tell when it has changed.
  406. */
  407. OldParmMap = RWORD(HostP->__ParmMapR);
  408. rio_dprintk (RIO_DEBUG_BOOT, "Original parmmap is 0x%xn",OldParmMap);
  409. /*
  410. ** And start it running (I hope).
  411. ** As there is nothing dodgy or obscure about the
  412. ** above code, this is guaranteed to work every time.
  413. */
  414. rio_dprintk (RIO_DEBUG_BOOT,  "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%xn",
  415.     HostP->Type, HostP->Mode, HostP->Ivec);
  416. rio_start_card_running(HostP);
  417. rio_dprintk (RIO_DEBUG_BOOT, "Set control portn");
  418. /*
  419. ** Now, wait for upto five seconds for the Tp to setup the parmmap
  420. ** pointer:
  421. */
  422. for ( wait_count=0; (wait_count<p->RIOConf.StartupTime)&&
  423. (RWORD(HostP->__ParmMapR)==OldParmMap); wait_count++ ) {
  424. rio_dprintk (RIO_DEBUG_BOOT, "Checkout %d, 0x%xn",wait_count,RWORD(HostP->__ParmMapR));
  425. delay(HostP, HUNDRED_MS);
  426. }
  427. /*
  428. ** If the parmmap pointer is unchanged, then the host code
  429. ** has crashed & burned in a really spectacular way
  430. */
  431. if ( RWORD(HostP->__ParmMapR) == OldParmMap ) {
  432. rio_dprintk (RIO_DEBUG_BOOT, "parmmap 0x%xn", RWORD(HostP->__ParmMapR));
  433. rio_dprintk (RIO_DEBUG_BOOT, "RIO Mesg Run Failn");
  434. #define HOST_DISABLE 
  435. HostP->Flags &= ~RUN_STATE; 
  436. HostP->Flags |= RC_STUFFED; 
  437. RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot );
  438. continue
  439. HOST_DISABLE;
  440. }
  441. rio_dprintk (RIO_DEBUG_BOOT, "Running 0x%xn", RWORD(HostP->__ParmMapR));
  442. /*
  443. ** Well, the board thought it was OK, and setup its parmmap
  444. ** pointer. For the time being, we will pretend that this
  445. ** board is running, and check out what the error flag says.
  446. */
  447. /*
  448. ** Grab a 32 bit pointer to the parmmap structure
  449. */
  450. ParmMapP = (PARM_MAP *)RIO_PTR(Cad,RWORD(HostP->__ParmMapR));
  451. rio_dprintk (RIO_DEBUG_BOOT, "ParmMapP : %xn", (int)ParmMapP);
  452. ParmMapP = (PARM_MAP *)((unsigned long)Cad + 
  453. (unsigned long)((RWORD((HostP->__ParmMapR))) & 0xFFFF)); 
  454. rio_dprintk (RIO_DEBUG_BOOT, "ParmMapP : %xn", (int)ParmMapP);
  455. /*
  456. ** The links entry should be 0xFFFF; we set it up
  457. ** with a mask to say how many PHBs to use, and 
  458. ** which links to use.
  459. */
  460. if ( (RWORD(ParmMapP->links) & 0xFFFF) != 0xFFFF ) {
  461. rio_dprintk (RIO_DEBUG_BOOT, "RIO Mesg Run Fail %sn", HostP->Name);
  462. rio_dprintk (RIO_DEBUG_BOOT, "Links = 0x%xn",RWORD(ParmMapP->links));
  463. HOST_DISABLE;
  464. }
  465. WWORD(ParmMapP->links , RIO_LINK_ENABLE);
  466. /*
  467. ** now wait for the card to set all the parmmap->XXX stuff
  468. ** this is a wait of upto two seconds....
  469. */
  470. rio_dprintk (RIO_DEBUG_BOOT, "Looking for init_done - %d ticksn",p->RIOConf.StartupTime);
  471. HostP->timeout_id = 0;
  472. for ( wait_count=0; (wait_count<p->RIOConf.StartupTime) && 
  473. !RWORD(ParmMapP->init_done); wait_count++ ) {
  474. rio_dprintk (RIO_DEBUG_BOOT, "Waiting for init_donen");
  475. delay(HostP, HUNDRED_MS);
  476. }
  477. rio_dprintk (RIO_DEBUG_BOOT, "OK! init_done!n");
  478. if (RWORD(ParmMapP->error) != E_NO_ERROR || 
  479. !RWORD(ParmMapP->init_done) ) {
  480. rio_dprintk (RIO_DEBUG_BOOT, "RIO Mesg Run Fail %sn", HostP->Name);
  481. rio_dprintk (RIO_DEBUG_BOOT, "Timedout waiting for init_donen");
  482. HOST_DISABLE;
  483. }
  484. rio_dprintk (RIO_DEBUG_BOOT, "Got init_donen");
  485. /*
  486. ** It runs! It runs!
  487. */
  488. rio_dprintk (RIO_DEBUG_BOOT, "Host ID %x Runningn",HostP->UniqueNum);
  489. /*
  490. ** set the time period between interrupts.
  491. */
  492. WWORD(ParmMapP->timer, (short)p->RIOConf.Timer );
  493. /*
  494. ** Translate all the 16 bit pointers in the __ParmMapR into
  495. ** 32 bit pointers for the driver.
  496. */
  497. HostP->ParmMapP  = ParmMapP;
  498. HostP->PhbP  = (PHB*)RIO_PTR(Cad,RWORD(ParmMapP->phb_ptr));
  499. HostP->RupP  = (RUP*)RIO_PTR(Cad,RWORD(ParmMapP->rups));
  500. HostP->PhbNumP   = (ushort*)RIO_PTR(Cad,RWORD(ParmMapP->phb_num_ptr));
  501. HostP->LinkStrP  = (LPB*)RIO_PTR(Cad,RWORD(ParmMapP->link_str_ptr));
  502. /*
  503. ** point the UnixRups at the real Rups
  504. */
  505. for ( RupN = 0; RupN<MAX_RUP; RupN++ ) {
  506. HostP->UnixRups[RupN].RupP = &HostP->RupP[RupN];
  507. HostP->UnixRups[RupN].Id   = RupN+1;
  508. HostP->UnixRups[RupN].BaseSysPort = NO_PORT;
  509. HostP->UnixRups[RupN].RupLock = SPIN_LOCK_UNLOCKED;
  510. }
  511. for ( RupN = 0; RupN<LINKS_PER_UNIT; RupN++ ) {
  512. HostP->UnixRups[RupN+MAX_RUP].RupP = &HostP->LinkStrP[RupN].rup;
  513. HostP->UnixRups[RupN+MAX_RUP].Id  = 0;
  514. HostP->UnixRups[RupN+MAX_RUP].BaseSysPort = NO_PORT;
  515. HostP->UnixRups[RupN+MAX_RUP].RupLock = SPIN_LOCK_UNLOCKED;
  516. }
  517. /*
  518. ** point the PortP->Phbs at the real Phbs
  519. */
  520. for ( PortN=p->RIOFirstPortsMapped; 
  521. PortN<p->RIOLastPortsMapped+PORTS_PER_RTA; PortN++ ) {
  522. if ( p->RIOPortp[PortN]->HostP == HostP ) {
  523. struct Port *PortP = p->RIOPortp[PortN];
  524. struct PHB *PhbP;
  525. /* int oldspl; */
  526. if ( !PortP->Mapped )
  527. continue;
  528. PhbP = &HostP->PhbP[PortP->HostPort];
  529. rio_spin_lock_irqsave(&PortP->portSem, flags);
  530. PortP->PhbP = PhbP;
  531. PortP->TxAdd = (WORD *)RIO_PTR(Cad,RWORD(PhbP->tx_add));
  532. PortP->TxStart  = (WORD *)RIO_PTR(Cad,RWORD(PhbP->tx_start));
  533. PortP->TxEnd = (WORD *)RIO_PTR(Cad,RWORD(PhbP->tx_end));
  534. PortP->RxRemove = (WORD *)RIO_PTR(Cad,RWORD(PhbP->rx_remove));
  535. PortP->RxStart  = (WORD *)RIO_PTR(Cad,RWORD(PhbP->rx_start));
  536. PortP->RxEnd = (WORD *)RIO_PTR(Cad,RWORD(PhbP->rx_end));
  537. rio_spin_unlock_irqrestore(&PortP->portSem, flags);
  538. /*
  539. ** point the UnixRup at the base SysPort
  540. */
  541. if ( !(PortN % PORTS_PER_RTA) )
  542. HostP->UnixRups[PortP->RupNum].BaseSysPort = PortN;
  543. }
  544. }
  545. rio_dprintk (RIO_DEBUG_BOOT, "Set the card running... n");
  546. /*
  547. ** last thing - show the world that everything is in place
  548. */
  549. HostP->Flags &= ~RUN_STATE;
  550. HostP->Flags |= RC_RUNNING;
  551. }
  552. /*
  553. ** MPX always uses a poller. This is actually patched into the system
  554. ** configuration and called directly from each clock tick.
  555. **
  556. */
  557. p->RIOPolling = 1;
  558. p->RIOSystemUp++;
  559. rio_dprintk (RIO_DEBUG_BOOT, "Done everything %xn", HostP->Ivec);
  560. func_exit ();
  561. return 0;
  562. }
  563. /*
  564. ** Boot an RTA. If we have successfully processed this boot, then
  565. ** return 1. If we havent, then return 0.
  566. */
  567. int
  568. RIOBootRup( p, Rup, HostP, PacketP)
  569. struct rio_info * p;
  570. uint Rup;
  571. struct Host *HostP;
  572. struct PKT *PacketP; 
  573. {
  574. struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data;
  575. struct PktCmd_M *PktReplyP;
  576. struct CmdBlk *CmdBlkP;
  577. uint sequence;
  578. #ifdef CHECK
  579. CheckHost(Host);
  580. CheckRup(Rup);
  581. CheckHostP(HostP);
  582. CheckPacketP(PacketP);
  583. #endif
  584. /*
  585. ** If we haven't been told what to boot, we can't boot it.
  586. */
  587. if ( p->RIONumBootPkts == 0 ) {
  588. rio_dprintk (RIO_DEBUG_BOOT, "No RTA code to download yetn");
  589. return 0;
  590. }
  591. /* rio_dprint(RIO_DEBUG_BOOT, NULL,DBG_BOOT,"Incoming command packetn"); */
  592. /* ShowPacket( DBG_BOOT, PacketP ); */
  593. /*
  594. ** Special case of boot completed - if we get one of these then we
  595. ** don't need a command block. For all other cases we do, so handle
  596. ** this first and then get a command block, then handle every other
  597. ** case, relinquishing the command block if disaster strikes!
  598. */
  599. if ( (RBYTE(PacketP->len) & PKT_CMD_BIT) && 
  600. (RBYTE(PktCmdP->Command)==BOOT_COMPLETED) )
  601. return RIOBootComplete(p, HostP, Rup, PktCmdP );
  602. /*
  603. ** try to unhook a command block from the command free list.
  604. */
  605. if ( !(CmdBlkP = RIOGetCmdBlk()) ) {
  606. rio_dprintk (RIO_DEBUG_BOOT, "No command blocks to boot RTA! come back later.n");
  607. return 0;
  608. }
  609. /*
  610. ** Fill in the default info on the command block
  611. */
  612. CmdBlkP->Packet.dest_unit = Rup < (ushort)MAX_RUP ? Rup : 0;
  613. CmdBlkP->Packet.dest_port = BOOT_RUP;
  614. CmdBlkP->Packet.src_unit  = 0;
  615. CmdBlkP->Packet.src_port  = BOOT_RUP;
  616. CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;
  617. PktReplyP = (struct PktCmd_M *)CmdBlkP->Packet.data;
  618. /*
  619. ** process COMMANDS on the boot rup!
  620. */
  621. if ( RBYTE(PacketP->len) & PKT_CMD_BIT ) {
  622. /*
  623. ** We only expect one type of command - a BOOT_REQUEST!
  624. */
  625. if ( RBYTE(PktCmdP->Command) != BOOT_REQUEST ) {
  626. rio_dprintk (RIO_DEBUG_BOOT, "Unexpected command %d on BOOT RUP %d of host %dn", 
  627. PktCmdP->Command,Rup,HostP-p->RIOHosts);
  628. ShowPacket( DBG_BOOT, PacketP );
  629. RIOFreeCmdBlk( CmdBlkP );
  630. return 1;
  631. }
  632. /*
  633. ** Build a Boot Sequence command block
  634. **
  635. ** 02.03.1999 ARG - ESIL 0820 fix
  636. ** We no longer need to use "Boot Mode", we'll always allow
  637. ** boot requests - the boot will not complete if the device
  638. ** appears in the bindings table.
  639. ** So, this conditional is not required ...
  640. **
  641. if (p->RIOBootMode == RC_BOOT_NONE)
  642. **
  643. ** If the system is in slave mode, and a boot request is
  644. ** received, set command to BOOT_ABORT so that the boot
  645. ** will not complete.
  646. **
  647. PktReplyP->Command  = BOOT_ABORT;
  648. else
  649. **
  650. ** We'll just (always) set the command field in packet reply
  651. ** to allow an attempted boot sequence :
  652. */
  653. PktReplyP->Command = BOOT_SEQUENCE;
  654. PktReplyP->BootSequence.NumPackets = p->RIONumBootPkts;
  655. PktReplyP->BootSequence.LoadBase   = p->RIOConf.RtaLoadBase;
  656. PktReplyP->BootSequence.CodeSize   = p->RIOBootCount;
  657. CmdBlkP->Packet.len = BOOT_SEQUENCE_LEN | PKT_CMD_BIT;
  658. bcopy("BOOT",(void *)&CmdBlkP->Packet.data[BOOT_SEQUENCE_LEN],4);
  659. rio_dprintk (RIO_DEBUG_BOOT, "Boot RTA on Host %d Rup %d - %d (0x%x) packets to 0x%xn",
  660. HostP-p->RIOHosts, Rup, p->RIONumBootPkts, p->RIONumBootPkts, 
  661. p->RIOConf.RtaLoadBase);
  662. /*
  663. ** If this host is in slave mode, send the RTA an invalid boot
  664. ** sequence command block to force it to kill the boot. We wait
  665. ** for half a second before sending this packet to prevent the RTA
  666. ** attempting to boot too often. The master host should then grab
  667. ** the RTA and make it its own.
  668. */
  669. p->RIOBooting++;
  670. RIOQueueCmdBlk( HostP, Rup, CmdBlkP );
  671. return 1;
  672. }
  673. /*
  674. ** It is a request for boot data.
  675. */
  676. sequence = RWORD(PktCmdP->Sequence);
  677. rio_dprintk (RIO_DEBUG_BOOT, "Boot block %d on Host %d Rup%dn",sequence,HostP-p->RIOHosts,Rup);
  678. if ( sequence >= p->RIONumBootPkts ) {
  679. rio_dprintk (RIO_DEBUG_BOOT, "Got a request for packet %d, max is %dn", sequence, 
  680. p->RIONumBootPkts);
  681. ShowPacket( DBG_BOOT, PacketP );
  682. }
  683. PktReplyP->Sequence = sequence;
  684. bcopy( p->RIOBootPackets[ p->RIONumBootPkts - sequence - 1 ], 
  685. PktReplyP->BootData, RTA_BOOT_DATA_SIZE );
  686. CmdBlkP->Packet.len = PKT_MAX_DATA_LEN;
  687. ShowPacket( DBG_BOOT, &CmdBlkP->Packet );
  688. RIOQueueCmdBlk( HostP, Rup, CmdBlkP );
  689. return 1;
  690. }
  691. /*
  692. ** This function is called when an RTA been booted.
  693. ** If booted by a host, HostP->HostUniqueNum is the booting host.
  694. ** If booted by an RTA, HostP->Mapping[Rup].RtaUniqueNum is the booting RTA.
  695. ** RtaUniq is the booted RTA.
  696. */
  697. int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct PktCmd *PktCmdP )
  698. {
  699. struct Map *MapP = NULL;
  700. struct Map *MapP2 = NULL;
  701. int Flag;
  702. int found;
  703. int host, rta;
  704. int EmptySlot = -1;
  705. int entry, entry2;
  706. char *MyType, *MyName;
  707. uint MyLink;
  708. ushort RtaType;
  709. uint RtaUniq = (RBYTE(PktCmdP->UniqNum[0])) +
  710.   (RBYTE(PktCmdP->UniqNum[1]) << 8) +
  711.   (RBYTE(PktCmdP->UniqNum[2]) << 16) +
  712.   (RBYTE(PktCmdP->UniqNum[3]) << 24);
  713. /* Was RIOBooting-- . That's bad. If an RTA sends two of them, the
  714.    driver will never think that the RTA has booted... -- REW */
  715. p->RIOBooting = 0;
  716. rio_dprintk (RIO_DEBUG_BOOT, "RTA Boot completed - BootInProgress now %dn", p->RIOBooting);
  717. /*
  718. ** Determine type of unit (16/8 port RTA).
  719. */
  720. RtaType = GetUnitType(RtaUniq);
  721.         if ( Rup >= (ushort)MAX_RUP ) {
  722.     rio_dprintk (RIO_DEBUG_BOOT, "RIO: Host %s has booted an RTA(%d) on link %cn",
  723.      HostP->Name, 8 * RtaType, RBYTE(PktCmdP->LinkNum)+'A');
  724. } else {
  725.     rio_dprintk (RIO_DEBUG_BOOT, "RIO: RTA %s has booted an RTA(%d) on link %cn",
  726.      HostP->Mapping[Rup].Name, 8 * RtaType,
  727.      RBYTE(PktCmdP->LinkNum)+'A');
  728. }
  729. rio_dprintk (RIO_DEBUG_BOOT, "UniqNum is 0x%xn",RtaUniq);
  730.         if ( ( RtaUniq == 0x00000000 ) || ( RtaUniq == 0xffffffff ) )
  731. {
  732.     rio_dprintk (RIO_DEBUG_BOOT, "Illegal RTA Uniq Numbern");
  733.     return TRUE;
  734. }
  735. /*
  736. ** If this RTA has just booted an RTA which doesn't belong to this
  737. ** system, or the system is in slave mode, do not attempt to create
  738. ** a new table entry for it.
  739. */
  740. if (!RIOBootOk(p, HostP, RtaUniq))
  741. {
  742.     MyLink = RBYTE(PktCmdP->LinkNum);
  743.     if (Rup < (ushort) MAX_RUP)
  744.     {
  745. /*
  746. ** RtaUniq was clone booted (by this RTA). Instruct this RTA
  747. ** to hold off further attempts to boot on this link for 30
  748. ** seconds.
  749. */
  750. if (RIOSuspendBootRta(HostP, HostP->Mapping[Rup].ID, MyLink))
  751. {
  752.     rio_dprintk (RIO_DEBUG_BOOT, "RTA failed to suspend booting on link %cn",
  753.      'A' + MyLink);
  754. }
  755.     }
  756.     else
  757.     {
  758. /*
  759. ** RtaUniq was booted by this host. Set the booting link
  760. ** to hold off for 30 seconds to give another unit a
  761. ** chance to boot it.
  762. */
  763. WWORD(HostP->LinkStrP[MyLink].WaitNoBoot, 30);
  764.     }
  765.     rio_dprintk (RIO_DEBUG_BOOT, "RTA %x not owned - suspend booting down link %c on unit %xn",
  766.       RtaUniq, 'A' + MyLink, HostP->Mapping[Rup].RtaUniqueNum);
  767.     return TRUE;
  768. }
  769. /*
  770. ** Check for a SLOT_IN_USE entry for this RTA attached to the
  771. ** current host card in the driver table.
  772. **
  773. ** If it exists, make a note that we have booted it. Other parts of
  774. ** the driver are interested in this information at a later date,
  775. ** in particular when the booting RTA asks for an ID for this unit,
  776. ** we must have set the BOOTED flag, and the NEWBOOT flag is used
  777. ** to force an open on any ports that where previously open on this
  778. ** unit.
  779. */
  780.         for ( entry=0; entry<MAX_RUP; entry++ )
  781. {
  782.     uint sysport;
  783.     if ((HostP->Mapping[entry].Flags & SLOT_IN_USE) && 
  784.        (HostP->Mapping[entry].RtaUniqueNum==RtaUniq))
  785.     {
  786.         HostP->Mapping[entry].Flags |= RTA_BOOTED|RTA_NEWBOOT;
  787. #if NEED_TO_FIX
  788. RIO_SV_BROADCAST(HostP->svFlags[entry]);
  789. #endif
  790. if ( (sysport=HostP->Mapping[entry].SysPort) != NO_PORT )
  791. {
  792.    if ( sysport < p->RIOFirstPortsBooted )
  793. p->RIOFirstPortsBooted = sysport;
  794.    if ( sysport > p->RIOLastPortsBooted )
  795. p->RIOLastPortsBooted = sysport;
  796.    /*
  797.    ** For a 16 port RTA, check the second bank of 8 ports
  798.    */
  799.    if (RtaType == TYPE_RTA16)
  800.    {
  801. entry2 = HostP->Mapping[entry].ID2 - 1;
  802. HostP->Mapping[entry2].Flags |= RTA_BOOTED|RTA_NEWBOOT;
  803. #if NEED_TO_FIX
  804. RIO_SV_BROADCAST(HostP->svFlags[entry2]);
  805. #endif
  806. sysport = HostP->Mapping[entry2].SysPort;
  807. if ( sysport < p->RIOFirstPortsBooted )
  808.     p->RIOFirstPortsBooted = sysport;
  809. if ( sysport > p->RIOLastPortsBooted )
  810.     p->RIOLastPortsBooted = sysport;
  811.    }
  812. }
  813. if (RtaType == TYPE_RTA16) {
  814.    rio_dprintk (RIO_DEBUG_BOOT, "RTA will be given IDs %d+%dn",
  815.     entry+1, entry2+1);
  816. } else {
  817.    rio_dprintk (RIO_DEBUG_BOOT, "RTA will be given ID %dn",entry+1);
  818. }
  819. return TRUE;
  820.     }
  821. }
  822. rio_dprintk (RIO_DEBUG_BOOT, "RTA not configured for this hostn");
  823. if ( Rup >= (ushort)MAX_RUP )
  824. {
  825.     /*
  826.     ** It was a host that did the booting
  827.     */
  828.     MyType = "Host";
  829.     MyName = HostP->Name;
  830. }
  831. else
  832. {
  833.     /*
  834.     ** It was an RTA that did the booting
  835.     */
  836.     MyType = "RTA";
  837.     MyName = HostP->Mapping[Rup].Name;
  838. }
  839. #ifdef CHECK
  840. CheckString(MyType);
  841. CheckString(MyName);
  842. #endif
  843. MyLink = RBYTE(PktCmdP->LinkNum);
  844. /*
  845. ** There is no SLOT_IN_USE entry for this RTA attached to the current
  846. ** host card in the driver table.
  847. **
  848. ** Check for a SLOT_TENTATIVE entry for this RTA attached to the
  849. ** current host card in the driver table.
  850. **
  851. ** If we find one, then we re-use that slot.
  852. */
  853. for ( entry=0; entry<MAX_RUP; entry++ )
  854. {
  855.     if ( (HostP->Mapping[entry].Flags & SLOT_TENTATIVE) &&
  856.  (HostP->Mapping[entry].RtaUniqueNum == RtaUniq) )
  857.     {
  858. if (RtaType == TYPE_RTA16)
  859. {
  860.     entry2 = HostP->Mapping[entry].ID2 - 1;
  861.     if ( (HostP->Mapping[entry2].Flags & SLOT_TENTATIVE) &&
  862.  (HostP->Mapping[entry2].RtaUniqueNum == RtaUniq) )
  863. rio_dprintk (RIO_DEBUG_BOOT, "Found previous tentative slots (%d+%d)n",
  864.  entry, entry2);
  865.     else
  866. continue;
  867. }
  868. else
  869. rio_dprintk (RIO_DEBUG_BOOT, "Found previous tentative slot (%d)n",entry);
  870. if (! p->RIONoMessage)
  871.     cprintf("RTA connected to %s '%s' (%c) not configured.n",MyType,MyName,MyLink+'A');
  872. return TRUE;
  873.     }
  874. }
  875. /*
  876. ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
  877. ** attached to the current host card in the driver table.
  878. **
  879. ** Check if there is a SLOT_IN_USE or SLOT_TENTATIVE entry on another
  880. ** host for this RTA in the driver table.
  881. **
  882. ** For a SLOT_IN_USE entry on another host, we need to delete the RTA
  883. ** entry from the other host and add it to this host (using some of
  884. ** the functions from table.c which do this).
  885. ** For a SLOT_TENTATIVE entry on another host, we must cope with the
  886. ** following scenario:
  887. **
  888. ** + Plug 8 port RTA into host A. (This creates SLOT_TENTATIVE entry
  889. **   in table)
  890. ** + Unplug RTA and plug into host B. (We now have 2 SLOT_TENTATIVE
  891. **   entries)
  892. ** + Configure RTA on host B. (This slot now becomes SLOT_IN_USE)
  893. ** + Unplug RTA and plug back into host A.
  894. ** + Configure RTA on host A. We now have the same RTA configured
  895. **   with different ports on two different hosts.
  896. */
  897. rio_dprintk (RIO_DEBUG_BOOT, "Have we seen RTA %x before?n", RtaUniq );
  898. found = 0;
  899. Flag = 0; /* Convince the compiler this variable is initialized */
  900. for ( host = 0; !found && (host < p->RIONumHosts); host++ )
  901. {
  902.     for ( rta=0; rta<MAX_RUP; rta++ )
  903.     {
  904. if ((p->RIOHosts[host].Mapping[rta].Flags &
  905.  (SLOT_IN_USE | SLOT_TENTATIVE)) &&
  906.  (p->RIOHosts[host].Mapping[rta].RtaUniqueNum==RtaUniq))
  907. {
  908.     Flag = p->RIOHosts[host].Mapping[rta].Flags;
  909.     MapP = &p->RIOHosts[host].Mapping[rta];
  910.     if (RtaType == TYPE_RTA16)
  911.     {
  912. MapP2 = &p->RIOHosts[host].Mapping[MapP->ID2 - 1];
  913. rio_dprintk (RIO_DEBUG_BOOT, "This RTA is units %d+%d from host %sn",
  914.  rta+1, MapP->ID2, p->RIOHosts[host].Name);
  915.     }
  916.     else
  917. rio_dprintk (RIO_DEBUG_BOOT, "This RTA is unit %d from host %sn",
  918.  rta+1, p->RIOHosts[host].Name);
  919.     found = 1;
  920.     break;
  921. }
  922.     }
  923. }
  924. /*
  925. ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
  926. ** attached to the current host card in the driver table.
  927. **
  928. ** If we have not found a SLOT_IN_USE or SLOT_TENTATIVE entry on
  929. ** another host for this RTA in the driver table...
  930. **
  931. ** Check for a SLOT_IN_USE entry for this RTA in the config table.
  932. */
  933. if ( !MapP )
  934. {
  935.     rio_dprintk (RIO_DEBUG_BOOT, "Look for RTA %x in RIOSavedTablen",RtaUniq);
  936.     for ( rta=0; rta < TOTAL_MAP_ENTRIES; rta++ )
  937.     {
  938. rio_dprintk (RIO_DEBUG_BOOT, "Check table entry %d (%x)",
  939.       rta,
  940.       p->RIOSavedTable[rta].RtaUniqueNum);
  941. if ( (p->RIOSavedTable[rta].Flags & SLOT_IN_USE) &&
  942.  (p->RIOSavedTable[rta].RtaUniqueNum == RtaUniq) )
  943. {
  944.     MapP = &p->RIOSavedTable[rta];
  945.     Flag = p->RIOSavedTable[rta].Flags;
  946.     if (RtaType == TYPE_RTA16)
  947.     {
  948.                         for (entry2 = rta + 1; entry2 < TOTAL_MAP_ENTRIES;
  949.                          entry2++)
  950.                         {
  951.                             if (p->RIOSavedTable[entry2].RtaUniqueNum == RtaUniq)
  952.                                 break;
  953.                         }
  954.                         MapP2 = &p->RIOSavedTable[entry2];
  955.                         rio_dprintk (RIO_DEBUG_BOOT, "This RTA is from table entries %d+%dn",
  956.                               rta, entry2);
  957.     }
  958.     else
  959. rio_dprintk (RIO_DEBUG_BOOT, "This RTA is from table entry %dn", rta);
  960.     break;
  961. }
  962.     }
  963. }
  964. /*
  965. ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
  966. ** attached to the current host card in the driver table.
  967. **
  968. ** We may have found a SLOT_IN_USE entry on another host for this
  969. ** RTA in the config table, or a SLOT_IN_USE or SLOT_TENTATIVE entry
  970. ** on another host for this RTA in the driver table.
  971. **
  972. ** Check the driver table for room to fit this newly discovered RTA.
  973. ** RIOFindFreeID() first looks for free slots and if it does not
  974. ** find any free slots it will then attempt to oust any
  975. ** tentative entry in the table.
  976. */
  977. EmptySlot = 1;
  978. if (RtaType == TYPE_RTA16)
  979. {
  980.     if (RIOFindFreeID(p, HostP, &entry, &entry2) == 0)
  981.     {
  982. RIODefaultName(p, HostP, entry);
  983. FillSlot(entry, entry2, RtaUniq, HostP);
  984. EmptySlot = 0;
  985.     }
  986. }
  987. else
  988. {
  989.     if (RIOFindFreeID(p, HostP, &entry, NULL) == 0)
  990.     {
  991. RIODefaultName(p, HostP, entry);
  992. FillSlot(entry, 0, RtaUniq, HostP);
  993. EmptySlot = 0;
  994.     }
  995. }
  996. /*
  997. ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
  998. ** attached to the current host card in the driver table.
  999. **
  1000. ** If we found a SLOT_IN_USE entry on another host for this
  1001. ** RTA in the config or driver table, and there are enough free
  1002. ** slots in the driver table, then we need to move it over and
  1003. ** delete it from the other host.
  1004. ** If we found a SLOT_TENTATIVE entry on another host for this
  1005. ** RTA in the driver table, just delete the other host entry.
  1006. */
  1007. if (EmptySlot == 0)
  1008. {
  1009.     if ( MapP )
  1010.     {
  1011. if (Flag & SLOT_IN_USE)
  1012. {
  1013.     rio_dprintk (RIO_DEBUG_BOOT, 
  1014.     "This RTA configured on another host - move entry to current host (1)n");
  1015.     HostP->Mapping[entry].SysPort = MapP->SysPort;
  1016.     CCOPY( MapP->Name, HostP->Mapping[entry].Name, MAX_NAME_LEN );
  1017.     HostP->Mapping[entry].Flags =
  1018.      SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT;
  1019. #if NEED_TO_FIX
  1020.     RIO_SV_BROADCAST(HostP->svFlags[entry]);
  1021. #endif
  1022.     RIOReMapPorts( p, HostP, &HostP->Mapping[entry] );
  1023.     if ( HostP->Mapping[entry].SysPort < p->RIOFirstPortsBooted )
  1024. p->RIOFirstPortsBooted = HostP->Mapping[entry].SysPort;
  1025.     if ( HostP->Mapping[entry].SysPort > p->RIOLastPortsBooted )
  1026. p->RIOLastPortsBooted = HostP->Mapping[entry].SysPort;
  1027.     rio_dprintk (RIO_DEBUG_BOOT, "SysPort %d, Name %sn",(int)MapP->SysPort,MapP->Name);
  1028. }
  1029. else
  1030. {
  1031.     rio_dprintk (RIO_DEBUG_BOOT, 
  1032.    "This RTA has a tentative entry on another host - delete that entry (1)n");
  1033.     HostP->Mapping[entry].Flags =
  1034.      SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT;
  1035. #if NEED_TO_FIX
  1036.     RIO_SV_BROADCAST(HostP->svFlags[entry]);
  1037. #endif
  1038. }
  1039. if (RtaType == TYPE_RTA16)
  1040. {
  1041.     if (Flag & SLOT_IN_USE)
  1042.     {
  1043. HostP->Mapping[entry2].Flags = SLOT_IN_USE |
  1044.  RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT;
  1045. #if NEED_TO_FIX
  1046. RIO_SV_BROADCAST(HostP->svFlags[entry2]);
  1047. #endif
  1048. HostP->Mapping[entry2].SysPort = MapP2->SysPort;
  1049. /*
  1050. ** Map second block of ttys for 16 port RTA
  1051. */
  1052. RIOReMapPorts( p, HostP, &HostP->Mapping[entry2] );
  1053.        if (HostP->Mapping[entry2].SysPort < p->RIOFirstPortsBooted)
  1054.  p->RIOFirstPortsBooted = HostP->Mapping[entry2].SysPort;
  1055.        if (HostP->Mapping[entry2].SysPort > p->RIOLastPortsBooted)
  1056.  p->RIOLastPortsBooted = HostP->Mapping[entry2].SysPort;
  1057. rio_dprintk (RIO_DEBUG_BOOT, "SysPort %d, Name %sn",
  1058.        (int)HostP->Mapping[entry2].SysPort,
  1059.        HostP->Mapping[entry].Name);
  1060.     }
  1061.     else
  1062. HostP->Mapping[entry2].Flags = SLOT_TENTATIVE |
  1063.  RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT;
  1064. #if NEED_TO_FIX
  1065. RIO_SV_BROADCAST(HostP->svFlags[entry2]);
  1066. #endif
  1067.     bzero( (caddr_t)MapP2, sizeof(struct Map) );
  1068. }
  1069. bzero( (caddr_t)MapP, sizeof(struct Map) );
  1070. if (! p->RIONoMessage)
  1071.     cprintf("An orphaned RTA has been adopted by %s '%s' (%c).n",MyType,MyName,MyLink+'A');
  1072.     }
  1073.     else if (! p->RIONoMessage)
  1074. cprintf("RTA connected to %s '%s' (%c) not configured.n",MyType,MyName,MyLink+'A');
  1075.     RIOSetChange(p);
  1076.     return TRUE;
  1077. }
  1078. /*
  1079. ** There is no room in the driver table to make an entry for the
  1080. ** booted RTA. Keep a note of its Uniq Num in the overflow table,
  1081. ** so we can ignore it's ID requests.
  1082. */
  1083. if (! p->RIONoMessage)
  1084.     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');
  1085. for ( entry=0; entry<HostP->NumExtraBooted; entry++ )
  1086. {
  1087.     if ( HostP->ExtraUnits[entry] == RtaUniq )
  1088.     {
  1089. /*
  1090. ** already got it!
  1091. */
  1092. return TRUE;
  1093.     }
  1094. }
  1095. /*
  1096. ** If there is room, add the unit to the list of extras
  1097. */
  1098. if ( HostP->NumExtraBooted < MAX_EXTRA_UNITS )
  1099.     HostP->ExtraUnits[HostP->NumExtraBooted++] = RtaUniq;
  1100. return TRUE;
  1101. }
  1102. /*
  1103. ** If the RTA or its host appears in the RIOBindTab[] structure then
  1104. ** we mustn't boot the RTA and should return FALSE.
  1105. ** This operation is slightly different from the other drivers for RIO
  1106. ** in that this is designed to work with the new utilities
  1107. ** not config.rio and is FAR SIMPLER.
  1108. ** We no longer support the RIOBootMode variable. It is all done from the
  1109. ** "boot/noboot" field in the rio.cf file.
  1110. */
  1111. int
  1112. RIOBootOk(p, HostP, RtaUniq)
  1113. struct rio_info * p;
  1114. struct Host * HostP;
  1115. ulong RtaUniq;
  1116. {
  1117.     int Entry;
  1118.     uint HostUniq = HostP->UniqueNum;
  1119. /*
  1120. ** Search bindings table for RTA or its parent.
  1121. ** If it exists, return 0, else 1.
  1122. */
  1123. for (Entry = 0;
  1124.     ( Entry < MAX_RTA_BINDINGS ) && ( p->RIOBindTab[Entry] != 0 );
  1125.     Entry++)
  1126. {
  1127. if ( (p->RIOBindTab[Entry] == HostUniq) ||
  1128.      (p->RIOBindTab[Entry] == RtaUniq) )
  1129. return 0;
  1130. }
  1131. return 1;
  1132. }
  1133. /*
  1134. ** Make an empty slot tentative. If this is a 16 port RTA, make both
  1135. ** slots tentative, and the second one RTA_SECOND_SLOT as well.
  1136. */
  1137. void
  1138. FillSlot(entry, entry2, RtaUniq, HostP)
  1139. int entry;
  1140. int entry2;
  1141. uint RtaUniq;
  1142. struct Host *HostP;
  1143. {
  1144. int link;
  1145. rio_dprintk (RIO_DEBUG_BOOT, "FillSlot(%d, %d, 0x%x...)n", entry, entry2, RtaUniq);
  1146. HostP->Mapping[entry].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE);
  1147. HostP->Mapping[entry].SysPort = NO_PORT;
  1148. HostP->Mapping[entry].RtaUniqueNum = RtaUniq;
  1149. HostP->Mapping[entry].HostUniqueNum = HostP->UniqueNum;
  1150. HostP->Mapping[entry].ID = entry + 1;
  1151. HostP->Mapping[entry].ID2 = 0;
  1152. if (entry2) {
  1153. HostP->Mapping[entry2].Flags = (RTA_BOOTED | RTA_NEWBOOT | 
  1154. SLOT_TENTATIVE | RTA16_SECOND_SLOT);
  1155. HostP->Mapping[entry2].SysPort = NO_PORT;
  1156. HostP->Mapping[entry2].RtaUniqueNum = RtaUniq;
  1157. HostP->Mapping[entry2].HostUniqueNum = HostP->UniqueNum;
  1158. HostP->Mapping[entry2].Name[0] = '';
  1159. HostP->Mapping[entry2].ID = entry2 + 1;
  1160. HostP->Mapping[entry2].ID2 = entry + 1;
  1161. HostP->Mapping[entry].ID2 = entry2 + 1;
  1162. }
  1163. /*
  1164. ** Must set these up, so that utilities show
  1165. ** topology of 16 port RTAs correctly
  1166. */
  1167. for ( link=0; link<LINKS_PER_UNIT; link++ ) {
  1168. HostP->Mapping[entry].Topology[link].Unit = ROUTE_DISCONNECT;
  1169. HostP->Mapping[entry].Topology[link].Link = NO_LINK;
  1170. if (entry2) {
  1171. HostP->Mapping[entry2].Topology[link].Unit = ROUTE_DISCONNECT;
  1172. HostP->Mapping[entry2].Topology[link].Link = NO_LINK;
  1173. }
  1174. }
  1175. }
  1176. #if 0
  1177. /*
  1178. Function: This function is to disable the disk interrupt 
  1179.     Returns :   Nothing
  1180. */
  1181. void
  1182. disable_interrupt(vector)
  1183. int vector;
  1184. {
  1185. int ps;
  1186. int val;
  1187. disable(ps);
  1188. if (vector > 40)  {
  1189. val = 1 << (vector - 40);
  1190. __outb(S8259+1, __inb(S8259+1) | val);
  1191. }
  1192. else {
  1193. val = 1 << (vector - 32);
  1194. __outb(M8259+1, __inb(M8259+1) | val);
  1195. }
  1196. restore(ps);
  1197. }
  1198. /*
  1199. Function: This function is to enable the disk interrupt 
  1200.     Returns :   Nothing
  1201. */
  1202. void
  1203. enable_interrupt(vector)
  1204. int vector;
  1205. {
  1206. int ps;
  1207. int val;
  1208. disable(ps);
  1209. if (vector > 40)  {
  1210. val = 1 << (vector - 40);
  1211. val = ~val;
  1212. __outb(S8259+1, __inb(S8259+1) & val);
  1213. }
  1214. else {
  1215. val = 1 << (vector - 32);
  1216. val = ~val;
  1217. __outb(M8259+1, __inb(M8259+1) & val);
  1218. }
  1219. restore(ps);
  1220. }
  1221. #endif