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/sr/if_sr_isa.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) 1996 - 2001 John Hay.
    3  * Copyright (c) 1996 SDL Communications, Inc.
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. Neither the name of the author nor the names of any co-contributors
   15  *    may be used to endorse or promote products derived from this software
   16  *    without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  *
   30  * $FreeBSD$
   31  */
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/conf.h>           /* cdevsw stuff */
   36 #include <sys/kernel.h>         /* SYSINIT stuff */
   37 #include <sys/uio.h>            /* SYSINIT stuff */
   38 #include <sys/malloc.h>         /* malloc region definitions */
   39 #include <sys/module.h>
   40 #include <sys/bus.h>
   41 #include <machine/bus.h>
   42 #include <machine/resource.h>
   43 #include <machine/bus_pio.h>
   44 #include <machine/bus_memio.h>
   45 #include <sys/rman.h>
   46 #include <sys/time.h>
   47 
   48 #include <isa/isavar.h>
   49 #include "isa_if.h"
   50 
   51 #include <dev/ic/hd64570.h>
   52 #include <dev/sr/if_srregs.h>
   53 
   54 /*
   55  * List of valid interrupt numbers for the N2 ISA card.
   56  */
   57 static int sr_irqtable[16] = {
   58         0,      /*  0 */
   59         0,      /*  1 */
   60         0,      /*  2 */
   61         1,      /*  3 */
   62         1,      /*  4 */
   63         1,      /*  5 */
   64         0,      /*  6 */
   65         1,      /*  7 */
   66         0,      /*  8 */
   67         0,      /*  9 */
   68         1,      /* 10 */
   69         1,      /* 11 */
   70         1,      /* 12 */
   71         0,      /* 13 */
   72         0,      /* 14 */
   73         1       /* 15 */
   74 };
   75 
   76 static int sr_isa_probe (device_t);
   77 static int sr_isa_attach (device_t);
   78 
   79 static struct isa_pnp_id sr_ids[] = {
   80         {0,             NULL}
   81 };
   82 
   83 static device_method_t sr_methods[] = {
   84         DEVMETHOD(device_probe,         sr_isa_probe),
   85         DEVMETHOD(device_attach,        sr_isa_attach),
   86         DEVMETHOD(device_detach,        sr_detach),
   87         { 0, 0 }
   88 };
   89 
   90 static driver_t sr_isa_driver = {
   91         "sr",
   92         sr_methods,
   93         sizeof (struct sr_hardc)
   94 };
   95 
   96 DRIVER_MODULE(if_sr, isa, sr_isa_driver, sr_devclass, 0, 0);
   97 
   98 static u_int    src_get8_io(u_int base, u_int off);
   99 static u_int    src_get16_io(u_int base, u_int off);
  100 static void     src_put8_io(u_int base, u_int off, u_int val);
  101 static void     src_put16_io(u_int base, u_int off, u_int val);
  102 static u_int    src_dpram_size(device_t device);
  103 
  104 /*
  105  * Probe for an ISA card. If it is there, size its memory. Then get the
  106  * rest of its information and fill it in.
  107  */
  108 static int
  109 sr_isa_probe (device_t device)
  110 {
  111         struct sr_hardc *hc;
  112         int error;
  113         u_int32_t flags;
  114         u_int i, tmp;
  115         u_short port;
  116         u_long irq, junk, membase, memsize, port_start, port_count;
  117         sca_regs *sca = 0;
  118 
  119         error = ISA_PNP_PROBE(device_get_parent(device), device, sr_ids);
  120         if (error == ENXIO || error == 0)
  121                 return (error);
  122 
  123         hc = device_get_softc(device);
  124         bzero(hc, sizeof(struct sr_hardc));
  125 
  126         if (sr_allocate_ioport(device, 0, SRC_IO_SIZ)) {
  127                 return (ENXIO);
  128         }
  129 
  130         /*
  131          * Now see if the card is realy there.
  132          */
  133         error = bus_get_resource(device, SYS_RES_IOPORT, 0, &port_start,
  134             &port_count);
  135         port = port_start;
  136 
  137         hc->cardtype = SR_CRD_N2;
  138         hc->cunit = device_get_unit(device);
  139         hc->iobase = port_start;
  140         /*
  141          * We have to fill these in early because the SRC_PUT* and SRC_GET*
  142          * macros use them.
  143          */
  144         hc->src_get8 = src_get8_io;
  145         hc->src_get16 = src_get16_io;
  146         hc->src_put8 = src_put8_io;
  147         hc->src_put16 = src_put16_io;
  148 
  149         hc->sca = 0;
  150         hc->numports = NCHAN;   /* assumed # of channels on the card */
  151 
  152         flags = device_get_flags(device);
  153         if (flags & SR_FLAGS_NCHAN_MSK)
  154                 hc->numports = flags & SR_FLAGS_NCHAN_MSK;
  155 
  156         outb(port + SR_PCR, 0); /* turn off the card */
  157 
  158         /*
  159          * Next, we'll test the Base Address Register to retension of
  160          * data... ... seeing if we're *really* talking to an N2.
  161          */
  162         for (i = 0; i < 0x100; i++) {
  163                 outb(port + SR_BAR, i);
  164                 inb(port + SR_PCR);
  165                 tmp = inb(port + SR_BAR);
  166                 if (tmp != i) {
  167                         printf("sr%d: probe failed BAR %x, %x.\n",
  168                                hc->cunit, i, tmp);
  169                         goto errexit;
  170                 }
  171         }
  172 
  173         /*
  174          * Now see if we can see the SCA.
  175          */
  176         outb(port + SR_PCR, SR_PCR_SCARUN | inb(port + SR_PCR));
  177         SRC_PUT8(port, sca->wcrl, 0);
  178         SRC_PUT8(port, sca->wcrm, 0);
  179         SRC_PUT8(port, sca->wcrh, 0);
  180         SRC_PUT8(port, sca->pcr, 0);
  181         SRC_PUT8(port, sca->msci[0].tmc, 0);
  182         inb(port);
  183 
  184         tmp = SRC_GET8(port, sca->msci[0].tmc);
  185         if (tmp != 0) {
  186                 printf("sr%d: Error reading SCA 0, %x\n", hc->cunit, tmp);
  187                 goto errexit;
  188         }
  189         SRC_PUT8(port, sca->msci[0].tmc, 0x5A);
  190         inb(port);
  191 
  192         tmp = SRC_GET8(port, sca->msci[0].tmc);
  193         if (tmp != 0x5A) {
  194                 printf("sr%d: Error reading SCA 0x5A, %x\n", hc->cunit, tmp);
  195                 goto errexit;
  196         }
  197         SRC_PUT16(port, sca->dmac[0].cda, 0);
  198         inb(port);
  199 
  200         tmp = SRC_GET16(port, sca->dmac[0].cda);
  201         if (tmp != 0) {
  202                 printf("sr%d: Error reading SCA 0, %x\n", hc->cunit, tmp);
  203                 goto errexit;
  204         }
  205         SRC_PUT16(port, sca->dmac[0].cda, 0x55AA);
  206         inb(port);
  207 
  208         tmp = SRC_GET16(port, sca->dmac[0].cda);
  209         if (tmp != 0x55AA) {
  210                 printf("sr%d: Error reading SCA 0x55AA, %x\n",
  211                        hc->cunit, tmp);
  212                 goto errexit;
  213         }
  214 
  215         membase = bus_get_resource_start(device, SYS_RES_MEMORY, 0);
  216         memsize = SRC_WIN_SIZ;
  217         if (bus_set_resource(device, SYS_RES_MEMORY, 0, membase, memsize))
  218                 goto errexit;
  219 
  220         if (sr_allocate_memory(device, 0, SRC_WIN_SIZ))
  221                 goto errexit;
  222 
  223         if (src_dpram_size(device) < 4)
  224                 goto errexit;
  225 
  226         if (sr_allocate_irq(device, 0, 1))
  227                 goto errexit;
  228 
  229         if (bus_get_resource(device, SYS_RES_IRQ, 0, &irq, &junk)) {
  230                 goto errexit;
  231         }
  232         /*
  233          * Do a little sanity check.
  234          */
  235         if (sr_irqtable[irq] == 0)
  236                 printf("sr%d: Warning: illegal interrupt %ld chosen.\n",
  237                        hc->cunit, irq);
  238 
  239         /*
  240          * Bogus card configuration
  241          */
  242         if ((hc->numports > NCHAN)      /* only 2 ports/card */
  243             ||(hc->memsize > (512 * 1024)))     /* no more than 256K */
  244                 goto errexit;
  245 
  246         sr_deallocate_resources(device);
  247         return (0);
  248 
  249 errexit:
  250         sr_deallocate_resources(device);
  251         return (ENXIO);
  252 }
  253 
  254 /*
  255  * srattach_isa and srattach_pci allocate memory for hardc, softc and
  256  * data buffers. It also does any initialization that is bus specific.
  257  * At the end they call the common srattach() function.
  258  */
  259 static int
  260 sr_isa_attach (device_t device)
  261 {
  262         u_char mar;
  263         u_int32_t flags;
  264         struct sr_hardc *hc;
  265 
  266         hc = device_get_softc(device);
  267         bzero(hc, sizeof(struct sr_hardc));
  268 
  269         if (sr_allocate_ioport(device, 0, SRC_IO_SIZ))
  270                 goto errexit;
  271         if (sr_allocate_memory(device, 0, SRC_WIN_SIZ))
  272                 goto errexit;
  273         if (sr_allocate_irq(device, 0, 1))
  274                 goto errexit;
  275 
  276         /*
  277          * We have to fill these in early because the SRC_PUT* and SRC_GET*
  278          * macros use them.
  279          */
  280         hc->src_get8 = src_get8_io;
  281         hc->src_get16 = src_get16_io;
  282         hc->src_put8 = src_put8_io;
  283         hc->src_put16 = src_put16_io;
  284 
  285         hc->cardtype = SR_CRD_N2;
  286         hc->cunit = device_get_unit(device);
  287         hc->sca = 0;
  288         hc->numports = NCHAN;   /* assumed # of channels on the card */
  289         flags = device_get_flags(device);
  290         if (flags & SR_FLAGS_NCHAN_MSK)
  291                 hc->numports = flags & SR_FLAGS_NCHAN_MSK;
  292 
  293         hc->iobase = rman_get_start(hc->res_ioport);
  294         hc->sca_base = hc->iobase;
  295         hc->mem_start = (caddr_t)rman_get_virtual(hc->res_memory);
  296         hc->mem_end = hc->mem_start + SRC_WIN_SIZ;
  297         hc->mem_pstart = 0;
  298         hc->winmsk = SRC_WIN_MSK;
  299 
  300         hc->mempages = src_dpram_size(device);
  301         hc->memsize = hc->mempages * SRC_WIN_SIZ;
  302 
  303         outb(hc->iobase + SR_PCR, inb(hc->iobase + SR_PCR) | SR_PCR_SCARUN);
  304         outb(hc->iobase + SR_PSR, inb(hc->iobase + SR_PSR) | SR_PSR_EN_SCA_DMA);
  305         outb(hc->iobase + SR_MCR,
  306              SR_MCR_DTR0 | SR_MCR_DTR1 | SR_MCR_TE0 | SR_MCR_TE1);
  307 
  308         SRC_SET_ON(hc->iobase);
  309 
  310         /*
  311          * Configure the card. Mem address, irq,
  312          */
  313         mar = (rman_get_start(hc->res_memory) >> 16) & SR_PCR_16M_SEL;
  314         outb(hc->iobase + SR_PCR,
  315              mar | (inb(hc->iobase + SR_PCR) & ~SR_PCR_16M_SEL));
  316         mar = rman_get_start(hc->res_memory) >> 12;
  317         outb(hc->iobase + SR_BAR, mar);
  318 
  319         return sr_attach(device);
  320 
  321 errexit:
  322         sr_deallocate_resources(device);
  323         return (ENXIO);
  324 }
  325 
  326 /*
  327  * I/O for ISA N2 card(s)
  328  */
  329 #define SRC_REG(iobase,y)       ((((y) & 0xf) + (((y) & 0xf0) << 6) +       \
  330                                 (iobase)) | 0x8000)
  331 
  332 static u_int
  333 src_get8_io(u_int base, u_int off)
  334 {
  335         return inb(SRC_REG(base, off));
  336 }
  337 
  338 static u_int
  339 src_get16_io(u_int base, u_int off)
  340 {
  341         return inw(SRC_REG(base, off));
  342 }
  343 
  344 static void
  345 src_put8_io(u_int base, u_int off, u_int val)
  346 {
  347         outb(SRC_REG(base, off), val);
  348 }
  349 
  350 static void
  351 src_put16_io(u_int base, u_int off, u_int val)
  352 {
  353         outw(SRC_REG(base, off), val);
  354 }
  355 
  356 static u_int
  357 src_dpram_size(device_t device)
  358 {
  359         u_int pgs, i;
  360         u_short port;
  361         u_short *smem;
  362         u_char mar;
  363         u_long membase;
  364         struct sr_hardc *hc;
  365 
  366         hc = device_get_softc(device);
  367         port = hc->iobase;
  368 
  369         /*
  370          * OK, the board's interface registers seem to work. Now we'll see
  371          * if the Dual-Ported RAM is fully accessible...
  372          */
  373         outb(port + SR_PCR, SR_PCR_EN_VPM | SR_PCR_ISA16);
  374         outb(port + SR_PSR, SR_PSR_WIN_16K);
  375 
  376         /*
  377          * Take the kernel "virtual" address supplied to us and convert
  378          * it to a "real" address. Then program the card to use that.
  379          */
  380         membase = rman_get_start(hc->res_memory);
  381         mar = (membase >> 16) & SR_PCR_16M_SEL;
  382         outb(port + SR_PCR, mar | inb(port + SR_PCR));
  383         mar = membase >> 12;
  384         outb(port + SR_BAR, mar);
  385         outb(port + SR_PCR, inb(port + SR_PCR) | SR_PCR_MEM_WIN);
  386         smem = (u_short *)rman_get_virtual(hc->res_memory);/* DP RAM Address */
  387         /*
  388          * Here we will perform the memory scan to size the device.
  389          *
  390          * This is done by marking each potential page with a magic number.
  391          * We then loop through the pages looking for that magic number. As
  392          * soon as we no longer see that magic number, we'll quit the scan,
  393          * knowing that no more memory is present. This provides the number
  394          * of pages present on the card.
  395          *
  396          * Note: We're sizing 16K memory granules.
  397          */
  398         for (i = 0; i <= SR_PSR_PG_SEL; i++) {
  399                 outb(port + SR_PSR,
  400                      (inb(port + SR_PSR) & ~SR_PSR_PG_SEL) | i);
  401 
  402                 *smem = 0xAA55;
  403         }
  404 
  405         for (i = 0; i <= SR_PSR_PG_SEL; i++) {
  406                 outb(port + SR_PSR,
  407                      (inb(port + SR_PSR) & ~SR_PSR_PG_SEL) | i);
  408 
  409                 if (*smem != 0xAA55) {
  410                         /*
  411                          * If we have less than 64k of memory, give up. That
  412                          * is 4 x 16k pages.
  413                          */
  414                         if (i < 4) {
  415                                 printf("sr%d: Bad mem page %d, mem %x, %x.\n",
  416                                        hc->cunit, i, 0xAA55, *smem);
  417                                 return 0;
  418                         }
  419                         break;
  420                 }
  421                 *smem = i;
  422         }
  423 
  424         hc->mempages = i;
  425         hc->memsize = i * SRC_WIN_SIZ;
  426         hc->winmsk = SRC_WIN_MSK;
  427         pgs = i;                /* final count of 16K pages */
  428 
  429         /*
  430          * This next loop erases the contents of that page in DPRAM
  431          */
  432         for (i = 0; i <= pgs; i++) {
  433                 outb(port + SR_PSR,
  434                      (inb(port + SR_PSR) & ~SR_PSR_PG_SEL) | i);
  435                 bzero(smem, SRC_WIN_SIZ);
  436         }
  437 
  438         SRC_SET_OFF(port);
  439         return (pgs);
  440 }

Cache object: 72143524e89e9476bddbdb5ea61b482e


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