#pragma ident "%Z%%M% %I% %E% SMI"
#define EHC_SUCCESS 0
#define EHC_FAILURE (-1)
#define EHC_NO_SLAVE_ACK 3
#define EHC_MAX_WAIT 100
#define EHC_S1_PIN 0x80
#define EHC_S1_ES1 0x20
#define EHC_S1_ES0 0x40
#define EHC_S1_NBB 0x01
#define EHC_S1_ACK 0x01
#define EHC_S1_STA 0x04
#define EHC_S1_STO 0x02
#define EHC_S1_LRB 0x08
#define EHC_S1_BER 0x10
#define EHC_S1_LAB 0x02
#define EHC_S1_AAS 0x04
#define EHC_S1_AD0 0x08
#define EHC_S1_STS 0x20
#define EHC_S0_OWN 0x55
#define EHC_S0_CLK 0x1d
#define EHC_BYTE_READ 0x01
#define EHC_LONGEST_MSG 200000
#define DUMMY_WRITE_ADDR 0x20
#define DUMMY_WRITE_DATA 0x00
#define EHC_PCF8591_MAX_DEVS 0x08
#define EHC_DEV0 0x00
#define EHC_DEV1 0x02
#define EHC_DEV2 0x04
#define EHC_DEV3 0x06
#define EHC_DEV4 0x08
#define EHC_DEV5 0x0A
#define EHC_DEV6 0x0C
#define EHC_DEV7 0x0E
#define EHC_PCF8591_ANALOG_OUTPUT_EN 0x40
#define EHC_PCF8591_ANALOG_INPUT_EN 0x00
#define EHC_PCF8591_READ_BIT 0x01
#define EHC_PCF8591_AUTO_INCR 0x04
#define EHC_PCF8591_OSCILATOR 0x40
#define EHC_PCF8591_MAX_PORTS 0x04
#define EHC_PCF8591_CH_0 0x00
#define EHC_PCF8591_CH_1 0x01
#define EHC_PCF8591_CH_2 0x02
#define EHC_PCF8591_CH_3 0x03
#define EHC_PCF8574_PORT0 0x01
#define EHC_PCF8574_PORT1 0x02
#define EHC_PCF8574_PORT2 0x04
#define EHC_PCF8574_PORT3 0x08
#define EHC_PCF8574_PORT4 0x10
#define EHC_PCF8574_PORT5 0x20
#define EHC_PCF8574_PORT6 0x40
#define EHC_PCF8574_PORT7 0x80
#define EHC_PCF8583_READ_BIT 0x01
struct ehc_pcd8584_regs {
uint8_t s0;
uint8_t s1;
uint8_t clock_s2;
};
struct ehc_envcunit {
struct ehc_pcd8584_regs *bus_ctl_regs;
ddi_acc_handle_t ctlr_handle;
kmutex_t umutex;
};
int ehc_debug = 0;
#define DCMN_ERR if (ehc_debug & 0x1) cmn_err
#define DCMN2_ERR if (ehc_debug & 0x2) cmn_err
void ehc_init_pcf8584(struct ehc_envcunit *);
int ehc_read_tda8444(struct ehc_envcunit *ehcp);
int ehc_write_tda8444(struct ehc_envcunit *, int, int, int, uint8_t *, int);
int ehc_write_pcf8591(struct ehc_envcunit *, int, int, int, int, int,
uint8_t *, int);
int ehc_read_pcf8591(struct ehc_envcunit *, int, int, int, int, int,
uint8_t *, int);
int ehc_read_pcf8574a(struct ehc_envcunit *, int, uint8_t *, int);
int ehc_write_pcf8574a(struct ehc_envcunit *, int, uint8_t *, int);
int ehc_read_pcf8574(struct ehc_envcunit *, int, uint8_t *, int);
int ehc_write_pcf8574(struct ehc_envcunit *, int, uint8_t *, int);
int ehc_read_lm75(struct ehc_envcunit *, int, uint8_t *, int);
int ehc_write_pcf8583(struct ehc_envcunit *, int, uint8_t *, int);
static int ehc_start_pcf8584(struct ehc_envcunit *, uint8_t);
static void ehc_stop_pcf8584(struct ehc_envcunit *);
static int ehc_read_pcf8584(struct ehc_envcunit *, uint8_t *);
static int ehc_write_pcf8584(struct ehc_envcunit *, uint8_t);
static int ehc_after_read_pcf8584(struct ehc_envcunit *, uint8_t *);
static int
ehc_start_pcf8584(struct ehc_envcunit *ehcp, uint8_t byteaddress)
{
uint8_t poll_status;
uint8_t discard;
int i;
i = 0;
do {
drv_usecwait(1000);
poll_status =
ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
i++;
} while (((poll_status & EHC_S1_NBB) == 0) && i < EHC_MAX_WAIT);
if (i == EHC_MAX_WAIT) {
DCMN_ERR(CE_WARN, "ehc_start_pcf8584(): busy bit clear failed");
return (EHC_FAILURE);
}
if (poll_status & EHC_S1_BER) {
DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()1: Bus error");
ehc_init_pcf8584(ehcp);
return (EHC_FAILURE);
}
if (poll_status & EHC_S1_LAB) {
DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()1: Lost Arbitration");
ehc_init_pcf8584(ehcp);
return (EHC_FAILURE);
}
ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, DUMMY_WRITE_ADDR);
ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1,
EHC_S1_PIN | EHC_S1_ES0 | EHC_S1_STA | EHC_S1_ACK);
i = 0;
do {
drv_usecwait(1000);
poll_status =
ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
i++;
} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
if (i == EHC_MAX_WAIT) {
DCMN_ERR(CE_WARN, "ehc_start_pcf8584_5(): read of S1 failed");
return (EHC_FAILURE);
}
if (poll_status & EHC_S1_BER) {
DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()5: Bus error");
ehc_init_pcf8584(ehcp);
return (EHC_FAILURE);
}
if (poll_status & EHC_S1_LAB) {
DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()5: Lost Arbitration");
ehc_init_pcf8584(ehcp);
return (EHC_FAILURE);
}
ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, DUMMY_WRITE_DATA);
i = 0;
do {
drv_usecwait(1000);
poll_status =
ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
i++;
} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
if (i == EHC_MAX_WAIT) {
DCMN_ERR(CE_WARN, "ehc_start_pcf8584(): read of S1 failed");
return (EHC_FAILURE);
}
if (poll_status & EHC_S1_BER) {
DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()4: Bus error");
ehc_init_pcf8584(ehcp);
return (EHC_FAILURE);
}
if (poll_status & EHC_S1_LAB) {
DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()4: Lost Arbitration");
ehc_init_pcf8584(ehcp);
return (EHC_FAILURE);
}
ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1,
EHC_S1_ES0 | EHC_S1_STA | EHC_S1_ACK);
ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, byteaddress);
i = 0;
do {
drv_usecwait(1000);
poll_status =
ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
i++;
} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
if (i == EHC_MAX_WAIT) {
DCMN_ERR(CE_WARN, "ehc_start_pcf8584(): read of S1 failed");
return (EHC_FAILURE);
}
if (poll_status & EHC_S1_BER) {
DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()2: Bus error");
ehc_init_pcf8584(ehcp);
return (EHC_FAILURE);
}
if (poll_status & EHC_S1_LAB) {
DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()2: Lost Arbitration");
ehc_init_pcf8584(ehcp);
return (EHC_FAILURE);
}
if (poll_status & EHC_S1_LRB) {
DCMN_ERR(CE_WARN, "ehc_start_pcf8584(): No slave ACK");
return (EHC_NO_SLAVE_ACK);
}
i = 0;
if (byteaddress & EHC_BYTE_READ) {
discard = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
#ifdef lint
discard = discard;
#endif
do {
drv_usecwait(1000);
poll_status =
ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
i++;
} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
if (i == EHC_MAX_WAIT) {
DCMN_ERR(CE_WARN,
"ehc_start_pcf8584(): read of S1 failed");
return (EHC_FAILURE);
}
if (poll_status & EHC_S1_BER) {
DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()3: Bus error");
ehc_init_pcf8584(ehcp);
return (EHC_FAILURE);
}
if (poll_status & EHC_S1_LAB) {
DCMN2_ERR(CE_WARN,
"ehc_start_pcf8584()3: Lost Arbitration");
ehc_init_pcf8584(ehcp);
return (EHC_FAILURE);
}
}
return (EHC_SUCCESS);
}
static void
ehc_stop_pcf8584(struct ehc_envcunit *ehcp)
{
ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1,
EHC_S1_PIN | EHC_S1_ES0 | EHC_S1_STO | EHC_S1_ACK);
}
static int
ehc_read_pcf8584(struct ehc_envcunit *ehcp, uint8_t *data)
{
uint8_t poll_status;
int i = 0;
*data = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
do {
drv_usecwait(1000);
poll_status =
ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
i++;
} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
if (i == EHC_MAX_WAIT) {
DCMN_ERR(CE_WARN, "ehc_read_pcf8584(): read of S1 failed");
return (EHC_FAILURE);
}
if (poll_status & EHC_S1_BER) {
DCMN2_ERR(CE_WARN, "ehc_read_pcf8584(): Bus error");
ehc_init_pcf8584(ehcp);
return (EHC_FAILURE);
}
if (poll_status & EHC_S1_LAB) {
DCMN2_ERR(CE_WARN, "ehc_read_pcf8584(): Lost Arbitration");
ehc_init_pcf8584(ehcp);
return (EHC_FAILURE);
}
return (EHC_SUCCESS);
}
static int
ehc_write_pcf8584(struct ehc_envcunit *ehcp, uint8_t data)
{
uint8_t poll_status;
int i = 0;
ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, data);
do {
drv_usecwait(1000);
poll_status =
ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
i++;
} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
if (i == EHC_MAX_WAIT) {
DCMN_ERR(CE_WARN, "ehc_write_pcf8584(): read of S1 failed");
return (EHC_FAILURE);
}
if (poll_status & EHC_S1_BER) {
DCMN2_ERR(CE_WARN, "ehc_write_pcf8584(): Bus error");
ehc_init_pcf8584(ehcp);
return (EHC_FAILURE);
}
if (poll_status & EHC_S1_LAB) {
DCMN2_ERR(CE_WARN, "ehc_write_pcf8584(): Lost Arbitration");
ehc_init_pcf8584(ehcp);
return (EHC_FAILURE);
}
if (poll_status & EHC_S1_LRB) {
DCMN_ERR(CE_WARN, "ehc_write_pcf8584(): No slave ACK");
return (EHC_NO_SLAVE_ACK);
}
return (EHC_SUCCESS);
}
static int
ehc_after_read_pcf8584(struct ehc_envcunit *ehcp, uint8_t *data)
{
uint8_t discard;
uint8_t poll_status;
int i = 0;
ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1, EHC_S1_ES0);
*data = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
do {
drv_usecwait(1000);
poll_status =
ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
i++;
} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
if (i == EHC_MAX_WAIT) {
DCMN_ERR(CE_WARN, "ehc_after_rd_pcf8584(): read of S1 failed");
return (EHC_FAILURE);
}
if (poll_status & EHC_S1_BER) {
DCMN2_ERR(CE_WARN, "ehc_after_rd_pcf8584(): Bus error");
ehc_init_pcf8584(ehcp);
return (EHC_FAILURE);
}
if (poll_status & EHC_S1_LAB) {
DCMN2_ERR(CE_WARN, "ehc_after_rd_pcf8584(): Lost Arbitration");
ehc_init_pcf8584(ehcp);
return (EHC_FAILURE);
}
ehc_stop_pcf8584(ehcp);
discard = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
#ifdef lint
discard = discard;
#endif
return (EHC_SUCCESS);
}
void
ehc_init_pcf8584(struct ehc_envcunit *ehcp)
{
ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1, EHC_S1_PIN);
ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, EHC_S0_OWN);
ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1,
EHC_S1_PIN | EHC_S1_ES1);
ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, EHC_S0_CLK);
ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1,
EHC_S1_PIN | EHC_S1_ES0 | EHC_S1_ACK);
drv_usecwait(EHC_LONGEST_MSG);
}
int
ehc_read_tda8444(struct ehc_envcunit *ehcp)
{
#ifdef lint
ehcp = ehcp;
#endif
return (EHC_FAILURE);
}
int
ehc_write_tda8444(struct ehc_envcunit *ehcp, int byteaddress, int instruction,
int subaddress, uint8_t *buf, int size)
{
uint8_t control;
int i, status;
ASSERT((byteaddress & 0x1) == 0);
ASSERT(subaddress < 8);
ASSERT(instruction == 0xf || instruction == 0x0);
ASSERT(MUTEX_HELD(&ehcp->umutex));
control = (instruction << 4) | subaddress;
if ((status = ehc_start_pcf8584(ehcp, byteaddress)) != EHC_SUCCESS) {
if (status == EHC_NO_SLAVE_ACK) {
ehc_stop_pcf8584(ehcp);
}
return (EHC_FAILURE);
}
if ((status = ehc_write_pcf8584(ehcp, control)) != EHC_SUCCESS) {
if (status == EHC_NO_SLAVE_ACK) {
ehc_stop_pcf8584(ehcp);
}
return (EHC_FAILURE);
}
for (i = 0; i < size; i++) {
if ((status = ehc_write_pcf8584(ehcp, (buf[i] & 0x3f))) !=
EHC_SUCCESS) {
if (status == EHC_NO_SLAVE_ACK)
ehc_stop_pcf8584(ehcp);
return (EHC_FAILURE);
}
}
ehc_stop_pcf8584(ehcp);
return (EHC_SUCCESS);
}
int
ehc_read_pcf8574a(struct ehc_envcunit *ehcp, int byteaddress, uint8_t *buf,
int size)
{
int i;
int status;
uint8_t discard;
ASSERT((byteaddress & 0x1) == 0);
ASSERT(MUTEX_HELD(&ehcp->umutex));
if ((status = ehc_start_pcf8584(ehcp, EHC_BYTE_READ | byteaddress)) !=
EHC_SUCCESS) {
if (status == EHC_NO_SLAVE_ACK) {
ehc_stop_pcf8584(ehcp);
discard =
ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
#ifdef lint
discard = discard;
#endif
}
return (EHC_FAILURE);
}
for (i = 0; i < size - 1; i++) {
if ((status = ehc_read_pcf8584(ehcp, &buf[i])) != EHC_SUCCESS) {
return (EHC_FAILURE);
}
}
if (ehc_after_read_pcf8584(ehcp, &buf[i]) != EHC_SUCCESS) {
return (EHC_FAILURE);
}
return (EHC_SUCCESS);
}
int
ehc_write_pcf8574a(struct ehc_envcunit *ehcp, int byteaddress, uint8_t *buf,
int size)
{
int i;
int status;
ASSERT((byteaddress & 0x1) == 0);
ASSERT(MUTEX_HELD(&ehcp->umutex));
if ((status = ehc_start_pcf8584(ehcp, byteaddress)) != EHC_SUCCESS) {
if (status == EHC_NO_SLAVE_ACK) {
ehc_stop_pcf8584(ehcp);
}
return (EHC_FAILURE);
}
for (i = 0; i < size; i++) {
if ((status = ehc_write_pcf8584(ehcp, buf[i])) != EHC_SUCCESS) {
if (status == EHC_NO_SLAVE_ACK)
ehc_stop_pcf8584(ehcp);
return (EHC_FAILURE);
}
}
ehc_stop_pcf8584(ehcp);
return (EHC_SUCCESS);
}
int
ehc_read_pcf8574(struct ehc_envcunit *ehcp, int byteaddress, uint8_t *buf,
int size)
{
int i;
int status;
uint8_t discard;
ASSERT((byteaddress & 0x1) == 0);
ASSERT(MUTEX_HELD(&ehcp->umutex));
if ((status = ehc_start_pcf8584(ehcp, EHC_BYTE_READ | byteaddress)) !=
EHC_SUCCESS) {
if (status == EHC_NO_SLAVE_ACK) {
ehc_stop_pcf8584(ehcp);
discard =
ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
#ifdef lint
discard = discard;
#endif
}
return (EHC_FAILURE);
}
for (i = 0; i < size - 1; i++) {
if ((status = ehc_read_pcf8584(ehcp, &buf[i])) != EHC_SUCCESS) {
return (EHC_FAILURE);
}
}
if (ehc_after_read_pcf8584(ehcp, &buf[i]) != EHC_SUCCESS) {
return (EHC_FAILURE);
}
return (EHC_SUCCESS);
}
int
ehc_write_pcf8574(struct ehc_envcunit *ehcp, int byteaddress, uint8_t *buf,
int size)
{
int i;
int status;
ASSERT((byteaddress & 0x1) == 0);
ASSERT(MUTEX_HELD(&ehcp->umutex));
if ((status = ehc_start_pcf8584(ehcp, byteaddress)) != EHC_SUCCESS) {
if (status == EHC_NO_SLAVE_ACK) {
ehc_stop_pcf8584(ehcp);
}
return (EHC_FAILURE);
}
for (i = 0; i < size; i++) {
if ((status = ehc_write_pcf8584(ehcp, buf[i])) != EHC_SUCCESS) {
if (status == EHC_NO_SLAVE_ACK)
ehc_stop_pcf8584(ehcp);
return (EHC_FAILURE);
}
}
ehc_stop_pcf8584(ehcp);
return (EHC_SUCCESS);
}
int
ehc_read_lm75(struct ehc_envcunit *ehcp, int byteaddress, uint8_t *buf,
int size)
{
int i;
int status;
uint8_t discard;
ASSERT((byteaddress & 0x1) == 0);
ASSERT(MUTEX_HELD(&ehcp->umutex));
if ((status = ehc_start_pcf8584(ehcp, EHC_BYTE_READ | byteaddress)) !=
EHC_SUCCESS) {
if (status == EHC_NO_SLAVE_ACK) {
ehc_stop_pcf8584(ehcp);
discard =
ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
#ifdef lint
discard = discard;
#endif
}
return (EHC_FAILURE);
}
for (i = 0; i < size - 1; i++) {
if ((status = ehc_read_pcf8584(ehcp, &buf[i])) != EHC_SUCCESS) {
return (EHC_FAILURE);
}
}
if (ehc_after_read_pcf8584(ehcp, &buf[i]) != EHC_SUCCESS) {
return (EHC_FAILURE);
}
return (EHC_SUCCESS);
}
int
ehc_write_pcf8583(struct ehc_envcunit *ehcp, int byteaddress, uint8_t *buf,
int size)
{
int i;
int status;
ASSERT((byteaddress & 0x1) == 0);
ASSERT(MUTEX_HELD(&ehcp->umutex));
if ((status = ehc_start_pcf8584(ehcp, byteaddress)) != EHC_SUCCESS) {
if (status == EHC_NO_SLAVE_ACK) {
ehc_stop_pcf8584(ehcp);
}
return (EHC_FAILURE);
}
for (i = 0; i < size; i++) {
if ((status = ehc_write_pcf8584(ehcp, buf[i])) != EHC_SUCCESS) {
if (status == EHC_NO_SLAVE_ACK)
ehc_stop_pcf8584(ehcp);
return (EHC_FAILURE);
}
}
ehc_stop_pcf8584(ehcp);
return (EHC_SUCCESS);
}
int
ehc_read_pcf8591(struct ehc_envcunit *ehcp, int byteaddress, int channel,
int autoinc, int amode, int aenable, uint8_t *buf, int size)
{
int i;
int status;
register uint8_t control;
uint8_t discard;
ASSERT((byteaddress & 0x1) == 0);
ASSERT(channel < 4);
ASSERT(amode < 4);
ASSERT(MUTEX_HELD(&ehcp->umutex));
control = ((aenable << 6) | (amode << 4) | (autoinc << 2) | channel);
if ((status = ehc_start_pcf8584(ehcp, byteaddress)) != EHC_SUCCESS) {
if (status == EHC_NO_SLAVE_ACK) {
ehc_stop_pcf8584(ehcp);
}
return (EHC_FAILURE);
}
if ((status = ehc_write_pcf8584(ehcp, control)) != EHC_SUCCESS) {
if (status == EHC_NO_SLAVE_ACK)
ehc_stop_pcf8584(ehcp);
return (EHC_FAILURE);
}
ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1,
EHC_S1_ES0 | EHC_S1_STA | EHC_S1_ACK);
ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0,
EHC_BYTE_READ | byteaddress);
i = 0;
do {
drv_usecwait(1000);
status =
ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
i++;
} while ((status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
if (i == EHC_MAX_WAIT) {
DCMN_ERR(CE_WARN, "ehc_read_pcf8591(): read of S1 failed");
return (EHC_FAILURE);
}
if (status & EHC_S1_BER) {
DCMN2_ERR(CE_WARN, "ehc_read_pcf8591(): Bus error");
ehc_init_pcf8584(ehcp);
return (EHC_FAILURE);
}
if (status & EHC_S1_LAB) {
DCMN2_ERR(CE_WARN, "ehc_read_pcf8591(): Lost Arbitration");
ehc_init_pcf8584(ehcp);
return (EHC_FAILURE);
}
if (status & EHC_S1_LRB) {
DCMN_ERR(CE_WARN, "ehc_read_pcf8591(): No slave ACK");
ehc_stop_pcf8584(ehcp);
discard = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
#ifdef lint
discard = discard;
#endif
return (EHC_FAILURE);
}
if ((status = ehc_read_pcf8584(ehcp, &discard)) != EHC_SUCCESS) {
return (EHC_FAILURE);
}
if ((status = ehc_read_pcf8584(ehcp, &discard)) != EHC_SUCCESS) {
return (EHC_FAILURE);
}
for (i = 0; i < size - 1; i++) {
if ((status = ehc_read_pcf8584(ehcp, &buf[i])) != EHC_SUCCESS) {
return (EHC_FAILURE);
}
}
if (ehc_after_read_pcf8584(ehcp, &buf[i]) != EHC_SUCCESS) {
return (EHC_FAILURE);
}
return (EHC_SUCCESS);
}
int
ehc_write_pcf8591(struct ehc_envcunit *ehcp, int byteaddress, int channel,
int autoinc, int amode, int aenable, uint8_t *buf, int size)
{
int i, status;
register uint8_t control;
ASSERT((byteaddress & 0x1) == 0);
ASSERT(MUTEX_HELD(&ehcp->umutex));
control = ((aenable << 6) | (amode << 4) | (autoinc << 2) | channel);
status = ehc_start_pcf8584(ehcp, byteaddress);
if (status != EHC_SUCCESS) {
if (status == EHC_NO_SLAVE_ACK) {
ehc_stop_pcf8584(ehcp);
}
return (EHC_FAILURE);
}
if ((status = ehc_write_pcf8584(ehcp, control)) != EHC_SUCCESS) {
if (status == EHC_NO_SLAVE_ACK)
ehc_stop_pcf8584(ehcp);
return (EHC_FAILURE);
}
for (i = 0; i < size; i++) {
status = ehc_write_pcf8584(ehcp, buf[i]);
if (status != EHC_SUCCESS) {
if (status == EHC_NO_SLAVE_ACK)
ehc_stop_pcf8584(ehcp);
return (EHC_FAILURE);
}
}
ehc_stop_pcf8584(ehcp);
return (EHC_SUCCESS);
}