#ifndef __IPMIVARS_H__
#define __IPMIVARS_H__
struct ipmi_get_info {
int iface_type;
uint64_t address;
int offset;
int io_mode;
int irq;
};
struct ipmi_device;
struct ipmi_request {
TAILQ_ENTRY(ipmi_request) ir_link;
struct ipmi_device *ir_owner;
u_char *ir_request;
size_t ir_requestlen;
u_char *ir_reply;
size_t ir_replybuflen;
int ir_replylen;
int ir_error;
long ir_msgid;
uint8_t ir_addr;
uint8_t ir_command;
uint8_t ir_compcode;
};
#define MAX_RES 3
#define KCS_DATA 0
#define KCS_CTL_STS 1
#define SMIC_DATA 0
#define SMIC_CTL_STS 1
#define SMIC_FLAGS 2
struct ipmi_softc;
struct ipmi_device {
TAILQ_ENTRY(ipmi_device) ipmi_link;
TAILQ_HEAD(,ipmi_request) ipmi_completed_requests;
struct ipmi_softc *ipmi_softc;
int ipmi_closing;
int ipmi_requests;
u_char ipmi_address;
u_char ipmi_lun;
};
struct ipmi_kcs {
};
struct ipmi_smic {
};
struct ipmi_ssif {
device_t smbus;
int smbus_address;
};
struct ipmi_softc {
device_t ipmi_dev;
union {
struct ipmi_kcs kcs;
struct ipmi_smic smic;
struct ipmi_ssif ssif;
} _iface;
int ipmi_io_rid;
int ipmi_io_type;
struct resource *ipmi_io_res[MAX_RES];
int ipmi_io_spacing;
int ipmi_irq_rid;
struct resource *ipmi_irq_res;
void *ipmi_irq;
int ipmi_detaching;
int ipmi_opened;
struct cdev *ipmi_cdev;
TAILQ_HEAD(,ipmi_request) ipmi_pending_requests;
int ipmi_watchdog_active;
struct intr_config_hook ipmi_ich;
struct lock ipmi_lock;
struct cv ipmi_request_added;
struct thread *ipmi_kthread;
driver_intr_t *ipmi_intr;
struct kqinfo ipmi_kq;
struct callout ipmi_watchdog;
int ipmi_wdog_period;
int ipmi_wdog_enable;
int (*ipmi_startup)(struct ipmi_softc *);
int (*ipmi_enqueue_request)(struct ipmi_softc *, struct ipmi_request *);
};
#define ipmi_ssif_smbus_address _iface.ssif.smbus_address
#define ipmi_ssif_smbus _iface.ssif.smbus
struct ipmi_ipmb {
u_char foo;
};
#define KCS_MODE 0x01
#define SMIC_MODE 0x02
#define BT_MODE 0x03
#define SSIF_MODE 0x04
#define KCS_STATUS_OBF 0x01
#define KCS_STATUS_IBF 0x02
#define KCS_STATUS_SMS_ATN 0x04
#define KCS_STATUS_C_D 0x08
#define KCS_STATUS_OEM1 0x10
#define KCS_STATUS_OEM2 0x20
#define KCS_STATUS_S0 0x40
#define KCS_STATUS_S1 0x80
#define KCS_STATUS_STATE(x) ((x)>>6)
#define KCS_STATUS_STATE_IDLE 0x0
#define KCS_STATUS_STATE_READ 0x1
#define KCS_STATUS_STATE_WRITE 0x2
#define KCS_STATUS_STATE_ERROR 0x3
#define KCS_IFACE_STATUS_OK 0x00
#define KCS_IFACE_STATUS_ABORT 0x01
#define KCS_IFACE_STATUS_ILLEGAL 0x02
#define KCS_IFACE_STATUS_LENGTH_ERR 0x06
#define KCS_IFACE_STATUS_UNKNOWN_ERR 0xff
#define KCS_CONTROL_GET_STATUS_ABORT 0x60
#define KCS_CONTROL_WRITE_START 0x61
#define KCS_CONTROL_WRITE_END 0x62
#define KCS_DATA_IN_READ 0x68
#define SMIC_STATUS_BUSY 0x01
#define SMIC_STATUS_SMS_ATN 0x04
#define SMIC_STATUS_EVT_ATN 0x08
#define SMIC_STATUS_SMI 0x10
#define SMIC_STATUS_TX_RDY 0x40
#define SMIC_STATUS_RX_RDY 0x80
#define SMIC_STATUS_RESERVED 0x22
#define SMIC_CC_SMS_GET_STATUS 0x40
#define SMIC_CC_SMS_WR_START 0x41
#define SMIC_CC_SMS_WR_NEXT 0x42
#define SMIC_CC_SMS_WR_END 0x43
#define SMIC_CC_SMS_RD_START 0x44
#define SMIC_CC_SMS_RD_NEXT 0x45
#define SMIC_CC_SMS_RD_END 0x46
#define SMIC_SC_SMS_RDY 0xc0
#define SMIC_SC_SMS_WR_START 0xc1
#define SMIC_SC_SMS_WR_NEXT 0xc2
#define SMIC_SC_SMS_WR_END 0xc3
#define SMIC_SC_SMS_RD_START 0xc4
#define SMIC_SC_SMS_RD_NEXT 0xc5
#define SMIC_SC_SMS_RD_END 0xc6
#define IPMI_ADDR(netfn, lun) ((netfn) << 2 | (lun))
#define IPMI_REPLY_ADDR(addr) ((addr) + 0x4)
#define IPMI_LOCK(sc) lockmgr(&(sc)->ipmi_lock, LK_EXCLUSIVE)
#define IPMI_UNLOCK(sc) lockmgr(&(sc)->ipmi_lock, LK_RELEASE)
#define IPMI_LOCK_ASSERT(sc) KKASSERT(lockowned(&(sc)->ipmi_lock))
#define ipmi_alloc_driver_request(addr, cmd, reqlen, replylen) \
ipmi_alloc_request(NULL, 0, (addr), (cmd), (reqlen), (replylen))
#define INB_SINGLE(sc, x) \
bus_read_1((sc)->ipmi_io_res[0], (sc)->ipmi_io_spacing * (x))
#define OUTB_SINGLE(sc, x, value) \
bus_write_1((sc)->ipmi_io_res[0], (sc)->ipmi_io_spacing * (x), value)
#define INB_MULTIPLE(sc, x) \
bus_read_1((sc)->ipmi_io_res[(x)], 0)
#define OUTB_MULTIPLE(sc, x, value) \
bus_write_1((sc)->ipmi_io_res[(x)], 0, value)
#define INB(sc, x) \
((sc)->ipmi_io_res[1] != NULL ? INB_MULTIPLE(sc, x) : INB_SINGLE(sc, x))
#define OUTB(sc, x, value) \
((sc)->ipmi_io_res[1] != NULL ? OUTB_MULTIPLE(sc, x, value) : \
OUTB_SINGLE(sc, x, value))
#define MAX_TIMEOUT 6 * hz
int ipmi_attach(device_t);
int ipmi_detach(device_t);
void ipmi_release_resources(device_t);
struct ipmi_request *ipmi_alloc_request(struct ipmi_device *, long, uint8_t,
uint8_t, size_t, size_t);
void ipmi_complete_request(struct ipmi_softc *, struct ipmi_request *);
struct ipmi_request *ipmi_dequeue_request(struct ipmi_softc *);
void ipmi_free_request(struct ipmi_request *);
int ipmi_polled_enqueue_request(struct ipmi_softc *, struct ipmi_request *);
int ipmi_submit_driver_request(struct ipmi_softc *, struct ipmi_request *,
int);
int ipmi_smbios_identify(struct ipmi_get_info *);
const char *ipmi_pci_match(uint16_t, uint16_t);
int ipmi_kcs_attach(struct ipmi_softc *);
int ipmi_kcs_probe_align(struct ipmi_softc *);
int ipmi_smic_attach(struct ipmi_softc *);
int ipmi_ssif_attach(struct ipmi_softc *, device_t, int);
#ifdef IPMB
int ipmi_handle_attn(struct ipmi_softc *);
#endif
extern devclass_t ipmi_devclass;
extern int ipmi_attached;
#endif