Annotation of Gnu-Mach/chips/lance_mapped.c, revision 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.