📄 ipmi_smic_sm.c
字号:
#define SMIC_SC_SMS_WR_START (SMIC_STATUS|SMIC_SMS|SMIC_WR_START)#define SMIC_SC_SMS_WR_NEXT (SMIC_STATUS|SMIC_SMS|SMIC_WR_NEXT)#define SMIC_SC_SMS_WR_END (SMIC_STATUS|SMIC_SMS|SMIC_WR_END)#define SMIC_SC_SMS_RD_START (SMIC_STATUS|SMIC_SMS|SMIC_RD_START)#define SMIC_SC_SMS_RD_NEXT (SMIC_STATUS|SMIC_SMS|SMIC_RD_NEXT)#define SMIC_SC_SMS_RD_END (SMIC_STATUS|SMIC_SMS|SMIC_RD_END)#define SMIC_SC_SMM_READY (SMIC_STATUS|SMIC_SMM|SMIC_READY)#define SMIC_SC_SMM_WR_START (SMIC_STATUS|SMIC_SMM|SMIC_WR_START)#define SMIC_SC_SMM_WR_NEXT (SMIC_STATUS|SMIC_SMM|SMIC_WR_NEXT)#define SMIC_SC_SMM_WR_END (SMIC_STATUS|SMIC_SMM|SMIC_WR_END)#define SMIC_SC_SMM_RD_START (SMIC_STATUS|SMIC_SMM|SMIC_RD_START)#define SMIC_SC_SMM_RD_NEXT (SMIC_STATUS|SMIC_SMM|SMIC_RD_NEXT)#define SMIC_SC_SMM_RD_END (SMIC_STATUS|SMIC_SMM|SMIC_RD_END)/* these are the control/status codes we actually use SMIC_CC_SMS_GET_STATUS 0x40 SMIC_CC_SMS_WR_START 0x41 SMIC_CC_SMS_WR_NEXT 0x42 SMIC_CC_SMS_WR_END 0x43 SMIC_CC_SMS_RD_START 0x44 SMIC_CC_SMS_RD_NEXT 0x45 SMIC_CC_SMS_RD_END 0x46 SMIC_SC_SMS_READY 0xC0 SMIC_SC_SMS_WR_START 0xC1 SMIC_SC_SMS_WR_NEXT 0xC2 SMIC_SC_SMS_WR_END 0xC3 SMIC_SC_SMS_RD_START 0xC4 SMIC_SC_SMS_RD_NEXT 0xC5 SMIC_SC_SMS_RD_END 0xC6*/static enum si_sm_result smic_event (struct si_sm_data *smic, long time){ unsigned char status; unsigned char flags; unsigned char data; if (smic->state == SMIC_HOSED) { init_smic_data(smic, smic->io); return SI_SM_HOSED; } if (smic->state != SMIC_IDLE) { if (smic_debug & SMIC_DEBUG_STATES) { printk(KERN_INFO "smic_event - smic->smic_timeout = %ld," " time = %ld\n", smic->smic_timeout, time); }/* FIXME: smic_event is sometimes called with time > SMIC_RETRY_TIMEOUT */ if (time < SMIC_RETRY_TIMEOUT) { smic->smic_timeout -= time; if (smic->smic_timeout < 0) { start_error_recovery(smic, "smic timed out."); return SI_SM_CALL_WITH_DELAY; } } } flags = read_smic_flags(smic); if (flags & SMIC_FLAG_BSY) return SI_SM_CALL_WITH_DELAY; status = read_smic_status (smic); if (smic_debug & SMIC_DEBUG_STATES) printk(KERN_INFO "smic_event - state = %d, flags = 0x%02x," " status = 0x%02x\n", smic->state, flags, status); switch (smic->state) { case SMIC_IDLE: /* in IDLE we check for available messages */ if (flags & SMIC_SMS_DATA_AVAIL) { return SI_SM_ATTN; } return SI_SM_IDLE; case SMIC_START_OP: /* sanity check whether smic is really idle */ write_smic_control(smic, SMIC_CC_SMS_GET_STATUS); write_smic_flags(smic, flags | SMIC_FLAG_BSY); smic->state = SMIC_OP_OK; break; case SMIC_OP_OK: if (status != SMIC_SC_SMS_READY) { /* this should not happen */ start_error_recovery(smic, "state = SMIC_OP_OK," " status != SMIC_SC_SMS_READY"); return SI_SM_CALL_WITH_DELAY; } /* OK so far; smic is idle let us start ... */ write_smic_control(smic, SMIC_CC_SMS_WR_START); write_next_byte(smic); write_smic_flags(smic, flags | SMIC_FLAG_BSY); smic->state = SMIC_WRITE_START; break; case SMIC_WRITE_START: if (status != SMIC_SC_SMS_WR_START) { start_error_recovery(smic, "state = SMIC_WRITE_START, " "status != SMIC_SC_SMS_WR_START"); return SI_SM_CALL_WITH_DELAY; } /* we must not issue WR_(NEXT|END) unless TX_DATA_READY is set */ if (flags & SMIC_TX_DATA_READY) { if (smic->write_count == 1) { /* last byte */ write_smic_control(smic, SMIC_CC_SMS_WR_END); smic->state = SMIC_WRITE_END; } else { write_smic_control(smic, SMIC_CC_SMS_WR_NEXT); smic->state = SMIC_WRITE_NEXT; } write_next_byte(smic); write_smic_flags(smic, flags | SMIC_FLAG_BSY); } else { return SI_SM_CALL_WITH_DELAY; } break; case SMIC_WRITE_NEXT: if (status != SMIC_SC_SMS_WR_NEXT) { start_error_recovery(smic, "state = SMIC_WRITE_NEXT, " "status != SMIC_SC_SMS_WR_NEXT"); return SI_SM_CALL_WITH_DELAY; } /* this is the same code as in SMIC_WRITE_START */ if (flags & SMIC_TX_DATA_READY) { if (smic->write_count == 1) { write_smic_control(smic, SMIC_CC_SMS_WR_END); smic->state = SMIC_WRITE_END; } else { write_smic_control(smic, SMIC_CC_SMS_WR_NEXT); smic->state = SMIC_WRITE_NEXT; } write_next_byte(smic); write_smic_flags(smic, flags | SMIC_FLAG_BSY); } else { return SI_SM_CALL_WITH_DELAY; } break; case SMIC_WRITE_END: if (status != SMIC_SC_SMS_WR_END) { start_error_recovery (smic, "state = SMIC_WRITE_END, " "status != SMIC_SC_SMS_WR_END"); return SI_SM_CALL_WITH_DELAY; } /* data register holds an error code */ data = read_smic_data(smic); if (data != 0) { if (smic_debug & SMIC_DEBUG_ENABLE) { printk(KERN_INFO "SMIC_WRITE_END: data = %02x\n", data); } start_error_recovery(smic, "state = SMIC_WRITE_END, " "data != SUCCESS"); return SI_SM_CALL_WITH_DELAY; } else { smic->state = SMIC_WRITE2READ; } break; case SMIC_WRITE2READ: /* we must wait for RX_DATA_READY to be set before we can continue */ if (flags & SMIC_RX_DATA_READY) { write_smic_control(smic, SMIC_CC_SMS_RD_START); write_smic_flags(smic, flags | SMIC_FLAG_BSY); smic->state = SMIC_READ_START; } else { return SI_SM_CALL_WITH_DELAY; } break; case SMIC_READ_START: if (status != SMIC_SC_SMS_RD_START) { start_error_recovery(smic, "state = SMIC_READ_START, " "status != SMIC_SC_SMS_RD_START"); return SI_SM_CALL_WITH_DELAY; } if (flags & SMIC_RX_DATA_READY) { read_next_byte(smic); write_smic_control(smic, SMIC_CC_SMS_RD_NEXT); write_smic_flags(smic, flags | SMIC_FLAG_BSY); smic->state = SMIC_READ_NEXT; } else { return SI_SM_CALL_WITH_DELAY; } break; case SMIC_READ_NEXT: switch (status) { /* smic tells us that this is the last byte to be read --> clean up */ case SMIC_SC_SMS_RD_END: read_next_byte(smic); write_smic_control(smic, SMIC_CC_SMS_RD_END); write_smic_flags(smic, flags | SMIC_FLAG_BSY); smic->state = SMIC_READ_END; break; case SMIC_SC_SMS_RD_NEXT: if (flags & SMIC_RX_DATA_READY) { read_next_byte(smic); write_smic_control(smic, SMIC_CC_SMS_RD_NEXT); write_smic_flags(smic, flags | SMIC_FLAG_BSY); smic->state = SMIC_READ_NEXT; } else { return SI_SM_CALL_WITH_DELAY; } break; default: start_error_recovery( smic, "state = SMIC_READ_NEXT, " "status != SMIC_SC_SMS_RD_(NEXT|END)"); return SI_SM_CALL_WITH_DELAY; } break; case SMIC_READ_END: if (status != SMIC_SC_SMS_READY) { start_error_recovery(smic, "state = SMIC_READ_END, " "status != SMIC_SC_SMS_READY"); return SI_SM_CALL_WITH_DELAY; } data = read_smic_data(smic); /* data register holds an error code */ if (data != 0) { if (smic_debug & SMIC_DEBUG_ENABLE) { printk(KERN_INFO "SMIC_READ_END: data = %02x\n", data); } start_error_recovery(smic, "state = SMIC_READ_END, " "data != SUCCESS"); return SI_SM_CALL_WITH_DELAY; } else { smic->state = SMIC_IDLE; return SI_SM_TRANSACTION_COMPLETE; } case SMIC_HOSED: init_smic_data(smic, smic->io); return SI_SM_HOSED; default: if (smic_debug & SMIC_DEBUG_ENABLE) { printk(KERN_WARNING "smic->state = %d\n", smic->state); start_error_recovery(smic, "state = UNKNOWN"); return SI_SM_CALL_WITH_DELAY; } } smic->smic_timeout = SMIC_RETRY_TIMEOUT; return SI_SM_CALL_WITHOUT_DELAY;}static int smic_detect(struct si_sm_data *smic){ /* It's impossible for the SMIC fnags register to be all 1's, (assuming a properly functioning, self-initialized BMC) but that's what you get from reading a bogus address, so we test that first. */ if (read_smic_flags(smic) == 0xff) return 1; return 0;}static void smic_cleanup(struct si_sm_data *kcs){}static int smic_size(void){ return sizeof(struct si_sm_data);}struct si_sm_handlers smic_smi_handlers ={ .init_data = init_smic_data, .start_transaction = start_smic_transaction, .get_result = smic_get_result, .event = smic_event, .detect = smic_detect, .cleanup = smic_cleanup, .size = smic_size,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -