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/chips/lance_mapped.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  * Mach Operating System
    3  * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        lance_mapped.c,v $
   29  * Revision 2.22  93/11/17  16:12:02  dbg
   30  *      Changed mmap routines to return physical address instead of
   31  *      physical page number.  Added prototypes.
   32  *      [93/06/16            dbg]
   33  * 
   34  * Revision 2.21  93/05/15  19:36:50  mrt
   35  *      machparam.h -> machspl.h
   36  * 
   37  * Revision 2.20  93/05/10  20:08:11  rvb
   38  *      No more sys/types.h.
   39  *      [93/05/06  09:52:53  af]
   40  * 
   41  * Revision 2.19  93/03/26  17:58:07  mrt
   42  *      Removed dev_t, minor();
   43  *      [93/03/17            af]
   44  * 
   45  * Revision 2.18  93/03/11  14:06:09  danner
   46  *      eliminate u_long.
   47  *      [93/03/09            danner]
   48  * 
   49  * Revision 2.17  93/02/05  08:18:50  danner
   50  *      Include fixes.
   51  *      [93/02/04            danner]
   52  * 
   53  * Revision 2.16  93/02/01  09:55:15  danner
   54  *      Put return types on some functions to quiet warnings.
   55  *      [93/01/25            jfriedl]
   56  * 
   57  * Revision 2.15  93/01/14  17:16:46  danner
   58  *      corrected typo.
   59  *      [93/01/12            danner]
   60  *      Added LUNA88K and portability support.
   61  *      [92/12/02            jfriedl]
   62  *      Proper spl typing.
   63  *      [92/11/30            af]
   64  * 
   65  * Revision 2.14  92/01/03  20:39:03  dbg
   66  *      No need to destroy/init the eventcounter all the time.
   67  *      [91/12/27            af]
   68  * 
   69  *      Since we are actually using this, made user-safe.
   70  *      [91/12/27            af]
   71  * 
   72  * Revision 2.13  91/12/13  14:54:23  jsb
   73  *      Use eventcounters.
   74  *      [91/12/12  17:43:08  af]
   75  * 
   76  * Revision 2.12  91/08/24  11:52:17  af
   77  *      Bugfix: typos, spl for 3min.
   78  *      [91/08/02  01:52:26  af]
   79  * 
   80  * Revision 2.11  91/06/25  20:54:03  rpd
   81  *      Tweaks to make gcc happy.
   82  * 
   83  * Revision 2.10  91/06/19  15:19:40  rvb
   84  *      mips->DECSTATION; vax->VAXSTATION
   85  *      [91/06/12  14:01:45  rvb]
   86  * 
   87  *      File moved here from mips/PMAX since it tries to be generic;
   88  *      it is used on the PMAX and could be used on the Vax3100.
   89  *      [91/06/04            rvb]
   90  * 
   91  * Revision 2.9  91/05/14  17:22:24  mrt
   92  *      Correcting copyright
   93  * 
   94  * Revision 2.8  91/03/16  14:54:00  rpd
   95  *      Picked up a further spl fix from Sandro.
   96  *      [91/03/09            rpd]
   97  *      Updated for new kmem_alloc interface.
   98  *      [91/03/03            rpd]
   99  *      Removed thread_swappable.
  100  *      [91/01/18            rpd]
  101  * 
  102  * Revision 2.7  91/02/14  14:34:16  mrt
  103  *      In interrupt routine, drop priority as now required.
  104  *      Also sanity check for spurious interrupts anyways.
  105  *      [91/02/12  12:41:46  af]
  106  * 
  107  * Revision 2.6  91/02/05  17:41:22  mrt
  108  *      Added author notices
  109  *      [91/02/04  11:13:58  mrt]
  110  * 
  111  *      Changed to use new Mach copyright
  112  *      [91/02/02  12:12:01  mrt]
  113  * 
  114  * Revision 2.5  90/12/05  23:31:33  af
  115  *      Cleanups.
  116  *      [90/12/03  23:20:13  af]
  117  * 
  118  * Revision 2.3.1.1  90/10/03  12:06:02  af
  119  *      Made it work with multiple ether boards (e.g. thick ether
  120  *      on 3maxen).  This is the first time a mapped device does
  121  *      something before the un-mapped one..
  122  * 
  123  * Revision 2.3  90/09/09  23:52:11  rpd
  124  *      Changed thread_resume_from_kernel to thread_resume.
  125  * 
  126  * Revision 2.2  90/09/09  23:20:35  rpd
  127  *      Correctly return the ram size for the givem machine: 3maxen
  128  *      have twice as much ram as pmaxen.
  129  *      [90/09/09  18:59:41  af]
  130  * 
  131  *      Created.
  132  *      [90/08/22            af]
  133  */
  134 /*
  135  *      File: if_se_mapped.c
  136  *      Author: Alessandro Forin, Carnegie Mellon University
  137  *      Date:   8/90
  138  *
  139  *      In-kernel side of the user-mapped ethernet driver.
  140  */
  141 
  142 #include <ln.h>
  143 #if     NLN > 0
  144 #include <platforms.h>
  145 
  146 #include <mach/machine/vm_types.h>
  147 #include <machine/machspl.h>            /* spl definitions */
  148 #include <ipc/ipc_types.h>
  149 #include <kern/kern_io.h>
  150 #include <kern/memory.h>
  151 #include <chips/lance.h>
  152 #include <chips/busses.h>
  153 
  154 #include <device/device_types.h>
  155 #include <device/errno.h>
  156 #include <device/io_req.h>
  157 #include <device/net_status.h>
  158 #include <device/net_io.h>
  159 #include <device/if_hdr.h>
  160 #include <device/if_ether.h>
  161 
  162 #include <vm/vm_kern.h>
  163 #include <kern/eventcount.h>
  164 
  165 #include <machine/machspl.h>
  166 
  167 #ifdef  DECSTATION
  168 
  169 #define machine_btop    mips_btop
  170 
  171 #define kvctophys(v)    K0SEG_TO_PHYS((vm_offset_t)(v))
  172                                                 /* kernel virtual cached */
  173 #define phystokvc(p)    PHYS_TO_K0SEG((p))      /* and back */
  174 #define kvutophys(v)    K1SEG_TO_PHYS((vm_offset_t)(v))
  175                                                 /* kernel virtual uncached */
  176 #define phystokvu(p)    PHYS_TO_K1SEG((p))      /* and back */
  177         /* remap from k2 to k0 */
  178 #define kvirt(v)        ((phystokvc(pmap_extract(pmap_kernel(),v))))
  179 
  180 #include <mips/mips_cpu.h>
  181 /*
  182  * Wired addresses and sizes
  183  */
  184 #define SE0_REG_EMRG    (se_reg_t)(0xb8000000)
  185 
  186 #define REGBASE(unit)   (((u_int)SE_statii[unit].registers) - se_sw->regspace)
  187 
  188 #define SE_REG_PHYS(unit)       kvutophys(REGBASE(unit)+se_sw->regspace)
  189 #define SE_REG_SIZE             PAGE_SIZE
  190 
  191 #define SE_BUF_PHYS(unit)       kvutophys(REGBASE(unit)+se_sw->bufspace)
  192 #define SE_BUF_SIZE             (128*1024)
  193 
  194 #define SE_ADR_PHYS(unit)       kvutophys(REGBASE(unit)+se_sw->romspace)
  195 #define SE_ADR_SIZE             PAGE_SIZE
  196 #endif  /*DECSTATION*/
  197 
  198 #ifdef  VAXSTATION
  199 #define machine_btop    vax_btop
  200 #endif  /*VAXSTATION*/
  201 
  202 #ifdef LUNA88K
  203 #  define machine_btop          m88k_btop
  204 #  define kvirt(v)              (v)
  205 #  define kvctophys(v)          pmap_extract(pmap_kernel(),(vm_offset_t)(v))
  206 #  define SE0_REG_EMRG          ((se_reg_t)0xF1000000U)
  207 #  define REGBASE(unit) (((u_int)SE_statii[unit].registers) - se_sw->regspace)
  208 #  define SE_REG_PHYS(unit)     (REGBASE(unit) + se_sw->regspace)
  209 #  define SE_REG_SIZE           PAGE_SIZE
  210 #  define SE_BUF_PHYS(unit)     (REGBASE(unit) + se_sw->bufspace)
  211 #  define SE_BUF_SIZE           (64*1024)
  212 #  define SE_ADR_PHYS(unit)     kvctophys(REGBASE(unit) + se_sw->romspace)
  213 #  define SE_ADR_SIZE           PAGE_SIZE
  214 #  define wbflush()     /*empty*/
  215 #endif /*LUNA88K*/
  216 
  217 /*
  218  * Autoconf info
  219  */
  220 
  221 static  vm_offset_t SEstd[NLN] = { 0 };
  222 static  struct bus_device *SEinfo[NLN];
  223         void SE_attach(struct bus_device *);
  224         boolean_t SE_probe(vm_offset_t, struct bus_device *);
  225 
  226 struct bus_driver SEdriver =
  227        { SE_probe, 0, SE_attach, 0, SEstd, "SE", SEinfo, };
  228 
  229 /*
  230  * Externally visible functions
  231  */
  232 /* int          SE_probe(); */          /* Kernel */
  233 void            SE_intr(), SE_portdeath();
  234                                                 /* User */
  235 int             SE_open(), SE_close();
  236 vm_offset_t     SE_mmap();
  237 
  238 
  239 /* forward declarations */
  240 
  241 static void SE_stop(unsigned int unit);
  242 
  243 /*
  244  * Status information for all interfaces
  245  */
  246 /*static*/ struct SE_status {
  247         se_reg_t                         registers;
  248         mapped_ether_info_t              info;
  249         struct evc                       eventcounter;
  250 } SE_statii[NLN];
  251 
  252 
  253 /*
  254  * Probe the Lance to see (if) that it's there
  255  */
  256 boolean_t
  257 SE_probe(
  258         vm_offset_t regbase,
  259         register struct bus_device *ui)
  260 {
  261         int                     unit = ui->unit;
  262         se_reg_t                regs;
  263         vm_offset_t             addr;
  264         mapped_ether_info_t     info;
  265         struct SE_status        *self;
  266 
  267 
  268         if (unit >= NLN)
  269                 return FALSE;
  270 
  271         self = &SE_statii[unit];
  272 
  273         printf("[mappable] ");
  274 
  275         regs = (se_reg_t) (regbase + se_sw->regspace);
  276         self->registers = regs;
  277 
  278         /*
  279          * Reset the interface 
  280          */
  281         SE_stop(unit);
  282 
  283         /*
  284          * Grab a page to be mapped later to users 
  285          */
  286         (void) kmem_alloc_wired(kernel_map, &addr, PAGE_SIZE);  
  287         /* 
  288           on the decstation, kmem_alloc_wired returns virtual addresses
  289           in the k2 seg. Since this page is going to get mapped in
  290           user space, we need to transform it to a better understood
  291           virtual address. The kvirt function does this.
  292         */
  293         bzero((void *)addr, PAGE_SIZE);
  294         info = (mapped_ether_info_t) kvirt(addr);
  295         self->info = info;
  296 
  297         /*
  298          * Set permanent info
  299          */
  300         info->rom_stride = se_sw->romstride;
  301         info->ram_stride = se_sw->ramstride;
  302         info->buffer_size = se_sw->ramsize;
  303         info->buffer_physaddr = se_sw->ln_bufspace;
  304 
  305         /*
  306          * Synch setup
  307          */
  308         evc_init(&self->eventcounter);
  309         info->wait_event = self->eventcounter.ev_id;
  310 
  311         return TRUE;
  312 }
  313 
  314 void
  315 SE_attach(
  316         register struct bus_device *ui)
  317 {
  318 }
  319  
  320 
  321 /*
  322  * Shut off the lance
  323  */
  324 static void SE_stop(unsigned int unit)
  325 {
  326         register se_reg_t       regs = SE_statii[unit].registers;
  327 
  328         if (regs == 0)
  329                 /* Stray interrupt */
  330                 regs = SE0_REG_EMRG;
  331 
  332         regs[2] = CSR0_SELECT;  /* XXXX rap XXXX */
  333         wbflush();
  334         regs[0] = LN_CSR0_STOP;
  335         wbflush();
  336 }
  337 
  338 
  339 /*
  340  * Ethernet interface interrupt routine
  341  */
  342 void SE_intr(
  343         int     unit,
  344         spl_t   spllevel)
  345 {
  346         register struct SE_status *self = &SE_statii[unit];
  347         register se_reg_t          regs = self->registers;
  348         register                   csr;
  349 
  350         if (regs == 0) {        /* stray */
  351                 SE_stop(unit);
  352                 return;
  353         }
  354 
  355         /* Acknowledge interrupt request, drop spurious intr */
  356         csr = regs[0];
  357         if ((csr & LN_CSR0_INTR) == 0)
  358                 return;
  359         regs[0] = csr & LN_CSR0_WTC;            /* silence it */
  360 
  361         splx(spllevel); /* drop priority now */
  362 
  363         /* Pass csr state up to user thread */
  364         if (self->info) {
  365                 self->info->interrupt_count++;  /* total interrupts */
  366                 self->info->saved_csr0 = csr;
  367         }
  368 
  369         /* Awake user thread */
  370         evc_signal(&self->eventcounter);
  371 }
  372  
  373 
  374 extern boolean_t se_use_mapped_interface[NLN];
  375 
  376 /*
  377  * Device open procedure
  378  */
  379 io_return_t
  380 SE_open(
  381         int     dev,
  382         int     flag,
  383         io_req_t ior)
  384 {
  385         int             unit = dev;
  386         register struct SE_status *self = &SE_statii[unit];
  387 
  388         if (unit >= NLN)
  389                 return EINVAL;
  390 
  391         /*
  392          * Silence interface, just in case 
  393          */
  394         SE_stop(unit);
  395 
  396         /*
  397          * Reset eventcounter
  398          */
  399         evc_signal(&self->eventcounter);
  400 
  401         se_use_mapped_interface[unit] = 1;
  402 
  403         /*
  404          * Do not turn Ether interrupts on.  The user can do it when ready
  405          * to take them. 
  406          */
  407 
  408         return 0;
  409 }
  410 
  411 /*
  412  * Device close procedure
  413  */
  414 io_return_t SE_close(
  415         int     dev,
  416         int     flag)
  417 {
  418         register struct SE_status *self = &SE_statii[dev];
  419 
  420         if (dev >= NLN)
  421                 return EINVAL;
  422 
  423         /*
  424          * Silence interface, in case user forgot
  425          */
  426         SE_stop(dev);
  427         evc_signal(&self->eventcounter);
  428 
  429         se_normal(dev);
  430 
  431         return 0;
  432 }
  433 
  434 
  435 /*
  436  * Get status procedure.
  437  * We need to tell that we are mappable.
  438  */
  439 io_return_t
  440 SE_get_status(
  441         int             dev,
  442         dev_flavor_t    flavor,
  443         dev_status_t    status,         /* pointer to OUT array */
  444         natural_t       *status_count)  /* OUT */
  445 {
  446         switch (flavor) {
  447             case NET_STATUS:
  448             {
  449                 register struct net_status *ns = (struct net_status *)status;
  450 
  451                 ns->min_packet_size = sizeof(struct ether_header);
  452                 ns->max_packet_size = sizeof(struct ether_header) + ETHERMTU;
  453                 ns->header_format   = HDR_ETHERNET;
  454                 ns->header_size     = sizeof(struct ether_header);
  455                 ns->address_size    = 6;
  456                 ns->flags           = IFF_BROADCAST;
  457                 ns->mapped_size     = SE_BUF_SIZE + (3 * PAGE_SIZE);
  458 
  459                 *status_count = NET_STATUS_COUNT;
  460                 break;
  461             }
  462 /*          case NET_ADDRESS:   find it yourself */
  463             default:
  464                 return D_INVALID_OPERATION;
  465         }
  466         return D_SUCCESS;
  467 }
  468 
  469 /*
  470  * Should not refuse this either
  471  */
  472 io_return_t
  473 SE_set_status(
  474         int             dev,
  475         dev_flavor_t    flavor,
  476         dev_status_t    status,
  477         natural_t       status_count)
  478 {
  479         return D_SUCCESS;
  480 }
  481 
  482 /*
  483  * Port death notification routine
  484  */
  485 void SE_portdeath(int dev, ipc_port_t dead_port)
  486 {
  487 }
  488 
  489 
  490 /*
  491  * Virtual->physical mapping routine.
  492  */
  493 vm_offset_t
  494 SE_mmap(
  495         int             dev,
  496         vm_offset_t     off,
  497         vm_prot_t       prot)
  498 {
  499         vm_offset_t     addr;
  500 
  501         /*
  502          * The offset (into the VM object) defines the following layout
  503          *
  504          *      off     size    what
  505          *      0       1pg     mapping information (csr & #interrupts)
  506          *      1pg     1pg     lance registers
  507          *      2pg     1pg     lance station address (ROM)
  508          *      3pg     128k    lance buffers 
  509          */
  510 #define S0      PAGE_SIZE
  511 #define S1      (S0+SE_REG_SIZE)
  512 #define S2      (S1+SE_ADR_SIZE)
  513 #define S3      (S2+SE_BUF_SIZE)
  514 
  515         if (off < S0) {
  516                 addr = kvctophys (SE_statii[dev].info);
  517         } else if (off < S1) {
  518                 addr = (vm_offset_t) SE_REG_PHYS(dev);
  519                 off -= S0;
  520         } else if (off < S2) {
  521                 addr = (vm_offset_t) SE_ADR_PHYS(dev);
  522                 off -= S1;
  523         } else if (off < S3) {
  524                 addr = (vm_offset_t) SE_BUF_PHYS(dev);
  525                 off -= S2;
  526         } else
  527                 return -1;
  528 
  529         return addr + off;
  530 }
  531 
  532 #endif  /* NLN > 0 */

Cache object: 9d94628cd3db08acf7c663f00f5b0748


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