The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


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

FreeBSD/Linux Kernel Cross Reference
sys/dev/iicbus/iiconf.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 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: releng/5.0/sys/dev/iicbus/iiconf.c 93023 2002-03-23 15:49:15Z nsouch $
   27  *
   28  */
   29 #include <sys/param.h>
   30 #include <sys/systm.h>
   31 #include <sys/module.h>
   32 #include <sys/bus.h>
   33 
   34 #include <dev/iicbus/iiconf.h>
   35 #include <dev/iicbus/iicbus.h>
   36 #include "iicbus_if.h"
   37 
   38 /*
   39  * iicbus_intr()
   40  */
   41 void
   42 iicbus_intr(device_t bus, int event, char *buf)
   43 {
   44         struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
   45 
   46         /* call owner's intr routine */
   47         if (sc->owner)
   48                 IICBUS_INTR(sc->owner, event, buf);
   49 
   50         return;
   51 }
   52 
   53 static int
   54 iicbus_poll(struct iicbus_softc *sc, int how)
   55 {
   56         int error;
   57 
   58         switch (how) {
   59         case (IIC_WAIT | IIC_INTR):
   60                 error = tsleep(sc, IICPRI|PCATCH, "iicreq", 0);
   61                 break;
   62 
   63         case (IIC_WAIT | IIC_NOINTR):
   64                 error = tsleep(sc, IICPRI, "iicreq", 0);
   65                 break;
   66 
   67         default:
   68                 return (EWOULDBLOCK);
   69                 break;
   70         }
   71 
   72         return (error);
   73 }
   74 
   75 /*
   76  * iicbus_request_bus()
   77  *
   78  * Allocate the device to perform transfers.
   79  *
   80  * how  : IIC_WAIT or IIC_DONTWAIT
   81  */
   82 int
   83 iicbus_request_bus(device_t bus, device_t dev, int how)
   84 {
   85         struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
   86         int s, error = 0;
   87 
   88         /* first, ask the underlying layers if the request is ok */
   89         do {
   90                 error = IICBUS_CALLBACK(device_get_parent(bus),
   91                                                 IIC_REQUEST_BUS, (caddr_t)&how);
   92                 if (error)
   93                         error = iicbus_poll(sc, how);
   94         } while (error == EWOULDBLOCK);
   95 
   96         while (!error) {
   97                 s = splhigh();  
   98                 if (sc->owner && sc->owner != dev) {
   99                         splx(s);
  100 
  101                         error = iicbus_poll(sc, how);
  102                 } else {
  103                         sc->owner = dev;
  104 
  105                         splx(s);
  106                         return (0);
  107                 }
  108 
  109                 /* free any allocated resource */
  110                 if (error)
  111                         IICBUS_CALLBACK(device_get_parent(bus), IIC_RELEASE_BUS,
  112                                         (caddr_t)&how);
  113         }
  114 
  115         return (error);
  116 }
  117 
  118 /*
  119  * iicbus_release_bus()
  120  *
  121  * Release the device allocated with iicbus_request_dev()
  122  */
  123 int
  124 iicbus_release_bus(device_t bus, device_t dev)
  125 {
  126         struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
  127         int s, error;
  128 
  129         /* first, ask the underlying layers if the release is ok */
  130         error = IICBUS_CALLBACK(device_get_parent(bus), IIC_RELEASE_BUS, NULL);
  131 
  132         if (error)
  133                 return (error);
  134 
  135         s = splhigh();
  136         if (sc->owner != dev) {
  137                 splx(s);
  138                 return (EACCES);
  139         }
  140 
  141         sc->owner = 0;
  142         splx(s);
  143 
  144         /* wakeup waiting processes */
  145         wakeup(sc);
  146 
  147         return (0);
  148 }
  149 
  150 /*
  151  * iicbus_started()
  152  *
  153  * Test if the iicbus is started by the controller
  154  */
  155 int
  156 iicbus_started(device_t bus)
  157 {
  158         struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
  159 
  160         return (sc->started);
  161 }
  162 
  163 /*
  164  * iicbus_start()
  165  *
  166  * Send start condition to the slave addressed by 'slave'
  167  */
  168 int
  169 iicbus_start(device_t bus, u_char slave, int timeout)
  170 {
  171         struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
  172         int error = 0;
  173 
  174         if (sc->started)
  175                 return (EINVAL);                /* bus already started */
  176 
  177         if (!(error = IICBUS_START(device_get_parent(bus), slave, timeout)))
  178                 sc->started = slave;
  179         else
  180                 sc->started = 0;
  181 
  182         return (error);
  183 }
  184 
  185 /*
  186  * iicbus_repeated_start()
  187  *
  188  * Send start condition to the slave addressed by 'slave'
  189  */
  190 int
  191 iicbus_repeated_start(device_t bus, u_char slave, int timeout)
  192 {
  193         struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
  194         int error = 0;
  195 
  196         if (!sc->started)
  197                 return (EINVAL);     /* bus should have been already started */
  198 
  199         if (!(error = IICBUS_REPEATED_START(device_get_parent(bus), slave, timeout)))
  200                 sc->started = slave;
  201         else
  202                 sc->started = 0;
  203 
  204         return (error);
  205 }
  206 
  207 /*
  208  * iicbus_stop()
  209  *
  210  * Send stop condition to the bus
  211  */
  212 int
  213 iicbus_stop(device_t bus)
  214 {
  215         struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
  216         int error = 0;
  217 
  218         if (!sc->started)
  219                 return (EINVAL);                /* bus not started */
  220 
  221         error = IICBUS_STOP(device_get_parent(bus));
  222 
  223         /* refuse any further access */
  224         sc->started = 0;
  225 
  226         return (error);
  227 }
  228 
  229 /*
  230  * iicbus_write()
  231  *
  232  * Write a block of data to the slave previously started by
  233  * iicbus_start() call
  234  */
  235 int
  236 iicbus_write(device_t bus, char *buf, int len, int *sent, int timeout)
  237 {
  238         struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
  239         
  240         /* a slave must have been started with the appropriate address */
  241         if (!sc->started || (sc->started & LSB))
  242                 return (EINVAL);
  243 
  244         return (IICBUS_WRITE(device_get_parent(bus), buf, len, sent, timeout));
  245 }
  246 
  247 /*
  248  * iicbus_read()
  249  *
  250  * Read a block of data from the slave previously started by
  251  * iicbus_read() call
  252  */
  253 int 
  254 iicbus_read(device_t bus, char *buf, int len, int *read, int last, int delay)
  255 {
  256         struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
  257         
  258         /* a slave must have been started with the appropriate address */
  259         if (!sc->started || !(sc->started & LSB))
  260                 return (EINVAL);
  261 
  262         return (IICBUS_READ(device_get_parent(bus), buf, len, read, last, delay));
  263 }
  264 
  265 /*
  266  * iicbus_write_byte()
  267  *
  268  * Write a byte to the slave previously started by iicbus_start() call
  269  */
  270 int
  271 iicbus_write_byte(device_t bus, char byte, int timeout)
  272 {
  273         char data = byte;
  274         int sent;
  275 
  276         return (iicbus_write(bus, &data, 1, &sent, timeout));
  277 }
  278 
  279 /*
  280  * iicbus_read_byte()
  281  *
  282  * Read a byte from the slave previously started by iicbus_start() call
  283  */
  284 int
  285 iicbus_read_byte(device_t bus, char *byte, int timeout)
  286 {
  287         int read;
  288 
  289         return (iicbus_read(bus, byte, 1, &read, IIC_LAST_READ, timeout));
  290 }
  291 
  292 /*
  293  * iicbus_block_write()
  294  *
  295  * Write a block of data to slave ; start/stop protocol managed
  296  */
  297 int
  298 iicbus_block_write(device_t bus, u_char slave, char *buf, int len, int *sent)
  299 {
  300         u_char addr = slave & ~LSB;
  301         int error;
  302 
  303         if ((error = iicbus_start(bus, addr, 0)))
  304                 return (error);
  305 
  306         error = iicbus_write(bus, buf, len, sent, 0);
  307 
  308         iicbus_stop(bus);
  309 
  310         return (error);
  311 }
  312 
  313 /*
  314  * iicbus_block_read()
  315  *
  316  * Read a block of data from slave ; start/stop protocol managed
  317  */
  318 int
  319 iicbus_block_read(device_t bus, u_char slave, char *buf, int len, int *read)
  320 {
  321         u_char addr = slave | LSB;
  322         int error;
  323 
  324         if ((error = iicbus_start(bus, addr, 0)))
  325                 return (error);
  326 
  327         error = iicbus_read(bus, buf, len, read, IIC_LAST_READ, 0);
  328 
  329         iicbus_stop(bus);
  330 
  331         return (error);
  332 }

Cache object: 33b490fe0d6e53c6e655a58e6572fa7c


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