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

FreeBSD/Linux Kernel Cross Reference
sys/pci/alpm.c

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

Cache object: dd62765f0641da43cd4da217b0f5d147


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