Annotation of Gnu-Mach/chips/lance_mapped.c, revision 1.1.1.1

1.1       root        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  [email protected]
                     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:  *     File: if_se_mapped.c
                     28:  *     Author: Alessandro Forin, Carnegie Mellon University
                     29:  *     Date:   8/90
                     30:  *
                     31:  *     In-kernel side of the user-mapped ethernet driver.
                     32:  */
                     33: 
                     34: #include <ln.h>
                     35: #if     NLN > 0
                     36: #include <platforms.h>
                     37: 
                     38: #include <mach/machine/vm_types.h>
                     39: #include <machine/machspl.h>           /* spl definitions */
                     40: #include <chips/lance.h>
                     41: #include <chips/busses.h>
                     42: 
                     43: #include <device/device_types.h>
                     44: #include <device/errno.h>
                     45: #include <device/io_req.h>
                     46: #include <device/net_status.h>
                     47: #include <device/net_io.h>
                     48: #include <device/if_hdr.h>
                     49: #include <device/if_ether.h>
                     50: 
                     51: #include <vm/vm_kern.h>
                     52: #include <kern/eventcount.h>
                     53: 
                     54: #include <machine/machspl.h>
                     55: 
                     56: #ifdef DECSTATION
                     57: 
                     58: #define        machine_btop    mips_btop
                     59: 
                     60: #define        kvctophys(v)    K0SEG_TO_PHYS((v))      /* kernel virtual cached */
                     61: #define        phystokvc(p)    PHYS_TO_K0SEG((p))      /* and back */
                     62: #define        kvutophys(v)    K1SEG_TO_PHYS((v))      /* kernel virtual uncached */
                     63: #define        phystokvu(p)    PHYS_TO_K1SEG((p))      /* and back */
                     64:        /* remap from k2 to k0 */
                     65: #define kvirt(v)        ((phystokvc(pmap_extract(pmap_kernel(),v))))
                     66: 
                     67: #include <mips/mips_cpu.h>
                     68: /*
                     69:  * Wired addresses and sizes
                     70:  */
                     71: #define SE0_REG_EMRG   (se_reg_t)(0xb8000000)
                     72: 
                     73: #define        REGBASE(unit)   (((u_int)SE_statii[unit].registers) - se_sw->regspace)
                     74: 
                     75: #define SE_REG_PHYS(unit)      kvutophys(REGBASE(unit)+se_sw->regspace)
                     76: #define SE_REG_SIZE            PAGE_SIZE
                     77: 
                     78: #define SE_BUF_PHYS(unit)      kvutophys(REGBASE(unit)+se_sw->bufspace)
                     79: #define SE_BUF_SIZE            (128*1024)
                     80: 
                     81: #define SE_ADR_PHYS(unit)      kvutophys(REGBASE(unit)+se_sw->romspace)
                     82: #define SE_ADR_SIZE            PAGE_SIZE
                     83: #endif /*DECSTATION*/
                     84: 
                     85: #ifdef VAXSTATION
                     86: #define        machine_btop    vax_btop
                     87: #endif /*VAXSTATION*/
                     88: 
                     89: #ifdef LUNA88K
                     90: #  define machine_btop         m88k_btop
                     91: #  define kvirt(v)             (v)
                     92: #  define kvctophys(v)         pmap_extract(pmap_kernel(),(v))
                     93: #  define SE0_REG_EMRG         ((se_reg_t)0xF1000000U)
                     94: #  define REGBASE(unit)        (((u_int)SE_statii[unit].registers) - se_sw->regspace)
                     95: #  define SE_REG_PHYS(unit)    (REGBASE(unit) + se_sw->regspace)
                     96: #  define SE_REG_SIZE          PAGE_SIZE
                     97: #  define SE_BUF_PHYS(unit)    (REGBASE(unit) + se_sw->bufspace)
                     98: #  define SE_BUF_SIZE          (64*1024)
                     99: #  define SE_ADR_PHYS(unit)    kvctophys(REGBASE(unit) + se_sw->romspace)
                    100: #  define SE_ADR_SIZE          PAGE_SIZE
                    101: #  define wbflush()    /*empty*/
                    102: #endif /*LUNA88K*/
                    103: 
                    104: /*
                    105:  * Autoconf info
                    106:  */
                    107: 
                    108: static  vm_offset_t SEstd[NLN] = { 0 };
                    109: static struct bus_device *SEinfo[NLN];
                    110:        void SE_attach();
                    111:        int SE_probe();
                    112: 
                    113: struct bus_driver SEdriver =
                    114:        { SE_probe, 0, SE_attach, 0, SEstd, "SE", SEinfo, };
                    115: 
                    116: /*
                    117:  * Externally visible functions
                    118:  */
                    119: int            SE_probe();             /* Kernel */
                    120: void           SE_intr(), SE_portdeath();
                    121:                                                /* User */
                    122: int            SE_open(), SE_close();
                    123: vm_offset_t    SE_mmap();
                    124: 
                    125: 
                    126: /* forward declarations */
                    127: 
                    128: static void SE_stop(unsigned int unit);
                    129: 
                    130: /*
                    131:  * Status information for all interfaces
                    132:  */
                    133: /*static*/ struct SE_status {
                    134:        se_reg_t                         registers;
                    135:        mapped_ether_info_t              info;
                    136:        struct evc                       eventcounter;
                    137: } SE_statii[NLN];
                    138: 
                    139: 
                    140: /*
                    141:  * Probe the Lance to see (if) that it's there
                    142:  */
                    143: int
                    144: SE_probe(regbase, ui)
                    145:        vm_offset_t regbase;
                    146:        register struct bus_device *ui;
                    147: {
                    148:        int                     unit = ui->unit;
                    149:        se_reg_t                regs;
                    150:        vm_offset_t             addr;
                    151:        mapped_ether_info_t     info;
                    152:        struct SE_status        *self;
                    153: 
                    154: 
                    155:        if (unit >= NLN)
                    156:                return 0;
                    157: 
                    158:        self = &SE_statii[unit];
                    159: 
                    160:        printf("[mappable] ");
                    161: 
                    162:        regs = (se_reg_t) (regbase + se_sw->regspace);
                    163:        self->registers = regs;
                    164: 
                    165:        /*
                    166:         * Reset the interface 
                    167:         */
                    168:        SE_stop(unit);
                    169: 
                    170:        /*
                    171:         * Grab a page to be mapped later to users 
                    172:         */
                    173:        (void) kmem_alloc_wired(kernel_map, &addr, PAGE_SIZE);  
                    174:        /* 
                    175:          on the decstation, kmem_alloc_wired returns virtual addresses
                    176:          in the k2 seg. Since this page is going to get mapped in
                    177:          user space, we need to transform it to a better understood
                    178:          virtual address. The kvirt function does this.
                    179:        */
                    180:        bzero(addr, PAGE_SIZE);
                    181:        info = (mapped_ether_info_t) kvirt(addr);
                    182:        self->info = info;
                    183: 
                    184:        /*
                    185:         * Set permanent info
                    186:         */
                    187:        info->rom_stride = se_sw->romstride;
                    188:        info->ram_stride = se_sw->ramstride;
                    189:        info->buffer_size = se_sw->ramsize;
                    190:        info->buffer_physaddr = se_sw->ln_bufspace;
                    191: 
                    192:        /*
                    193:         * Synch setup
                    194:         */
                    195:        evc_init(&self->eventcounter);
                    196:        info->wait_event = self->eventcounter.ev_id;
                    197: 
                    198:        return 1;
                    199: }
                    200: 
                    201: void
                    202: SE_attach(ui)
                    203:        register struct bus_device *ui;
                    204: {
                    205: }
                    206:  
                    207: 
                    208: /*
                    209:  * Shut off the lance
                    210:  */
                    211: static void SE_stop(unsigned int unit)
                    212: {
                    213:        register se_reg_t       regs = SE_statii[unit].registers;
                    214: 
                    215:        if (regs == 0)
                    216:                /* Stray interrupt */
                    217:                regs = SE0_REG_EMRG;
                    218: 
                    219:        regs[2] = CSR0_SELECT;  /* XXXX rap XXXX */
                    220:        wbflush();
                    221:        regs[0] = LN_CSR0_STOP;
                    222:        wbflush();
                    223: }
                    224: 
                    225: 
                    226: /*
                    227:  * Ethernet interface interrupt routine
                    228:  */
                    229: void SE_intr(unit,spllevel)
                    230:        int     unit;
                    231:        spl_t   spllevel;
                    232: {
                    233:        register struct SE_status *self = &SE_statii[unit];
                    234:        register se_reg_t          regs = self->registers;
                    235:        register                   csr;
                    236: 
                    237:        if (regs == 0) {        /* stray */
                    238:                SE_stop(unit);
                    239:                return;
                    240:        }
                    241: 
                    242:        /* Acknowledge interrupt request, drop spurious intr */
                    243:        csr = regs[0];
                    244:        if ((csr & LN_CSR0_INTR) == 0)
                    245:                return;
                    246:        regs[0] = csr & LN_CSR0_WTC;            /* silence it */
                    247: 
                    248:        splx(spllevel); /* drop priority now */
                    249: 
                    250:        /* Pass csr state up to user thread */
                    251:        if (self->info) {
                    252:                self->info->interrupt_count++;  /* total interrupts */
                    253:                self->info->saved_csr0 = csr;
                    254:        }
                    255: 
                    256:        /* Awake user thread */
                    257:        evc_signal(&self->eventcounter);
                    258: }
                    259:  
                    260: 
                    261: extern boolean_t se_use_mapped_interface[NLN];
                    262: 
                    263: /*
                    264:  * Device open procedure
                    265:  */
                    266: int SE_open(dev, flag, ior)
                    267:        io_req_t ior;
                    268: {
                    269:        int             unit = dev;
                    270:        register struct SE_status *self = &SE_statii[unit];
                    271: 
                    272:        if (unit >= NLN)
                    273:                return EINVAL;
                    274: 
                    275:        /*
                    276:         * Silence interface, just in case 
                    277:         */
                    278:        SE_stop(unit);
                    279: 
                    280:        /*
                    281:         * Reset eventcounter
                    282:         */
                    283:        evc_signal(&self->eventcounter);
                    284: 
                    285:        se_use_mapped_interface[unit] = 1;
                    286: 
                    287:        /*
                    288:         * Do not turn Ether interrupts on.  The user can do it when ready
                    289:         * to take them. 
                    290:         */
                    291: 
                    292:        return 0;
                    293: }
                    294: 
                    295: /*
                    296:  * Device close procedure
                    297:  */
                    298: int SE_close(dev, flag)
                    299: {
                    300:        int             unit = dev;
                    301:        register struct SE_status *self = &SE_statii[unit];
                    302: 
                    303:        if (unit >= NLN)
                    304:                return EINVAL;
                    305: 
                    306:        /*
                    307:         * Silence interface, in case user forgot
                    308:         */
                    309:        SE_stop(unit);
                    310:        evc_signal(&self->eventcounter);
                    311: 
                    312:        se_normal(unit);
                    313: 
                    314:        return 0;
                    315: }
                    316: 
                    317: 
                    318: /*
                    319:  * Get status procedure.
                    320:  * We need to tell that we are mappable.
                    321:  */
                    322: io_return_t
                    323: SE_get_status(ifp, flavor, status, status_count)
                    324: /*     struct ifnet    *ifp; not really..*/
                    325:        int             flavor;
                    326:        dev_status_t    status;         /* pointer to OUT array */
                    327:        unsigned int    *status_count;          /* OUT */
                    328: {
                    329:        switch (flavor) {
                    330:            case NET_STATUS:
                    331:            {
                    332:                register struct net_status *ns = (struct net_status *)status;
                    333: 
                    334:                ns->min_packet_size = sizeof(struct ether_header);
                    335:                ns->max_packet_size = sizeof(struct ether_header) + ETHERMTU;
                    336:                ns->header_format   = HDR_ETHERNET;
                    337:                ns->header_size     = sizeof(struct ether_header);
                    338:                ns->address_size    = 6;
                    339:                ns->flags           = IFF_BROADCAST;
                    340:                ns->mapped_size     = SE_BUF_SIZE + (3 * PAGE_SIZE);
                    341: 
                    342:                *status_count = NET_STATUS_COUNT;
                    343:                break;
                    344:            }
                    345: /*         case NET_ADDRESS:   find it yourself */
                    346:            default:
                    347:                return (D_INVALID_OPERATION);
                    348:        }
                    349:        return (D_SUCCESS);
                    350: }
                    351: 
                    352: /*
                    353:  * Should not refuse this either
                    354:  */
                    355: int SE_set_status(dev, flavor, status, status_count)
                    356:        int             dev;
                    357:        int             flavor;
                    358:        dev_status_t    status;
                    359:        unsigned int    status_count;
                    360: {
                    361:        return (D_SUCCESS);
                    362: }
                    363: 
                    364: /*
                    365:  * Port death notification routine
                    366:  */
                    367: void SE_portdeath(dev, dead_port)
                    368: {
                    369: }
                    370: 
                    371: 
                    372: /*
                    373:  * Virtual->physical mapping routine.
                    374:  */
                    375: vm_offset_t
                    376: SE_mmap(dev, off, prot)
                    377:        int             dev;
                    378:        vm_offset_t     off;
                    379:        vm_prot_t       prot;
                    380: {
                    381:        vm_offset_t     page;
                    382:        vm_offset_t     addr;
                    383:        int             unit = dev;
                    384: 
                    385:        /*
                    386:         * The offset (into the VM object) defines the following layout
                    387:         *
                    388:         *      off     size    what
                    389:         *      0       1pg     mapping information (csr & #interrupts)
                    390:         *      1pg     1pg     lance registers
                    391:         *      2pg     1pg     lance station address (ROM)
                    392:         *      3pg     128k    lance buffers 
                    393:         */
                    394: #define S0     PAGE_SIZE
                    395: #define S1     (S0+SE_REG_SIZE)
                    396: #define S2     (S1+SE_ADR_SIZE)
                    397: #define S3     (S2+SE_BUF_SIZE)
                    398: 
                    399:        if (off < S0) {
                    400:                addr = kvctophys (SE_statii[unit].info);
                    401:        } else if (off < S1) {
                    402:                addr = (vm_offset_t) SE_REG_PHYS(unit);
                    403:                off -= S0;
                    404:        } else if (off < S2) {
                    405:                addr = (vm_offset_t) SE_ADR_PHYS(unit);
                    406:                off -= S1;
                    407:        } else if (off < S3) {
                    408:                addr = (vm_offset_t) SE_BUF_PHYS(unit);
                    409:                off -= S2;
                    410:        } else
                    411:                return (EINVAL);
                    412: 
                    413:        page = machine_btop(addr + off);
                    414:        return (page);
                    415: }
                    416: 
                    417: #endif NLN > 0

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.