2002-03-23 15:49:15 +00:00
|
|
|
/*-
|
|
|
|
* Copyright (c) 2001 Alcove - Nicolas Souchu
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
2003-06-11 06:34:30 +00:00
|
|
|
|
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
2005-10-31 18:31:16 +00:00
|
|
|
#include "opt_isa.h"
|
|
|
|
|
2002-03-23 15:49:15 +00:00
|
|
|
#include <sys/param.h>
|
2007-01-11 19:56:24 +00:00
|
|
|
#include <sys/bus.h>
|
2002-03-23 15:49:15 +00:00
|
|
|
#include <sys/kernel.h>
|
2007-01-11 19:56:24 +00:00
|
|
|
#include <sys/lock.h>
|
2002-03-23 15:49:15 +00:00
|
|
|
#include <sys/module.h>
|
2007-01-11 19:56:24 +00:00
|
|
|
#include <sys/mutex.h>
|
|
|
|
#include <sys/systm.h>
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
#include <machine/bus.h>
|
|
|
|
#include <machine/resource.h>
|
|
|
|
#include <sys/rman.h>
|
|
|
|
|
2005-10-31 18:31:16 +00:00
|
|
|
#ifdef DEV_ISA
|
|
|
|
#include <isa/isavar.h>
|
|
|
|
#include <isa/isa_common.h>
|
|
|
|
#endif
|
2003-08-22 07:20:27 +00:00
|
|
|
#include <dev/pci/pcivar.h>
|
|
|
|
#include <dev/pci/pcireg.h>
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
#include <dev/iicbus/iiconf.h>
|
|
|
|
|
|
|
|
#include <dev/smbus/smbconf.h>
|
|
|
|
|
|
|
|
#include "iicbb_if.h"
|
|
|
|
#include "smbus_if.h"
|
|
|
|
|
|
|
|
#define VIAPM_DEBUG(x) if (viapm_debug) (x)
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
static int viapm_debug = 1;
|
|
|
|
#else
|
|
|
|
static int viapm_debug = 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define VIA_586B_PMU_ID 0x30401106
|
|
|
|
#define VIA_596A_PMU_ID 0x30501106
|
|
|
|
#define VIA_596B_PMU_ID 0x30511106
|
|
|
|
#define VIA_686A_PMU_ID 0x30571106
|
|
|
|
#define VIA_8233_PMU_ID 0x30741106
|
2003-06-22 06:50:02 +00:00
|
|
|
#define VIA_8233A_PMU_ID 0x31471106
|
2005-10-31 18:43:28 +00:00
|
|
|
#define VIA_8235_PMU_ID 0x31771106
|
2008-06-22 20:53:29 +00:00
|
|
|
#define VIA_8237_PMU_ID 0x32271106
|
2007-08-02 04:29:19 +00:00
|
|
|
#define VIA_CX700_PMU_ID 0x83241106
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
#define VIAPM_INB(port) \
|
2008-06-06 18:29:56 +00:00
|
|
|
((u_char)bus_read_1(viapm->iores, port))
|
2002-03-23 15:49:15 +00:00
|
|
|
#define VIAPM_OUTB(port,val) \
|
2008-06-06 18:29:56 +00:00
|
|
|
(bus_write_1(viapm->iores, port, (u_char)(val)))
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
#define VIAPM_TYP_UNKNOWN 0
|
|
|
|
#define VIAPM_TYP_586B_3040E 1
|
|
|
|
#define VIAPM_TYP_586B_3040F 2
|
|
|
|
#define VIAPM_TYP_596B 3
|
|
|
|
#define VIAPM_TYP_686A 4
|
|
|
|
#define VIAPM_TYP_8233 5
|
|
|
|
|
2007-01-11 19:56:24 +00:00
|
|
|
#define VIAPM_LOCK(sc) mtx_lock(&(sc)->lock)
|
|
|
|
#define VIAPM_UNLOCK(sc) mtx_unlock(&(sc)->lock)
|
|
|
|
#define VIAPM_LOCK_ASSERT(sc) mtx_assert(&(sc)->lock, MA_OWNED)
|
|
|
|
|
2002-03-23 15:49:15 +00:00
|
|
|
struct viapm_softc {
|
|
|
|
int type;
|
|
|
|
u_int32_t base;
|
|
|
|
int iorid;
|
|
|
|
int irqrid;
|
|
|
|
struct resource *iores;
|
|
|
|
struct resource *irqres;
|
|
|
|
void *irqih;
|
|
|
|
device_t iicbb;
|
|
|
|
device_t smbus;
|
2007-01-11 19:56:24 +00:00
|
|
|
struct mtx lock;
|
2002-03-23 15:49:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static devclass_t viapm_devclass;
|
|
|
|
static devclass_t viapropm_devclass;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* VT82C586B definitions
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define VIAPM_586B_REVID 0x08
|
|
|
|
|
|
|
|
#define VIAPM_586B_3040E_BASE 0x20
|
|
|
|
#define VIAPM_586B_3040E_ACTIV 0x4 /* 16 bits */
|
|
|
|
|
|
|
|
#define VIAPM_586B_3040F_BASE 0x48
|
|
|
|
#define VIAPM_586B_3040F_ACTIV 0x41 /* 8 bits */
|
|
|
|
|
|
|
|
#define VIAPM_586B_OEM_REV_E 0x00
|
|
|
|
#define VIAPM_586B_OEM_REV_F 0x01
|
|
|
|
#define VIAPM_586B_PROD_REV_A 0x10
|
|
|
|
|
|
|
|
#define VIAPM_586B_BA_MASK 0x0000ff00
|
|
|
|
|
|
|
|
#define GPIO_DIR 0x40
|
|
|
|
#define GPIO_VAL 0x42
|
|
|
|
#define EXTSMI_VAL 0x44
|
|
|
|
|
|
|
|
#define VIAPM_SCL 0x02 /* GPIO1_VAL */
|
|
|
|
#define VIAPM_SDA 0x04 /* GPIO2_VAL */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* VIAPRO common definitions
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define VIAPM_PRO_BA_MASK 0x0000fff0
|
|
|
|
#define VIAPM_PRO_SMBCTRL 0xd2
|
|
|
|
#define VIAPM_PRO_REVID 0xd6
|
|
|
|
|
|
|
|
/*
|
|
|
|
* VT82C686A definitions
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define VIAPM_PRO_BASE 0x90
|
|
|
|
|
|
|
|
#define SMBHST 0x0
|
|
|
|
#define SMBHSL 0x1
|
|
|
|
#define SMBHCTRL 0x2
|
|
|
|
#define SMBHCMD 0x3
|
|
|
|
#define SMBHADDR 0x4
|
|
|
|
#define SMBHDATA0 0x5
|
|
|
|
#define SMBHDATA1 0x6
|
|
|
|
#define SMBHBLOCK 0x7
|
|
|
|
|
|
|
|
#define SMBSST 0x1
|
|
|
|
#define SMBSCTRL 0x8
|
|
|
|
#define SMBSSDWCMD 0x9
|
|
|
|
#define SMBSEVENT 0xa
|
|
|
|
#define SMBSDATA 0xc
|
|
|
|
|
|
|
|
#define SMBHST_RESERVED 0xef /* reserved bits */
|
|
|
|
#define SMBHST_FAILED 0x10 /* failed bus transaction */
|
|
|
|
#define SMBHST_COLLID 0x08 /* bus collision */
|
|
|
|
#define SMBHST_ERROR 0x04 /* device error */
|
|
|
|
#define SMBHST_INTR 0x02 /* command completed */
|
|
|
|
#define SMBHST_BUSY 0x01 /* host busy */
|
|
|
|
|
|
|
|
#define SMBHCTRL_START 0x40 /* start command */
|
|
|
|
#define SMBHCTRL_PROTO 0x1c /* command protocol mask */
|
|
|
|
#define SMBHCTRL_QUICK 0x00
|
|
|
|
#define SMBHCTRL_SENDRECV 0x04
|
|
|
|
#define SMBHCTRL_BYTE 0x08
|
|
|
|
#define SMBHCTRL_WORD 0x0c
|
|
|
|
#define SMBHCTRL_BLOCK 0x14
|
|
|
|
#define SMBHCTRL_KILL 0x02 /* stop the current transaction */
|
|
|
|
#define SMBHCTRL_ENABLE 0x01 /* enable interrupts */
|
|
|
|
|
|
|
|
#define SMBSCTRL_ENABLE 0x01 /* enable slave */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* VIA8233 definitions
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define VIAPM_8233_BASE 0xD0
|
|
|
|
|
|
|
|
static int
|
|
|
|
viapm_586b_probe(device_t dev)
|
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
|
|
|
|
u_int32_t l;
|
|
|
|
u_int16_t s;
|
|
|
|
u_int8_t c;
|
|
|
|
|
|
|
|
switch (pci_get_devid(dev)) {
|
|
|
|
case VIA_586B_PMU_ID:
|
|
|
|
|
|
|
|
bzero(viapm, sizeof(struct viapm_softc));
|
|
|
|
|
|
|
|
l = pci_read_config(dev, VIAPM_586B_REVID, 1);
|
|
|
|
switch (l) {
|
|
|
|
case VIAPM_586B_OEM_REV_E:
|
|
|
|
viapm->type = VIAPM_TYP_586B_3040E;
|
|
|
|
viapm->iorid = VIAPM_586B_3040E_BASE;
|
|
|
|
|
|
|
|
/* Activate IO block access */
|
|
|
|
s = pci_read_config(dev, VIAPM_586B_3040E_ACTIV, 2);
|
|
|
|
pci_write_config(dev, VIAPM_586B_3040E_ACTIV, s | 0x1, 2);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIAPM_586B_OEM_REV_F:
|
|
|
|
case VIAPM_586B_PROD_REV_A:
|
|
|
|
default:
|
|
|
|
viapm->type = VIAPM_TYP_586B_3040F;
|
|
|
|
viapm->iorid = VIAPM_586B_3040F_BASE;
|
|
|
|
|
|
|
|
/* Activate IO block access */
|
|
|
|
c = pci_read_config(dev, VIAPM_586B_3040F_ACTIV, 1);
|
|
|
|
pci_write_config(dev, VIAPM_586B_3040F_ACTIV, c | 0x80, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
viapm->base = pci_read_config(dev, viapm->iorid, 4) &
|
|
|
|
VIAPM_586B_BA_MASK;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We have to set the I/O resources by hand because it is
|
|
|
|
* described outside the viapmope of the traditional maps
|
|
|
|
*/
|
|
|
|
if (bus_set_resource(dev, SYS_RES_IOPORT, viapm->iorid,
|
|
|
|
viapm->base, 256)) {
|
|
|
|
device_printf(dev, "could not set bus resource\n");
|
|
|
|
return ENXIO;
|
|
|
|
}
|
|
|
|
device_set_desc(dev, "VIA VT82C586B Power Management Unit");
|
2005-02-24 21:32:56 +00:00
|
|
|
return (BUS_PROBE_DEFAULT);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
viapm_pro_probe(device_t dev)
|
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
|
|
|
|
#ifdef VIAPM_BASE_ADDR
|
|
|
|
u_int32_t l;
|
|
|
|
#endif
|
|
|
|
u_int32_t base_cfgreg;
|
|
|
|
char *desc;
|
|
|
|
|
|
|
|
switch (pci_get_devid(dev)) {
|
|
|
|
case VIA_596A_PMU_ID:
|
|
|
|
desc = "VIA VT82C596A Power Management Unit";
|
|
|
|
viapm->type = VIAPM_TYP_596B;
|
|
|
|
base_cfgreg = VIAPM_PRO_BASE;
|
|
|
|
goto viapro;
|
|
|
|
|
|
|
|
case VIA_596B_PMU_ID:
|
|
|
|
desc = "VIA VT82C596B Power Management Unit";
|
|
|
|
viapm->type = VIAPM_TYP_596B;
|
|
|
|
base_cfgreg = VIAPM_PRO_BASE;
|
|
|
|
goto viapro;
|
|
|
|
|
|
|
|
case VIA_686A_PMU_ID:
|
|
|
|
desc = "VIA VT82C686A Power Management Unit";
|
|
|
|
viapm->type = VIAPM_TYP_686A;
|
|
|
|
base_cfgreg = VIAPM_PRO_BASE;
|
|
|
|
goto viapro;
|
|
|
|
|
|
|
|
case VIA_8233_PMU_ID:
|
2003-06-22 06:50:02 +00:00
|
|
|
case VIA_8233A_PMU_ID:
|
2002-03-23 15:49:15 +00:00
|
|
|
desc = "VIA VT8233 Power Management Unit";
|
|
|
|
viapm->type = VIAPM_TYP_UNKNOWN;
|
|
|
|
base_cfgreg = VIAPM_8233_BASE;
|
|
|
|
goto viapro;
|
|
|
|
|
2005-10-31 18:43:28 +00:00
|
|
|
case VIA_8235_PMU_ID:
|
|
|
|
desc = "VIA VT8235 Power Management Unit";
|
|
|
|
viapm->type = VIAPM_TYP_UNKNOWN;
|
|
|
|
base_cfgreg = VIAPM_8233_BASE;
|
|
|
|
goto viapro;
|
|
|
|
|
2008-06-22 20:53:29 +00:00
|
|
|
case VIA_8237_PMU_ID:
|
|
|
|
desc = "VIA VT8237 Power Management Unit";
|
|
|
|
viapm->type = VIAPM_TYP_UNKNOWN;
|
|
|
|
base_cfgreg = VIAPM_8233_BASE;
|
|
|
|
goto viapro;
|
|
|
|
|
2007-08-02 04:29:19 +00:00
|
|
|
case VIA_CX700_PMU_ID:
|
|
|
|
desc = "VIA CX700 Power Management Unit";
|
|
|
|
viapm->type = VIAPM_TYP_UNKNOWN;
|
|
|
|
base_cfgreg = VIAPM_8233_BASE;
|
|
|
|
goto viapro;
|
|
|
|
|
2002-03-23 15:49:15 +00:00
|
|
|
viapro:
|
|
|
|
|
|
|
|
#ifdef VIAPM_BASE_ADDR
|
|
|
|
/* force VIAPM I/O base address */
|
|
|
|
|
|
|
|
/* enable the SMBus controller function */
|
|
|
|
l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
|
|
|
|
pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 1, 1);
|
|
|
|
|
|
|
|
/* write the base address */
|
|
|
|
pci_write_config(dev, base_cfgreg,
|
|
|
|
VIAPM_BASE_ADDR & VIAPM_PRO_BA_MASK, 4);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
viapm->base = pci_read_config(dev, base_cfgreg, 4) & VIAPM_PRO_BA_MASK;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We have to set the I/O resources by hand because it is
|
|
|
|
* described outside the viapmope of the traditional maps
|
|
|
|
*/
|
|
|
|
viapm->iorid = base_cfgreg;
|
|
|
|
if (bus_set_resource(dev, SYS_RES_IOPORT, viapm->iorid,
|
|
|
|
viapm->base, 16)) {
|
|
|
|
device_printf(dev, "could not set bus resource 0x%x\n",
|
|
|
|
viapm->base);
|
|
|
|
return ENXIO;
|
|
|
|
}
|
|
|
|
|
2007-08-02 04:29:19 +00:00
|
|
|
if (bootverbose) {
|
2002-03-23 15:49:15 +00:00
|
|
|
device_printf(dev, "SMBus I/O base at 0x%x\n", viapm->base);
|
|
|
|
}
|
|
|
|
|
|
|
|
device_set_desc(dev, desc);
|
2005-02-24 21:32:56 +00:00
|
|
|
return (BUS_PROBE_DEFAULT);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
viapm_pro_attach(device_t dev)
|
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
|
|
|
|
u_int32_t l;
|
|
|
|
|
2007-01-11 19:56:24 +00:00
|
|
|
mtx_init(&viapm->lock, device_get_nameunit(dev), "viapm", MTX_DEF);
|
2004-03-17 17:50:55 +00:00
|
|
|
if (!(viapm->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
|
|
|
|
&viapm->iorid, RF_ACTIVE))) {
|
2002-03-23 15:49:15 +00:00
|
|
|
device_printf(dev, "could not allocate bus space\n");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2005-12-04 10:06:06 +00:00
|
|
|
#ifdef notyet
|
2002-03-23 15:49:15 +00:00
|
|
|
/* force irq 9 */
|
|
|
|
l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
|
|
|
|
pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 0x80, 1);
|
|
|
|
|
|
|
|
viapm->irqrid = 0;
|
|
|
|
if (!(viapm->irqres = bus_alloc_resource(dev, SYS_RES_IRQ,
|
|
|
|
&viapm->irqrid, 9, 9, 1,
|
|
|
|
RF_SHAREABLE | RF_ACTIVE))) {
|
|
|
|
device_printf(dev, "could not allocate irq\n");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2008-06-06 18:29:56 +00:00
|
|
|
if (bus_setup_intr(dev, viapm->irqres, INTR_TYPE_MISC | INTR_MPSAFE,
|
2002-03-23 15:49:15 +00:00
|
|
|
(driver_intr_t *) viasmb_intr, viapm, &viapm->irqih)) {
|
|
|
|
device_printf(dev, "could not setup irq\n");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-08-02 04:29:19 +00:00
|
|
|
if (bootverbose) {
|
2002-03-23 15:49:15 +00:00
|
|
|
l = pci_read_config(dev, VIAPM_PRO_REVID, 1);
|
|
|
|
device_printf(dev, "SMBus revision code 0x%x\n", l);
|
|
|
|
}
|
|
|
|
|
|
|
|
viapm->smbus = device_add_child(dev, "smbus", -1);
|
|
|
|
|
|
|
|
/* probe and attach the smbus */
|
|
|
|
bus_generic_attach(dev);
|
|
|
|
|
|
|
|
/* disable slave function */
|
|
|
|
VIAPM_OUTB(SMBSCTRL, VIAPM_INB(SMBSCTRL) & ~SMBSCTRL_ENABLE);
|
|
|
|
|
|
|
|
/* enable the SMBus controller function */
|
|
|
|
l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
|
|
|
|
pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 1, 1);
|
|
|
|
|
2005-12-04 10:06:06 +00:00
|
|
|
#ifdef notyet
|
2002-03-23 15:49:15 +00:00
|
|
|
/* enable interrupts */
|
|
|
|
VIAPM_OUTB(SMBHCTRL, VIAPM_INB(SMBHCTRL) | SMBHCTRL_ENABLE);
|
|
|
|
#endif
|
|
|
|
|
2005-10-31 18:31:16 +00:00
|
|
|
#ifdef DEV_ISA
|
|
|
|
/* If this device is a PCI-ISA bridge, then attach an ISA bus. */
|
|
|
|
if ((pci_get_class(dev) == PCIC_BRIDGE) &&
|
|
|
|
(pci_get_subclass(dev) == PCIS_BRIDGE_ISA))
|
|
|
|
isab_attach(dev);
|
|
|
|
#endif
|
2002-03-23 15:49:15 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
if (viapm->iores)
|
|
|
|
bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, viapm->iores);
|
2005-12-04 10:06:06 +00:00
|
|
|
#ifdef notyet
|
2002-03-23 15:49:15 +00:00
|
|
|
if (viapm->irqres)
|
|
|
|
bus_release_resource(dev, SYS_RES_IRQ, viapm->irqrid, viapm->irqres);
|
|
|
|
#endif
|
2007-01-11 19:56:24 +00:00
|
|
|
mtx_destroy(&viapm->lock);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
return ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
viapm_586b_attach(device_t dev)
|
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
|
2007-01-11 19:56:24 +00:00
|
|
|
|
|
|
|
mtx_init(&viapm->lock, device_get_nameunit(dev), "viapm", MTX_DEF);
|
2004-03-17 17:50:55 +00:00
|
|
|
if (!(viapm->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
|
|
|
|
&viapm->iorid, RF_ACTIVE | RF_SHAREABLE))) {
|
2002-03-23 15:49:15 +00:00
|
|
|
device_printf(dev, "could not allocate bus resource\n");
|
2007-01-11 19:56:24 +00:00
|
|
|
goto error;
|
2002-03-23 15:49:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VIAPM_OUTB(GPIO_DIR, VIAPM_INB(GPIO_DIR) | VIAPM_SCL | VIAPM_SDA);
|
|
|
|
|
|
|
|
/* add generic bit-banging code */
|
|
|
|
if (!(viapm->iicbb = device_add_child(dev, "iicbb", -1)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
bus_generic_attach(dev);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
if (viapm->iores)
|
|
|
|
bus_release_resource(dev, SYS_RES_IOPORT,
|
|
|
|
viapm->iorid, viapm->iores);
|
2007-01-11 19:56:24 +00:00
|
|
|
mtx_destroy(&viapm->lock);
|
2002-03-23 15:49:15 +00:00
|
|
|
return ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
viapm_586b_detach(device_t dev)
|
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
|
|
|
|
|
|
|
|
bus_generic_detach(dev);
|
|
|
|
if (viapm->iicbb) {
|
|
|
|
device_delete_child(dev, viapm->iicbb);
|
|
|
|
}
|
|
|
|
|
2007-01-11 19:56:24 +00:00
|
|
|
if (viapm->iores)
|
|
|
|
bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid,
|
|
|
|
viapm->iores);
|
|
|
|
mtx_destroy(&viapm->lock);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
viapm_pro_detach(device_t dev)
|
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
|
|
|
|
|
|
|
|
bus_generic_detach(dev);
|
|
|
|
if (viapm->smbus) {
|
|
|
|
device_delete_child(dev, viapm->smbus);
|
|
|
|
}
|
|
|
|
|
2007-01-11 19:56:24 +00:00
|
|
|
bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, viapm->iores);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
2005-12-04 10:06:06 +00:00
|
|
|
#ifdef notyet
|
2007-01-11 19:56:24 +00:00
|
|
|
bus_release_resource(dev, SYS_RES_IRQ, viapm->irqrid, viapm->irqres);
|
2002-03-23 15:49:15 +00:00
|
|
|
#endif
|
2007-01-11 19:56:24 +00:00
|
|
|
mtx_destroy(&viapm->lock);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2009-03-03 18:54:57 +00:00
|
|
|
viabb_callback(device_t dev, int index, caddr_t data)
|
2002-03-23 15:49:15 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
viabb_setscl(device_t dev, int ctrl)
|
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = device_get_softc(dev);
|
|
|
|
u_char val;
|
|
|
|
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_LOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
val = VIAPM_INB(GPIO_VAL);
|
|
|
|
|
|
|
|
if (ctrl)
|
|
|
|
val |= VIAPM_SCL;
|
|
|
|
else
|
|
|
|
val &= ~VIAPM_SCL;
|
|
|
|
|
|
|
|
VIAPM_OUTB(GPIO_VAL, val);
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_UNLOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
viabb_setsda(device_t dev, int data)
|
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = device_get_softc(dev);
|
|
|
|
u_char val;
|
|
|
|
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_LOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
val = VIAPM_INB(GPIO_VAL);
|
|
|
|
|
|
|
|
if (data)
|
|
|
|
val |= VIAPM_SDA;
|
|
|
|
else
|
|
|
|
val &= ~VIAPM_SDA;
|
|
|
|
|
|
|
|
VIAPM_OUTB(GPIO_VAL, val);
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_UNLOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
viabb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
|
|
|
|
{
|
|
|
|
/* reset bus */
|
|
|
|
viabb_setsda(dev, 1);
|
|
|
|
viabb_setscl(dev, 1);
|
|
|
|
|
|
|
|
return (IIC_ENOADDR);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
viabb_getscl(device_t dev)
|
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = device_get_softc(dev);
|
2007-01-11 19:56:24 +00:00
|
|
|
u_char val;
|
2002-03-23 15:49:15 +00:00
|
|
|
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_LOCK(viapm);
|
|
|
|
val = VIAPM_INB(EXTSMI_VAL);
|
|
|
|
VIAPM_UNLOCK(viapm);
|
|
|
|
return ((val & VIAPM_SCL) != 0);
|
2002-03-23 15:49:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
viabb_getsda(device_t dev)
|
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = device_get_softc(dev);
|
2007-01-11 19:56:24 +00:00
|
|
|
u_char val;
|
2002-03-23 15:49:15 +00:00
|
|
|
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_LOCK(viapm);
|
|
|
|
val = VIAPM_INB(EXTSMI_VAL);
|
|
|
|
VIAPM_UNLOCK(viapm);
|
|
|
|
return ((val & VIAPM_SDA) != 0);
|
2002-03-23 15:49:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
viapm_abort(struct viapm_softc *viapm)
|
|
|
|
{
|
|
|
|
VIAPM_OUTB(SMBHCTRL, SMBHCTRL_KILL);
|
|
|
|
DELAY(10);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
viapm_clear(struct viapm_softc *viapm)
|
|
|
|
{
|
|
|
|
VIAPM_OUTB(SMBHST, SMBHST_FAILED | SMBHST_COLLID |
|
|
|
|
SMBHST_ERROR | SMBHST_INTR);
|
|
|
|
DELAY(10);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
viapm_busy(struct viapm_softc *viapm)
|
|
|
|
{
|
|
|
|
u_char sts;
|
|
|
|
|
|
|
|
sts = VIAPM_INB(SMBHST);
|
|
|
|
|
|
|
|
VIAPM_DEBUG(printf("viapm: idle? STS=0x%x\n", sts));
|
|
|
|
|
|
|
|
return (sts & SMBHST_BUSY);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Poll the SMBus controller
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
viapm_wait(struct viapm_softc *viapm)
|
|
|
|
{
|
|
|
|
int count = 10000;
|
|
|
|
u_char sts = 0;
|
|
|
|
int error;
|
|
|
|
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_LOCK_ASSERT(viapm);
|
|
|
|
|
2002-03-23 15:49:15 +00:00
|
|
|
/* wait for command to complete and SMBus controller is idle */
|
|
|
|
while(count--) {
|
|
|
|
DELAY(10);
|
|
|
|
sts = VIAPM_INB(SMBHST);
|
|
|
|
|
|
|
|
/* check if the controller is processing a command */
|
|
|
|
if (!(sts & SMBHST_BUSY) && (sts & SMBHST_INTR))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIAPM_DEBUG(printf("viapm: SMBHST=0x%x\n", sts));
|
|
|
|
|
|
|
|
error = SMB_ENOERR;
|
|
|
|
|
|
|
|
if (!count)
|
|
|
|
error |= SMB_ETIMEOUT;
|
|
|
|
|
|
|
|
if (sts & SMBHST_FAILED)
|
|
|
|
error |= SMB_EABORT;
|
|
|
|
|
|
|
|
if (sts & SMBHST_COLLID)
|
|
|
|
error |= SMB_ENOACK;
|
|
|
|
|
|
|
|
if (sts & SMBHST_ERROR)
|
|
|
|
error |= SMB_EBUSERR;
|
|
|
|
|
|
|
|
if (error != SMB_ENOERR)
|
|
|
|
viapm_abort(viapm);
|
|
|
|
|
|
|
|
viapm_clear(viapm);
|
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2009-03-03 18:54:57 +00:00
|
|
|
viasmb_callback(device_t dev, int index, void *data)
|
2002-03-23 15:49:15 +00:00
|
|
|
{
|
|
|
|
int error = 0;
|
|
|
|
|
|
|
|
switch (index) {
|
|
|
|
case SMB_REQUEST_BUS:
|
|
|
|
case SMB_RELEASE_BUS:
|
|
|
|
/* ok, bus allocation accepted */
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error = EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
viasmb_quick(device_t dev, u_char slave, int how)
|
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
|
|
|
|
int error;
|
|
|
|
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_LOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
viapm_clear(viapm);
|
2007-01-11 19:56:24 +00:00
|
|
|
if (viapm_busy(viapm)) {
|
|
|
|
VIAPM_UNLOCK(viapm);
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
return (SMB_EBUSY);
|
2007-01-11 19:56:24 +00:00
|
|
|
}
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
switch (how) {
|
|
|
|
case SMB_QWRITE:
|
|
|
|
VIAPM_DEBUG(printf("viapm: QWRITE to 0x%x", slave));
|
|
|
|
VIAPM_OUTB(SMBHADDR, slave & ~LSB);
|
|
|
|
break;
|
|
|
|
case SMB_QREAD:
|
|
|
|
VIAPM_DEBUG(printf("viapm: QREAD to 0x%x", slave));
|
|
|
|
VIAPM_OUTB(SMBHADDR, slave | LSB);
|
|
|
|
break;
|
|
|
|
default:
|
2004-09-22 17:16:04 +00:00
|
|
|
panic("%s: unknown QUICK command (%x)!", __func__, how);
|
2002-03-23 15:49:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_QUICK);
|
|
|
|
|
|
|
|
error = viapm_wait(viapm);
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_UNLOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
viasmb_sendb(device_t dev, u_char slave, char byte)
|
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
|
|
|
|
int error;
|
|
|
|
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_LOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
viapm_clear(viapm);
|
2007-01-11 19:56:24 +00:00
|
|
|
if (viapm_busy(viapm)) {
|
|
|
|
VIAPM_UNLOCK(viapm);
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
return (SMB_EBUSY);
|
2007-01-11 19:56:24 +00:00
|
|
|
}
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
|
|
|
|
VIAPM_OUTB(SMBHCMD, byte);
|
|
|
|
|
|
|
|
VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_SENDRECV);
|
|
|
|
|
|
|
|
error = viapm_wait(viapm);
|
|
|
|
|
|
|
|
VIAPM_DEBUG(printf("viapm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_UNLOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
viasmb_recvb(device_t dev, u_char slave, char *byte)
|
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
|
|
|
|
int error;
|
|
|
|
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_LOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
viapm_clear(viapm);
|
2007-01-11 19:56:24 +00:00
|
|
|
if (viapm_busy(viapm)) {
|
|
|
|
VIAPM_UNLOCK(viapm);
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
return (SMB_EBUSY);
|
2007-01-11 19:56:24 +00:00
|
|
|
}
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
VIAPM_OUTB(SMBHADDR, slave | LSB);
|
|
|
|
|
|
|
|
VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_SENDRECV);
|
|
|
|
|
|
|
|
if ((error = viapm_wait(viapm)) == SMB_ENOERR)
|
|
|
|
*byte = VIAPM_INB(SMBHDATA0);
|
|
|
|
|
|
|
|
VIAPM_DEBUG(printf("viapm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_UNLOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
viasmb_writeb(device_t dev, u_char slave, char cmd, char byte)
|
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
|
|
|
|
int error;
|
|
|
|
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_LOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
viapm_clear(viapm);
|
2007-01-11 19:56:24 +00:00
|
|
|
if (viapm_busy(viapm)) {
|
|
|
|
VIAPM_UNLOCK(viapm);
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
return (SMB_EBUSY);
|
2007-01-11 19:56:24 +00:00
|
|
|
}
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
|
|
|
|
VIAPM_OUTB(SMBHCMD, cmd);
|
|
|
|
VIAPM_OUTB(SMBHDATA0, byte);
|
|
|
|
|
|
|
|
VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BYTE);
|
|
|
|
|
|
|
|
error = viapm_wait(viapm);
|
|
|
|
|
|
|
|
VIAPM_DEBUG(printf("viapm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_UNLOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
viasmb_readb(device_t dev, u_char slave, char cmd, char *byte)
|
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
|
|
|
|
int error;
|
|
|
|
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_LOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
viapm_clear(viapm);
|
2007-01-11 19:56:24 +00:00
|
|
|
if (viapm_busy(viapm)) {
|
|
|
|
VIAPM_UNLOCK(viapm);
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
return (SMB_EBUSY);
|
2007-01-11 19:56:24 +00:00
|
|
|
}
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
VIAPM_OUTB(SMBHADDR, slave | LSB);
|
|
|
|
VIAPM_OUTB(SMBHCMD, cmd);
|
|
|
|
|
|
|
|
VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BYTE);
|
|
|
|
|
|
|
|
if ((error = viapm_wait(viapm)) == SMB_ENOERR)
|
|
|
|
*byte = VIAPM_INB(SMBHDATA0);
|
|
|
|
|
|
|
|
VIAPM_DEBUG(printf("viapm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_UNLOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
viasmb_writew(device_t dev, u_char slave, char cmd, short word)
|
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
|
|
|
|
int error;
|
|
|
|
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_LOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
viapm_clear(viapm);
|
2007-01-11 19:56:24 +00:00
|
|
|
if (viapm_busy(viapm)) {
|
|
|
|
VIAPM_UNLOCK(viapm);
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
return (SMB_EBUSY);
|
2007-01-11 19:56:24 +00:00
|
|
|
}
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
|
|
|
|
VIAPM_OUTB(SMBHCMD, cmd);
|
|
|
|
VIAPM_OUTB(SMBHDATA0, word & 0x00ff);
|
|
|
|
VIAPM_OUTB(SMBHDATA1, (word & 0xff00) >> 8);
|
|
|
|
|
|
|
|
VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_WORD);
|
|
|
|
|
|
|
|
error = viapm_wait(viapm);
|
|
|
|
|
|
|
|
VIAPM_DEBUG(printf("viapm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_UNLOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
viasmb_readw(device_t dev, u_char slave, char cmd, short *word)
|
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
|
|
|
|
int error;
|
|
|
|
u_char high, low;
|
|
|
|
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_LOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
viapm_clear(viapm);
|
2007-01-11 19:56:24 +00:00
|
|
|
if (viapm_busy(viapm)) {
|
|
|
|
VIAPM_UNLOCK(viapm);
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
return (SMB_EBUSY);
|
2007-01-11 19:56:24 +00:00
|
|
|
}
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
VIAPM_OUTB(SMBHADDR, slave | LSB);
|
|
|
|
VIAPM_OUTB(SMBHCMD, cmd);
|
|
|
|
|
|
|
|
VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_WORD);
|
|
|
|
|
|
|
|
if ((error = viapm_wait(viapm)) == SMB_ENOERR) {
|
|
|
|
low = VIAPM_INB(SMBHDATA0);
|
|
|
|
high = VIAPM_INB(SMBHDATA1);
|
|
|
|
|
|
|
|
*word = ((high & 0xff) << 8) | (low & 0xff);
|
|
|
|
}
|
|
|
|
|
|
|
|
VIAPM_DEBUG(printf("viapm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_UNLOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
viasmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
|
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
u_char i;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (count < 1 || count > 32)
|
|
|
|
return (SMB_EINVAL);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_LOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
viapm_clear(viapm);
|
2007-01-11 19:56:24 +00:00
|
|
|
if (viapm_busy(viapm)) {
|
|
|
|
VIAPM_UNLOCK(viapm);
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
return (SMB_EBUSY);
|
2007-01-11 19:56:24 +00:00
|
|
|
}
|
2002-03-23 15:49:15 +00:00
|
|
|
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
VIAPM_OUTB(SMBHADDR, slave & ~LSB);
|
|
|
|
VIAPM_OUTB(SMBHCMD, cmd);
|
|
|
|
VIAPM_OUTB(SMBHDATA0, count);
|
|
|
|
i = VIAPM_INB(SMBHCTRL);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
/* fill the 32-byte internal buffer */
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
VIAPM_OUTB(SMBHBLOCK, buf[i]);
|
|
|
|
DELAY(2);
|
2002-03-23 15:49:15 +00:00
|
|
|
}
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
VIAPM_OUTB(SMBHCMD, cmd);
|
|
|
|
VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK);
|
|
|
|
|
|
|
|
error = viapm_wait(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
VIAPM_DEBUG(printf("viapm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_UNLOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
viasmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
|
2002-03-23 15:49:15 +00:00
|
|
|
{
|
|
|
|
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
u_char data, len, i;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (*count < 1 || *count > 32)
|
|
|
|
return (SMB_EINVAL);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_LOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
viapm_clear(viapm);
|
2007-01-11 19:56:24 +00:00
|
|
|
if (viapm_busy(viapm)) {
|
|
|
|
VIAPM_UNLOCK(viapm);
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
return (SMB_EBUSY);
|
2007-01-11 19:56:24 +00:00
|
|
|
}
|
2002-03-23 15:49:15 +00:00
|
|
|
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
VIAPM_OUTB(SMBHADDR, slave | LSB);
|
|
|
|
VIAPM_OUTB(SMBHCMD, cmd);
|
|
|
|
VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
if ((error = viapm_wait(viapm)) != SMB_ENOERR)
|
|
|
|
goto error;
|
2002-03-23 15:49:15 +00:00
|
|
|
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
len = VIAPM_INB(SMBHDATA0);
|
|
|
|
i = VIAPM_INB(SMBHCTRL); /* reset counter */
|
2002-03-23 15:49:15 +00:00
|
|
|
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
/* read the 32-byte internal buffer */
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
data = VIAPM_INB(SMBHBLOCK);
|
|
|
|
if (i < *count)
|
|
|
|
buf[i] = data;
|
|
|
|
DELAY(2);
|
2002-03-23 15:49:15 +00:00
|
|
|
}
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
*count = len;
|
|
|
|
|
2002-03-23 15:49:15 +00:00
|
|
|
error:
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
VIAPM_DEBUG(printf("viapm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error));
|
2007-01-11 19:56:24 +00:00
|
|
|
VIAPM_UNLOCK(viapm);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static device_method_t viapm_methods[] = {
|
|
|
|
/* device interface */
|
|
|
|
DEVMETHOD(device_probe, viapm_586b_probe),
|
|
|
|
DEVMETHOD(device_attach, viapm_586b_attach),
|
|
|
|
DEVMETHOD(device_detach, viapm_586b_detach),
|
|
|
|
|
|
|
|
/* iicbb interface */
|
|
|
|
DEVMETHOD(iicbb_callback, viabb_callback),
|
|
|
|
DEVMETHOD(iicbb_setscl, viabb_setscl),
|
|
|
|
DEVMETHOD(iicbb_setsda, viabb_setsda),
|
|
|
|
DEVMETHOD(iicbb_getscl, viabb_getscl),
|
|
|
|
DEVMETHOD(iicbb_getsda, viabb_getsda),
|
|
|
|
DEVMETHOD(iicbb_reset, viabb_reset),
|
|
|
|
|
2005-10-31 18:31:16 +00:00
|
|
|
/* Bus interface */
|
|
|
|
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
|
|
|
|
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
|
|
|
|
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
|
|
|
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
|
|
|
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
|
|
|
|
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
|
|
|
|
2011-11-22 21:28:20 +00:00
|
|
|
DEVMETHOD_END
|
2002-03-23 15:49:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static driver_t viapm_driver = {
|
|
|
|
"viapm",
|
|
|
|
viapm_methods,
|
|
|
|
sizeof(struct viapm_softc),
|
|
|
|
};
|
|
|
|
|
|
|
|
static device_method_t viapropm_methods[] = {
|
|
|
|
/* device interface */
|
|
|
|
DEVMETHOD(device_probe, viapm_pro_probe),
|
|
|
|
DEVMETHOD(device_attach, viapm_pro_attach),
|
|
|
|
DEVMETHOD(device_detach, viapm_pro_detach),
|
|
|
|
|
|
|
|
/* smbus interface */
|
|
|
|
DEVMETHOD(smbus_callback, viasmb_callback),
|
|
|
|
DEVMETHOD(smbus_quick, viasmb_quick),
|
|
|
|
DEVMETHOD(smbus_sendb, viasmb_sendb),
|
|
|
|
DEVMETHOD(smbus_recvb, viasmb_recvb),
|
|
|
|
DEVMETHOD(smbus_writeb, viasmb_writeb),
|
|
|
|
DEVMETHOD(smbus_readb, viasmb_readb),
|
|
|
|
DEVMETHOD(smbus_writew, viasmb_writew),
|
|
|
|
DEVMETHOD(smbus_readw, viasmb_readw),
|
|
|
|
DEVMETHOD(smbus_bwrite, viasmb_bwrite),
|
|
|
|
DEVMETHOD(smbus_bread, viasmb_bread),
|
|
|
|
|
2005-10-31 18:31:16 +00:00
|
|
|
/* Bus interface */
|
|
|
|
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
|
|
|
|
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
|
|
|
|
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
|
|
|
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
|
|
|
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
|
|
|
|
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
|
|
|
|
2011-11-22 21:28:20 +00:00
|
|
|
DEVMETHOD_END
|
2002-03-23 15:49:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static driver_t viapropm_driver = {
|
|
|
|
"viapropm",
|
|
|
|
viapropm_methods,
|
|
|
|
sizeof(struct viapm_softc),
|
|
|
|
};
|
|
|
|
|
|
|
|
DRIVER_MODULE(viapm, pci, viapm_driver, viapm_devclass, 0, 0);
|
|
|
|
DRIVER_MODULE(viapropm, pci, viapropm_driver, viapropm_devclass, 0, 0);
|
2008-08-04 20:46:15 +00:00
|
|
|
DRIVER_MODULE(iicbb, viapm, iicbb_driver, iicbb_devclass, 0, 0);
|
Minor overhaul of SMBus support:
- Change smbus_callback() to pass a void * rather than caddr_t.
- Change smbus_bread() to pass a pointer to the count and have it be an
in/out parameter. The input is the size of the buffer (same as before),
but on return it will contain the actual amount of data read back from
the bus. Note that this value may be larger than the input value. It
is up to the caller to treat this as an error if desired.
- Change the SMB_BREAD ioctl to write out the updated struct smbcmd which
will contain the actual number of bytes read in the 'count' field. To
preserve the previous ABI, the old ioctl value is mapped to SMB_OLD_BREAD
which doesn't copy the updated smbcmd back out to userland. I doubt anyone
actually used the old BREAD anyway as it was rediculous to do a bulk-read
but not tell the using program how much data was actually read.
- Make the smbus driver and devclass public in the smbus module and
push all the DRIVER_MODULE()'s for attaching the smbus driver to
various foosmb drivers out into the foosmb modules. This makes all
the foosmb logic centralized and allows new foosmb modules to be
self-contained w/o having to hack smbus.c everytime a new smbus driver
is added.
- Add a new SMB_EINVAL error bit and use it in place of EINVAL to return
an error for bad arguments (such as invalid counts for bread and bwrite).
- Map SMB bus error bits to EIO in smbus_error().
- Make the smbus driver call bus_generic_probe() and require child drivers
such as smb(4) to create device_t's via identify routines. Previously,
smbus just created one anonymous device during attach, and if you had
multiple drivers that could attach it was just random chance as to which
driver got to probe for the sole device_t first.
- Add a mutex to the smbus(4) softc and use it in place of dummy splhigh()
to protect the 'owner' field and perform necessary synchronization for
smbus_request_bus() and smbus_release_bus().
- Change the bread() and bwrite() methods of alpm(4), amdpm(4), and
viapm(4) to only perform a single transaction and not try to use a
loop of multiple transactions for a large request. The framing and
commands to use for a large transaction depend on the upper-layer
protocol (such as SSIF for IPMI over SMBus) from what I can tell, and the
smb(4) driver never allowed bulk read/writes of more than 32-bytes
anyway. The other smb drivers only performed single transactions.
- Fix buffer overflows in the bread() methods of ichsmb(4), alpm(4),
amdpm(4), amdsmb(4), intpm(4), and nfsmb(4).
- Use SMB_xxx errors in viapm(4).
- Destroy ichsmb(4)'s mutex after bus_generic_detach() to avoid problems
from child devices making smb upcalls that would use the mutex during
their detach methods.
MFC after: 1 week
Reviewed by: jmg (mostly)
2006-09-11 20:52:41 +00:00
|
|
|
DRIVER_MODULE(smbus, viapropm, smbus_driver, smbus_devclass, 0, 0);
|
2002-03-23 15:49:15 +00:00
|
|
|
|
2003-04-15 06:37:30 +00:00
|
|
|
MODULE_DEPEND(viapm, pci, 1, 1, 1);
|
2005-10-31 18:31:16 +00:00
|
|
|
MODULE_DEPEND(viapropm, pci, 1, 1, 1);
|
2002-03-23 15:49:15 +00:00
|
|
|
MODULE_DEPEND(viapm, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER);
|
|
|
|
MODULE_DEPEND(viapropm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
|
|
|
|
MODULE_VERSION(viapm, 1);
|
2005-10-31 18:31:16 +00:00
|
|
|
|
|
|
|
#ifdef DEV_ISA
|
|
|
|
DRIVER_MODULE(isa, viapm, isa_driver, isa_devclass, 0, 0);
|
|
|
|
DRIVER_MODULE(isa, viapropm, isa_driver, isa_devclass, 0, 0);
|
|
|
|
MODULE_DEPEND(viapm, isa, 1, 1, 1);
|
|
|
|
MODULE_DEPEND(viapropm, isa, 1, 1, 1);
|
|
|
|
#endif
|