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

Cache object: f96d60ca1b44536ac8e0d5885f50c978


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