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/viapm.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) 2001 Alcove - 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 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: releng/6.3/sys/pci/viapm.c 173886 2007-11-24 19:45:58Z cvs2svn $");
   29 
   30 #include "opt_isa.h"
   31 
   32 #include <sys/param.h>
   33 #include <sys/kernel.h>
   34 #include <sys/systm.h>
   35 #include <sys/module.h>
   36 #include <sys/bus.h>
   37 #include <sys/uio.h>
   38 
   39 #include <machine/bus.h>
   40 #include <machine/clock.h>              /* for DELAY */
   41 #include <machine/resource.h>
   42 #include <sys/rman.h>
   43 
   44 #ifdef DEV_ISA
   45 #include <isa/isavar.h>
   46 #include <isa/isa_common.h>
   47 #endif
   48 #include <dev/pci/pcivar.h>
   49 #include <dev/pci/pcireg.h>
   50 
   51 #include <dev/iicbus/iiconf.h>
   52 
   53 #include <dev/smbus/smbconf.h>
   54 
   55 #include "iicbb_if.h"
   56 #include "smbus_if.h"
   57 
   58 #define VIAPM_DEBUG(x)  if (viapm_debug) (x)
   59 
   60 #ifdef DEBUG
   61 static int viapm_debug = 1;
   62 #else
   63 static int viapm_debug = 0;
   64 #endif
   65 
   66 #define VIA_586B_PMU_ID         0x30401106
   67 #define VIA_596A_PMU_ID         0x30501106
   68 #define VIA_596B_PMU_ID         0x30511106
   69 #define VIA_686A_PMU_ID         0x30571106
   70 #define VIA_8233_PMU_ID         0x30741106
   71 #define VIA_8233A_PMU_ID        0x31471106
   72 #define VIA_8235_PMU_ID         0x31771106
   73 
   74 #define VIAPM_INB(port) \
   75         ((u_char)bus_space_read_1(viapm->st, viapm->sh, port))
   76 #define VIAPM_OUTB(port,val) \
   77         (bus_space_write_1(viapm->st, viapm->sh, port, (u_char)(val)))
   78 
   79 #define VIAPM_TYP_UNKNOWN       0
   80 #define VIAPM_TYP_586B_3040E    1
   81 #define VIAPM_TYP_586B_3040F    2
   82 #define VIAPM_TYP_596B          3
   83 #define VIAPM_TYP_686A          4
   84 #define VIAPM_TYP_8233          5
   85 
   86 struct viapm_softc {
   87         int type;
   88         u_int32_t base;
   89         bus_space_tag_t st;
   90         bus_space_handle_t sh;
   91         int iorid;
   92         int irqrid;
   93         struct resource *iores;
   94         struct resource *irqres;
   95         void *irqih;
   96 
   97         device_t iicbb;
   98         device_t smbus;
   99 };
  100 
  101 static devclass_t viapm_devclass;
  102 static devclass_t viapropm_devclass;
  103 
  104 /*
  105  * VT82C586B definitions
  106  */
  107 
  108 #define VIAPM_586B_REVID        0x08
  109 
  110 #define VIAPM_586B_3040E_BASE   0x20
  111 #define VIAPM_586B_3040E_ACTIV  0x4             /* 16 bits */
  112 
  113 #define VIAPM_586B_3040F_BASE   0x48
  114 #define VIAPM_586B_3040F_ACTIV  0x41            /* 8 bits */
  115 
  116 #define VIAPM_586B_OEM_REV_E    0x00
  117 #define VIAPM_586B_OEM_REV_F    0x01
  118 #define VIAPM_586B_PROD_REV_A   0x10
  119 
  120 #define VIAPM_586B_BA_MASK      0x0000ff00
  121 
  122 #define GPIO_DIR        0x40
  123 #define GPIO_VAL        0x42
  124 #define EXTSMI_VAL      0x44
  125 
  126 #define VIAPM_SCL       0x02                    /* GPIO1_VAL */
  127 #define VIAPM_SDA       0x04                    /* GPIO2_VAL */
  128 
  129 /*
  130  * VIAPRO common definitions
  131  */
  132 
  133 #define VIAPM_PRO_BA_MASK       0x0000fff0
  134 #define VIAPM_PRO_SMBCTRL       0xd2
  135 #define VIAPM_PRO_REVID         0xd6
  136 
  137 /*
  138  * VT82C686A definitions
  139  */
  140 
  141 #define VIAPM_PRO_BASE          0x90
  142 
  143 #define SMBHST                  0x0
  144 #define SMBHSL                  0x1
  145 #define SMBHCTRL                0x2
  146 #define SMBHCMD                 0x3
  147 #define SMBHADDR                0x4
  148 #define SMBHDATA0               0x5
  149 #define SMBHDATA1               0x6
  150 #define SMBHBLOCK               0x7
  151 
  152 #define SMBSST                  0x1
  153 #define SMBSCTRL                0x8
  154 #define SMBSSDWCMD              0x9
  155 #define SMBSEVENT               0xa
  156 #define SMBSDATA                0xc
  157 
  158 #define SMBHST_RESERVED         0xef    /* reserved bits */
  159 #define SMBHST_FAILED           0x10    /* failed bus transaction */
  160 #define SMBHST_COLLID           0x08    /* bus collision */
  161 #define SMBHST_ERROR            0x04    /* device error */
  162 #define SMBHST_INTR             0x02    /* command completed */
  163 #define SMBHST_BUSY             0x01    /* host busy */
  164 
  165 #define SMBHCTRL_START          0x40    /* start command */
  166 #define SMBHCTRL_PROTO          0x1c    /* command protocol mask */
  167 #define SMBHCTRL_QUICK          0x00
  168 #define SMBHCTRL_SENDRECV       0x04
  169 #define SMBHCTRL_BYTE           0x08
  170 #define SMBHCTRL_WORD           0x0c
  171 #define SMBHCTRL_BLOCK          0x14
  172 #define SMBHCTRL_KILL           0x02    /* stop the current transaction */
  173 #define SMBHCTRL_ENABLE         0x01    /* enable interrupts */
  174 
  175 #define SMBSCTRL_ENABLE         0x01    /* enable slave */
  176 
  177 
  178 /*
  179  * VIA8233 definitions
  180  */
  181 
  182 #define VIAPM_8233_BASE         0xD0
  183 
  184 static int
  185 viapm_586b_probe(device_t dev)
  186 {
  187         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  188         u_int32_t l;
  189         u_int16_t s;
  190         u_int8_t c;
  191 
  192         switch (pci_get_devid(dev)) {
  193         case VIA_586B_PMU_ID:
  194 
  195                 bzero(viapm, sizeof(struct viapm_softc));
  196 
  197                 l = pci_read_config(dev, VIAPM_586B_REVID, 1);
  198                 switch (l) {
  199                 case VIAPM_586B_OEM_REV_E:
  200                         viapm->type = VIAPM_TYP_586B_3040E;
  201                         viapm->iorid = VIAPM_586B_3040E_BASE;
  202 
  203                         /* Activate IO block access */
  204                         s = pci_read_config(dev, VIAPM_586B_3040E_ACTIV, 2);
  205                         pci_write_config(dev, VIAPM_586B_3040E_ACTIV, s | 0x1, 2);
  206                         break;
  207 
  208                 case VIAPM_586B_OEM_REV_F:
  209                 case VIAPM_586B_PROD_REV_A:
  210                 default:
  211                         viapm->type = VIAPM_TYP_586B_3040F;
  212                         viapm->iorid = VIAPM_586B_3040F_BASE;
  213 
  214                         /* Activate IO block access */
  215                         c = pci_read_config(dev, VIAPM_586B_3040F_ACTIV, 1);
  216                         pci_write_config(dev, VIAPM_586B_3040F_ACTIV, c | 0x80, 1);
  217                         break;
  218                 }
  219 
  220                 viapm->base = pci_read_config(dev, viapm->iorid, 4) &
  221                                 VIAPM_586B_BA_MASK;
  222 
  223                 /*
  224                  * We have to set the I/O resources by hand because it is
  225                  * described outside the viapmope of the traditional maps
  226                  */
  227                 if (bus_set_resource(dev, SYS_RES_IOPORT, viapm->iorid,
  228                                                         viapm->base, 256)) {
  229                         device_printf(dev, "could not set bus resource\n");
  230                         return ENXIO;
  231                 }
  232                 device_set_desc(dev, "VIA VT82C586B Power Management Unit");
  233                 return (BUS_PROBE_DEFAULT);
  234 
  235         default:
  236                 break;
  237         }
  238 
  239         return ENXIO;
  240 }
  241 
  242 
  243 static int
  244 viapm_pro_probe(device_t dev)
  245 {
  246         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  247 #ifdef VIAPM_BASE_ADDR
  248         u_int32_t l;
  249 #endif
  250         u_int32_t base_cfgreg;
  251         char *desc;
  252 
  253         switch (pci_get_devid(dev)) {
  254         case VIA_596A_PMU_ID:
  255                 desc = "VIA VT82C596A Power Management Unit";
  256                 viapm->type = VIAPM_TYP_596B;
  257                 base_cfgreg = VIAPM_PRO_BASE;
  258                 goto viapro;
  259 
  260         case VIA_596B_PMU_ID:
  261                 desc = "VIA VT82C596B Power Management Unit";
  262                 viapm->type = VIAPM_TYP_596B;
  263                 base_cfgreg = VIAPM_PRO_BASE;
  264                 goto viapro;
  265 
  266         case VIA_686A_PMU_ID:
  267                 desc = "VIA VT82C686A Power Management Unit";
  268                 viapm->type = VIAPM_TYP_686A;
  269                 base_cfgreg = VIAPM_PRO_BASE;
  270                 goto viapro;
  271 
  272         case VIA_8233_PMU_ID:
  273         case VIA_8233A_PMU_ID:
  274                 desc = "VIA VT8233 Power Management Unit";
  275                 viapm->type = VIAPM_TYP_UNKNOWN;
  276                 base_cfgreg = VIAPM_8233_BASE;
  277                 goto viapro;
  278 
  279         case VIA_8235_PMU_ID:
  280                 desc = "VIA VT8235 Power Management Unit";
  281                 viapm->type = VIAPM_TYP_UNKNOWN;
  282                 base_cfgreg = VIAPM_8233_BASE;
  283                 goto viapro;
  284 
  285         viapro:
  286 
  287 #ifdef VIAPM_BASE_ADDR
  288                 /* force VIAPM I/O base address */
  289 
  290                 /* enable the SMBus controller function */
  291                 l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
  292                 pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 1, 1);
  293 
  294                 /* write the base address */
  295                 pci_write_config(dev, base_cfgreg,
  296                                  VIAPM_BASE_ADDR & VIAPM_PRO_BA_MASK, 4);
  297 #endif
  298 
  299                 viapm->base = pci_read_config(dev, base_cfgreg, 4) & VIAPM_PRO_BA_MASK;
  300 
  301                 /*
  302                  * We have to set the I/O resources by hand because it is
  303                  * described outside the viapmope of the traditional maps
  304                  */
  305                 viapm->iorid = base_cfgreg;
  306                 if (bus_set_resource(dev, SYS_RES_IOPORT, viapm->iorid,
  307                                      viapm->base, 16)) {
  308                         device_printf(dev, "could not set bus resource 0x%x\n",
  309                                         viapm->base);
  310                         return ENXIO;
  311                 }
  312 
  313                 if (1 || bootverbose) {
  314                         device_printf(dev, "SMBus I/O base at 0x%x\n", viapm->base);
  315                 }
  316 
  317                 device_set_desc(dev, desc);
  318                 return (BUS_PROBE_DEFAULT);
  319 
  320         default:
  321                 break;
  322         }
  323 
  324         return ENXIO;
  325 }
  326 
  327 static int
  328 viapm_pro_attach(device_t dev)
  329 {
  330         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  331         u_int32_t l;
  332 
  333         if (!(viapm->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
  334                 &viapm->iorid, RF_ACTIVE))) {
  335                 device_printf(dev, "could not allocate bus space\n");
  336                 goto error;
  337         }
  338         viapm->st = rman_get_bustag(viapm->iores);
  339         viapm->sh = rman_get_bushandle(viapm->iores);
  340 
  341 #if notyet
  342         /* force irq 9 */
  343         l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
  344         pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 0x80, 1);
  345 
  346         viapm->irqrid = 0;
  347         if (!(viapm->irqres = bus_alloc_resource(dev, SYS_RES_IRQ,
  348                                 &viapm->irqrid, 9, 9, 1,
  349                                 RF_SHAREABLE | RF_ACTIVE))) {
  350                 device_printf(dev, "could not allocate irq\n");
  351                 goto error;
  352         }
  353 
  354         if (bus_setup_intr(dev, viapm->irqres, INTR_TYPE_MISC,
  355                         (driver_intr_t *) viasmb_intr, viapm, &viapm->irqih)) {
  356                 device_printf(dev, "could not setup irq\n");
  357                 goto error;
  358         }
  359 #endif
  360 
  361         if (1 | bootverbose) {
  362                 l = pci_read_config(dev, VIAPM_PRO_REVID, 1);
  363                 device_printf(dev, "SMBus revision code 0x%x\n", l);
  364         }
  365 
  366         viapm->smbus = device_add_child(dev, "smbus", -1);
  367 
  368         /* probe and attach the smbus */
  369         bus_generic_attach(dev);
  370 
  371         /* disable slave function */
  372         VIAPM_OUTB(SMBSCTRL, VIAPM_INB(SMBSCTRL) & ~SMBSCTRL_ENABLE);
  373 
  374         /* enable the SMBus controller function */
  375         l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
  376         pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 1, 1);
  377 
  378 #if notyet
  379         /* enable interrupts */
  380         VIAPM_OUTB(SMBHCTRL, VIAPM_INB(SMBHCTRL) | SMBHCTRL_ENABLE);
  381 #endif
  382 
  383 #ifdef DEV_ISA
  384         /* If this device is a PCI-ISA bridge, then attach an ISA bus. */
  385         if ((pci_get_class(dev) == PCIC_BRIDGE) &&
  386             (pci_get_subclass(dev) == PCIS_BRIDGE_ISA))
  387                 isab_attach(dev);
  388 #endif
  389         return 0;
  390 
  391 error:
  392         if (viapm->iores)
  393                 bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, viapm->iores);
  394 #if notyet
  395         if (viapm->irqres)
  396                 bus_release_resource(dev, SYS_RES_IRQ, viapm->irqrid, viapm->irqres);
  397 #endif
  398 
  399         return ENXIO;
  400 }
  401 
  402 static int
  403 viapm_586b_attach(device_t dev)
  404 {
  405         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  406         
  407         if (!(viapm->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
  408                 &viapm->iorid, RF_ACTIVE | RF_SHAREABLE))) {
  409                 device_printf(dev, "could not allocate bus resource\n");
  410                 return ENXIO;
  411         }
  412         viapm->st = rman_get_bustag(viapm->iores);
  413         viapm->sh = rman_get_bushandle(viapm->iores);
  414 
  415         VIAPM_OUTB(GPIO_DIR, VIAPM_INB(GPIO_DIR) | VIAPM_SCL | VIAPM_SDA);
  416 
  417         /* add generic bit-banging code */
  418         if (!(viapm->iicbb = device_add_child(dev, "iicbb", -1)))
  419                 goto error;
  420 
  421         bus_generic_attach(dev);
  422 
  423         return 0;
  424 
  425 error:
  426         if (viapm->iores)
  427                 bus_release_resource(dev, SYS_RES_IOPORT,
  428                                         viapm->iorid, viapm->iores);
  429         return ENXIO;
  430 }
  431 
  432 static int
  433 viapm_586b_detach(device_t dev)
  434 {
  435         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  436         int error;
  437 
  438         bus_generic_detach(dev);
  439         if (viapm->iicbb) {
  440                 device_delete_child(dev, viapm->iicbb);
  441         }
  442 
  443         if (viapm->iores && (error = bus_release_resource(dev, SYS_RES_IOPORT,
  444                                                 viapm->iorid, viapm->iores)))
  445                 return (error);
  446 
  447         return 0;
  448 }
  449 
  450 static int
  451 viapm_pro_detach(device_t dev)
  452 {
  453         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  454         int error;
  455 
  456         bus_generic_detach(dev);
  457         if (viapm->smbus) {
  458                 device_delete_child(dev, viapm->smbus);
  459         }
  460 
  461         if ((error = bus_release_resource(dev, SYS_RES_IOPORT,
  462                                 viapm->iorid, viapm->iores)))
  463                 return (error);
  464 
  465 #if notyet
  466         if ((error = bus_release_resource(dev, SYS_RES_IRQ,
  467                                         viapm->irqrid, viapm->irqres))
  468                 return (error);
  469 #endif
  470 
  471         return 0;
  472 }
  473 
  474 static int
  475 viabb_callback(device_t dev, int index, caddr_t *data)
  476 {
  477         return 0;
  478 }
  479 
  480 static void
  481 viabb_setscl(device_t dev, int ctrl)
  482 {
  483         struct viapm_softc *viapm = device_get_softc(dev);
  484         u_char val;
  485 
  486         val = VIAPM_INB(GPIO_VAL);
  487 
  488         if (ctrl)
  489                 val |= VIAPM_SCL;
  490         else
  491                 val &= ~VIAPM_SCL;
  492 
  493         VIAPM_OUTB(GPIO_VAL, val);
  494 
  495         return;
  496 }
  497 
  498 static void
  499 viabb_setsda(device_t dev, int data)
  500 {
  501         struct viapm_softc *viapm = device_get_softc(dev);
  502         u_char val;
  503 
  504         val = VIAPM_INB(GPIO_VAL);
  505 
  506         if (data)
  507                 val |= VIAPM_SDA;
  508         else
  509                 val &= ~VIAPM_SDA;
  510 
  511         VIAPM_OUTB(GPIO_VAL, val);
  512 
  513         return;
  514 }
  515         
  516 static int
  517 viabb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
  518 {
  519         /* reset bus */
  520         viabb_setsda(dev, 1);
  521         viabb_setscl(dev, 1);
  522 
  523         return (IIC_ENOADDR);
  524 }
  525 
  526 static int
  527 viabb_getscl(device_t dev)
  528 {
  529         struct viapm_softc *viapm = device_get_softc(dev);
  530 
  531         return ((VIAPM_INB(EXTSMI_VAL) & VIAPM_SCL) != 0);
  532 }
  533 
  534 static int
  535 viabb_getsda(device_t dev)
  536 {
  537         struct viapm_softc *viapm = device_get_softc(dev);
  538 
  539         return ((VIAPM_INB(EXTSMI_VAL) & VIAPM_SDA) != 0);
  540 }
  541 
  542 static int
  543 viapm_abort(struct viapm_softc *viapm)
  544 {
  545         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_KILL);
  546         DELAY(10);
  547 
  548         return (0);
  549 }
  550 
  551 static int
  552 viapm_clear(struct viapm_softc *viapm)
  553 {
  554         VIAPM_OUTB(SMBHST, SMBHST_FAILED | SMBHST_COLLID |
  555                 SMBHST_ERROR | SMBHST_INTR);
  556         DELAY(10);
  557 
  558         return (0);
  559 }
  560 
  561 static int
  562 viapm_busy(struct viapm_softc *viapm)
  563 {
  564         u_char sts;
  565 
  566         sts = VIAPM_INB(SMBHST);
  567 
  568         VIAPM_DEBUG(printf("viapm: idle? STS=0x%x\n", sts));
  569 
  570         return (sts & SMBHST_BUSY);
  571 }
  572 
  573 /*
  574  * Poll the SMBus controller
  575  */
  576 static int
  577 viapm_wait(struct viapm_softc *viapm)
  578 {
  579         int count = 10000;
  580         u_char sts = 0;
  581         int error;
  582 
  583         /* wait for command to complete and SMBus controller is idle */
  584         while(count--) {
  585                 DELAY(10);
  586                 sts = VIAPM_INB(SMBHST);
  587 
  588                 /* check if the controller is processing a command */
  589                 if (!(sts & SMBHST_BUSY) && (sts & SMBHST_INTR))
  590                         break;
  591         }
  592 
  593         VIAPM_DEBUG(printf("viapm: SMBHST=0x%x\n", sts));
  594 
  595         error = SMB_ENOERR;
  596 
  597         if (!count)
  598                 error |= SMB_ETIMEOUT;
  599 
  600         if (sts & SMBHST_FAILED)
  601                 error |= SMB_EABORT;
  602 
  603         if (sts & SMBHST_COLLID)
  604                 error |= SMB_ENOACK;
  605 
  606         if (sts & SMBHST_ERROR)
  607                 error |= SMB_EBUSERR;
  608 
  609         if (error != SMB_ENOERR)
  610                 viapm_abort(viapm);
  611 
  612         viapm_clear(viapm);
  613 
  614         return (error);
  615 }
  616 
  617 static int
  618 viasmb_callback(device_t dev, int index, caddr_t *data)
  619 {
  620         int error = 0;
  621 
  622         switch (index) {
  623         case SMB_REQUEST_BUS:
  624         case SMB_RELEASE_BUS:
  625                 /* ok, bus allocation accepted */
  626                 break;
  627         default:
  628                 error = EINVAL;
  629         }
  630 
  631         return (error);
  632 }
  633 
  634 static int
  635 viasmb_quick(device_t dev, u_char slave, int how)
  636 {
  637         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  638         int error;
  639 
  640         viapm_clear(viapm);
  641         if (viapm_busy(viapm))
  642                 return (SMB_EBUSY);
  643 
  644         switch (how) {
  645         case SMB_QWRITE:
  646                 VIAPM_DEBUG(printf("viapm: QWRITE to 0x%x", slave));
  647                 VIAPM_OUTB(SMBHADDR, slave & ~LSB);
  648                 break;
  649         case SMB_QREAD:
  650                 VIAPM_DEBUG(printf("viapm: QREAD to 0x%x", slave));
  651                 VIAPM_OUTB(SMBHADDR, slave | LSB);
  652                 break;
  653         default:
  654                 panic("%s: unknown QUICK command (%x)!", __func__, how);
  655         }
  656 
  657         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_QUICK);
  658 
  659         error = viapm_wait(viapm);
  660 
  661         return (error);
  662 }
  663 
  664 static int
  665 viasmb_sendb(device_t dev, u_char slave, char byte)
  666 {
  667         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  668         int error;
  669 
  670         viapm_clear(viapm);
  671         if (viapm_busy(viapm))
  672                 return (SMB_EBUSY);
  673 
  674         VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
  675         VIAPM_OUTB(SMBHCMD, byte);
  676 
  677         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_SENDRECV);
  678 
  679         error = viapm_wait(viapm);
  680 
  681         VIAPM_DEBUG(printf("viapm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
  682 
  683         return (error);
  684 }
  685 
  686 static int
  687 viasmb_recvb(device_t dev, u_char slave, char *byte)
  688 {
  689         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  690         int error;
  691 
  692         viapm_clear(viapm);
  693         if (viapm_busy(viapm))
  694                 return (SMB_EBUSY);
  695 
  696         VIAPM_OUTB(SMBHADDR, slave | LSB);
  697 
  698         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_SENDRECV);
  699 
  700         if ((error = viapm_wait(viapm)) == SMB_ENOERR)
  701                 *byte = VIAPM_INB(SMBHDATA0);
  702 
  703         VIAPM_DEBUG(printf("viapm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
  704 
  705         return (error);
  706 }
  707 
  708 static int
  709 viasmb_writeb(device_t dev, u_char slave, char cmd, char byte)
  710 {
  711         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  712         int error;
  713 
  714         viapm_clear(viapm);
  715         if (viapm_busy(viapm))
  716                 return (SMB_EBUSY);
  717 
  718         VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
  719         VIAPM_OUTB(SMBHCMD, cmd);
  720         VIAPM_OUTB(SMBHDATA0, byte);
  721 
  722         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BYTE);
  723 
  724         error = viapm_wait(viapm);
  725 
  726         VIAPM_DEBUG(printf("viapm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
  727 
  728         return (error);
  729 }
  730 
  731 static int
  732 viasmb_readb(device_t dev, u_char slave, char cmd, char *byte)
  733 {
  734         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  735         int error;
  736 
  737         viapm_clear(viapm);
  738         if (viapm_busy(viapm))
  739                 return (SMB_EBUSY);
  740 
  741         VIAPM_OUTB(SMBHADDR, slave | LSB);
  742         VIAPM_OUTB(SMBHCMD, cmd);
  743 
  744         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BYTE);
  745 
  746         if ((error = viapm_wait(viapm)) == SMB_ENOERR)
  747                 *byte = VIAPM_INB(SMBHDATA0);
  748 
  749         VIAPM_DEBUG(printf("viapm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
  750 
  751         return (error);
  752 }
  753 
  754 static int
  755 viasmb_writew(device_t dev, u_char slave, char cmd, short word)
  756 {
  757         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  758         int error;
  759 
  760         viapm_clear(viapm);
  761         if (viapm_busy(viapm))
  762                 return (SMB_EBUSY);
  763 
  764         VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
  765         VIAPM_OUTB(SMBHCMD, cmd);
  766         VIAPM_OUTB(SMBHDATA0, word & 0x00ff);
  767         VIAPM_OUTB(SMBHDATA1, (word & 0xff00) >> 8);
  768 
  769         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_WORD);
  770 
  771         error = viapm_wait(viapm);
  772 
  773         VIAPM_DEBUG(printf("viapm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
  774 
  775         return (error);
  776 }
  777 
  778 static int
  779 viasmb_readw(device_t dev, u_char slave, char cmd, short *word)
  780 {
  781         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  782         int error;
  783         u_char high, low;
  784 
  785         viapm_clear(viapm);
  786         if (viapm_busy(viapm))
  787                 return (SMB_EBUSY);
  788 
  789         VIAPM_OUTB(SMBHADDR, slave | LSB);
  790         VIAPM_OUTB(SMBHCMD, cmd);
  791 
  792         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_WORD);
  793 
  794         if ((error = viapm_wait(viapm)) == SMB_ENOERR) {
  795                 low = VIAPM_INB(SMBHDATA0);
  796                 high = VIAPM_INB(SMBHDATA1);
  797 
  798                 *word = ((high & 0xff) << 8) | (low & 0xff);
  799         }
  800 
  801         VIAPM_DEBUG(printf("viapm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
  802 
  803         return (error);
  804 }
  805 
  806 static int
  807 viasmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
  808 {
  809         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  810         u_char i;
  811         int error;
  812 
  813         if (count < 1 || count > 32)
  814                 return (SMB_EINVAL);
  815 
  816         viapm_clear(viapm);
  817         if (viapm_busy(viapm))
  818                 return (SMB_EBUSY);
  819 
  820         VIAPM_OUTB(SMBHADDR, slave & ~LSB);
  821         VIAPM_OUTB(SMBHCMD, cmd);
  822         VIAPM_OUTB(SMBHDATA0, count);
  823         i = VIAPM_INB(SMBHCTRL);
  824 
  825         /* fill the 32-byte internal buffer */
  826         for (i = 0; i < count; i++) {
  827                 VIAPM_OUTB(SMBHBLOCK, buf[i]);
  828                 DELAY(2);
  829         }
  830         VIAPM_OUTB(SMBHCMD, cmd);
  831         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK);
  832 
  833         error = viapm_wait(viapm);
  834 
  835         VIAPM_DEBUG(printf("viapm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
  836 
  837         return (error);
  838 
  839 }
  840 
  841 static int
  842 viasmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
  843 {
  844         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  845         u_char data, len, i;
  846         int error;
  847 
  848         if (*count < 1 || *count > 32)
  849                 return (SMB_EINVAL);
  850 
  851         viapm_clear(viapm);
  852         if (viapm_busy(viapm))
  853                 return (SMB_EBUSY);
  854 
  855         VIAPM_OUTB(SMBHADDR, slave | LSB);
  856         VIAPM_OUTB(SMBHCMD, cmd);
  857         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK);
  858 
  859         if ((error = viapm_wait(viapm)) != SMB_ENOERR)
  860                 goto error;
  861 
  862         len = VIAPM_INB(SMBHDATA0);
  863         i = VIAPM_INB(SMBHCTRL);                /* reset counter */
  864 
  865         /* read the 32-byte internal buffer */
  866         for (i = 0; i < len; i++) {
  867                 data = VIAPM_INB(SMBHBLOCK);
  868                 if (i < *count)
  869                         buf[i] = data;
  870                 DELAY(2);
  871         }
  872         *count = len;
  873 
  874 error:
  875         VIAPM_DEBUG(printf("viapm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error));
  876 
  877         return (error);
  878 }
  879 
  880 static device_method_t viapm_methods[] = {
  881         /* device interface */
  882         DEVMETHOD(device_probe,         viapm_586b_probe),
  883         DEVMETHOD(device_attach,        viapm_586b_attach),
  884         DEVMETHOD(device_detach,        viapm_586b_detach),
  885 
  886         /* iicbb interface */
  887         DEVMETHOD(iicbb_callback,       viabb_callback),
  888         DEVMETHOD(iicbb_setscl,         viabb_setscl),
  889         DEVMETHOD(iicbb_setsda,         viabb_setsda),
  890         DEVMETHOD(iicbb_getscl,         viabb_getscl),
  891         DEVMETHOD(iicbb_getsda,         viabb_getsda),
  892         DEVMETHOD(iicbb_reset,          viabb_reset),
  893 
  894         /* Bus interface */
  895         DEVMETHOD(bus_print_child,      bus_generic_print_child),
  896         DEVMETHOD(bus_alloc_resource,   bus_generic_alloc_resource),
  897         DEVMETHOD(bus_release_resource, bus_generic_release_resource),
  898         DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
  899         DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
  900         DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
  901         DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
  902 
  903         { 0, 0 }
  904 };
  905 
  906 static driver_t viapm_driver = {
  907         "viapm",
  908         viapm_methods,
  909         sizeof(struct viapm_softc),
  910 };
  911 
  912 static device_method_t viapropm_methods[] = {
  913         /* device interface */
  914         DEVMETHOD(device_probe,         viapm_pro_probe),
  915         DEVMETHOD(device_attach,        viapm_pro_attach),
  916         DEVMETHOD(device_detach,        viapm_pro_detach),
  917 
  918         /* smbus interface */
  919         DEVMETHOD(smbus_callback,       viasmb_callback),
  920         DEVMETHOD(smbus_quick,          viasmb_quick),
  921         DEVMETHOD(smbus_sendb,          viasmb_sendb),
  922         DEVMETHOD(smbus_recvb,          viasmb_recvb),
  923         DEVMETHOD(smbus_writeb,         viasmb_writeb),
  924         DEVMETHOD(smbus_readb,          viasmb_readb),
  925         DEVMETHOD(smbus_writew,         viasmb_writew),
  926         DEVMETHOD(smbus_readw,          viasmb_readw),
  927         DEVMETHOD(smbus_bwrite,         viasmb_bwrite),
  928         DEVMETHOD(smbus_bread,          viasmb_bread),
  929         
  930         /* Bus interface */
  931         DEVMETHOD(bus_print_child,      bus_generic_print_child),
  932         DEVMETHOD(bus_alloc_resource,   bus_generic_alloc_resource),
  933         DEVMETHOD(bus_release_resource, bus_generic_release_resource),
  934         DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
  935         DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
  936         DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
  937         DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
  938 
  939         { 0, 0 }
  940 };
  941 
  942 static driver_t viapropm_driver = {
  943         "viapropm",
  944         viapropm_methods,
  945         sizeof(struct viapm_softc),
  946 };
  947 
  948 DRIVER_MODULE(viapm, pci, viapm_driver, viapm_devclass, 0, 0);
  949 DRIVER_MODULE(viapropm, pci, viapropm_driver, viapropm_devclass, 0, 0);
  950 DRIVER_MODULE(smbus, viapropm, smbus_driver, smbus_devclass, 0, 0);
  951 
  952 MODULE_DEPEND(viapm, pci, 1, 1, 1);
  953 MODULE_DEPEND(viapropm, pci, 1, 1, 1);
  954 MODULE_DEPEND(viapm, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER);
  955 MODULE_DEPEND(viapropm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
  956 MODULE_VERSION(viapm, 1);
  957 
  958 #ifdef DEV_ISA
  959 DRIVER_MODULE(isa, viapm, isa_driver, isa_devclass, 0, 0);
  960 DRIVER_MODULE(isa, viapropm, isa_driver, isa_devclass, 0, 0);
  961 MODULE_DEPEND(viapm, isa, 1, 1, 1);
  962 MODULE_DEPEND(viapropm, isa, 1, 1, 1);
  963 #endif

Cache object: 4279b0d8b7590b368e876815244debed


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