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/powermng/alpm/alpm.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  * Copyright (c) 1998, 1999, 2001 Nicolas Souchu
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD: src/sys/pci/alpm.c,v 1.26 2007/01/11 19:56:24 jhb Exp $
   27  *
   28  */
   29 
   30 /*
   31  * Power Management support for the Acer M15x3 chipsets
   32  */
   33 #include <sys/param.h>
   34 #include <sys/bus.h>
   35 #include <sys/kernel.h>
   36 #include <sys/lock.h>
   37 #include <sys/module.h>
   38 #include <sys/rman.h>
   39 #include <sys/systm.h>
   40 
   41 #include <bus/pci/pcivar.h>
   42 #include <bus/pci/pcireg.h>
   43 
   44 #include <bus/smbus/smbconf.h>
   45 #include "smbus_if.h"
   46 
   47 #define ALPM_DEBUG(x)   if (alpm_debug) (x)
   48 
   49 #ifdef DEBUG
   50 static int alpm_debug = 1;
   51 #else
   52 static int alpm_debug = 0;
   53 #endif
   54 
   55 #define ACER_M1543_PMU_ID       0x710110b9
   56 
   57 /*
   58  * I/O registers offsets - the base address is programmed via the
   59  * SMBBA PCI configuration register
   60  */
   61 #define SMBSTS          0x0     /* SMBus host/slave status register */
   62 #define SMBCMD          0x1     /* SMBus host/slave command register */
   63 #define SMBSTART        0x2     /* start to generate programmed cycle */
   64 #define SMBHADDR        0x3     /* host address register */
   65 #define SMBHDATA        0x4     /* data A register for host controller */
   66 #define SMBHDATB        0x5     /* data B register for host controller */
   67 #define SMBHBLOCK       0x6     /* block register for host controller */
   68 #define SMBHCMD         0x7     /* command register for host controller */
   69 
   70 /* SMBHADDR mask. */
   71 #define LSB             0x1     /* XXX: Better name: Read/Write? */
   72 
   73 /* SMBSTS masks */
   74 #define TERMINATE       0x80
   75 #define BUS_COLLI       0x40
   76 #define DEVICE_ERR      0x20
   77 #define SMI_I_STS       0x10
   78 #define HST_BSY         0x08
   79 #define IDL_STS         0x04
   80 #define HSTSLV_STS      0x02
   81 #define HSTSLV_BSY      0x01
   82 
   83 /* SMBCMD masks */
   84 #define SMB_BLK_CLR     0x80
   85 #define T_OUT_CMD       0x08
   86 #define ABORT_HOST      0x04
   87 
   88 /* SMBus commands */
   89 #define SMBQUICK        0x00
   90 #define SMBSRBYTE       0x10            /* send/receive byte */
   91 #define SMBWRBYTE       0x20            /* write/read byte */
   92 #define SMBWRWORD       0x30            /* write/read word */
   93 #define SMBWRBLOCK      0x40            /* write/read block */
   94 
   95 /* PCI configuration registers and masks
   96  */
   97 #define COM             0x4
   98 #define COM_ENABLE_IO   0x1
   99 
  100 #define SMBBA           PCIR_BAR(1)
  101 
  102 #define ATPC            0x5b
  103 #define ATPC_SMBCTRL    0x04            /* XX linux has this as 0x6 */
  104 
  105 #define SMBHSI          0xe0
  106 #define SMBHSI_SLAVE    0x2
  107 #define SMBHSI_HOST     0x1
  108 
  109 #define SMBHCBC         0xe2
  110 #define SMBHCBC_CLOCK   0x70
  111 
  112 #define SMBCLOCK_149K   0x0
  113 #define SMBCLOCK_74K    0x20
  114 #define SMBCLOCK_37K    0x40
  115 #define SMBCLOCK_223K   0x80
  116 #define SMBCLOCK_111K   0xa0
  117 #define SMBCLOCK_55K    0xc0
  118 
  119 struct alpm_softc {
  120         int base;
  121         struct resource *res;
  122         bus_space_tag_t smbst;
  123         bus_space_handle_t smbsh;
  124         device_t smbus;
  125         struct lock lock;
  126 };
  127 
  128 #define ALPM_LOCK(alpm)         lockmgr(&(alpm)->lock, LK_EXCLUSIVE)
  129 #define ALPM_UNLOCK(alpm)       lockmgr(&(alpm)->lock, LK_RELEASE)
  130 #define ALPM_LOCK_ASSERT(alpm)  KKASSERT(lockstatus(&(alpm)->lock, curthread) != 0)
  131 
  132 #define ALPM_SMBINB(alpm,register) \
  133         (bus_space_read_1(alpm->smbst, alpm->smbsh, register))
  134 #define ALPM_SMBOUTB(alpm,register,value) \
  135         (bus_space_write_1(alpm->smbst, alpm->smbsh, register, value))
  136 
  137 static int      alpm_detach(device_t dev);
  138 
  139 static int
  140 alpm_probe(device_t dev)
  141 {
  142 
  143         if (pci_get_devid(dev) == ACER_M1543_PMU_ID) {
  144                 device_set_desc(dev, "AcerLabs M15x3 Power Management Unit");
  145 
  146                 return (BUS_PROBE_DEFAULT);
  147         }
  148 
  149         return (ENXIO);
  150 }
  151 
  152 static int
  153 alpm_attach(device_t dev)
  154 {
  155         int rid;
  156         u_int32_t l;
  157         struct alpm_softc *alpm;
  158 
  159         alpm = device_get_softc(dev);
  160 
  161         /* Unlock SMBIO base register access */
  162         l = pci_read_config(dev, ATPC, 1);
  163         pci_write_config(dev, ATPC, l & ~ATPC_SMBCTRL, 1);
  164 
  165         /*
  166          * XX linux sets clock to 74k, should we?
  167         l = pci_read_config(dev, SMBHCBC, 1);
  168         l &= 0x1f;
  169         l |= SMBCLOCK_74K;
  170         pci_write_config(dev, SMBHCBC, l, 1);
  171          */
  172 
  173         if (bootverbose || alpm_debug) {
  174                 l = pci_read_config(dev, SMBHSI, 1);
  175                 device_printf(dev, "%s/%s",
  176                         (l & SMBHSI_HOST) ? "host":"nohost",
  177                         (l & SMBHSI_SLAVE) ? "slave":"noslave");
  178 
  179                 l = pci_read_config(dev, SMBHCBC, 1);
  180                 switch (l & SMBHCBC_CLOCK) {
  181                 case SMBCLOCK_149K:
  182                         kprintf(" 149K");
  183                         break;
  184                 case SMBCLOCK_74K:
  185                         kprintf(" 74K");
  186                         break;
  187                 case SMBCLOCK_37K:
  188                         kprintf(" 37K");
  189                         break;
  190                 case SMBCLOCK_223K:
  191                         kprintf(" 223K");
  192                         break;
  193                 case SMBCLOCK_111K:
  194                         kprintf(" 111K");
  195                         break;
  196                 case SMBCLOCK_55K:
  197                         kprintf(" 55K");
  198                         break;
  199                 default:
  200                         kprintf("unknown");
  201                         break;
  202                 }
  203                 kprintf("\n");
  204         }
  205 
  206         rid = SMBBA;
  207         alpm->res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
  208             RF_ACTIVE);
  209 
  210         if (alpm->res == NULL) {
  211                 device_printf(dev, "Could not allocate Bus space\n");
  212                 return (ENXIO);
  213         }
  214         alpm->smbst = rman_get_bustag(alpm->res);
  215         alpm->smbsh = rman_get_bushandle(alpm->res);
  216         lockinit(&alpm->lock, "alpm", 0, LK_CANRECURSE);
  217 
  218         /* attach the smbus */
  219         alpm->smbus = device_add_child(dev, "smbus", -1);
  220         if (alpm->smbus == NULL) {
  221                 alpm_detach(dev);
  222                 return (EINVAL);
  223         }
  224         bus_generic_attach(dev);
  225 
  226         return (0);
  227 }
  228 
  229 static int
  230 alpm_detach(device_t dev)
  231 {
  232         struct alpm_softc *alpm = device_get_softc(dev);
  233 
  234         if (alpm->smbus) {
  235                 device_delete_child(dev, alpm->smbus);
  236                 alpm->smbus = NULL;
  237         }
  238         lockuninit(&alpm->lock);
  239 
  240         if (alpm->res)
  241                 bus_release_resource(dev, SYS_RES_IOPORT, SMBBA, alpm->res);
  242 
  243         return (0);
  244 }
  245 
  246 static int
  247 alpm_callback(device_t dev, int index, void *data)
  248 {
  249         int error = 0;
  250 
  251         switch (index) {
  252         case SMB_REQUEST_BUS:
  253         case SMB_RELEASE_BUS:
  254                 /* ok, bus allocation accepted */
  255                 break;
  256         default:
  257                 error = EINVAL;
  258         }
  259 
  260         return (error);
  261 }
  262 
  263 static int
  264 alpm_clear(struct alpm_softc *sc)
  265 {
  266         ALPM_SMBOUTB(sc, SMBSTS, 0xff);
  267         DELAY(10);
  268 
  269         return (0);
  270 }
  271 
  272 #if 0
  273 static int
  274 alpm_abort(struct alpm_softc *sc)
  275 {
  276         ALPM_SMBOUTB(sc, SMBCMD, T_OUT_CMD | ABORT_HOST);
  277 
  278         return (0);
  279 }
  280 #endif
  281 
  282 static int
  283 alpm_idle(struct alpm_softc *sc)
  284 {
  285         u_char sts;
  286 
  287         sts = ALPM_SMBINB(sc, SMBSTS);
  288 
  289         ALPM_DEBUG(kprintf("alpm: idle? STS=0x%x\n", sts));
  290 
  291         return (sts & IDL_STS);
  292 }
  293 
  294 /*
  295  * Poll the SMBus controller
  296  */
  297 static int
  298 alpm_wait(struct alpm_softc *sc)
  299 {
  300         int count = 10000;
  301         u_char sts = 0;
  302         int error;
  303 
  304         /* wait for command to complete and SMBus controller is idle */
  305         while (count--) {
  306                 DELAY(10);
  307                 sts = ALPM_SMBINB(sc, SMBSTS);
  308                 if (sts & SMI_I_STS)
  309                         break;
  310         }
  311 
  312         ALPM_DEBUG(kprintf("alpm: STS=0x%x\n", sts));
  313 
  314         error = SMB_ENOERR;
  315 
  316         if (!count)
  317                 error |= SMB_ETIMEOUT;
  318 
  319         if (sts & TERMINATE)
  320                 error |= SMB_EABORT;
  321 
  322         if (sts & BUS_COLLI)
  323                 error |= SMB_ENOACK;
  324 
  325         if (sts & DEVICE_ERR)
  326                 error |= SMB_EBUSERR;
  327 
  328         if (error != SMB_ENOERR)
  329                 alpm_clear(sc);
  330 
  331         return (error);
  332 }
  333 
  334 static int
  335 alpm_quick(device_t dev, u_char slave, int how)
  336 {
  337         struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
  338         int error;
  339 
  340         ALPM_LOCK(sc);
  341         alpm_clear(sc);
  342         if (!alpm_idle(sc)) {
  343                 ALPM_UNLOCK(sc);
  344                 return (EBUSY);
  345         }
  346 
  347         switch (how) {
  348         case SMB_QWRITE:
  349                 ALPM_DEBUG(kprintf("alpm: QWRITE to 0x%x", slave));
  350                 ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB);
  351                 break;
  352         case SMB_QREAD:
  353                 ALPM_DEBUG(kprintf("alpm: QREAD to 0x%x", slave));
  354                 ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB);
  355                 break;
  356         default:
  357                 panic("%s: unknown QUICK command (%x)!", __func__, how);
  358         }
  359         ALPM_SMBOUTB(sc, SMBCMD, SMBQUICK);
  360         ALPM_SMBOUTB(sc, SMBSTART, 0xff);
  361 
  362         error = alpm_wait(sc);
  363 
  364         ALPM_DEBUG(kprintf(", error=0x%x\n", error));
  365         ALPM_UNLOCK(sc);
  366 
  367         return (error);
  368 }
  369 
  370 static int
  371 alpm_sendb(device_t dev, u_char slave, char byte)
  372 {
  373         struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
  374         int error;
  375 
  376         ALPM_LOCK(sc);
  377         alpm_clear(sc);
  378         if (!alpm_idle(sc)) {
  379                 ALPM_UNLOCK(sc);
  380                 return (SMB_EBUSY);
  381         }
  382 
  383         ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB);
  384         ALPM_SMBOUTB(sc, SMBCMD, SMBSRBYTE);
  385         ALPM_SMBOUTB(sc, SMBHDATA, byte);
  386         ALPM_SMBOUTB(sc, SMBSTART, 0xff);
  387 
  388         error = alpm_wait(sc);
  389 
  390         ALPM_DEBUG(kprintf("alpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
  391         ALPM_UNLOCK(sc);
  392 
  393         return (error);
  394 }
  395 
  396 static int
  397 alpm_recvb(device_t dev, u_char slave, char *byte)
  398 {
  399         struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
  400         int error;
  401 
  402         ALPM_LOCK(sc);
  403         alpm_clear(sc);
  404         if (!alpm_idle(sc)) {
  405                 ALPM_UNLOCK(sc);
  406                 return (SMB_EBUSY);
  407         }
  408 
  409         ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB);
  410         ALPM_SMBOUTB(sc, SMBCMD, SMBSRBYTE);
  411         ALPM_SMBOUTB(sc, SMBSTART, 0xff);
  412 
  413         if ((error = alpm_wait(sc)) == SMB_ENOERR)
  414                 *byte = ALPM_SMBINB(sc, SMBHDATA);
  415 
  416         ALPM_DEBUG(kprintf("alpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
  417         ALPM_UNLOCK(sc);
  418 
  419         return (error);
  420 }
  421 
  422 static int
  423 alpm_writeb(device_t dev, u_char slave, char cmd, char byte)
  424 {
  425         struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
  426         int error;
  427 
  428         ALPM_LOCK(sc);
  429         alpm_clear(sc);
  430         if (!alpm_idle(sc)) {
  431                 ALPM_UNLOCK(sc);
  432                 return (SMB_EBUSY);
  433         }
  434 
  435         ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB);
  436         ALPM_SMBOUTB(sc, SMBCMD, SMBWRBYTE);
  437         ALPM_SMBOUTB(sc, SMBHDATA, byte);
  438         ALPM_SMBOUTB(sc, SMBHCMD, cmd);
  439         ALPM_SMBOUTB(sc, SMBSTART, 0xff);
  440 
  441         error = alpm_wait(sc);
  442 
  443         ALPM_DEBUG(kprintf("alpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
  444         ALPM_UNLOCK(sc);
  445 
  446         return (error);
  447 }
  448 
  449 static int
  450 alpm_readb(device_t dev, u_char slave, char cmd, char *byte)
  451 {
  452         struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
  453         int error;
  454 
  455         ALPM_LOCK(sc);
  456         alpm_clear(sc);
  457         if (!alpm_idle(sc)) {
  458                 ALPM_UNLOCK(sc);
  459                 return (SMB_EBUSY);
  460         }
  461 
  462         ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB);
  463         ALPM_SMBOUTB(sc, SMBCMD, SMBWRBYTE);
  464         ALPM_SMBOUTB(sc, SMBHCMD, cmd);
  465         ALPM_SMBOUTB(sc, SMBSTART, 0xff);
  466 
  467         if ((error = alpm_wait(sc)) == SMB_ENOERR)
  468                 *byte = ALPM_SMBINB(sc, SMBHDATA);
  469 
  470         ALPM_DEBUG(kprintf("alpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
  471         ALPM_UNLOCK(sc);
  472 
  473         return (error);
  474 }
  475 
  476 static int
  477 alpm_writew(device_t dev, u_char slave, char cmd, short word)
  478 {
  479         struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
  480         int error;
  481 
  482         ALPM_LOCK(sc);
  483         alpm_clear(sc);
  484         if (!alpm_idle(sc)) {
  485                 ALPM_UNLOCK(sc);
  486                 return (SMB_EBUSY);
  487         }
  488 
  489         ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB);
  490         ALPM_SMBOUTB(sc, SMBCMD, SMBWRWORD);
  491         ALPM_SMBOUTB(sc, SMBHDATA, word & 0x00ff);
  492         ALPM_SMBOUTB(sc, SMBHDATB, (word & 0xff00) >> 8);
  493         ALPM_SMBOUTB(sc, SMBHCMD, cmd);
  494         ALPM_SMBOUTB(sc, SMBSTART, 0xff);
  495 
  496         error = alpm_wait(sc);
  497 
  498         ALPM_DEBUG(kprintf("alpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
  499         ALPM_UNLOCK(sc);
  500 
  501         return (error);
  502 }
  503 
  504 static int
  505 alpm_readw(device_t dev, u_char slave, char cmd, short *word)
  506 {
  507         struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
  508         int error;
  509         u_char high, low;
  510 
  511         ALPM_LOCK(sc);
  512         alpm_clear(sc);
  513         if (!alpm_idle(sc)) {
  514                 ALPM_UNLOCK(sc);
  515                 return (SMB_EBUSY);
  516         }
  517 
  518         ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB);
  519         ALPM_SMBOUTB(sc, SMBCMD, SMBWRWORD);
  520         ALPM_SMBOUTB(sc, SMBHCMD, cmd);
  521         ALPM_SMBOUTB(sc, SMBSTART, 0xff);
  522 
  523         if ((error = alpm_wait(sc)) == SMB_ENOERR) {
  524                 low = ALPM_SMBINB(sc, SMBHDATA);
  525                 high = ALPM_SMBINB(sc, SMBHDATB);
  526 
  527                 *word = ((high & 0xff) << 8) | (low & 0xff);
  528         }
  529 
  530         ALPM_DEBUG(kprintf("alpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
  531         ALPM_UNLOCK(sc);
  532 
  533         return (error);
  534 }
  535 
  536 static int
  537 alpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
  538 {
  539         struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
  540         u_char i;
  541         int error;
  542 
  543         if (count < 1 || count > 32)
  544                 return (SMB_EINVAL);
  545 
  546         ALPM_LOCK(sc);
  547         alpm_clear(sc);
  548         if(!alpm_idle(sc)) {
  549                 ALPM_UNLOCK(sc);
  550                 return (SMB_EBUSY);
  551         }
  552 
  553         ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB);
  554 
  555         /* set the cmd and reset the
  556          * 32-byte long internal buffer */
  557         ALPM_SMBOUTB(sc, SMBCMD, SMBWRBLOCK | SMB_BLK_CLR);
  558 
  559         ALPM_SMBOUTB(sc, SMBHDATA, count);
  560 
  561         /* fill the 32-byte internal buffer */
  562         for (i = 0; i < count; i++) {
  563                 ALPM_SMBOUTB(sc, SMBHBLOCK, buf[i]);
  564                 DELAY(2);
  565         }
  566         ALPM_SMBOUTB(sc, SMBHCMD, cmd);
  567         ALPM_SMBOUTB(sc, SMBSTART, 0xff);
  568 
  569         error = alpm_wait(sc);
  570 
  571         ALPM_DEBUG(kprintf("alpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
  572         ALPM_UNLOCK(sc);
  573 
  574         return (error);
  575 }
  576 
  577 static int
  578 alpm_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
  579 {
  580         struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
  581         u_char data, len, i;
  582         int error;
  583 
  584         if (*count < 1 || *count > 32)
  585                 return (SMB_EINVAL);
  586 
  587         ALPM_LOCK(sc);
  588         alpm_clear(sc);
  589         if (!alpm_idle(sc)) {
  590                 ALPM_UNLOCK(sc);
  591                 return (SMB_EBUSY);
  592         }
  593 
  594         ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB);
  595 
  596         /* set the cmd and reset the
  597          * 32-byte long internal buffer */
  598         ALPM_SMBOUTB(sc, SMBCMD, SMBWRBLOCK | SMB_BLK_CLR);
  599 
  600         ALPM_SMBOUTB(sc, SMBHCMD, cmd);
  601         ALPM_SMBOUTB(sc, SMBSTART, 0xff);
  602 
  603         if ((error = alpm_wait(sc)) != SMB_ENOERR)
  604                 goto error;
  605 
  606         len = ALPM_SMBINB(sc, SMBHDATA);
  607 
  608         /* read the 32-byte internal buffer */
  609         for (i = 0; i < len; i++) {
  610                 data = ALPM_SMBINB(sc, SMBHBLOCK);
  611                 if (i < *count)
  612                         buf[i] = data;
  613                 DELAY(2);
  614         }
  615         *count = len;
  616 
  617 error:
  618         ALPM_DEBUG(kprintf("alpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error));
  619         ALPM_UNLOCK(sc);
  620 
  621         return (error);
  622 }
  623 
  624 static devclass_t alpm_devclass;
  625 
  626 static device_method_t alpm_methods[] = {
  627         /* device interface */
  628         DEVMETHOD(device_probe,         alpm_probe),
  629         DEVMETHOD(device_attach,        alpm_attach),
  630         DEVMETHOD(device_detach,        alpm_detach),
  631 
  632         /* smbus interface */
  633         DEVMETHOD(smbus_callback,       alpm_callback),
  634         DEVMETHOD(smbus_quick,          alpm_quick),
  635         DEVMETHOD(smbus_sendb,          alpm_sendb),
  636         DEVMETHOD(smbus_recvb,          alpm_recvb),
  637         DEVMETHOD(smbus_writeb,         alpm_writeb),
  638         DEVMETHOD(smbus_readb,          alpm_readb),
  639         DEVMETHOD(smbus_writew,         alpm_writew),
  640         DEVMETHOD(smbus_readw,          alpm_readw),
  641         DEVMETHOD(smbus_bwrite,         alpm_bwrite),
  642         DEVMETHOD(smbus_bread,          alpm_bread),
  643 
  644         DEVMETHOD_END
  645 };
  646 
  647 static driver_t alpm_driver = {
  648         "alpm",
  649         alpm_methods,
  650         sizeof(struct alpm_softc)
  651 };
  652 
  653 DRIVER_MODULE(alpm, pci, alpm_driver, alpm_devclass, NULL, NULL);
  654 DRIVER_MODULE(smbus, alpm, smbus_driver, smbus_devclass, NULL, NULL);
  655 MODULE_DEPEND(alpm, pci, 1, 1, 1);
  656 MODULE_DEPEND(alpm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
  657 MODULE_VERSION(alpm, 1);

Cache object: 2e813969233a48e5c01aedd1648d11ac


[ 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.