| /****************************************************************************** |
| * Copyright (c) 2004, 2008 IBM Corporation |
| * All rights reserved. |
| * This program and the accompanying materials |
| * are made available under the terms of the BSD License |
| * which accompanies this distribution, and is available at |
| * http://www.opensource.org/licenses/bsd-license.php |
| * |
| * Contributors: |
| * IBM Corporation - initial implementation |
| *****************************************************************************/ |
| |
| #include <stdint.h> |
| #include <rtas.h> |
| #include "rtas_board.h" |
| #include <bmc.h> |
| #include <rtas_i2c_bmc.h> |
| #include <rtas_ipmi_bmc.h> |
| #include "libipmi.h" |
| #include <hw.h> |
| |
| void io_init(void); |
| |
| typedef struct { |
| uint64_t r3; |
| uint64_t addr; |
| volatile uint64_t id; |
| } slave_t; |
| |
| volatile slave_t rtas_slave_interface; |
| |
| void |
| rtas_slave_loop(volatile slave_t * pIface) |
| { |
| uint64_t mask = pIface->id; |
| pIface->id = 0; |
| while (pIface->id != mask); { |
| int dly = 0x1000; |
| while (dly--); |
| } |
| pIface->id = 0; |
| asm(" mr 3,%0 ; mtctr %1 ; bctr "::"r"(pIface->r3), "r"(pIface->addr)); |
| |
| } |
| |
| void |
| rtas_fetch_slaves(rtas_args_t * pArgs) |
| { |
| int retVal = 0; |
| int idx = 0; |
| uint32_t mask = pArgs->args[0] & 0xFFFFFFFE; |
| while (mask) { |
| if (mask & 0x1) { |
| rtas_slave_interface.id = idx | 0x100; |
| *(int *) 0x3fc0 = (int)(unsigned long) &rtas_slave_interface; // r3 |
| *(int *) 0x3f80 = *(uint64_t *) rtas_slave_loop; // addr |
| *(int *) 0x3fa0 = idx | 0x100; // pid |
| while (rtas_slave_interface.id); |
| } |
| mask >>= 1; |
| idx++; |
| } |
| pArgs->args[pArgs->nargs] = retVal; |
| } |
| |
| void |
| rtas_start_cpu(rtas_args_t * pArgs) |
| { |
| int retVal = 0; |
| int idx = pArgs->args[0]; // pid |
| rtas_slave_interface.r3 = pArgs->args[2]; // r3 |
| rtas_slave_interface.addr = pArgs->args[1]; // addr |
| asm(" sync "); |
| rtas_slave_interface.id = idx | 0x100; // pid |
| while (rtas_slave_interface.id); |
| pArgs->args[pArgs->nargs] = retVal; |
| } |
| |
| void |
| rtas_read_vpd(rtas_args_t * pArgs) |
| { |
| pArgs->args[pArgs->nargs] = |
| bmc_read_vpd((uint8_t *) (uint64_t) pArgs->args[2], pArgs->args[1], |
| pArgs->args[0]); |
| } |
| |
| void |
| rtas_write_vpd(rtas_args_t * pArgs) |
| { |
| pArgs->args[pArgs->nargs] = |
| bmc_write_vpd((uint8_t *) (uint64_t) pArgs->args[2], pArgs->args[1], |
| pArgs->args[0]); |
| } |
| |
| void |
| rtas_set_indicator(rtas_args_t * pArgs) |
| { |
| pArgs->args[pArgs->nargs] = -1; |
| } |
| |
| void |
| rtas_event_scan(rtas_args_t * pArgs) |
| { |
| pArgs->args[pArgs->nargs] = -1; |
| } |
| |
| void |
| rtas_stop_bootwatchdog(rtas_args_t * pArgs) |
| { |
| pArgs->args[pArgs->nargs] = bmc_stop_bootwatchdog(); |
| } |
| |
| void |
| rtas_set_bootwatchdog(rtas_args_t * pArgs) |
| { |
| pArgs->args[pArgs->nargs] = bmc_set_bootwatchdog(pArgs->args[0]); |
| } |
| |
| void |
| rtas_set_flashside(rtas_args_t * pArgs) |
| { |
| pArgs->args[pArgs->nargs] = bmc_set_flashside(pArgs->args[0]); |
| } |
| |
| void |
| rtas_get_flashside(rtas_args_t * pArgs) |
| { |
| int retVal = bmc_get_flashside(); |
| pArgs->args[pArgs->nargs] = retVal; |
| } |
| |
| void |
| rtas_flash_test(rtas_args_t * pArgs) |
| { |
| pArgs->args[pArgs->nargs] = -1; |
| } |
| |
| void |
| rtas_system_reboot(rtas_args_t * pArgs) |
| { |
| bmc_system_reboot(); |
| pArgs->args[pArgs->nargs] = -1; |
| } |
| |
| void |
| rtas_power_off(rtas_args_t * pArgs) |
| { |
| bmc_power_off(); |
| pArgs->args[pArgs->nargs] = -1; |
| } |
| |
| void |
| rtas_get_blade_descr(rtas_args_t * pArgs) |
| { |
| uint8_t *buffer = (uint8_t *) (uint64_t) pArgs->args[0]; |
| uint32_t maxlen = pArgs->args[1]; |
| uint32_t retlen = 0; |
| uint32_t retval = bmc_get_blade_descr(buffer, maxlen, &retlen); |
| pArgs->args[pArgs->nargs] = retlen; |
| pArgs->args[pArgs->nargs + 1] = retval; |
| } |
| |
| // for JS20 cannot read blade descr |
| uint32_t |
| dummy_get_blade_descr(uint8_t *dst, uint32_t maxlen, uint32_t *len) |
| { |
| // to not have a warning we need to do _something_ with *dst and maxlen... |
| *dst = *dst; |
| maxlen = maxlen; |
| *len = 0; |
| return -1; |
| } |
| |
| /* read flashside from register */ |
| short |
| reg_get_flashside(void) |
| { |
| short retVal; |
| uint8_t val = load8_ci(0xf4003fe3); |
| if (val & 0x80) { |
| // temp |
| retVal = 1; |
| } else { |
| // perm |
| retVal = 0; |
| } |
| return retVal; |
| } |
| |
| void |
| rtas_init(void) |
| { |
| io_init(); |
| if (u4Flag) { |
| bmc_system_reboot = ipmi_system_reboot; |
| bmc_power_off = ipmi_power_off; |
| bmc_set_flashside = ipmi_set_flashside; |
| bmc_get_flashside = reg_get_flashside; |
| bmc_stop_bootwatchdog = ipmi_oem_stop_bootwatchdog; |
| bmc_set_bootwatchdog = ipmi_oem_set_bootwatchdog; |
| bmc_read_vpd = ipmi_oem_read_vpd; |
| bmc_write_vpd = ipmi_oem_write_vpd; |
| bmc_get_blade_descr = ipmi_oem_get_blade_descr; |
| } else { |
| bmc_system_reboot = i2c_system_reboot; |
| bmc_power_off = i2c_power_off; |
| bmc_set_flashside = i2c_set_flashside; |
| bmc_get_flashside = i2c_get_flashside; |
| bmc_stop_bootwatchdog = i2c_stop_bootwatchdog; |
| bmc_set_bootwatchdog = i2c_set_bootwatchdog; |
| bmc_read_vpd = i2c_read_vpd; |
| bmc_write_vpd = i2c_write_vpd; |
| bmc_get_blade_descr = dummy_get_blade_descr; |
| } |
| } |