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

Cache object: aadf314438bc9cc4421296f16cd98a1f


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