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/pci/oboe.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 /*      $NetBSD: oboe.c,v 1.17 2003/10/28 23:56:00 mycroft Exp $        */
    2 
    3 /*      XXXXFVDL THIS DRIVER IS BROKEN FOR NON-i386 -- vtophys() usage  */
    4 
    5 /*-
    6  * Copyright (c) 2001 The NetBSD Foundation, Inc.
    7  * All rights reserved.
    8  *
    9  * This code is derived from software contributed to The NetBSD Foundation
   10  * by Jan Sparud.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *      This product includes software developed by the NetBSD
   23  *      Foundation, Inc. and its contributors.
   24  * 4. Neither the name of The NetBSD Foundation nor the names of its
   25  *    contributors may be used to endorse or promote products derived
   26  *    from this software without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   38  * POSSIBILITY OF SUCH DAMAGE.
   39  */
   40 
   41 /*
   42  * Toshiba OBOE IrDA SIR/FIR driver.
   43  *
   44  * Based on information from the Linux driver, thus the magic hex numbers.
   45  */
   46 
   47 #include <sys/cdefs.h>
   48 __KERNEL_RCSID(0, "$NetBSD: oboe.c,v 1.17 2003/10/28 23:56:00 mycroft Exp $");
   49 
   50 #include <sys/param.h>
   51 #include <sys/systm.h>
   52 #include <sys/kernel.h>
   53 #include <sys/device.h>
   54 #include <sys/malloc.h>
   55 #include <sys/tty.h>
   56 #include <sys/vnode.h>
   57 #include <sys/poll.h>
   58 
   59 #include <dev/ir/ir.h>
   60 #include <dev/ir/irdaio.h>
   61 #include <dev/ir/irframevar.h>
   62 #include <dev/ir/sir.h>
   63 
   64 #include <dev/pci/pcidevs.h>
   65 #include <dev/pci/pcivar.h>
   66 
   67 #include <machine/bus.h>
   68 #include <machine/intr.h>
   69 #include <uvm/uvm_extern.h>
   70 
   71 #include <dev/pci/oboereg.h>
   72 
   73 int oboe_match(struct device *parent, struct cfdata *match, void *aux);
   74 void oboe_attach(struct device *parent, struct device *self, void *aux);
   75 int oboe_activate(struct device *self, enum devact act);
   76 int oboe_detach(struct device *self, int flags);
   77 
   78 int oboe_open(void *h, int flag, int mode, struct proc *p);
   79 int oboe_close(void *h, int flag, int mode, struct proc *p);
   80 int oboe_read(void *h, struct uio *uio, int flag);
   81 int oboe_write(void *h, struct uio *uio, int flag);
   82 int oboe_set_params(void *h, struct irda_params *params);
   83 int oboe_get_speeds(void *h, int *speeds);
   84 int oboe_get_turnarounds(void *h, int *times);
   85 int oboe_poll(void *h, int events, struct proc *p);
   86 int oboe_kqfilter(void *h, struct knote *kn);
   87 
   88 #ifdef OBOE_DEBUG
   89 #define DPRINTF(x)      if (oboedebug) printf x
   90 int oboedebug = 1;
   91 #else
   92 #define DPRINTF(x)
   93 #endif
   94 
   95 struct oboe_dma;
   96 
   97 struct oboe_softc {
   98         struct device           sc_dev;
   99         struct device           *sc_child;
  100         struct pci_attach_args  sc_pa;
  101         pci_intr_handle_t *     sc_ih;
  102         unsigned int            sc_revision;    /* PCI Revision ID */
  103         /* I/O Base device */
  104         bus_space_tag_t         sc_iot;
  105         bus_space_handle_t      sc_ioh;
  106         bus_dma_tag_t           sc_dmatag;      
  107         struct selinfo          sc_rsel;
  108         struct selinfo          sc_wsel;
  109 
  110         int                     sc_state;
  111 #define OBOE_RSLP               0x01    /* waiting for data (read) */
  112 #define OBOE_WSLP               0x02    /* waiting for data (write) */
  113 #define OBOE_CLOSING            0x04    /* waiting for output to drain */
  114 
  115         int                     sc_speeds;
  116         int                     sc_flags;
  117         int                     sc_speed;
  118         int                     sc_ebofs;
  119         
  120         struct oboe_dma         *sc_dmas;
  121         struct OboeTaskFile     *sc_taskfile;    /* The taskfile   */
  122         u_char *                sc_xmit_bufs[TX_SLOTS];
  123         u_char *                sc_recv_bufs[RX_SLOTS];
  124         void *                  sc_xmit_stores[TX_SLOTS];  
  125         void *                  sc_recv_stores[RX_SLOTS];
  126         int                     sc_txs; /* Current transmit slot number */
  127         int                     sc_rxs; /* Current receive slot number */
  128         int                     sc_saved; /* number of saved frames */
  129         int                     sc_lens[RX_SLOTS];
  130 
  131         int                     sc_txpending;
  132 
  133         /* Statistics */
  134         int                     sc_txpackets;
  135         int                     sc_rxpackets;
  136         int                     sc_txerrors;
  137         int                     sc_rxerrors;
  138 };
  139 
  140 static int oboe_intr(void *handle);
  141 static int oboe_reset(struct oboe_softc *);
  142 
  143 struct oboe_dma {
  144         bus_dmamap_t map;
  145         caddr_t addr;
  146         bus_dma_segment_t segs[1];
  147         int nsegs;
  148         size_t size;
  149         struct oboe_dma *next;
  150 };
  151 
  152 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
  153 #define KERNADDR(p) ((void *)((p)->addr))
  154 
  155 static int oboe_alloc_taskfile(struct oboe_softc *);
  156 static void oboe_init_taskfile(struct oboe_softc *);
  157 static void oboe_startchip(struct oboe_softc *);
  158 static void oboe_stopchip(struct oboe_softc *);
  159 static int oboe_setbaud(struct oboe_softc *, int);
  160 
  161 CFATTACH_DECL(oboe, sizeof(struct oboe_softc),
  162     oboe_match, oboe_attach, oboe_detach, oboe_activate);
  163 
  164 struct irframe_methods oboe_methods = {
  165         oboe_open, oboe_close, oboe_read, oboe_write, oboe_poll,
  166         oboe_kqfilter, oboe_set_params, oboe_get_speeds, oboe_get_turnarounds
  167 };
  168 
  169 int
  170 oboe_match(struct device *parent, struct cfdata *match, void *aux)
  171 {
  172         struct pci_attach_args *pa = aux;
  173 
  174         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TOSHIBA2 &&
  175             (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TOSHIBA2_OBOE ||
  176              PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TOSHIBA2_DONAUOBOE))
  177                 return (1);
  178         return 0;
  179 }
  180 
  181 void
  182 oboe_attach(struct device *parent, struct device *self, void *aux)
  183 {
  184         struct oboe_softc *sc = (struct oboe_softc *)self;
  185         struct pci_attach_args *pa = aux;
  186         pci_intr_handle_t ih;
  187         struct ir_attach_args ia;
  188         const char *intrstring;
  189 
  190         sc->sc_revision = PCI_REVISION(pa->pa_class);
  191         printf(": Toshiba Fast Infrared Type O, revision %d\n",
  192                sc->sc_revision);
  193 
  194         /* Map I/O registers. */
  195         if (pci_mapreg_map(pa, IO_BAR, PCI_MAPREG_TYPE_IO, 0,
  196             &sc->sc_iot, &sc->sc_ioh, NULL, NULL)) {
  197                 printf("%s: can't map I/O space\n", sc->sc_dev.dv_xname);
  198                 return;
  199         }
  200 
  201         sc->sc_dmatag = pa->pa_dmat;
  202 
  203         ia.ia_type = IR_TYPE_IRFRAME;
  204         ia.ia_methods = &oboe_methods;
  205         ia.ia_handle = sc;
  206 
  207         sc->sc_state = 0;
  208         sc->sc_speed = IRDA_SPEED_9600;
  209 
  210         /* Enable the device */
  211         pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
  212             pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) |
  213             PCI_COMMAND_MASTER_ENABLE);
  214 
  215         /* Reset the device; bail out upon failure. */
  216         if (oboe_reset(sc) != 0) {
  217                 printf("%s: can't reset\n", sc->sc_dev.dv_xname);
  218                 return;
  219         }
  220         /* Map and establish the interrupt. */
  221         if (pci_intr_map(pa, &ih)) {
  222                 printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
  223                 return;
  224         }
  225         intrstring = pci_intr_string(pa->pa_pc, ih);
  226         sc->sc_ih  = pci_intr_establish(pa->pa_pc, ih, IPL_IR, oboe_intr, sc);
  227         if (sc->sc_ih == NULL) {
  228                 printf("%s: couldn't establish interrupt",
  229                     sc->sc_dev.dv_xname);
  230                 if (intrstring != NULL)
  231                         printf(" at %s", intrstring);
  232                 printf("\n");
  233                 return;
  234         }
  235         printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstring);
  236 
  237         sc->sc_txs = 0;
  238         sc->sc_rxs = 0;
  239 
  240         sc->sc_speeds = 
  241                 IRDA_SPEED_2400   | IRDA_SPEED_9600    | IRDA_SPEED_19200 | 
  242                 IRDA_SPEED_38400  | IRDA_SPEED_57600   | IRDA_SPEED_115200 | 
  243                 IRDA_SPEED_576000 | IRDA_SPEED_1152000 | IRDA_SPEED_4000000;
  244 
  245         oboe_alloc_taskfile(sc);
  246 
  247         sc->sc_child = config_found((void *)sc, &ia, ir_print);
  248 }
  249 
  250 int
  251 oboe_activate(struct device *self, enum devact act)
  252 {
  253         struct oboe_softc *sc = (struct oboe_softc *)self;
  254         int error = 0;
  255 
  256         DPRINTF(("%s: sc=%p\n", __FUNCTION__, sc));
  257 
  258         switch (act) {
  259         case DVACT_ACTIVATE:
  260                 return (EOPNOTSUPP);
  261                 break;
  262 
  263         case DVACT_DEACTIVATE:
  264                 if (sc->sc_child != NULL)
  265                         error = config_deactivate(sc->sc_child);
  266                 break;
  267         }
  268         return (error);
  269 }
  270 
  271 int
  272 oboe_detach(struct device *self, int flags)
  273 {
  274 #if 0
  275         struct oboe_softc *sc = (struct oboe_softc *)self;
  276 #endif
  277         /* XXX needs reference counting for proper detach. */
  278         DPRINTF(("%s: sc=%p\n", __FUNCTION__, sc));
  279         return (0);
  280 }
  281 
  282 int
  283 oboe_open(void *h, int flag, int mode, struct proc *p)
  284 {
  285         struct oboe_softc *sc = h;
  286 
  287         DPRINTF(("%s: sc=%p\n", __FUNCTION__, sc));
  288 
  289         sc->sc_state = 0;
  290         sc->sc_saved = 0;
  291         oboe_init_taskfile(sc);
  292         oboe_startchip(sc);
  293 
  294         return (0);
  295 }
  296 
  297 int
  298 oboe_close(void *h, int flag, int mode, struct proc *p)
  299 {
  300         struct oboe_softc *sc = h;
  301         int error = 0;
  302         int s = splir();
  303         
  304         DPRINTF(("%s: sc=%p\n", __FUNCTION__, sc));
  305         /* Wait for output to drain */
  306 
  307         if (sc->sc_txpending > 0) {
  308                 sc->sc_state |= OBOE_CLOSING;
  309                 error = tsleep(&sc->sc_state, PZERO | PCATCH, "oboecl", hz/10);
  310         }
  311         splx(s);
  312 
  313         oboe_stopchip(sc);
  314         return (error);
  315 }
  316 
  317 int
  318 oboe_read(void *h, struct uio *uio, int flag)
  319 {
  320         struct oboe_softc *sc = h;
  321         int error = 0;
  322         int s;
  323         int slot;
  324 
  325         DPRINTF(("%s: resid=%d, iovcnt=%d, offset=%ld\n", 
  326                  __FUNCTION__, uio->uio_resid, uio->uio_iovcnt, 
  327                  (long)uio->uio_offset));
  328 
  329         s = splir();    
  330         while (sc->sc_saved == 0) {
  331                 if (flag & IO_NDELAY) {
  332                         splx(s);
  333                         return (EWOULDBLOCK);
  334                 }
  335                 sc->sc_state |= OBOE_RSLP;
  336                 DPRINTF(("oboe_read: sleep\n"));
  337                 error = tsleep(&sc->sc_rxs, PZERO | PCATCH, "oboerd", 0);
  338                 DPRINTF(("oboe_read: woke, error=%d\n", error));
  339                 if (error) {
  340                         sc->sc_state &= ~OBOE_RSLP;
  341                         break;
  342                 }
  343         }
  344 
  345         /* Do just one frame transfer per read */
  346         
  347         if (!error) {
  348                 slot = (sc->sc_rxs - sc->sc_saved + RX_SLOTS) % RX_SLOTS;
  349                 if (uio->uio_resid < sc->sc_lens[slot]) {
  350                         DPRINTF(("oboe_read: uio buffer smaller than frame size"
  351                             "(%d < %d)\n", uio->uio_resid, sc->sc_lens[slot]));
  352                         error = EINVAL;
  353                 } else {
  354                         DPRINTF(("oboe_read: moving %d bytes from %p\n", 
  355                                  sc->sc_lens[slot],
  356                                  sc->sc_recv_stores[slot]));
  357                         error = uiomove(sc->sc_recv_stores[slot], 
  358                                         sc->sc_lens[slot], uio);
  359                 }
  360         }
  361         sc->sc_saved--;
  362         splx(s);
  363 
  364         return (error);
  365 }
  366 
  367 int
  368 oboe_write(void *h, struct uio *uio, int flag)
  369 {
  370         struct oboe_softc *sc = h;
  371         int error = 0;
  372         int n;
  373         int s = splir();
  374 
  375         DPRINTF(("%s: sc=%p\n", __FUNCTION__, sc));
  376         while (sc->sc_txpending == TX_SLOTS) {
  377                 if (flag & IO_NDELAY) {
  378                         splx(s);
  379                         return (EWOULDBLOCK);
  380                 }
  381                 sc->sc_state |= OBOE_WSLP;
  382                 DPRINTF(("oboe_write: sleep\n"));
  383                 error = tsleep(&sc->sc_txs, PZERO | PCATCH, "oboewr", 0);
  384                 DPRINTF(("oboe_write: woke up, error=%d\n", error));
  385                 if (error) {
  386                         sc->sc_state &= ~OBOE_WSLP;
  387                         break;
  388                 }
  389         }
  390         if (error)
  391                 goto err;
  392         if (sc->sc_taskfile->xmit[sc->sc_txs].control) {
  393                 DPRINTF(("oboe_write: slot overrun\n"));
  394         }
  395                 
  396         n = irda_sir_frame(sc->sc_xmit_bufs[sc->sc_txs], TX_BUF_SZ, uio,
  397                            sc->sc_ebofs);
  398         if (n < 0) {
  399                 error = -n;
  400                 goto err;
  401         }
  402         sc->sc_taskfile->xmit[sc->sc_txs].len = n;
  403 
  404         OUTB(sc, 0, OBOE_RST);
  405         OUTB(sc, 0x1e, OBOE_REG_11);
  406 
  407         sc->sc_taskfile->xmit[sc->sc_txs].control = 0x84;
  408                 
  409         /* XXX Need delay here??? */
  410         delay(1000);
  411 
  412         sc->sc_txpending++;
  413         OUTB(sc, 0x80, OBOE_RST);
  414         OUTB(sc, 1, OBOE_REG_9);
  415         sc->sc_txs++;
  416         sc->sc_txs %= TX_SLOTS;
  417 
  418  err:
  419         splx(s);
  420         return (error);
  421 }
  422 
  423 int
  424 oboe_set_params(void *h, struct irda_params *p)
  425 {
  426         struct oboe_softc *sc = h;
  427         int error;
  428 
  429         if (p->speed > 0) {
  430                 error = oboe_setbaud(sc, p->speed);
  431                 if (error)
  432                         return (error);
  433         }
  434         sc->sc_ebofs = p->ebofs;
  435 
  436         /* XXX ignore ebofs and maxsize for now */
  437         return (0);
  438 }
  439 
  440 int
  441 oboe_get_speeds(void *h, int *speeds)
  442 {
  443         struct oboe_softc *sc = h;
  444         *speeds = sc->sc_speeds;
  445         return (0);
  446 }
  447 
  448 int
  449 oboe_get_turnarounds(void *h, int *turnarounds)
  450 {
  451 #if 0
  452         struct oboe_softc *sc = h;
  453 #endif
  454         DPRINTF(("%s: sc=%p\n", __FUNCTION__, sc));
  455         /* XXX Linux driver sets all bits */
  456         *turnarounds = IRDA_TURNT_10000; /* 10ms */
  457         return (0);
  458 }
  459 
  460 int
  461 oboe_poll(void *h, int events, struct proc *p)
  462 {
  463         struct oboe_softc *sc = h;
  464         int revents = 0;
  465         int s;
  466 
  467         DPRINTF(("%s: sc=%p\n", __FUNCTION__, sc));
  468 
  469         s = splir();
  470         if (events & (POLLOUT | POLLWRNORM))
  471                 revents |= events & (POLLOUT | POLLWRNORM);
  472         if (events & (POLLIN | POLLRDNORM)) {
  473                 if (sc->sc_saved > 0) {
  474                         DPRINTF(("%s: have data\n", __FUNCTION__));
  475                         revents |= events & (POLLIN | POLLRDNORM);
  476                 } else {
  477                         DPRINTF(("%s: recording select\n", __FUNCTION__));
  478                         selrecord(p, &sc->sc_rsel);
  479                 }
  480         }
  481         splx(s);
  482 
  483         return (revents);
  484 }
  485 
  486 static void
  487 filt_oboerdetach(struct knote *kn)
  488 {
  489         struct oboe_softc *sc = kn->kn_hook;
  490         int s;
  491 
  492         s = splir();
  493         SLIST_REMOVE(&sc->sc_rsel.sel_klist, kn, knote, kn_selnext);
  494         splx(s);
  495 }
  496 
  497 static int
  498 filt_oboeread(struct knote *kn, long hint)
  499 {
  500         struct oboe_softc *sc = kn->kn_hook;
  501 
  502         kn->kn_data = sc->sc_saved;
  503         return (kn->kn_data > 0);
  504 }
  505 
  506 static void
  507 filt_oboewdetach(struct knote *kn)
  508 {
  509         struct oboe_softc *sc = kn->kn_hook;
  510         int s;
  511 
  512         s = splir();
  513         SLIST_REMOVE(&sc->sc_wsel.sel_klist, kn, knote, kn_selnext);
  514         splx(s);
  515 }
  516 
  517 static const struct filterops oboeread_filtops =
  518         { 1, NULL, filt_oboerdetach, filt_oboeread };
  519 static const struct filterops oboewrite_filtops =
  520         { 1, NULL, filt_oboewdetach, filt_seltrue };
  521 
  522 int
  523 oboe_kqfilter(void *h, struct knote *kn)
  524 {
  525         struct oboe_softc *sc = h;
  526         struct klist *klist;
  527         int s;
  528 
  529         switch (kn->kn_filter) {
  530         case EVFILT_READ:
  531                 klist = &sc->sc_rsel.sel_klist;
  532                 kn->kn_fop = &oboeread_filtops;
  533                 break;
  534         case EVFILT_WRITE:
  535                 klist = &sc->sc_wsel.sel_klist;
  536                 kn->kn_fop = &oboewrite_filtops;
  537                 break;
  538         default:
  539                 return (1);
  540         }
  541 
  542         kn->kn_hook = sc;
  543 
  544         s = splir();
  545         SLIST_INSERT_HEAD(klist, kn, kn_selnext);
  546         splx(s);
  547 
  548         return (0);
  549 }
  550 
  551 static int
  552 oboe_reset(struct oboe_softc *sc)
  553 {
  554 #if 0
  555         OUTB(sc, 0x00, OBOE_RST);
  556         OUTB(sc, 0x80, OBOE_RST);
  557 #endif
  558         return 0;
  559 }
  560 
  561 static int
  562 oboe_intr(void *p)
  563 {
  564         struct oboe_softc *sc = p;
  565         uint8_t irqstat = INB(sc, OBOE_ISR);
  566 
  567         if (!(irqstat & 0xf8))
  568                 return (0); /* Not for me? */
  569 
  570         DPRINTF(("oboe_intr stat=0x%x\n", irqstat));
  571 
  572         OUTB(sc, irqstat, OBOE_ISR);
  573 
  574         if (irqstat & OBOE_ISR_RXDONE) {
  575                 while (sc->sc_taskfile->recv[sc->sc_rxs].control == 0) {
  576                         int len = sc->sc_taskfile->recv[sc->sc_rxs].len;
  577                         if (sc->sc_saved == RX_SLOTS) {
  578                                 DPRINTF(("oboe_intr: all buffers filled\n"));
  579                                 return 0;
  580                         }
  581 
  582                         if (len > 2)
  583                                 len -= 2; /* JSP: skip check sum? */
  584 
  585                         DPRINTF(("oboe_intr: moving %d bytes to %p\n", len,
  586                                  sc->sc_recv_stores[sc->sc_rxs]));
  587                         memcpy(sc->sc_recv_stores[sc->sc_rxs],
  588                                sc->sc_recv_bufs[sc->sc_rxs],
  589                                len);
  590                         sc->sc_lens[sc->sc_rxs] = len;
  591                         sc->sc_saved++;
  592 #if 0                   
  593                         (void)b_to_q(sc->sc_recv_bufs[sc->sc_rxs],
  594                                      len, &sc->sc_q);
  595 #endif
  596                         sc->sc_taskfile->recv[sc->sc_rxs].control = 0x83;
  597                         sc->sc_taskfile->recv[sc->sc_rxs].len = 0x0;
  598                         sc->sc_rxs = (sc->sc_rxs + 1) % RX_SLOTS;
  599                         DPRINTF(("oboe_intr new rxs=%d\n", sc->sc_rxs));
  600                 }               
  601                 DPRINTF(("oboe_intr no more frames available\n"));
  602                 if (sc->sc_state & OBOE_RSLP) {
  603                         DPRINTF(("oboe_intr changing state to ~OBOE_RSLP\n"));
  604                         sc->sc_state &= ~OBOE_RSLP;
  605                         DPRINTF(("oboe_intr: waking up reader\n"));
  606                         wakeup(&sc->sc_rxs);
  607                 }
  608                 selnotify(&sc->sc_rsel, 0);
  609                 DPRINTF(("oboe_intr returning\n"));
  610         }
  611         if (irqstat & OBOE_ISR_TXDONE) {
  612                 DPRINTF(("oboe_intr: write done\n"));
  613                 sc->sc_txpending--;
  614                 sc->sc_txpackets++;
  615 
  616                 if ((sc->sc_state & OBOE_CLOSING) && sc->sc_txpending == 0) {
  617                         wakeup(&sc->sc_state);
  618                         return 1;
  619                 }
  620 
  621                 if (sc->sc_state & OBOE_WSLP) {
  622                         DPRINTF(("oboe_intr changing state to ~OBOE_WSLP\n"));
  623                         sc->sc_state &= ~OBOE_WSLP;
  624                         DPRINTF(("oboe_intr: waking up writer\n"));
  625                         wakeup(&sc->sc_txs);
  626                 }
  627                 selnotify(&sc->sc_wsel, 0);
  628         }
  629         return (1);
  630 }
  631 
  632 /* XXX vtophys must go! */
  633 static void
  634 oboe_init_taskfile(struct oboe_softc *sc)
  635 {
  636         int i;
  637         int s = splir();
  638 
  639         for (i = 0; i < TX_SLOTS; ++i) {
  640                 sc->sc_taskfile->xmit[i].len = 0;
  641                 sc->sc_taskfile->xmit[i].control = 0x00;
  642                 sc->sc_taskfile->xmit[i].buffer = 
  643                         vtophys((u_int)sc->sc_xmit_bufs[i]); /* u_int? */
  644         }
  645 
  646         for (i = 0; i < RX_SLOTS; ++i) {
  647                 sc->sc_taskfile->recv[i].len = 0;
  648                 sc->sc_taskfile->recv[i].control = 0x83;
  649                 sc->sc_taskfile->recv[i].buffer = 
  650                         vtophys((u_int)sc->sc_recv_bufs[i]); /* u_int? */
  651         }
  652 
  653         sc->sc_txpending = 0;
  654 
  655         splx(s);        
  656 }
  657 
  658 static int
  659 oboe_alloc_taskfile(struct oboe_softc *sc)
  660 {
  661         int i;
  662         /* XXX */
  663         uint32_t addr = (uint32_t)malloc(OBOE_TASK_BUF_LEN, M_DEVBUF, M_WAITOK);
  664         if (addr == 0) {
  665                 goto bad;
  666         }
  667         addr &= ~(sizeof (struct OboeTaskFile) - 1);
  668         addr += sizeof (struct OboeTaskFile);
  669         sc->sc_taskfile = (struct OboeTaskFile *) addr;
  670 
  671         for (i = 0; i < TX_SLOTS; ++i) {
  672                 sc->sc_xmit_bufs[i] = 
  673                         malloc(TX_BUF_SZ, M_DEVBUF, M_WAITOK);
  674                 sc->sc_xmit_stores[i] = 
  675                         malloc(TX_BUF_SZ, M_DEVBUF, M_WAITOK);
  676                 if (sc->sc_xmit_bufs[i] == NULL ||
  677                     sc->sc_xmit_stores[i] == NULL) {
  678                         goto bad;
  679                 }
  680         }
  681         for (i = 0; i < RX_SLOTS; ++i) {
  682                 sc->sc_recv_bufs[i] = 
  683                         malloc(RX_BUF_SZ, M_DEVBUF, M_WAITOK);
  684                 sc->sc_recv_stores[i] = 
  685                         malloc(RX_BUF_SZ, M_DEVBUF, M_WAITOK);
  686                 if (sc->sc_recv_bufs[i] == NULL ||
  687                     sc->sc_recv_stores[i] == NULL) {
  688                         goto bad;
  689                 }
  690         }
  691 
  692         return 0;
  693 bad:
  694         printf("oboe: malloc for buffers failed()\n");
  695         return 1;
  696 }
  697 
  698 static void
  699 oboe_startchip (struct oboe_softc *sc)
  700 {
  701         uint32_t physaddr;
  702 
  703         OUTB(sc, 0, OBOE_LOCK);
  704         OUTB(sc, 0, OBOE_RST);
  705         OUTB(sc, OBOE_NTR_VAL, OBOE_NTR);
  706         OUTB(sc, 0xf0, OBOE_REG_D);
  707         OUTB(sc, 0xff, OBOE_ISR);
  708         OUTB(sc, 0x0f, OBOE_REG_1A);
  709         OUTB(sc, 0xff, OBOE_REG_1B);
  710 
  711         physaddr = vtophys((u_int)sc->sc_taskfile); /* u_int? */
  712         
  713         OUTB(sc, (physaddr >> 0x0a) & 0xff, OBOE_TFP0);
  714         OUTB(sc, (physaddr >> 0x12) & 0xff, OBOE_TFP1);
  715         OUTB(sc, (physaddr >> 0x1a) & 0x3f, OBOE_TFP2);
  716         
  717         OUTB(sc, 0x0e, OBOE_REG_11);
  718         OUTB(sc, 0x80, OBOE_RST);
  719         
  720         (void)oboe_setbaud(sc, 9600);
  721 
  722         sc->sc_rxs = INB(sc, OBOE_RCVT);
  723         if (sc->sc_rxs < 0 || sc->sc_rxs >= RX_SLOTS)
  724                 sc->sc_rxs = 0;
  725         sc->sc_txs = INB(sc, OBOE_XMTT) - OBOE_XMTT_OFFSET;
  726         if (sc->sc_txs < 0 || sc->sc_txs >= TX_SLOTS)
  727                 sc->sc_txs = 0;
  728 }
  729 
  730 static void
  731 oboe_stopchip (struct oboe_softc *sc)
  732 {
  733         OUTB(sc, 0x0e, OBOE_REG_11);
  734         OUTB(sc, 0x00, OBOE_RST);
  735         OUTB(sc, 0x3f, OBOE_TFP2);     /* Write the taskfile address */
  736         OUTB(sc, 0xff, OBOE_TFP1);
  737         OUTB(sc, 0xff, OBOE_TFP0);
  738         OUTB(sc, 0x0f, OBOE_REG_1B);
  739         OUTB(sc, 0xff, OBOE_REG_1A);
  740         OUTB(sc, 0x00, OBOE_ISR); /* XXX: should i do this to disable ints? */
  741         OUTB(sc, 0x80, OBOE_RST);
  742         OUTB(sc, 0x0e, OBOE_LOCK);
  743 }
  744 
  745 #define SPEEDCASE(speed, type, divisor) \
  746 case speed: \
  747 OUTB(sc, OBOE_PMDL_##type, OBOE_PMDL); \
  748 OUTB(sc, OBOE_SMDL_##type, OBOE_SMDL); \
  749 OUTB(sc, divisor, OBOE_UDIV); \
  750 break
  751         
  752 static int
  753 oboe_setbaud(struct oboe_softc *sc, int baud)
  754 {
  755         int s;
  756 
  757         DPRINTF(("oboe: setting baud to %d\n", baud));
  758 
  759         s = splir();
  760 
  761         switch (baud) {
  762         SPEEDCASE(   2400, SIR, 0xbf);
  763         SPEEDCASE(   9600, SIR, 0x2f);
  764         SPEEDCASE(  19200, SIR, 0x17);
  765         SPEEDCASE(  38400, SIR, 0x0b);
  766         SPEEDCASE(  57600, SIR, 0x07);
  767         SPEEDCASE( 115200, SIR, 0x03);
  768         SPEEDCASE(1152000, MIR, 0x01);
  769         SPEEDCASE(4000000, FIR, 0x00);
  770         default:
  771                 DPRINTF(("oboe: cannot set speed to %d\n", baud));
  772                 splx(s);
  773                 return (EINVAL);
  774         }
  775 
  776         OUTB(sc, 0x00, OBOE_RST);
  777         OUTB(sc, 0x80, OBOE_RST);
  778         OUTB(sc, 0x01, OBOE_REG_9);
  779         
  780         sc->sc_speed = baud;
  781 
  782         splx(s);
  783 
  784         return (0);
  785 }

Cache object: ef589e5de8b553dfaf27624c5749840f


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