📄 l1.c
字号:
} /* 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 ){#ifdef CONSOLE_POLLING_ALSO return(0);#else return(BRL1_INTERRUPT_LEVEL);#endif}/* Disconnect the callup functions - throw away interrupts */voidl1_unconnect_intr(void){ /* 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 */}/* Set up uart interrupt handling for this node's uart */voidl1_connect_intr(void *rx_notify, void *tx_notify){ 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 */}/* Set the line speed */voidl1_set_baud(int baud){#if 0 nasid_t nasid; static void uart_init(l1sc_t *, int);#endif L1_collectibles[L1C_SET_BAUD]++;#if 0 if ( L1_cons_is_inited ) { nasid = get_master_nasid(); if ( NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->module != (module_t *)0 ) uart_init(&NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->module->elsc, baud); }#endif return;}/* 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){ nasid_t nasid = get_master_nasid(); WRITE_L1_UART_REG(nasid, offset, value); }/* 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){ 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; } } } } 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){ 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);}/* Console output exported interface. Write message to the console. */intl1_serial_out( char *str, int len ){ nasid_t nasid = get_master_nasid(); int l1_write(l1sc_t *, char *, int, int); if ( L1_cons_is_inited ) { if ( NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->module != (module_t *)0 ) return(l1_write(&NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->module->elsc, str, len,#if defined(SYNC_CONSOLE_WRITE) 1#else !L1_interrupts_connected#endif )); } return(early_l1_serial_out(nasid, str, len, NOT_LOCKED));}/* * These are the 'early' functions - when we need to do things before we have * all the structs setup. */static l1sc_t Early_console; /* fake l1sc_t */static int Early_console_inited = 0;static voidearly_brl1_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); subch->tx_notify = NULL; subch->rx_notify = NULL; 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); subch->tx_notify = NULL; subch->rx_notify = NULL; if( sc->uart == BRL1_LOCALHUB_UART ) { static sc_cq_t x_iqp; subch->iqp = &x_iqp; ASSERT( subch->iqp ); cq_init( subch->iqp ); } else { /* we shouldn't be getting console input from remote UARTs */ subch->iqp = &sc->garbage_q; } 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 = NULL; 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 = NULL; subch->iqp = &sc->garbage_q; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -