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/wd82371.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 1996 Massachusetts Institute of Technology
    3  *
    4  * Permission to use, copy, modify, and distribute this software and
    5  * its documentation for any purpose and without fee is hereby
    6  * granted, provided that both the above copyright notice and this
    7  * permission notice appear in all copies, that both the above
    8  * copyright notice and this permission notice appear in all
    9  * supporting documentation, and that the name of M.I.T. not be used
   10  * in advertising or publicity pertaining to distribution of the
   11  * software without specific, written prior permission.  M.I.T. makes
   12  * no representations about the suitability of this software for any
   13  * purpose.  It is provided "as is" without express or implied
   14  * warranty.
   15  * 
   16  * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
   17  * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
   18  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
   20  * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   23  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   26  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  * $FreeBSD: src/sys/pci/wd82371.c,v 1.5.2.2 1999/09/05 08:21:28 peter Exp $
   30  */
   31 
   32 #include "pci.h"
   33 #if NPCI > 0
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/queue.h>
   38 #include <sys/proc.h>
   39 #include <sys/buf.h>
   40 #include <sys/malloc.h>
   41 #include <sys/kernel.h>
   42 #include <vm/vm.h>
   43 #include <vm/pmap.h>
   44 
   45 #include <machine/pmap.h>       /* for vtophys */
   46 
   47 #include <i386/isa/wdreg.h>
   48 
   49 #include <pci/pcivar.h>
   50 #include <pci/pcireg.h>
   51 #include <pci/wd82371reg.h>
   52 
   53 static void *piix_candma(int, int);
   54 static int piix_dmasetup(void *, char *, u_long, int);
   55 static void piix_dmastart(void *);
   56 static int piix_dmadone(void *);
   57 static int piix_status(void *);
   58 
   59 struct piix_cookie {
   60         LIST_ENTRY(piix_cookie) le;
   61         int ctlr;
   62         int unit;
   63         struct piix_prd *prd;
   64 };
   65 
   66 struct piix_softc {
   67         unsigned iobase;
   68         pcici_t tag;
   69         LIST_HEAD(, piix_cookie) cookies;
   70 };
   71 
   72 static struct piix_softc softc;
   73 
   74 static struct piix_cookie *
   75 mkcookie(int ctlr, int unit)
   76 {
   77         struct piix_cookie *cp;
   78 
   79         cp = malloc(sizeof *cp, M_DEVBUF, M_NOWAIT);
   80         if (!cp) return cp;
   81         cp->ctlr = ctlr;
   82         cp->unit = unit;
   83         cp->prd = malloc(PRD_ALLOC_SIZE, M_DEVBUF, M_NOWAIT);
   84         if (!cp->prd) {
   85                 FREE(cp, M_DEVBUF);
   86                 return 0;
   87         }
   88         LIST_INSERT_HEAD(&softc.cookies, cp, le);
   89         return cp;
   90 }
   91 
   92 static char *
   93 piix_probe(pcici_t tag, pcidi_t type)
   94 {
   95         if (type == 0x12308086)
   96                 return ("Intel 82371 (Triton) Bus-master IDE controller");
   97 
   98         return 0;
   99 }
  100 
  101 static void
  102 piix_attach(pcici_t tag, int unit)
  103 {
  104         u_long idetm;
  105         int bmista;
  106         int iobase;
  107 
  108         if (unit) return;
  109 
  110         softc.tag = tag;
  111         iobase = softc.iobase = pci_conf_read(tag, 0x20) & 0xfff0;
  112         idetm = pci_conf_read(tag, 0x40);
  113 
  114         LIST_INIT(&softc.cookies);
  115 
  116         if (IDETM_CTLR_0(idetm) & IDETM_ENABLE) {
  117                 bmista = inb(iobase + BMISTA_PORT);
  118                 if (bmista & BMISTA_DMA0CAP)
  119                         mkcookie(0, 0);
  120 
  121                 if (bmista & BMISTA_DMA1CAP)
  122                         mkcookie(0, 1);
  123         }
  124 
  125         if (IDETM_CTLR_1(idetm) & IDETM_ENABLE) {
  126                 bmista = inb(iobase + PIIX_CTLR_1 + BMISTA_PORT);
  127                 if (bmista & BMISTA_DMA0CAP)
  128                         mkcookie(1, 0);
  129                 if (bmista & BMISTA_DMA1CAP)
  130                         mkcookie(1, 1);
  131         }
  132 
  133         wddma.wdd_candma = piix_candma;
  134         wddma.wdd_dmaprep = piix_dmasetup;
  135         wddma.wdd_dmastart = piix_dmastart;
  136         wddma.wdd_dmadone = piix_dmadone;
  137         wddma.wdd_dmastatus = piix_status;
  138 }
  139 
  140 static u_long piix_count;
  141 
  142 static struct pci_device piix_device = {
  143         "piix",
  144         piix_probe,
  145         piix_attach,
  146         &piix_count,
  147         0
  148 };
  149 
  150 DATA_SET(pcidevice_set, piix_device);
  151 
  152 /*
  153  * Return a cookie if we can do DMA on the specified (ctlr, unit).
  154  */
  155 static void *
  156 piix_candma(int ctlr, int unit)
  157 {
  158         struct piix_cookie *cp;
  159 
  160         cp = softc.cookies.lh_first;
  161         while(cp) {
  162                 if (cp->unit == unit && cp->ctlr == ctlr)
  163                         break;
  164                 cp = cp->le.le_next;
  165         }
  166 
  167         return cp;
  168 }
  169 
  170 /*
  171  * Set up DMA for cp.  It is the responsibility of the caller
  172  * to ensure that the controller is idle before this routine
  173  * is called.
  174  */
  175 static int
  176 piix_dmasetup(void *xcp, char *vaddr, u_long count, int dir)
  177 {
  178         struct piix_cookie *cp = xcp;
  179         struct piix_prd *prd;
  180         int i;
  181         u_long pgresid;
  182         int iobase;
  183 
  184         prd = cp->prd;
  185         i = 0;
  186         iobase = softc.iobase + cp->ctlr ? PIIX_CTLR_1 : 0;
  187 
  188         /*
  189          * Deal with transfers that don't start on a page
  190          * boundary.
  191          */
  192         pgresid = (u_long)vaddr % PAGE_SIZE;
  193         if (pgresid) {
  194                 prd[i].prd_base = vtophys(vaddr);
  195                 if (count >= (PAGE_SIZE - pgresid))
  196                         prd[i].prd_count = PAGE_SIZE - pgresid;
  197                 else
  198                         prd[i].prd_count = count;
  199                 vaddr += prd[i].prd_count;
  200                 count -= prd[i].prd_count;
  201                 prd[i].prd_eot |= PRD_EOT_BIT;
  202                 i++;
  203         }
  204 
  205         /*
  206          * We have now ensured that vaddr is page-aligned, so just
  207          * step through the pages adding each one onto the list.
  208          */
  209         while(count) {
  210                 u_long phys, n;
  211 
  212                 phys = vtophys(vaddr);
  213                 n = (count > PAGE_SIZE) ? PAGE_SIZE : count;
  214                 /*
  215                  * If the current page is physically contiguous with
  216                  * whatever we have in the previous PRD, just tack it
  217                  * onto the end.
  218                  * CAVEAT: due to a hardware deficiency, PRDs
  219                  * cannot cross a 64K boundary.
  220                  */
  221                 if (i > 0 
  222                     && phys == prd[i - 1].prd_base + prd[i - 1].prd_count
  223                     && ((prd[i - 1].prd_base & 0xffff) 
  224                         + prd[i - 1].prd_count + n) <= 65535) {
  225 
  226                         prd[i - 1].prd_count += n;
  227                 } else {
  228                         if (i > 0)
  229                                 prd[i - 1].prd_eot &= ~PRD_EOT_BIT;
  230                         prd[i].prd_base = phys;
  231                         prd[i].prd_count = n;
  232                         prd[i].prd_eot |= PRD_EOT_BIT;
  233                         i++;
  234                         if (i >= PRD_MAX_SEGS)
  235                                 panic("wd82371: too many segments\n");
  236                 }
  237                 count -= n;
  238                 vaddr += n;
  239         }
  240 
  241         /* Set up PRD base register */
  242         outl(iobase + BMIDTP_PORT, vtophys(prd));
  243 
  244         /* Set direction of transfer */
  245         if (dir == B_READ) {
  246                 outb(iobase + BMICOM_PORT, 0);
  247         } else {
  248                 outb(iobase + BMICOM_PORT, BMICOM_READ_WRITE);
  249         }
  250 
  251         /* Clear interrupt and error bits */
  252         outb(iobase + BMISTA_PORT,
  253              (inb(iobase + BMISTA_PORT) 
  254               & ~(BMISTA_INTERRUPT | BMISTA_DMA_ERROR)));
  255 
  256         return 0;
  257 }               
  258 
  259 static void
  260 piix_dmastart(void *xcp)
  261 {
  262         struct piix_cookie *cp = xcp;
  263         int iobase;
  264 
  265         iobase = softc.iobase + cp->ctlr ? PIIX_CTLR_1 : 0;
  266 
  267         outb(iobase + BMICOM_PORT,
  268              inb(iobase + BMICOM_PORT) | BMICOM_STOP_START);
  269 }
  270 
  271 static int
  272 piix_dmadone(void *xcp)
  273 {
  274         struct piix_cookie *cp = xcp;
  275         int iobase, status;
  276 
  277         status = piix_status(xcp);
  278         iobase = softc.iobase + cp->ctlr ? PIIX_CTLR_1 : 0;
  279 
  280         outb(iobase + BMICOM_PORT,
  281              inb(iobase + BMICOM_PORT) & ~BMICOM_STOP_START);
  282 
  283         return status;
  284 }
  285 
  286 static int
  287 piix_status(void *xcp)
  288 {
  289         struct piix_cookie *cp = xcp;
  290         int iobase, status, bmista;
  291 
  292         status = 0;
  293         iobase = softc.iobase + cp->ctlr ? PIIX_CTLR_1 : 0;
  294 
  295         bmista = inb(iobase + BMISTA_PORT);
  296 
  297         if (bmista & BMISTA_INTERRUPT)
  298                 status |= WDDS_INTERRUPT;
  299         if (bmista & BMISTA_DMA_ERROR)
  300                 status |= WDDS_ERROR;
  301         if (bmista & BMISTA_DMA_ACTIVE)
  302                 status |= WDDS_ACTIVE;
  303 
  304         return status;
  305 }
  306 
  307 #endif /* NPCI > 0 */

Cache object: 00cefe5ad74f650f040c84f67c80cd5e


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