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

Cache object: a0ee0a6723b18c4b696fc1e8f317d845


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