?? l1_command.c
字號(hào):
/* send the request to the L1 */ if( SC_COMMAND( sc, subch, msg, msg, &len ) < 0 ) { sc_close( sc, subch ); return( ELSC_ERROR_CMD_SEND ); } /* free up subchannel */ sc_close( sc, subch ); /* check response */ if( sc_interpret_resp( msg, 0 ) < 0 ) { return( ELSC_ERROR_RESP_FORMAT ); } return 0;}/* * sc_power_down * * Shuts down the c-brick associated with sc, and any attached I/O bricks * or other c-bricks (won't go through r-bricks). */int sc_power_down(l1sc_t *sc){ return sc_command_interp( sc, L1_ADDR_TYPE_L1, L1_ADDR_RACK_LOCAL, L1_ADDR_BAY_LOCAL, "* pwr d" );}/* * sc_power_down_all * * Works similarly to sc_power_down, except that the request is sent to the * closest L2 and EVERYBODY gets turned off. */int sc_power_down_all(l1sc_t *sc){ if( nodepda->num_routers > 0 ) { return sc_command_interp( sc, L1_ADDR_TYPE_L2, L1_ADDR_RACK_LOCAL, L1_ADDR_BAY_LOCAL, "* pwr d" ); } else { return sc_power_down( sc ); }}/* * Routines for reading the R-brick's L1 */int router_module_get( nasid_t nasid, net_vec_t path ){ uint rnum, rack, bay, t; int ret; l1sc_t sc; /* prepare l1sc_t struct */ sc_init( &sc, nasid, path ); /* construct module ID from rack and slot info */ if ((ret = elsc_rack_bay_get(&sc, &rnum, &bay)) < 0) return ret; /* report unset location info. with a special, otherwise invalid modid */ if (rnum == 0 && bay == 0) return MODULE_NOT_SET; if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT) return ELSC_ERROR_MODULE; /* Build a moduleid_t-compatible rack number */ rack = 0; t = rnum / 100; /* rack class (CPU/IO) */ if (t > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack)) return ELSC_ERROR_MODULE; RACK_ADD_CLASS(rack, t); rnum %= 100; t = rnum / 10; /* rack group */ if (t > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack)) return ELSC_ERROR_MODULE; RACK_ADD_GROUP(rack, t); t = rnum % 10; /* rack number (one-based) */ if (t-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack)) return ELSC_ERROR_MODULE; RACK_ADD_NUM(rack, t); ret = RBT_TO_MODULE(rack, bay, MODULE_RBRICK); return ret;} /* * iobrick routines *//* iobrick_rack_bay_type_get fills in the three int * arguments with the * rack number, bay number and brick type of the L1 being addressed. Note * that if the L1 operation fails and this function returns an error value, * garbage may be written to brick_type. */int iobrick_rack_bay_type_get( l1sc_t *sc, uint *rack, uint *bay, uint *brick_type ){ char msg[BRL1_QSIZE]; /* L1 request/response info */ int subch; /* system controller subchannel used */ int len; /* length of message */ uint32_t buf32; /* used to copy 32-bit rack & bay out of msg */ /* fill in msg with the opcode & params */ bzero( msg, BRL1_QSIZE ); if( (subch = sc_open( sc, L1_ADDR_LOCALIO )) < 0 ) { return( ELSC_ERROR_CMD_SEND ); } if( (len = sc_construct_msg( sc, subch, msg, BRL1_QSIZE, L1_ADDR_TASK_GENERAL, L1_REQ_RRBT, 0 )) < 0 ) { sc_close( sc, subch ); return( ELSC_ERROR_CMD_ARGS ); } /* send the request to the L1 */ if( sc_command( sc, subch, msg, msg, &len ) ) { sc_close( sc, subch ); return( ELSC_ERROR_CMD_SEND ); } /* free up subchannel */ sc_close( sc, subch ); /* check response */ if( sc_interpret_resp( msg, 4, L1_ARG_INT, &buf32, L1_ARG_INT, brick_type ) < 0 ) { return( ELSC_ERROR_RESP_FORMAT ); } /* extract rack/bay info * * note that the 32-bit value returned by the L1 actually * only uses the low-order sixteen bits for rack and bay * information. A "normal" L1 address puts rack and bay * information in bit positions 12 through 28. So if * we initially shift the value returned 12 bits to the left, * we can use the L1 addressing #define's to extract the * values we need (see ksys/l1.h for a complete list of the * various fields of an L1 address). */ buf32 <<= L1_ADDR_BAY_SHFT; *rack = (buf32 & L1_ADDR_RACK_MASK) >> L1_ADDR_RACK_SHFT; *bay = (buf32 & L1_ADDR_BAY_MASK) >> L1_ADDR_BAY_SHFT; return 0;}int iobrick_module_get(l1sc_t *sc){ uint rnum, rack, bay, brick_type, t; int ret; /* construct module ID from rack and slot info */ if ((ret = iobrick_rack_bay_type_get(sc, &rnum, &bay, &brick_type)) < 0) return ret; if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT) return ELSC_ERROR_MODULE; /* Build a moduleid_t-compatible rack number */ rack = 0; t = rnum / 100; /* rack class (CPU/IO) */ if (t > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack)) return ELSC_ERROR_MODULE; RACK_ADD_CLASS(rack, t); rnum %= 100; t = rnum / 10; /* rack group */ if (t > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack)) return ELSC_ERROR_MODULE; RACK_ADD_GROUP(rack, t); t = rnum % 10; /* rack number (one-based) */ if (t-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack)) return ELSC_ERROR_MODULE; RACK_ADD_NUM(rack, t); switch( brick_type ) { case 'I': brick_type = MODULE_IBRICK; break; case 'P': brick_type = MODULE_PBRICK; break; case 'X': brick_type = MODULE_XBRICK; break; } ret = RBT_TO_MODULE(rack, bay, brick_type); return ret;}/* iobrick_get_sys_snum asks the attached iobrick for the system * serial number. This function will only be relevant to the master * cbrick (the one attached to the bootmaster ibrick); other nodes * may call the function, but the value returned to the master node * will be the one used as the system serial number by the kernel. */intiobrick_get_sys_snum( l1sc_t *sc, char *snum_str ){ char msg[BRL1_QSIZE]; /* L1 request/response info */ int subch; /* system controller subchannel used */ int len; /* length of message */ /* fill in msg with the opcode & params */ bzero( msg, BRL1_QSIZE ); if( (subch = sc_open( sc, L1_ADDR_LOCALIO )) < 0 ) { return( ELSC_ERROR_CMD_SEND ); } if( (len = sc_construct_msg( sc, subch, msg, BRL1_QSIZE, L1_ADDR_TASK_GENERAL, L1_REQ_SYS_SERIAL, 0 )) < 0 ) { sc_close( sc, subch ); return( ELSC_ERROR_CMD_ARGS ); } /* send the request to the L1 */ if( sc_command( sc, subch, msg, msg, &len ) ) { sc_close( sc, subch ); return( ELSC_ERROR_CMD_SEND ); } /* free up subchannel */ sc_close( sc, subch ); /* check response */ return( sc_interpret_resp( msg, 2, L1_ARG_ASCII, snum_str ) );}/* * The following functions apply (or cut off) power to the specified * pci bus or slot. */intiobrick_pci_pwr( l1sc_t *sc, int bus, int slot, int req_code ){#if 0 /* The "bedrock request" method of performing this function * seems to be broken in the L1, so for now use the command- * interpreter method */ char msg[BRL1_QSIZE]; int len; /* length of message being sent */ int subch; /* system controller subchannel used */ /* fill in msg with the opcode & params */ bzero( msg, BRL1_QSIZE ); subch = sc_open( sc, L1_ADDR_LOCALIO ); if( (len = sc_construct_msg( sc, subch, msg, BRL1_QSIZE, L1_ADDR_TASK_GENERAL, req_code, 4, L1_ARG_INT, bus, L1_ARG_INT, slot )) < 0 ) { sc_close( sc, subch ); return( ELSC_ERROR_CMD_ARGS ); } /* send the request to the L1 */ if( SC_COMMAND(sc, subch, msg, msg, &len ) < 0 ) { sc_close( sc, subch ); return( ELSC_ERROR_CMD_SEND ); } /* free up subchannel */ sc_close( sc, subch ); /* check response */ if( sc_interpret_resp( msg, 0 ) < 0 ) { return( ELSC_ERROR_RESP_FORMAT ); } return 0;#else char cmd[64]; char *fxn; switch( req_code ) { case L1_REQ_PCI_UP: fxn = "u"; break; case L1_REQ_PCI_DOWN: fxn = "d"; break; case L1_REQ_PCI_RESET: fxn = "rst"; break; default: return( ELSC_ERROR_CMD_ARGS ); } if( slot == -1 ) sprintf( cmd, "pci %d %s", bus, fxn ); else sprintf( cmd, "pci %d %d %s", bus, slot, fxn ); return sc_command_interp( sc, L1_ADDR_TYPE_IOBRICK, L1_ADDR_RACK_LOCAL, L1_ADDR_BAY_LOCAL, cmd );#endif} intiobrick_pci_slot_pwr( l1sc_t *sc, int bus, int slot, int up ){ return iobrick_pci_pwr( sc, bus, slot, up );}intiobrick_pci_bus_pwr( l1sc_t *sc, int bus, int up ){ return iobrick_pci_pwr( sc, bus, -1, up );}intiobrick_pci_slot_rst( l1sc_t *sc, int bus, int slot ){ return iobrick_pci_pwr( sc, bus, slot, L1_REQ_PCI_RESET );}intiobrick_pci_bus_rst( l1sc_t *sc, int bus ){ return iobrick_pci_pwr( sc, bus, -1, L1_REQ_PCI_RESET );}/* get the L1 firmware version for an iobrick */intiobrick_sc_version( l1sc_t *sc, char *result ){ char msg[BRL1_QSIZE]; int len; /* length of message being sent */ int subch; /* system controller subchannel used */ int major, /* major rev number */ minor, /* minor rev number */ bugfix; /* bugfix rev number */ /* fill in msg with the opcode & params */ bzero( msg, BRL1_QSIZE ); subch = sc_open( sc, L1_ADDR_LOCALIO ); if( (len = sc_construct_msg( sc, subch, msg, BRL1_QSIZE, L1_ADDR_TASK_GENERAL, L1_REQ_FW_REV, 0 )) < 0 ) { sc_close( sc, subch ); return( ELSC_ERROR_CMD_ARGS ); } /* send the request to the L1 */ if( SC_COMMAND(sc, subch, msg, msg, &len ) < 0 ) { sc_close( sc, subch ); return( ELSC_ERROR_CMD_SEND ); } /* free up subchannel */ sc_close( sc, subch ); /* check response */ if( sc_interpret_resp( msg, 6, L1_ARG_INT, &major, L1_ARG_INT, &minor, L1_ARG_INT, &bugfix ) < 0 ) { return( ELSC_ERROR_RESP_FORMAT ); } sprintf( result, "%d.%d.%d", major, minor, bugfix ); return 0;}/* elscuart routines * * Most of the elscuart functionality is implemented in l1.c. The following * is directly "recycled" from elsc.c. *//* * _elscuart_puts */int _elscuart_puts(elsc_t *e, char *s){ int c; if (s == 0) s = "<NULL>"; while ((c = LBYTE(s)) != 0) { if (_elscuart_putc(e, c) < 0) return -1; s++; } return 0;}/* * elscuart wrapper routines * * The following routines are similar to their counterparts in l1.c, * except instead of taking an elsc_t pointer directly, they call * a global routine "get_elsc" to obtain the pointer. * This is useful when the elsc is employed for stdio. */int elscuart_probe(void){ return _elscuart_probe(get_elsc());}void elscuart_init(void *init_data){ _elscuart_init(get_elsc()); /* dummy variable included for driver compatability */ init_data = init_data;}int elscuart_poll(void){ return _elscuart_poll(get_elsc());}int elscuart_readc(void){ return _elscuart_readc(get_elsc());}int elscuart_getc(void){ return _elscuart_getc(get_elsc());}int elscuart_puts(char *s){ return _elscuart_puts(get_elsc(), s);}int elscuart_putc(int c){ return _elscuart_putc(get_elsc(), c);}int elscuart_flush(void){ return _elscuart_flush(get_elsc());}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -