The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ichsmb/ichsmb.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * ichsmb.c
    3  *
    4  * Author: Archie Cobbs <archie@freebsd.org>
    5  * Copyright (c) 2000 Whistle Communications, Inc.
    6  * All rights reserved.
    7  * 
    8  * Subject to the following obligations and disclaimer of warranty, use and
    9  * redistribution of this software, in source or object code forms, with or
   10  * without modifications are expressly permitted by Whistle Communications;
   11  * provided, however, that:
   12  * 1. Any and all reproductions of the source or object code must include the
   13  *    copyright notice above and the following disclaimer of warranties; and
   14  * 2. No rights are granted, in any manner or form, to use Whistle
   15  *    Communications, Inc. trademarks, including the mark "WHISTLE
   16  *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
   17  *    such appears in the above copyright notice or in the software.
   18  * 
   19  * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
   20  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
   21  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
   22  * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
   23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
   24  * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
   25  * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
   26  * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
   27  * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
   28  * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
   29  * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
   30  * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
   31  * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
   32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   34  * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
   35  * OF SUCH DAMAGE.
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __FBSDID("$FreeBSD$");
   40 
   41 /*
   42  * Support for the SMBus controller logical device which is part of the
   43  * Intel 81801AA (ICH) and 81801AB (ICH0) I/O controller hub chips.
   44  *
   45  * This driver assumes that the generic SMBus code will ensure that
   46  * at most one process at a time calls into the SMBus methods below.
   47  */
   48 
   49 #include <sys/param.h>
   50 #include <sys/systm.h>
   51 #include <sys/kernel.h>
   52 #include <sys/errno.h>
   53 #include <sys/lock.h>
   54 #include <sys/mutex.h>
   55 #include <sys/syslog.h>
   56 #include <sys/bus.h>
   57 
   58 #include <machine/bus.h>
   59 #include <sys/rman.h>
   60 #include <machine/resource.h>
   61 
   62 #include <dev/smbus/smbconf.h>
   63 
   64 #include <dev/ichsmb/ichsmb_var.h>
   65 #include <dev/ichsmb/ichsmb_reg.h>
   66 
   67 /*
   68  * Enable debugging by defining ICHSMB_DEBUG to a non-zero value.
   69  */
   70 #define ICHSMB_DEBUG    0
   71 #if ICHSMB_DEBUG != 0 && (defined(__GNUC__) || defined(__INTEL_COMPILER))
   72 #define DBG(fmt, args...)       \
   73         do { log(LOG_DEBUG, "%s: " fmt, __func__ , ## args); } while (0)
   74 #else
   75 #define DBG(fmt, args...)       do { } while (0)
   76 #endif
   77 
   78 /*
   79  * Our child device driver name
   80  */
   81 #define DRIVER_SMBUS    "smbus"
   82 
   83 /*
   84  * Internal functions
   85  */
   86 static int ichsmb_wait(sc_p sc);
   87 
   88 /********************************************************************
   89                 BUS-INDEPENDENT BUS METHODS
   90 ********************************************************************/
   91 
   92 /*
   93  * Handle probe-time duties that are independent of the bus
   94  * our device lives on.
   95  */
   96 int
   97 ichsmb_probe(device_t dev)
   98 {
   99         return (BUS_PROBE_DEFAULT);
  100 }
  101 
  102 /*
  103  * Handle attach-time duties that are independent of the bus
  104  * our device lives on.
  105  */
  106 int
  107 ichsmb_attach(device_t dev)
  108 {
  109         const sc_p sc = device_get_softc(dev);
  110         int error;
  111 
  112         /* Add child: an instance of the "smbus" device */
  113         if ((sc->smb = device_add_child(dev, DRIVER_SMBUS, -1)) == NULL) {
  114                 log(LOG_ERR, "%s: no \"%s\" child found\n",
  115                     device_get_nameunit(dev), DRIVER_SMBUS);
  116                 return (ENXIO);
  117         }
  118 
  119         /* Clear interrupt conditions */
  120         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_STA, 0xff);
  121 
  122         /* Add "smbus" child */
  123         if ((error = bus_generic_attach(dev)) != 0) {
  124                 log(LOG_ERR, "%s: failed to attach child: %d\n",
  125                     device_get_nameunit(dev), error);
  126                 return (ENXIO);
  127         }
  128 
  129         /* Create mutex */
  130         mtx_init(&sc->mutex, device_get_nameunit(dev), "ichsmb", MTX_DEF);
  131         return (0);
  132 }
  133 
  134 /********************************************************************
  135                         SMBUS METHODS
  136 ********************************************************************/
  137 
  138 int 
  139 ichsmb_callback(device_t dev, int index, caddr_t data)
  140 {
  141         int smb_error = 0;
  142 
  143         DBG("index=%d how=%d\n", index, data ? *(int *)data : -1);
  144         switch (index) {
  145         case SMB_REQUEST_BUS:
  146                 break;
  147         case SMB_RELEASE_BUS:
  148                 break;
  149         default:
  150                 smb_error = SMB_EABORT; /* XXX */
  151                 break;
  152         }
  153         DBG("smb_error=%d\n", smb_error);
  154         return (smb_error);
  155 }
  156 
  157 int
  158 ichsmb_quick(device_t dev, u_char slave, int how)
  159 {
  160         const sc_p sc = device_get_softc(dev);
  161         int smb_error;
  162 
  163         DBG("slave=0x%02x how=%d\n", slave, how);
  164         KASSERT(sc->ich_cmd == -1,
  165             ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
  166         switch (how) {
  167         case SMB_QREAD:
  168         case SMB_QWRITE:
  169                 mtx_lock(&sc->mutex);
  170                 sc->ich_cmd = ICH_HST_CNT_SMB_CMD_QUICK;
  171                 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
  172                     (slave << 1) | (how == SMB_QREAD ?
  173                         ICH_XMIT_SLVA_READ : ICH_XMIT_SLVA_WRITE));
  174                 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
  175                     ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
  176                 smb_error = ichsmb_wait(sc);
  177                 mtx_unlock(&sc->mutex);
  178                 break;
  179         default:
  180                 smb_error = SMB_ENOTSUPP;
  181         }
  182         DBG("smb_error=%d\n", smb_error);
  183         return (smb_error);
  184 }
  185 
  186 int
  187 ichsmb_sendb(device_t dev, u_char slave, char byte)
  188 {
  189         const sc_p sc = device_get_softc(dev);
  190         int smb_error;
  191 
  192         DBG("slave=0x%02x byte=0x%02x\n", slave, (u_char)byte);
  193         KASSERT(sc->ich_cmd == -1,
  194             ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
  195         mtx_lock(&sc->mutex);
  196         sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BYTE;
  197         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
  198             (slave << 1) | ICH_XMIT_SLVA_WRITE);
  199         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, byte);
  200         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
  201             ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
  202         smb_error = ichsmb_wait(sc);
  203         mtx_unlock(&sc->mutex);
  204         DBG("smb_error=%d\n", smb_error);
  205         return (smb_error);
  206 }
  207 
  208 int
  209 ichsmb_recvb(device_t dev, u_char slave, char *byte)
  210 {
  211         const sc_p sc = device_get_softc(dev);
  212         int smb_error;
  213 
  214         DBG("slave=0x%02x\n", slave);
  215         KASSERT(sc->ich_cmd == -1,
  216             ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
  217         mtx_lock(&sc->mutex);
  218         sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BYTE;
  219         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
  220             (slave << 1) | ICH_XMIT_SLVA_READ);
  221         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
  222             ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
  223         if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR)
  224                 *byte = bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_D0);
  225         mtx_unlock(&sc->mutex);
  226         DBG("smb_error=%d byte=0x%02x\n", smb_error, (u_char)*byte);
  227         return (smb_error);
  228 }
  229 
  230 int
  231 ichsmb_writeb(device_t dev, u_char slave, char cmd, char byte)
  232 {
  233         const sc_p sc = device_get_softc(dev);
  234         int smb_error;
  235 
  236         DBG("slave=0x%02x cmd=0x%02x byte=0x%02x\n",
  237             slave, (u_char)cmd, (u_char)byte);
  238         KASSERT(sc->ich_cmd == -1,
  239             ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
  240         mtx_lock(&sc->mutex);
  241         sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BYTE_DATA;
  242         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
  243             (slave << 1) | ICH_XMIT_SLVA_WRITE);
  244         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
  245         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D0, byte);
  246         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
  247             ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
  248         smb_error = ichsmb_wait(sc);
  249         mtx_unlock(&sc->mutex);
  250         DBG("smb_error=%d\n", smb_error);
  251         return (smb_error);
  252 }
  253 
  254 int
  255 ichsmb_writew(device_t dev, u_char slave, char cmd, short word)
  256 {
  257         const sc_p sc = device_get_softc(dev);
  258         int smb_error;
  259 
  260         DBG("slave=0x%02x cmd=0x%02x word=0x%04x\n",
  261             slave, (u_char)cmd, (u_int16_t)word);
  262         KASSERT(sc->ich_cmd == -1,
  263             ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
  264         mtx_lock(&sc->mutex);
  265         sc->ich_cmd = ICH_HST_CNT_SMB_CMD_WORD_DATA;
  266         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
  267             (slave << 1) | ICH_XMIT_SLVA_WRITE);
  268         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
  269         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D0, word & 0xff);
  270         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D1, word >> 8);
  271         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
  272             ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
  273         smb_error = ichsmb_wait(sc);
  274         mtx_unlock(&sc->mutex);
  275         DBG("smb_error=%d\n", smb_error);
  276         return (smb_error);
  277 }
  278 
  279 int
  280 ichsmb_readb(device_t dev, u_char slave, char cmd, char *byte)
  281 {
  282         const sc_p sc = device_get_softc(dev);
  283         int smb_error;
  284 
  285         DBG("slave=0x%02x cmd=0x%02x\n", slave, (u_char)cmd);
  286         KASSERT(sc->ich_cmd == -1,
  287             ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
  288         mtx_lock(&sc->mutex);
  289         sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BYTE_DATA;
  290         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
  291             (slave << 1) | ICH_XMIT_SLVA_READ);
  292         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
  293         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
  294             ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
  295         if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR)
  296                 *byte = bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_D0);
  297         mtx_unlock(&sc->mutex);
  298         DBG("smb_error=%d byte=0x%02x\n", smb_error, (u_char)*byte);
  299         return (smb_error);
  300 }
  301 
  302 int
  303 ichsmb_readw(device_t dev, u_char slave, char cmd, short *word)
  304 {
  305         const sc_p sc = device_get_softc(dev);
  306         int smb_error;
  307 
  308         DBG("slave=0x%02x cmd=0x%02x\n", slave, (u_char)cmd);
  309         KASSERT(sc->ich_cmd == -1,
  310             ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
  311         mtx_lock(&sc->mutex);
  312         sc->ich_cmd = ICH_HST_CNT_SMB_CMD_WORD_DATA;
  313         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
  314             (slave << 1) | ICH_XMIT_SLVA_READ);
  315         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
  316         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
  317             ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
  318         if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR) {
  319                 *word = (bus_space_read_1(sc->io_bst,
  320                         sc->io_bsh, ICH_D0) & 0xff)
  321                   | (bus_space_read_1(sc->io_bst,
  322                         sc->io_bsh, ICH_D1) << 8);
  323         }
  324         mtx_unlock(&sc->mutex);
  325         DBG("smb_error=%d word=0x%04x\n", smb_error, (u_int16_t)*word);
  326         return (smb_error);
  327 }
  328 
  329 int
  330 ichsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata)
  331 {
  332         const sc_p sc = device_get_softc(dev);
  333         int smb_error;
  334 
  335         DBG("slave=0x%02x cmd=0x%02x sdata=0x%04x\n",
  336             slave, (u_char)cmd, (u_int16_t)sdata);
  337         KASSERT(sc->ich_cmd == -1,
  338             ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
  339         mtx_lock(&sc->mutex);
  340         sc->ich_cmd = ICH_HST_CNT_SMB_CMD_PROC_CALL;
  341         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
  342             (slave << 1) | ICH_XMIT_SLVA_WRITE);
  343         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
  344         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D0, sdata & 0xff);
  345         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D1, sdata >> 8);
  346         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
  347             ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
  348         if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR) {
  349                 *rdata = (bus_space_read_1(sc->io_bst,
  350                         sc->io_bsh, ICH_D0) & 0xff)
  351                   | (bus_space_read_1(sc->io_bst,
  352                         sc->io_bsh, ICH_D1) << 8);
  353         }
  354         mtx_unlock(&sc->mutex);
  355         DBG("smb_error=%d rdata=0x%04x\n", smb_error, (u_int16_t)*rdata);
  356         return (smb_error);
  357 }
  358 
  359 int
  360 ichsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
  361 {
  362         const sc_p sc = device_get_softc(dev);
  363         int smb_error;
  364 
  365         DBG("slave=0x%02x cmd=0x%02x count=%d\n", slave, (u_char)cmd, count);
  366 #if ICHSMB_DEBUG
  367 #define DISP(ch)        (((ch) < 0x20 || (ch) >= 0x7e) ? '.' : (ch))
  368         {
  369             u_char *p;
  370 
  371             for (p = (u_char *)buf; p - (u_char *)buf < 32; p += 8) {
  372                 DBG("%02x: %02x %02x %02x %02x %02x %02x %02x %02x"
  373                     "  %c%c%c%c%c%c%c%c", (p - (u_char *)buf),
  374                     p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
  375                     DISP(p[0]), DISP(p[1]), DISP(p[2]), DISP(p[3]), 
  376                     DISP(p[4]), DISP(p[5]), DISP(p[6]), DISP(p[7]));
  377             }
  378         }
  379 #undef DISP
  380 #endif
  381         KASSERT(sc->ich_cmd == -1,
  382             ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
  383         if (count < 1 || count > 32)
  384                 return (EINVAL);
  385         bcopy(buf, sc->block_data, count);
  386         sc->block_count = count;
  387         sc->block_index = 1;
  388         sc->block_write = 1;
  389 
  390         mtx_lock(&sc->mutex);
  391         sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BLOCK;
  392         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
  393             (slave << 1) | ICH_XMIT_SLVA_WRITE);
  394         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
  395         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D0, count);
  396         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_BLOCK_DB, buf[0]);
  397         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
  398             ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
  399         smb_error = ichsmb_wait(sc);
  400         mtx_unlock(&sc->mutex);
  401         DBG("smb_error=%d\n", smb_error);
  402         return (smb_error);
  403 }
  404 
  405 int
  406 ichsmb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
  407 {
  408         const sc_p sc = device_get_softc(dev);
  409         int smb_error;
  410 
  411         DBG("slave=0x%02x cmd=0x%02x count=%d\n", slave, (u_char)cmd, count);
  412         KASSERT(sc->ich_cmd == -1,
  413             ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
  414         if (count < 1 || count > 32)
  415                 return (EINVAL);
  416         bzero(sc->block_data, sizeof(sc->block_data));
  417         sc->block_count = count;
  418         sc->block_index = 0;
  419         sc->block_write = 0;
  420 
  421         mtx_lock(&sc->mutex);
  422         sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BLOCK;
  423         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
  424             (slave << 1) | ICH_XMIT_SLVA_READ);
  425         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
  426         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D0, count); /* XXX? */
  427         bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
  428             ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
  429         if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR)
  430                 bcopy(sc->block_data, buf, sc->block_count);
  431         mtx_unlock(&sc->mutex);
  432         DBG("smb_error=%d\n", smb_error);
  433 #if ICHSMB_DEBUG
  434 #define DISP(ch)        (((ch) < 0x20 || (ch) >= 0x7e) ? '.' : (ch))
  435         {
  436             u_char *p;
  437 
  438             for (p = (u_char *)buf; p - (u_char *)buf < 32; p += 8) {
  439                 DBG("%02x: %02x %02x %02x %02x %02x %02x %02x %02x"
  440                     "  %c%c%c%c%c%c%c%c", (p - (u_char *)buf),
  441                     p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
  442                     DISP(p[0]), DISP(p[1]), DISP(p[2]), DISP(p[3]), 
  443                     DISP(p[4]), DISP(p[5]), DISP(p[6]), DISP(p[7]));
  444             }
  445         }
  446 #undef DISP
  447 #endif
  448         return (smb_error);
  449 }
  450 
  451 /********************************************************************
  452                         OTHER FUNCTIONS
  453 ********************************************************************/
  454 
  455 /*
  456  * This table describes what interrupts we should ever expect to
  457  * see after each ICH command, not including the SMBALERT interrupt.
  458  */
  459 static const u_int8_t ichsmb_state_irqs[] = {
  460         /* quick */
  461         (ICH_HST_STA_BUS_ERR | ICH_HST_STA_DEV_ERR | ICH_HST_STA_INTR),
  462         /* byte */
  463         (ICH_HST_STA_BUS_ERR | ICH_HST_STA_DEV_ERR | ICH_HST_STA_INTR),
  464         /* byte data */
  465         (ICH_HST_STA_BUS_ERR | ICH_HST_STA_DEV_ERR | ICH_HST_STA_INTR),
  466         /* word data */
  467         (ICH_HST_STA_BUS_ERR | ICH_HST_STA_DEV_ERR | ICH_HST_STA_INTR),
  468         /* process call */
  469         (ICH_HST_STA_BUS_ERR | ICH_HST_STA_DEV_ERR | ICH_HST_STA_INTR),
  470         /* block */
  471         (ICH_HST_STA_BUS_ERR | ICH_HST_STA_DEV_ERR | ICH_HST_STA_INTR
  472             | ICH_HST_STA_BYTE_DONE_STS),
  473         /* i2c read (not used) */
  474         (ICH_HST_STA_BUS_ERR | ICH_HST_STA_DEV_ERR | ICH_HST_STA_INTR
  475             | ICH_HST_STA_BYTE_DONE_STS)
  476 };
  477 
  478 /*
  479  * Interrupt handler. This handler is bus-independent. Note that our
  480  * interrupt may be shared, so we must handle "false" interrupts.
  481  */
  482 void
  483 ichsmb_device_intr(void *cookie)
  484 {
  485         const sc_p sc = cookie;
  486         const device_t dev = sc->dev;
  487         const int maxloops = 16;
  488         u_int8_t status;
  489         u_int8_t ok_bits;
  490         int cmd_index;
  491         int count;
  492 
  493         mtx_lock(&sc->mutex);
  494         for (count = 0; count < maxloops; count++) {
  495 
  496                 /* Get and reset status bits */
  497                 status = bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_HST_STA);
  498 #if ICHSMB_DEBUG
  499                 if ((status & ~(ICH_HST_STA_INUSE_STS | ICH_HST_STA_HOST_BUSY))
  500                     || count > 0) {
  501                         DBG("%d stat=0x%02x\n", count, status);
  502                 }
  503 #endif
  504                 status &= ~(ICH_HST_STA_INUSE_STS | ICH_HST_STA_HOST_BUSY);
  505                 if (status == 0)
  506                         break;
  507 
  508                 /* Check for unexpected interrupt */
  509                 ok_bits = ICH_HST_STA_SMBALERT_STS;
  510                 cmd_index = sc->ich_cmd >> 2;
  511                 if (sc->ich_cmd != -1) {
  512                         KASSERT(cmd_index < sizeof(ichsmb_state_irqs),
  513                             ("%s: ich_cmd=%d", device_get_nameunit(dev),
  514                             sc->ich_cmd));
  515                         ok_bits |= ichsmb_state_irqs[cmd_index];
  516                 }
  517                 if ((status & ~ok_bits) != 0) {
  518                         log(LOG_ERR, "%s: irq 0x%02x during %d\n",
  519                             device_get_nameunit(dev), status, cmd_index);
  520                         bus_space_write_1(sc->io_bst, sc->io_bsh,
  521                             ICH_HST_STA, (status & ~ok_bits));
  522                         continue;
  523                 }
  524 
  525                 /* Handle SMBALERT interrupt */
  526                 if (status & ICH_HST_STA_SMBALERT_STS) {
  527                         static int smbalert_count = 16;
  528                         if (smbalert_count > 0) {
  529                                 log(LOG_WARNING, "%s: SMBALERT# rec'd\n",
  530                                     device_get_nameunit(dev));
  531                                 if (--smbalert_count == 0) {
  532                                         log(LOG_WARNING,
  533                                             "%s: not logging anymore\n",
  534                                             device_get_nameunit(dev));
  535                                 }
  536                         }
  537                 }
  538 
  539                 /* Check for bus error */
  540                 if (status & ICH_HST_STA_BUS_ERR) {
  541                         sc->smb_error = SMB_ECOLLI;     /* XXX SMB_EBUSERR? */
  542                         goto finished;
  543                 }
  544 
  545                 /* Check for device error */
  546                 if (status & ICH_HST_STA_DEV_ERR) {
  547                         sc->smb_error = SMB_ENOACK;     /* or SMB_ETIMEOUT? */
  548                         goto finished;
  549                 }
  550 
  551                 /* Check for byte completion in block transfer */
  552                 if (status & ICH_HST_STA_BYTE_DONE_STS) {
  553                         if (sc->block_write) {
  554                                 if (sc->block_index < sc->block_count) {
  555 
  556                                         /* Write next byte */
  557                                         bus_space_write_1(sc->io_bst,
  558                                             sc->io_bsh, ICH_BLOCK_DB,
  559                                             sc->block_data[sc->block_index++]);
  560                                 }
  561                         } else {
  562 
  563                                 /* First interrupt, get the count also */
  564                                 if (sc->block_index == 0) {
  565                                         sc->block_count = bus_space_read_1(
  566                                             sc->io_bst, sc->io_bsh, ICH_D0);
  567                                 }
  568 
  569                                 /* Get next byte, if any */
  570                                 if (sc->block_index < sc->block_count) {
  571 
  572                                         /* Read next byte */
  573                                         sc->block_data[sc->block_index++] =
  574                                             bus_space_read_1(sc->io_bst,
  575                                               sc->io_bsh, ICH_BLOCK_DB);
  576 
  577                                         /* Set "LAST_BYTE" bit before reading
  578                                            the last byte of block data */
  579                                         if (sc->block_index
  580                                             >= sc->block_count - 1) {
  581                                                 bus_space_write_1(sc->io_bst,
  582                                                     sc->io_bsh, ICH_HST_CNT,
  583                                                     ICH_HST_CNT_LAST_BYTE
  584                                                         | ICH_HST_CNT_INTREN
  585                                                         | sc->ich_cmd);
  586                                         }
  587                                 }
  588                         }
  589                 }
  590 
  591                 /* Check command completion */
  592                 if (status & ICH_HST_STA_INTR) {
  593                         sc->smb_error = SMB_ENOERR;
  594 finished:
  595                         sc->ich_cmd = -1;
  596                         bus_space_write_1(sc->io_bst, sc->io_bsh,
  597                             ICH_HST_STA, status);
  598                         wakeup(sc);
  599                         break;
  600                 }
  601 
  602                 /* Clear status bits and try again */
  603                 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_STA, status);
  604         }
  605         mtx_unlock(&sc->mutex);
  606 
  607         /* Too many loops? */
  608         if (count == maxloops) {
  609                 log(LOG_ERR, "%s: interrupt loop, status=0x%02x\n",
  610                     device_get_nameunit(dev),
  611                     bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_HST_STA));
  612         }
  613 }
  614 
  615 /*
  616  * Wait for command completion. Assumes mutex is held.
  617  * Returns an SMB_* error code.
  618  */
  619 static int
  620 ichsmb_wait(sc_p sc)
  621 {
  622         const device_t dev = sc->dev;
  623         int error, smb_error;
  624 
  625         KASSERT(sc->ich_cmd != -1,
  626             ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
  627         mtx_assert(&sc->mutex, MA_OWNED);
  628 sleep:
  629         error = msleep(sc, &sc->mutex, PZERO | PCATCH, "ichsmb", hz / 4);
  630         DBG("msleep -> %d\n", error);
  631         switch (error) {
  632         case ERESTART:
  633                 if (sc->ich_cmd != -1)
  634                         goto sleep;
  635                 /* FALLTHROUGH */
  636         case 0:
  637                 smb_error = sc->smb_error;
  638                 break;
  639         case EWOULDBLOCK:
  640                 log(LOG_ERR, "%s: device timeout, status=0x%02x\n",
  641                     device_get_nameunit(dev),
  642                     bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_HST_STA));
  643                 sc->ich_cmd = -1;
  644                 smb_error = SMB_ETIMEOUT;
  645                 break;
  646         default:
  647                 smb_error = SMB_EABORT;
  648                 break;
  649         }
  650         return (smb_error);
  651 }
  652 
  653 /*
  654  * Release resources associated with device.
  655  */
  656 void
  657 ichsmb_release_resources(sc_p sc)
  658 {
  659         const device_t dev = sc->dev;
  660 
  661         if (sc->irq_handle != NULL) {
  662                 bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
  663                 sc->irq_handle = NULL;
  664         }
  665         if (sc->irq_res != NULL) {
  666                 bus_release_resource(dev,
  667                     SYS_RES_IRQ, sc->irq_rid, sc->irq_res);
  668                 sc->irq_res = NULL;
  669         }
  670         if (sc->io_res != NULL) {
  671                 bus_release_resource(dev,
  672                     SYS_RES_IOPORT, sc->io_rid, sc->io_res);
  673                 sc->io_res = NULL;
  674         }
  675 }
  676 
  677 int ichsmb_detach(device_t dev)
  678 {
  679         const sc_p sc = device_get_softc(dev);
  680 
  681         mtx_destroy(&sc->mutex);
  682         bus_generic_detach(dev);
  683         device_delete_child(dev, sc->smb);
  684         ichsmb_release_resources(sc);
  685         
  686         return 0;
  687 }

Cache object: 16b4d147b15eb8dd8685bb93d7b58560


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.