📄 ci_init.c
字号:
#include "../io/gvp/gvpsysap.h"#include "../io/uba/uqsysap.h"#include "../io/sysap/sysap.h"#include "../io/ci/cippdscs.h"#include "../io/ci/ciscs.h"#include "../io/msi/msiscs.h"#include "../io/bi/bvpscs.h"#include "../io/gvp/gvpscs.h"#include "../io/uba/uqscs.h"#include "../io/scs/scs.h"#include "../io/gvp/gvp.h"#include "../io/ci/cippd.h"#include "../io/ci/ciport.h"#include "../io/ci/ciadapter.h"/* External Variables and Routines. */extern int cpu;extern SCSIB lscs;extern PDT ci_pdt;extern struct pte Sysmap[];extern CIISR ci_isr[];extern GVPBDDB *gvp_bddb;extern int *ci_ucode;extern struct lock_t lk_scadb;extern pccbq scs_lport_db;extern u_char *ci_black_hole;extern MRLTAB ci7b_mrltable[], cibca_aa_mrltab[], cibca_ba_mrltab[], cixcd_mrltable[], cikmf_mrltable[], cishc_mrltable[];extern SCSH *gvp_alloc_dg(), *gvp_alloc_msg();extern u_long *ci780_regoff[], *cibci_regoff[], *cibca_regoff[], *cixcd_regoff[], *cikmf1_regoff[], *cikmf2_regoff[], *cishc_regoff[];extern u_short ci_cippdburst, ci_cippdcontact, ci_first_port, ci_max_reinits, ci_maint_intrvl, ci_maint_timer, ci_ucode_type, cippd_max_port;extern void ci_crash_lport(), ci_dealloc_pkt(), ci_init_port(), ci_log_dev_attn(), ci_log_initerr(), ci_notify_port(), ci_unmap_port(), ci_unmapped_isr(), ci7b_disable(), cibx_disable(), cishc_disable(), cippd_start(), gvp_dealloc_dg(), gvp_dealloc_msg();extern u_long ci_bhole_pfn, ci_crctable[], gvp_max_bds, gvp_queue_retry, scs_dg_size, scs_msg_size, ci_setup_port(), ci_test_port(), ci7b_load(), ci7b_start(), cibca_aa_load(), cibx_start(), gvp_initialize(), scs_initialize();/* Name: ci_init_port - Initialize a Local CI Port * * Abstract: This routine directs the initialization of a local CI port. It * also oversees the port's initial initialization. It is always * invoked by forking to it. * * The local port must be completely disabled whenever execution * of this routine is scheduled including disablement of: * * 1. Port interrupts. * 2. Port boot/sanity timer. * 3. CI PPD finite state machine activity on the local port. * * The local CI port must also be in the UNINITIALIZED port state. * * This routine may also be scheduled to permanently shutdown * local ports. Such ports are always unmapped and marked broken * in addition to having been disabled. This distinguishes them * from local ports to be initialized which are mapped and not * marked broken. * * NOTE: This is a mandatory PD function( Init_port ) for use by * the CI PPD. * * Inputs: * * IPL_SCS - Interrupt processor level * ci_cippdburst - CI PPD port polling burst size * ci_cippdcontact - CI PPD port polling contact frequency * ci_first_port - Port number of first local CI port * ci_maint_intrvl - CI port maintenance timer interval * ci_maint_timer - CI port maintenance timer enable flag * ci_max_reinits - CI max number consecutive reinitializations * pccb - Port Command and Control Block pointer * ppd.cippd - CI PPD specific PCCB fields * fsmstatus.cleanup - 1 * fsmstatus.fkip - 1 * fsmstatus.online - 0 * lk_scadb - SCA database lock structure * * Outputs: * * IPL_SCS - Interrupt processor level * ci_first_port - Port number of first local CI port * pccb - Port Command and Control Block pinter * lpinfo.addr - Local port station address * lpinfo.nreinits - Number of local port re-initializations * lpinfo.ppd.cippd - CI PPD specific local port information * max_port - Maximum hardware remote port number * pd.gvp.pqb.type.ci - CI specific PQB fields * keepalive - Variable maintenance timer interval cell * pd.gvp.type.ci - CI specific PCCB fields * devattn.cirevlev - Port microcode information * lbcrc - Loopback CRC * lbstatus - 0 * lpstatus - Local port status flags * init - First time initialization status flag * connectivity - 0 * reinit_tries - Number consecutive re-initializations left * ppd.cippd - CI PPD specific PCCB fields * burst - Port polling burst size * contact - Port polling contact frequency * fsmstatus.broken - Port is broken status flag * fsmstatus.cleanup - 0 * fsmstatus.fkip - Fork operation in progress status flag * * SMP: The SCA database is locked for deletion of the PCCB following * exhaustion of consecutive re-initialization attempts without a * successful initial port initialization. * * The PCCB is locked to synchronize access and as required by * ci_log_dev_attn() in case event logging becomes necessary. * PCCB locking is probably unnecessary because of lack of * conflict for the PCCB due to the single threadedness of port * clean up and initialization. It is done anyway to guarantee * unrestricted access and because the CI PPD interval timer may * still be active. PCCB addresses are always valid because these * data structures are never deleted( except by this function on * exhaustion of consecutive re-initialization attempts without a * successful initial port initialization ). * * Access to port queues is by means of memory interlocking * queuing instructions. */voidci_init_port( pccb ) register PCCB *pccb;{ register MRLTAB *mrltab; register gvpbq *q, *qend; register u_long status; register u_long save_ipl = Splscs(); /* The steps involved in port initialization are as follows: * * 1. The PCCB is locked. * 2. Port clean up is marked completed. * 3. The existence of port power is verified( non-broken ports only ). * * - PORT RE-INITIALIZATION ONLY: * 4. All port queues are flushed and all flushed packets are deallocated. * 5. The local port maintenance timer interval, CI PPD port polling burst * size, and CI PPD port polling contact frequency are reset. * 6. Local port loopback is enabled and loopback status is cleared. * * - ALL INITIALIZATIONS: * 7. Presence of an operational port is verified. * 8. All configuration register errors are cleared( CI750, CI780, CIBCI * only ). * 9. The CPU microcode revision level is verified( 11/750 only ). * 10. An initial number of free datagrams and messages are allocated and * and placed on the appropriate port queues. * 11. Functional port microcode is loaded, read back, and verified( CI750, * CI780, CIBCI, and CIBCA-AA only ). * 12. Both port interrupts and the port itself are enabled. * 13. The port is notified of free message and datagram buffer * availability. * * - INITIAL PORT INITIALIZATION ONLY: * 14. The local port number is retrieved and stored as the port number of * the first local CI port encountered( when appropriate ). * 15. The local port loopback datagram CRC is computed. * 16. The maximum addressable port number is retrieved and verified. * 17. Microcode revision levels( ram/functional and prom/self-test ) are * verified. * * - ALL INITIALIZATIONS: * 18. The initialization of the local CI port is logged. * 19. The local CI port maintenance timer is engaged provided CI port * maintenance timers have been optionally enabled. * 20. The PCCB is unlocked. * 21. The CI PPD is notified of successful port initialization. * * Local ports can not be initialized when they are without power. This * presents no problems for those instances of power failure which involve * the entire system. It also poses no problems for local CIBCA/CIXCD * ports which can not independently power failure. Unfortunately, * potential problems do exist for power failure of local CI750/CI780/CIBCI * ports. Such ports can power failure independently. Worse yet, power * loss and gain on such ports can be discrete events separated in time. * This allows for the local port disablement and clean associated with the * loss of port power to complete and local port initialization to commence * before power is restored to the port. It is also the reason why * verification of port power occurs( Step 3 ) before proceeding further * with port initialization, to insure that initialization is postponed * while local ports are without power. For a more extensive discussion of * possible power failure recovery scenarios consult ci_crash_lport(). * * All port queues are flushed immediately prior to port re-initialization( * Step 4 ) to insure their pristine state. Logically this action should * occur as part of port clean up. However, it is done immediately prior * to port re-initialization in order to be able to meet the following * requirements: * * 1. Port queues can not be flushed until all possibility of further * packet queuing to them has ceased. * * 2. Port queue flushing must involve determination of whether or not the * queues were left permanently locked by failure of the port( Discovery * of a locked queue or any failure to obtain a queue interlock during * queue flushing results in zeroing of the offending queue and * permanent loss of all packets residing on it ). * * Neither of these requirements can be easily met during port clean up. * Nothing can prevent SYSAP or SCS motivated insertion of packets into * port queues without seriously affecting performance until all paths * associated with the failed port have been terminated. This condition is * not reached until the virtual end of port clean up. Furthermore, until * port re-initialization begins, multiple simultaneously active threads * may exist to complicate the determination of queues left permanently * locked by port failure. It is only during re-initialization that a * single thread with access to port queues exists, the thread responsible * for the re-initialization itself. Therefore, port queues are flushed * during port re-initialization instead of during port clean up mainly * because it is easier to meet these requirements and because it is just * safer and more straight forward to do so. * * Local port maintenance timer interval, CI PPD port polling burst size, * and CI PPD port polling contact frequency are all reset( Step 5 ) using * configuration variables. This allows their values to change following * failure and re-initialization of a local port. The values for CI PPD * port polling burst size and contact frequency actually change much more * frequently. They are reset on a per local port basis following the * completion of each CI PPD polling sweep( by ci_test_lpconn()). * * An error in Steps 7,9 or exhaustion of all consecutive port * initialization attempts permanently aborts port initialization. This is * also the fate of ports marked broken. * * Errors in Steps 10-12 abort the current port initialization attempt. A * consecutive port initialization attempt is scheduled and the PCCB is * unlocked. * * Retrieval of the maximum addressable port number( Step 16 ) is dependent * upon the format of the CI port parameter register. There are currently * two possible formats easily distinguishable by means of the diagnostic * information field. One format implements this field while for the other * it is always 0. Failure to retrieve a valid maximum addressable port * number crashes the local port and shuts it down permanently. * * Failure to verify the microcode revision level( Step 17 ) results either * in logging of an appropriate warning message or crashing of the local * port. The former occurs when the revision level is known, just out of * date. The port is allowed to continue to function. The latter occurs * when the revision level is both unknown and does NOT exceed the known * maximum level for the hardware port type. The local port is permanently * shut down. No action is taken when an unknown level is found to exceed * the known maximum revision level for the hardware port type. It is just * assumed that the port driver has not yet been updated to recognize a new * maximum microcode revision level. * * Permanent abortion of port initialization proceeds as follows: * * 1. The port is left disabled and unmapped. * 2. All associated resources are deallocated. * 3. The local port is marked broken. * 4. A console message is printed. * 5. The PCCB is removed from the system-wide local port database. * 6. The PCCB is unlocked. * 7. The PCCB is deallocated( only when the initial port initialization * attempts fail ). * * The local port is marked broken( Step 3 ) only when it was previously * NOT marked broken. It is also unmapped at this time. This situation * exists only when all consecutive port initialization attempts have been * exhausted. * * The PCCB is deallocated( Step 7 ) only when the initial port * initialization attempts fails. The SCA database is always locked prior * to PCCB removal and unlocked following it. In order to preserve the SCA * locking hierarchy the PCCB lock is first released and then re-obtained * after the SCA database is locked. Cached PCCB addresses remain valid at * this point because PCCBs are only deleted by this routine and such * action has not yet occurred. * * NOTE: Broken local ports are unmapped at the time of their disablement. * This is not the case for those local ports which are to be * shutdown because they have exhausted their consecutive * initialization attempts. Such ports are explicitly unmapped by * this routine during shutdown. */ Lock_pccb( pccb ) Pccb_fork_done( pccb, PANIC_PCCBFB ) pccb->Fsmstatus.cleanup = 0; if( !pccb->Fsmstatus.broken && !pccb->Lpstatus.power ) { Unlock_pccb( pccb ) ( void )splx( save_ipl ); return; } else if( !pccb->Lpstatus.init && !pccb->Fsmstatus.broken && pccb->Reinit_tries == ci_max_reinits ) { ++pccb->lpinfo.nreinits; for( q = &pccb->Pqb.cmdq0, qend = &pccb->Pqb.rspq; q <= qend; ++q ) { Flushq( pccb, q ) } for( q = &pccb->Dfreeq, qend = &pccb->Mfreeq; q <= qend; ++q ) { Flushq( pccb, q ) } pccb->Pqb.Keepalive = ( u_long )ci_maint_intrvl; pccb->Burst = cippd_max_port; /* poll all the nodes first */ pccb->Contact = ci_cippdcontact; pccb->Lpstatus.connectivity = 0; *( u_char * )&pccb->Lbstatus = 0; } if( !pccb->Fsmstatus.broken && ( status = ci_setup_port( pccb )) == RET_SUCCESS && ( pccb->Load_ucode == NULL || ( status = ( *pccb->Load_ucode )( pccb )) == RET_SUCCESS ) && ( status = ( *pccb->Start_port )( pccb )) == RET_SUCCESS ) { status = 0; if( pccb->Lpstatus.init ) { register u_long ppr; Lock_cidevice( pccb ) ppr = *pccb->Ppr; Unlock_cidevice( pccb ) pccb->Lpstatus.init = 0; pccb->Devattn.cirevlev.ci_romlev = pccb->Rom_level; pccb->Devattn.cirevlev.ci_ramlev = pccb->Fn_level;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -