📄 l1.c
字号:
/* otherwise, we've got a character that needs * to be unescaped */ cq_tent_add( q, (c ^ BRL1_XOR_CH) ); STATE_SET( sc, BRL1_BODY ); break; } /* end of switch( STATE_GET(sc) ) */ } /* end of while(!done) */ L1SC_RECV_UNLOCK( sc, cpl ); return result;} /* brl1_init initializes the Bedrock/L1 protocol layer. This includes * zeroing out the send and receive state information. */voidbrl1_init( l1sc_t *sc, nasid_t nasid, net_vec_t uart ){ int i; brl1_sch_t *subch; bzero( sc, sizeof( *sc ) ); sc->nasid = nasid; sc->uart = uart; sc->getc_f = (uart == BRL1_LOCALHUB_UART ? uart_getc : rtr_uart_getc); sc->putc_f = (uart == BRL1_LOCALHUB_UART ? uart_putc : rtr_uart_putc); sc->sol = 1; subch = sc->subch; /* initialize L1 subchannels */ /* assign processor TTY channels */ for( i = 0; i < CPUS_PER_NODE; i++, subch++ ) { subch->use = BRL1_SUBCH_RSVD; subch->packet_arrived = ATOMIC_INIT(0); spin_lock_init( &(subch->data_lock) ); sv_init( &(subch->arrive_sv), &(subch->data_lock), SV_MON_SPIN | SV_ORDER_FIFO /* | SV_INTS */ ); subch->tx_notify = NULL; /* (for now, drop elscuart packets in the kernel) */ subch->rx_notify = brl1_discard_packet; subch->iqp = &sc->garbage_q; } /* assign system TTY channel (first free subchannel after each * processor's individual TTY channel has been assigned) */ subch->use = BRL1_SUBCH_RSVD; subch->packet_arrived = ATOMIC_INIT(0); spin_lock_init( &(subch->data_lock) ); sv_init( &(subch->arrive_sv), &subch->data_lock, SV_MON_SPIN | SV_ORDER_FIFO /* | SV_INTS */ ); subch->tx_notify = NULL; if( sc->uart == BRL1_LOCALHUB_UART ) { subch->iqp = snia_kmem_zalloc_node( sizeof(sc_cq_t), KM_NOSLEEP, NASID_TO_COMPACT_NODEID(nasid) ); ASSERT( subch->iqp ); cq_init( subch->iqp ); subch->rx_notify = NULL; } else { /* we shouldn't be getting console input from remote UARTs */ subch->iqp = &sc->garbage_q; subch->rx_notify = brl1_discard_packet; } subch++; i++; /* "reserved" subchannels (0x05-0x0F); for now, throw away * incoming packets */ for( ; i < 0x10; i++, subch++ ) { subch->use = BRL1_SUBCH_FREE; subch->packet_arrived = ATOMIC_INIT(0); subch->tx_notify = NULL; subch->rx_notify = brl1_discard_packet; subch->iqp = &sc->garbage_q; } /* remaining subchannels are free */ for( ; i < BRL1_NUM_SUBCHANS; i++, subch++ ) { subch->use = BRL1_SUBCH_FREE; subch->packet_arrived = ATOMIC_INIT(0); subch->tx_notify = NULL; subch->rx_notify = brl1_discard_packet; subch->iqp = &sc->garbage_q; } /* initialize synchronization structures */ spin_lock_init( &(sc->subch_lock) ); spin_lock_init( &(sc->send_lock) ); spin_lock_init( &(sc->recv_lock) ); if( sc->uart == BRL1_LOCALHUB_UART ) { uart_init( sc, UART_BAUD_RATE ); } else { rtr_uart_init( sc, UART_BAUD_RATE ); } /* Set up remaining fields using L1 command functions-- elsc_module_get * to read the module id, elsc_debug_get to see whether or not we're * in verbose mode. */ { extern int elsc_module_get(l1sc_t *); sc->modid = elsc_module_get( sc ); sc->modid = (sc->modid < 0 ? INVALID_MODULE : sc->modid); sc->verbose = 1; }}/********************************************************************* * These are interrupt-related functions used in the kernel to service * the L1. *//* * brl1_intrd is the function which is called on a console interrupt. */#if defined(CONFIG_IA64_SGI_SN1)static voidbrl1_intrd(int irq, void *dev_id, struct pt_regs *stuff){ u_char isr_reg; l1sc_t *sc = get_elsc(); int ret; L1_collectibles[L1C_INTERRUPTS]++; isr_reg = READ_L1_UART_REG(sc->nasid, REG_ISR); /* Save for callup args in console */ sc->subch[SC_CONS_SYSTEM].irq_frame.bf_irq = irq; sc->subch[SC_CONS_SYSTEM].irq_frame.bf_dev_id = dev_id; sc->subch[SC_CONS_SYSTEM].irq_frame.bf_regs = stuff;#if defined(SYNC_CONSOLE_WRITE) while( isr_reg & ISR_RxRDY )#else while( isr_reg & (ISR_RxRDY | ISR_TxRDY) )#endif { if( isr_reg & ISR_RxRDY ) { L1_collectibles[L1C_OUR_R_INTERRUPTS]++; ret = brl1_receive(sc, SERIAL_INTERRUPT_MODE); if ( (ret != BRL1_VALID) && (ret != BRL1_NO_MESSAGE) && (ret != BRL1_PROTOCOL) && (ret != BRL1_CRC) ) L1_collectibles[L1C_REC_STALLS] = ret; }#if !defined(SYNC_CONSOLE_WRITE) if( (isr_reg & ISR_TxRDY) || (sc->send_in_use && UART_PUTC_READY(sc->nasid)) ) { L1_collectibles[L1C_OUR_X_INTERRUPTS]++; brl1_send_cont(sc); }#endif /* SYNC_CONSOLE_WRITE */ isr_reg = READ_L1_UART_REG(sc->nasid, REG_ISR); }}#endif /* CONFIG_IA64_SGI_SN1 *//* * Install a callback function for the system console subchannel * to allow an upper layer to be notified when the send buffer * has been emptied. */static inline voidl1_tx_notif( brl1_notif_t func ){ subch_set_tx_notify( &NODEPDA(NASID_TO_COMPACT_NODEID(get_master_nasid()))->module->elsc, SC_CONS_SYSTEM, func );}/* * Install a callback function for the system console subchannel * to allow an upper layer to be notified when a packet has been * received. */static inline voidl1_rx_notif( brl1_notif_t func ){ subch_set_rx_notify( &NODEPDA(NASID_TO_COMPACT_NODEID(get_master_nasid()))->module->elsc, SC_CONS_SYSTEM, func );}/* brl1_intr is called directly from the uart interrupt; after it runs, the * interrupt "daemon" xthread is signalled to continue. */voidbrl1_intr( void ){}#define BRL1_INTERRUPT_LEVEL 65 /* linux request_irq() value *//* Return the current interrupt level *///#define CONSOLE_POLLING_ALSOintl1_get_intr_value( void ){#if defined(USE_SAL_CONSOLE_IO) return(0);#else#if defined(CONSOLE_POLLING_ALSO) return(0);#else return(BRL1_INTERRUPT_LEVEL);#endif /* CONSOLE_POLLING_ALSO */#endif /* USE_SAL_CONSOLE_IO */}/* Disconnect the callup functions - throw away interrupts */voidl1_unconnect_intr(void){#if !defined(USE_SAL_CONSOLE_IO) /* UnRegister the upper-level callup functions */ l1_rx_notif((brl1_notif_t)NULL); l1_tx_notif((brl1_notif_t)NULL); /* We do NOT unregister the interrupts */#endif /* !USE_SAL_CONSOLE_IO */}/* Set up uart interrupt handling for this node's uart */voidl1_connect_intr(void *rx_notify, void *tx_notify){#if defined(USE_SAL_CONSOLE_IO)#if 0 // Will need code here for sn2 - something like this console_nodepda = NODEPDA(NASID_TO_COMPACT_NODEID(get_master_nasid()); intr_connect_level(console_nodepda->node_first_cpu, SGI_UART_VECTOR, INTPEND0_MAXMASK, dummy_intr_func); request_irq(SGI_UART_VECTOR | (console_nodepda->node_first_cpu << 8), intr_func, SA_INTERRUPT | SA_SHIRQ, "l1_protocol_driver", (void *)sc);#endif#else l1sc_t *sc; nasid_t nasid;#if defined(CONFIG_IA64_SGI_SN1) int tmp;#endif nodepda_t *console_nodepda; int intr_connect_level(cpuid_t, int, ilvl_t, intr_func_t); if ( L1_interrupts_connected ) { /* Interrupts are connected, so just register the callups */ l1_rx_notif((brl1_notif_t)rx_notify); l1_tx_notif((brl1_notif_t)tx_notify); L1_collectibles[L1C_CONNECT_CALLS]++; return; } else L1_interrupts_connected = 1; nasid = get_master_nasid(); console_nodepda = NODEPDA(NASID_TO_COMPACT_NODEID(nasid)); sc = &console_nodepda->module->elsc; sc->intr_cpu = console_nodepda->node_first_cpu;#if defined(CONFIG_IA64_SGI_SN1) if ( intr_connect_level(sc->intr_cpu, UART_INTR, INTPEND0_MAXMASK, (intr_func_t)brl1_intr) ) { L1_interrupts_connected = 0; /* FAILS !! */ } else { void synergy_intr_connect(int, int); synergy_intr_connect(UART_INTR, sc->intr_cpu); L1_collectibles[L1C_R_IRQ]++; tmp = request_irq(BRL1_INTERRUPT_LEVEL, brl1_intrd, SA_INTERRUPT | SA_SHIRQ, "l1_protocol_driver", (void *)sc); L1_collectibles[L1C_R_IRQ_RET] = (uint64_t)tmp; if ( tmp ) { L1_interrupts_connected = 0; /* FAILS !! */ } else { /* Register the upper-level callup functions */ l1_rx_notif((brl1_notif_t)rx_notify); l1_tx_notif((brl1_notif_t)tx_notify); /* Set the uarts the way we like it */ uart_enable_recv_intr( sc ); uart_disable_xmit_intr( sc ); } }#endif /* CONFIG_IA64_SGI_SN1 */#endif /* USE_SAL_CONSOLE_IO */}/* These are functions to use from serial_in/out when in protocol * mode to send and receive uart control regs. These are external * interfaces into the protocol driver. */voidl1_control_out(int offset, int value){#if defined(USE_SAL_CONSOLE_IO) /* quietly ignore unless simulator */ if ( IS_RUNNING_ON_SIMULATOR() ) { extern u64 master_node_bedrock_address; if ( master_node_bedrock_address != (u64)0 ) { writeb(value, (unsigned long)master_node_bedrock_address + (offset<< 3)); } return; }#else nasid_t nasid = get_master_nasid(); WRITE_L1_UART_REG(nasid, offset, value); #endif}/* Console input exported interface. Return a register value. */intl1_control_in_polled(int offset){ static int l1_control_in_local(int, int); return(l1_control_in_local(offset, SERIAL_POLLED_MODE));}intl1_control_in(int offset){ static int l1_control_in_local(int, int); return(l1_control_in_local(offset, SERIAL_INTERRUPT_MODE));}static intl1_control_in_local(int offset, int mode){#if defined(USE_SAL_CONSOLE_IO) int sal_call_status = 0, input; int ret = 0; if ( offset == REG_LSR ) { ret = (LSR_XHRE | LSR_XSRE); /* can send anytime */ sal_call_status = ia64_sn_console_check(&input); if ( !sal_call_status && input ) { /* input pending */ ret |= LSR_RCA; } } /* If the sal call failed, do it the old-fashioned way */ if ( sal_call_status ) { if ( IS_RUNNING_ON_SIMULATOR() ) { extern u64 master_node_bedrock_address; ret = readb((unsigned long)master_node_bedrock_address + (offset<< 3)); } else {#endif /* USE_SAL_CONSOLE_IO */ nasid_t nasid; int ret, input; static int l1_poll(l1sc_t *, int); nasid = get_master_nasid(); ret = READ_L1_UART_REG(nasid, offset); if ( offset == REG_LSR ) { ret |= (LSR_XHRE | LSR_XSRE); /* can send anytime */ if ( L1_cons_is_inited ) { if ( NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->module != (module_t *)0 ) { input = l1_poll(&NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->module->elsc, mode); if ( input ) { ret |= LSR_RCA; } } } }#if defined(USE_SAL_CONSOLE_IO) } }#endif return(ret);}/* * Console input exported interface. Return a character (if one is available) */intl1_serial_in_polled(void){ static int l1_serial_in_local(int mode); return(l1_serial_in_local(SERIAL_POLLED_MODE));}intl1_serial_in(void){ static int l1_serial_in_local(int mode); return(l1_serial_in_local(SERIAL_INTERRUPT_MODE));}static intl1_serial_in_local(int mode){#if defined(USE_SAL_CONSOLE_IO) int sal_call_status; int ch; sal_call_status = ia64_sn_console_getc(&ch); if ( !sal_call_status ) { return(ch); } else { /* If the sal called failed - do it the old-fashioned way */ if ( IS_RUNNING_ON_SIMULATOR() ) { extern u64 master_node_bedrock_address; return(readb((unsigned long)master_node_bedrock_address + (REG_DAT<< 3))); } else {#endif /* USE_SAL_CONSOLE_IO */ nasid_t nasid; l1sc_t *sc; int value; static int l1_getc( l1sc_t *, int ); static inline l1sc_t *early_sc_init(nasid_t); nasid = get_master_nasid(); sc = early_sc_init(nasid); if ( L1_cons_is_inited ) { if ( NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->module != (module_t *)0 ) { sc = &NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->module->elsc; } } value = l1_getc(sc, mode); return(value);#if defined(USE_SAL_CONSOLE_IO) } }#endif}/* Console output exported interface. Write message to the console. */intl1_serial_out( char *str, int len ){#if defined(USE_SAL_CONSOLE_IO) int sal_call_status = 0; int counter = len; /* Attempt to write things out thru the sal */ while ( counter > 0 ) { if ( (sal_call_status = ia64_sn_console_putc(*str)) ) { break; } counter--; str++; } if ( sal_call_status ) { /* If the sal called failed - do it the old-fashioned way */ if ( IS_RUNNING_ON_SIMULATOR() ) { extern u64 master_node_bedrock_address; if (!master_node_bedrock_address) early_sn_setup(); if ( master_node_bedrock_address != (u64)0 ) {#ifdef FLAG_DIRECT_CONSOLE_WRITES /* This is an easy way to pre-pend the output to know whether the output * was done via sal or directly */ writeb('[', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3)); writeb('+', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3)); writeb(']', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3)); writeb(' ', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));#endif /* FLAG_DIRECT_CONSOLE_WRITES */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -