Annotation of Examples/DriverKit/SMC16/SMC16_reloc.tproj/SMC16.m, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1993 NeXT Computer, Inc.
        !             3:  *
        !             4:  * Driver class for SMC EtherCard Plus Elite16 adaptors.
        !             5:  *
        !             6:  * HISTORY
        !             7:  *
        !             8:  * 19 Apr 1993 
        !             9:  *     Added multicast & promiscuous mode support.
        !            10:  *
        !            11:  * 26 Jan 1993
        !            12:  *     Created.
        !            13:  */
        !            14: 
        !            15: #define MACH_USER_API  1
        !            16: 
        !            17: #import <driverkit/generalFuncs.h>
        !            18: #import <driverkit/IONetbufQueue.h>
        !            19: 
        !            20: #import "SMC16.h"
        !            21: #import "SMC16IOInline.h"
        !            22: #import "SMC16Private.h"
        !            23: 
        !            24: #import <kernserv/kern_server_types.h>
        !            25: #import <kernserv/prototypes.h>
        !            26: #import <kernserv/i386/spl.h>
        !            27: 
        !            28: @implementation SMC16
        !            29: 
        !            30: /*
        !            31:  * Private Instance Methods
        !            32:  */
        !            33: 
        !            34: /*
        !            35:  * _memAvail
        !            36:  * Returns the amount of onboard memory not currently in use.
        !            37:  * Never returns less than zero.
        !            38:  */
        !            39: - (SMC16_len_t)_memAvail
        !            40: {
        !            41:     int                available;
        !            42:     
        !            43:     available = (memtotal - memused);
        !            44:     
        !            45:     return ((SMC16_len_t) ((available < 0)? 0: available));
        !            46: }
        !            47: 
        !            48: /*
        !            49:  * _memRegion
        !            50:  * Returns the next available NIC_PAGE_SIZE chunk of onboard memory.
        !            51:  */
        !            52: - (SMC16_off_t)_memRegion:(SMC16_len_t)length
        !            53: {
        !            54:     if ([self _memAvail] < length)
        !            55:        IOPanic("SMC16: onboard memory exhausted");
        !            56:        
        !            57:     return ((SMC16_off_t) (memused / NIC_PAGE_SIZE));
        !            58: }
        !            59: 
        !            60: /*
        !            61:  * _memAlloc
        !            62:  * Allocates onboard memory in chunks of NIC_PAGE_SIZE 
        !            63:  */
        !            64: - (SMC16_off_t)_memAlloc:(SMC16_len_t)length
        !            65: {
        !            66:     SMC16_off_t        region;
        !            67:     
        !            68:     /*
        !            69:      * Round up to the next multiple of NIC_PAGE_SIZE
        !            70:      */
        !            71:     length = ((length + NIC_PAGE_SIZE - 1) & ~(NIC_PAGE_SIZE - 1));
        !            72:     
        !            73:     region = [self _memRegion:length];
        !            74:     
        !            75:     memused += length;
        !            76:     
        !            77:     return (region);
        !            78: }
        !            79: 
        !            80: /*
        !            81:  * _initializeHardware
        !            82:  * Resets the SMC adaptor.  Disables interrupts, resets the NIC, and
        !            83:  * configures the onboard memory.
        !            84:  */
        !            85: - (void)_initializeHardware
        !            86: {    
        !            87:     setIRQ(irq, YES, base);
        !            88:     
        !            89:     resetNIC(base);
        !            90:     
        !            91:     memtotal = setupRAM(membase, memsize, base);
        !            92:     memused = 0;
        !            93: }
        !            94: 
        !            95: /*
        !            96:  * _receiveInitialize
        !            97:  * Prepares the card for receive operations.  Allocates as many NIC_PAGE_SIZE
        !            98:  * buffers from the available onboard memory.
        !            99:  */
        !           100: - (void)_receiveInitialize
        !           101: {
        !           102:     SMC16_len_t                avail = [self _memAvail];
        !           103:     
        !           104:     rstart = [self _memAlloc:avail];
        !           105:     rstop = rstart + (avail / NIC_PAGE_SIZE);
        !           106: 
        !           107:     /*
        !           108:      * Setup the receive ring
        !           109:      */        
        !           110:     put_rstart_reg(rstart, base); put_rstop_reg(rstop, base);
        !           111:     
        !           112:     /*
        !           113:      * Reset the boundary buffer pointer
        !           114:      */        
        !           115:     put_bound_reg(rstart, base);
        !           116:     
        !           117:     rnext = rstart + 1;
        !           118:     
        !           119:     /*
        !           120:      * Reset the current buffer pointer    
        !           121:      */        
        !           122:     (void)sel_reg_page(REG_PAGE1, base);
        !           123:        put_curr_reg(rnext, base);
        !           124:     (void)sel_reg_page(REG_PAGE0, base);
        !           125: }
        !           126: 
        !           127: /*
        !           128:  * _transmitInitialize
        !           129:  * Prepares for transmit operations.  We use 1 transmit buffer of maximum
        !           130:  * size.
        !           131:  */
        !           132: - (void)_transmitInitialize
        !           133: {
        !           134:     tstart = [self _memAlloc:ETHERMAXPACKET];
        !           135: }
        !           136: 
        !           137: /*
        !           138:  * _initializeSoftware
        !           139:  * Prepare the adaptor for network operations and start them.
        !           140:  */
        !           141: - (void)_initializeSoftware
        !           142: {
        !           143:     setStationAddress(&myAddress, base);
        !           144:     
        !           145:     [self _transmitInitialize]; 
        !           146:     [self _receiveInitialize];
        !           147:         
        !           148:     startNIC(base, rconsave);
        !           149: }
        !           150: 
        !           151: /*
        !           152:  * _receiveInterruptOccurred
        !           153:  * This method handles the process of moving received frames from 
        !           154:  * onboard adaptor memory to netbufs and handing them up to the network
        !           155:  * object.
        !           156:  */
        !           157: - (void)_receiveInterruptOccurred
        !           158: {
        !           159:     nic_recv_hdr_t     *rhdr;
        !           160:     netbuf_t           pkt;
        !           161:     int                        pkt_len, pre_wrap_len;
        !           162:     void               *pkt_data = NULL;
        !           163: 
        !           164: #ifdef DEBUG
        !           165: 
        !           166:     /*
        !           167:      * Change this to 1 to be inundated with messages.
        !           168:      */
        !           169:     boolean_t  SMC16_recvTrace = 0;
        !           170: 
        !           171: #endif DEBUG
        !           172: 
        !           173:     
        !           174:     /*
        !           175:      * Grab buffers until we point to the next available one.
        !           176:      */
        !           177:     while (rnext != getCurrentBuffer(base)) {
        !           178: 
        !           179:        /*
        !           180:         * Point to the receive header in this buffer.
        !           181:         */
        !           182:        rhdr = (nic_recv_hdr_t *)nic_page_addr(rnext,membase);
        !           183: 
        !           184: #ifdef DEBUG
        !           185:        if (SMC16_recvTrace) {
        !           186:            IOLog("[rstat %02x next %02x len %03x rnext "
        !           187:                "%02x bound %02x curr %02x]\n",
        !           188:                *(unsigned char *)&rhdr->rstat, 
        !           189:                rhdr->next, rhdr->len, rnext, 
        !           190:                get_bound_reg(base), getCurrentBuffer(base));
        !           191:        }
        !           192: #endif DEBUG
        !           193:        
        !           194:        
        !           195:        /*
        !           196:         * Display a somewhat cryptic message if the prx bit is set.
        !           197:         */
        !           198:        if (!rhdr->rstat.prx) {
        !           199:            IOLog("rhdr1 rstat %02x next %02x len %x\n", 
        !           200:                *(unsigned char *)&rhdr->rstat, rhdr->next, rhdr->len);
        !           201:            [network incrementInputErrors];
        !           202:            rnext = rhdr->next; 
        !           203:            continue;
        !           204:        }
        !           205:        
        !           206:        /*
        !           207:         * Display a slightly different, equally cryptic message 
        !           208:         * if the pointer to the next buffer in this header is outside
        !           209:         * the range configured buffers.  If this is the case, force a
        !           210:         * reset by invoking -timeoutOccurred.
        !           211:         */
        !           212:        if (rhdr->next >= rstop || rhdr->next < rstart) {
        !           213:            IOLog("rhdr2 rstat %02x next %02x len %x\n", 
        !           214:                *(unsigned char *)&rhdr->rstat, rhdr->next, rhdr->len);
        !           215:            [network incrementInputErrors];
        !           216:            [self timeoutOccurred]; 
        !           217:            return;
        !           218:        }
        !           219: 
        !           220:        /*
        !           221:         * Get the overall packet length and the length between
        !           222:         * the start of the packet and the end of onboard memory.
        !           223:         * Any packet data beyond that will wrap back to the start
        !           224:         * of onboard memory.
        !           225:         */
        !           226:        pkt_len = rhdr->len - ETHERCRC;
        !           227:        pre_wrap_len =  nic_page_addr(rstop,membase) -
        !           228:                        nic_page_addr(rnext,membase) -
        !           229:                        sizeof (*rhdr);
        !           230: 
        !           231:        /*
        !           232:         * If the packet length looks reasonable, allocate a net buffer
        !           233:         * for it and establish a pointer to the data in that net buffer.
        !           234:         */
        !           235:        if (pkt_len >= (ETHERMINPACKET - ETHERCRC) && 
        !           236:                pkt_len <= ETHERMAXPACKET) {
        !           237:            pkt = nb_alloc(pkt_len);
        !           238:            if (pkt)
        !           239:                pkt_data = nb_map(pkt);
        !           240:        }
        !           241:        else {
        !           242:            [network incrementInputErrors];
        !           243:            pkt = 0;
        !           244:        }
        !           245:            
        !           246:        /*
        !           247:         * If none of the packet wraps around the ring, just
        !           248:         * copy it into the netbuf.
        !           249:         */
        !           250:        if (pkt_len <= pre_wrap_len) {
        !           251:            if (pkt)
        !           252:                IOCopyMemory(
        !           253:                        (void *)nic_page_addr(rnext,membase) + sizeof (*rhdr),
        !           254:                        pkt_data,
        !           255:                        pkt_len,
        !           256:                        sizeof(short));
        !           257:        /*
        !           258:         * Otherwise, copy up to the end of memory, then copy the remaining
        !           259:         * portion from the start of memory.
        !           260:         */
        !           261:        }
        !           262:        else {
        !           263:            if (pkt) {
        !           264:                IOCopyMemory(
        !           265:                        (void *)nic_page_addr(rnext,membase) + sizeof (*rhdr),
        !           266:                        pkt_data,
        !           267:                        pre_wrap_len,
        !           268:                        sizeof(short));
        !           269:                IOCopyMemory(
        !           270:                        (void *)nic_page_addr(rstart,membase),
        !           271:                        pkt_data + pre_wrap_len,
        !           272:                        pkt_len - pre_wrap_len,
        !           273:                        sizeof(short));
        !           274:            }
        !           275:        }
        !           276:        
        !           277:        /*
        !           278:         * Increment the ring buffer pointers.
        !           279:         */
        !           280:        rnext = rhdr->next;
        !           281:        if ((rnext - 1) >= rstart)
        !           282:            put_bound_reg(rnext - 1, base);
        !           283:        else
        !           284:            put_bound_reg(rstop - 1, base);
        !           285: 
        !           286:        /*
        !           287:         * We only pass packets upward if they pass thru multicast filter.
        !           288:         */
        !           289:        if(pkt) {
        !           290:            if(rconsave.prom == 0 && [super 
        !           291:                    isUnwantedMulticastPacket:(ether_header_t *)nb_map(pkt)]) {
        !           292:                nb_free(pkt);
        !           293:            } 
        !           294:            else {
        !           295:                
        !           296:                [network handleInputPacket:pkt extra:0];
        !           297: 
        !           298:            } 
        !           299:        }
        !           300:     }
        !           301: 
        !           302: }
        !           303: 
        !           304: /*
        !           305:  * _receiveOverwriteOccurred
        !           306:  * Called when the adaptor tells us that we haven't fetched frames from
        !           307:  * onboard memory fast enough, so it's overwritten an old frame with a new
        !           308:  * one.  Oh well...
        !           309:  */
        !           310: - (void)_receiveOverwriteOccurred
        !           311: {
        !           312: #ifdef DEBUG
        !           313:     IOLog("overwrite bound %02x curr %02x rnext %02x\n", get_bound_reg(base), getCurrentBuffer(base), rnext);
        !           314:     [network incrementInputErrors];
        !           315: #endif DEBUG
        !           316: }
        !           317: 
        !           318: /*
        !           319:  * _transmitInterruptOccurred
        !           320:  * Called when the adaptor indicated a transmit operation is complete.  Check
        !           321:  * tstat register and increment the appropriate counters.  Clear the
        !           322:  * timeout we set when we initiated the transmit and clear the transmitActive
        !           323:  * flag.  Finally, if there are any outgoing packets in the queue, send the
        !           324:  * next one.
        !           325:  */
        !           326: - (void)_transmitInterruptOccurred
        !           327: {
        !           328:     nic_tstat_reg_t    tstat_reg;
        !           329:     netbuf_t           pkt;
        !           330: 
        !           331:     if (transmitActive) {
        !           332:        tstat_reg = get_tstat_reg(base);
        !           333:        
        !           334:        /*
        !           335:         * Always check transmit status (if available) here.  On a
        !           336:         * transmit error, increment statistics and reset the
        !           337:         * adaptor if necessary (not for SMC).  NEVER TRY TO 
        !           338:         * RETRANSMIT A PACKET.  Leave this up to higher level
        !           339:         * software, which should insure reliability when
        !           340:         * it's needed.
        !           341:         */
        !           342:        if (tstat_reg.ptx)
        !           343:            [network incrementOutputPackets];
        !           344:        else
        !           345:            [network incrementOutputErrors];
        !           346:            
        !           347:        if (tstat_reg.abort || tstat_reg.twc)
        !           348:            [network incrementCollisions];
        !           349:        
        !           350:        [self clearTimeout];    
        !           351:        transmitActive = NO;
        !           352:     }
        !           353:     
        !           354:     if (pkt = [transmitQueue dequeue])
        !           355:        [self transmit:pkt];
        !           356: }
        !           357: 
        !           358: /*
        !           359:  * Public Factory Methods
        !           360:  */
        !           361:  
        !           362: + (BOOL)probe:(IODeviceDescription *)devDesc
        !           363: {
        !           364:     SMC16              *dev = [self alloc];
        !           365:     IOEISADeviceDescription
        !           366:                *deviceDescription = (IOEISADeviceDescription *)devDesc;
        !           367:     IORange            *io;
        !           368: 
        !           369:     if (dev == nil)
        !           370:        return NO;
        !           371:        
        !           372:     /* 
        !           373:      * Valid configuration?
        !           374:      */
        !           375:     if (       [deviceDescription numPortRanges] < 1
        !           376:            ||
        !           377:                [deviceDescription numMemoryRanges] < 1
        !           378:            ||
        !           379:                [deviceDescription numInterrupts] < 1) {
        !           380:        [dev free]; 
        !           381:        return NO;
        !           382:     }
        !           383:     
        !           384:     /*
        !           385:      * Make sure we're configured for 16K (even though we can only use 8)
        !           386:      */
        !           387:     io = [deviceDescription memoryRangeList];
        !           388:     if (io->size < 16*1024) {
        !           389:        [dev free]; 
        !           390:        return NO;
        !           391:     }
        !           392:     
        !           393:     /*
        !           394:      * More configuration validation
        !           395:      */
        !           396:     io = [deviceDescription portRangeList];
        !           397:     if (io->size < 16) {
        !           398:        [dev free]; 
        !           399:        return NO;
        !           400:     }
        !           401: 
        !           402:     /* 
        !           403:      * Configuration checks out so let's actually probe for hardware.
        !           404:      */
        !           405:     if (!checksumLAR(io->start)) {
        !           406:        IOLog("SMC16: Adaptor not present or invalid EEROM checksum.\n");
        !           407:        [dev free]; 
        !           408:        return NO;
        !           409:     }
        !           410:     
        !           411:     if (!checkBoardRev(io->start)) {
        !           412:        IOLog("SMC16: Unsupported board revision.\n");
        !           413:        [dev free]; 
        !           414:        return NO;
        !           415:     }
        !           416:     
        !           417:     return [dev initFromDeviceDescription:devDesc] != nil;
        !           418: }
        !           419: 
        !           420: /*
        !           421:  * Public Instance Methods
        !           422:  */
        !           423: 
        !           424: - initFromDeviceDescription:(IODeviceDescription *)devDesc
        !           425: {
        !           426:     IOEISADeviceDescription
        !           427:                    *deviceDescription = (IOEISADeviceDescription *)devDesc;
        !           428:     IORange            *io;
        !           429: 
        !           430:     if ([super initFromDeviceDescription:devDesc] == nil) 
        !           431:        return nil;
        !           432:        
        !           433:     /* 
        !           434:      * Initialize ivars
        !           435:      */
        !           436:     irq = [deviceDescription interrupt];
        !           437:     
        !           438:     io = [deviceDescription portRangeList];
        !           439:     base = io->start;
        !           440:     
        !           441:     io = [deviceDescription memoryRangeList];
        !           442:     membase = io->start;       
        !           443:     memsize = io->size;
        !           444: 
        !           445:     /*
        !           446:      * Broadcasts should be enabled
        !           447:      */
        !           448:     rconsave.broad = 1;
        !           449: 
        !           450:     /*
        !           451:      * Reset the adaptor, but don't enable yet.  We'll receive 
        !           452:      * -resetAndEnable:YES as a side effect of calling
        !           453:      * -attachToNetworkWithAddress:
        !           454:      */
        !           455:     [self resetAndEnable:NO];  
        !           456:     
        !           457:     IOLog("SMC16 at port %x irq %d\n",base, irq);
        !           458:            
        !           459:     transmitQueue = [[IONetbufQueue alloc] initWithMaxCount:32];
        !           460:     
        !           461:     network = [super attachToNetworkWithAddress:myAddress];
        !           462:     return self;               
        !           463: }
        !           464: 
        !           465: - free
        !           466: {
        !           467:     [transmitQueue free];
        !           468:     
        !           469:     return [super free];
        !           470: }
        !           471: 
        !           472: - (IOReturn)enableAllInterrupts
        !           473: {
        !           474:     unmaskInterrupts(base);
        !           475: 
        !           476:     setIRQ(irq, YES, base);
        !           477:     
        !           478:     return [super enableAllInterrupts];
        !           479: }
        !           480: 
        !           481: - (void)disableAllInterrupts
        !           482: {
        !           483:     setIRQ(irq, NO, base);
        !           484:     
        !           485:     [super disableAllInterrupts];
        !           486: }
        !           487: 
        !           488: - (BOOL)resetAndEnable:(BOOL)enable
        !           489: {
        !           490:     [self disableAllInterrupts];
        !           491:    
        !           492:     transmitActive = NO;
        !           493:     
        !           494:     [self _initializeHardware];
        !           495:     
        !           496:     getStationAddress(&myAddress, base);
        !           497:     
        !           498:     [self _initializeSoftware];
        !           499:     
        !           500:     if (enable && [self enableAllInterrupts] != IO_R_SUCCESS) {
        !           501:        [self setRunning:NO];
        !           502:        return NO;
        !           503:     }
        !           504:        
        !           505:     [self setRunning:enable];
        !           506:     return YES;
        !           507: }
        !           508: 
        !           509: - (void)timeoutOccurred
        !           510: {
        !           511:     netbuf_t   pkt = NULL;
        !           512:     
        !           513:     if ([self isRunning]) {
        !           514:        if ([self resetAndEnable:YES]) {
        !           515: 
        !           516:            if (pkt = [transmitQueue dequeue])
        !           517:                [self transmit:pkt];
        !           518:        }
        !           519:     }
        !           520:     /*
        !           521:      * Value of [self isRunning] may have been modified by
        !           522:      * resetAndEnable:
        !           523:      */
        !           524:     if (![self isRunning]) {   
        !           525:        /*
        !           526:         * Free any packets in the queue since we're not running.
        !           527:         */
        !           528:        if ([transmitQueue count]) {
        !           529:            transmitActive = NO;
        !           530:            while (pkt = [transmitQueue dequeue])
        !           531:                nb_free(pkt);
        !           532:        }
        !           533:     }
        !           534: }
        !           535: 
        !           536: /* 
        !           537:  * Called by our IOThread when it receives a message signifying
        !           538:  * an interrupt.  We check the istat register and vector off
        !           539:  * to the appropriate handler routines.
        !           540:  */
        !           541: - (void)interruptOccurred
        !           542: {
        !           543:     nic_istat_reg_t    istat_reg;
        !           544:     
        !           545:     istat_reg = get_istat_reg(base);
        !           546:     put_istat_reg(istat_reg, base);
        !           547:     
        !           548:     if (istat_reg.ovw)
        !           549:        [self _receiveOverwriteOccurred];
        !           550:     
        !           551:     if (istat_reg.prx)
        !           552:        [self _receiveInterruptOccurred];
        !           553:                
        !           554:     if (istat_reg.ptx || istat_reg.txe)
        !           555:        [self _transmitInterruptOccurred];
        !           556: }
        !           557: 
        !           558:  
        !           559: /*
        !           560:  * Enable promiscuous mode (invoked by superclass).
        !           561:  */
        !           562: - (BOOL)enablePromiscuousMode
        !           563: {
        !           564:     int        old_page = sel_reg_page(REG_PAGE0, base);
        !           565: 
        !           566:     rconsave.prom = 1;
        !           567:     put_rcon_reg(rconsave, base);
        !           568:     sel_reg_page(old_page, base);
        !           569: 
        !           570:     return YES;
        !           571: }
        !           572: 
        !           573: /*
        !           574:  * Disable promiscuous mode (invoked by superclass).
        !           575:  */
        !           576: - (void)disablePromiscuousMode
        !           577: {
        !           578:    int         old_page = sel_reg_page(REG_PAGE0, base);
        !           579: 
        !           580:     rconsave.prom = 0;
        !           581:     put_rcon_reg(rconsave, base);
        !           582:     sel_reg_page(old_page, base);
        !           583: 
        !           584: }
        !           585: 
        !           586: 
        !           587: - (BOOL)enableMulticastMode
        !           588: {
        !           589:     int        old_page = sel_reg_page(REG_PAGE0, base);
        !           590: 
        !           591:     rconsave.group = 1;
        !           592:     put_rcon_reg(rconsave, base);
        !           593:     sel_reg_page(old_page, base);
        !           594: 
        !           595:     return YES;
        !           596: }
        !           597: 
        !           598: - (void)disableMulticastMode
        !           599: {
        !           600:     int        old_page = sel_reg_page(REG_PAGE0, base);
        !           601: 
        !           602:     rconsave.group = 0;
        !           603:     put_rcon_reg(rconsave, base);
        !           604:     sel_reg_page(old_page, base);
        !           605: 
        !           606: }
        !           607: 
        !           608: - (void)transmit:(netbuf_t)pkt
        !           609: {
        !           610:     int                        pkt_len;
        !           611: 
        !           612:     /*
        !           613:      * If we're already transmitting, just queue up the packet.
        !           614:      */
        !           615:     if (transmitActive)
        !           616:        [transmitQueue enqueue:pkt];
        !           617:     else {
        !           618:        
        !           619:        /*
        !           620:         * We execute a softare loopback since this adaptor doesn't
        !           621:         * deal with this in hardware.
        !           622:         */
        !           623:        [self performLoopback:pkt];      
        !           624:        
        !           625:        /*
        !           626:         * Copy the packet into our transmit buffer, then free it.
        !           627:         */
        !           628:        pkt_len = nb_size(pkt);
        !           629:        IOCopyMemory(
        !           630:                nb_map(pkt),
        !           631:                (void *)nic_page_addr(tstart,membase),
        !           632:                pkt_len,
        !           633:                sizeof(short));
        !           634:        
        !           635:        /*
        !           636:         * Once the packet is copied out to the adaptor's onboard RAM,
        !           637:         * always free the packet.  DON'T SAVE A REFERENCE FOR 
        !           638:         * RETRANSMISSION PURPOSES.  Retransmission should be handled
        !           639:         * at the higher levels.  
        !           640:         */
        !           641:        nb_free(pkt);
        !           642:        
        !           643:        /*
        !           644:         * Setup up and initiate the transmit operation
        !           645:         */
        !           646:        put_tcnt_reg(pkt_len, base);
        !           647:        put_tstart_reg(tstart, base);
        !           648:        startTransmit(base);
        !           649:        
        !           650:        /*
        !           651:         * Start a timer whose expiration will call -timeoutOccurred, then
        !           652:         * set the transmitActive flag so we don't step on this operation.
        !           653:         */
        !           654:        [self setRelativeTimeout:3000];
        !           655:        transmitActive = YES;
        !           656:     }
        !           657: }
        !           658: 
        !           659: 
        !           660: @end
        !           661: 
        !           662: /*
        !           663:  * Private Functions
        !           664:  */
        !           665: 
        !           666: static BOOL
        !           667: checksumLAR(
        !           668:     IOEISAPortAddress  base
        !           669: )
        !           670: {
        !           671:     IOEISAPortAddress  offset;
        !           672:     unsigned char      sum = 0;
        !           673:     
        !           674:     for (offset = BIC_LAR_OFF; offset <= BIC_LAR_CKSUM_OFF; offset++)
        !           675:        sum += inb(base + SMC16_BIC_OFF + offset);
        !           676:        
        !           677:     return (sum == 0xff);
        !           678: }
        !           679: 
        !           680: static void
        !           681: getStationAddress(
        !           682:     enet_addr_t                *ea,
        !           683:     IOEISAPortAddress  base
        !           684: )
        !           685: {
        !           686:     int                        i;
        !           687:     unsigned char      *enaddr = (unsigned char *)ea;
        !           688:     
        !           689:     for (i = 0; i < sizeof (*ea); i++)
        !           690:        *(enaddr + i) = inb(base + SMC16_BIC_OFF + BIC_LAR_OFF + i);
        !           691: }
        !           692: 
        !           693: static void
        !           694: setStationAddress(
        !           695:     enet_addr_t                *ea,
        !           696:     IOEISAPortAddress  base
        !           697: )
        !           698: {
        !           699:     int                        i, old_page;
        !           700:     unsigned char      *enaddr = (unsigned char *)ea;
        !           701:     
        !           702:     old_page = sel_reg_page(REG_PAGE1, base);
        !           703:     
        !           704:     for (i = 0; i < sizeof (*ea); i++)
        !           705:        outb(base + SMC16_NIC_OFF + NIC_STA_REG_OFF + i, *(enaddr + i));
        !           706:        
        !           707:     (void)sel_reg_page(old_page, base);
        !           708: }
        !           709: 
        !           710: static BOOL
        !           711: checkBoardRev(
        !           712:     IOEISAPortAddress  base
        !           713: )
        !           714: {
        !           715:     unsigned int       bid;
        !           716:     
        !           717:     bid = get_bid(base);
        !           718:     
        !           719:     if (SMC16_REV(bid) < 2)
        !           720:        return NO;
        !           721:        
        !           722:     return YES;
        !           723: }
        !           724: 
        !           725: static void
        !           726: resetNIC(
        !           727:     IOEISAPortAddress  base
        !           728: )
        !           729: {
        !           730:     bic_msr_t          msr = { 0 };
        !           731:     nic_istat_reg_t    istat_reg;
        !           732: 
        !           733:     /*
        !           734:      * Perform HW Reset of NIC 
        !           735:      */        
        !           736:     msr.rst = 1;       put_msr(msr, base);
        !           737:     IODelay(500);
        !           738:     msr.rst = 0;       put_msr(msr, base);
        !           739: 
        !           740:     /*
        !           741:      * Wait for NIC to enter stopped state     
        !           742:      */        
        !           743:     do {
        !           744:        istat_reg = get_istat_reg(base);
        !           745:     } while (istat_reg.rst == 0);
        !           746: }
        !           747: 
        !           748: static SMC16_len_t
        !           749: setupRAM(
        !           750:     vm_offset_t                addr,
        !           751:     vm_size_t          size,
        !           752:     IOEISAPortAddress  base
        !           753: )
        !           754: {
        !           755:     SMC16_len_t                total;
        !           756:     SMC16_off_t                block_addr;
        !           757:     bic_laar_t         laar;
        !           758:     bic_msr_t          msr;
        !           759: #ifdef SIXTEEN_BIT_MODE
        !           760:     bic_icr_t          icr;
        !           761: #endif SIXTEEN_BIT_MODE
        !           762:     union {
        !           763:        struct {
        !           764:            unsigned int                :13,
        !           765:                            madr        :6,
        !           766:                            ladr        :5,
        !           767:                                        :8;
        !           768:        } bic_addr;
        !           769:        struct {
        !           770:           unsigned int                 :16,
        !           771:                            block       :8,
        !           772:                                        :8;
        !           773:        } nic_addr;
        !           774:        unsigned int    address;
        !           775:     } _mconv;
        !           776: 
        !           777: /*
        !           778:  * NOTE:  We cannot put the card into 16-bit (and therefore 16K) mode because
        !           779:  * the bus interface chip will behave as though a full 64K is mapped, even
        !           780:  * though only 16K exists on the board.  Needless to say this causes problems,
        !           781:  * whether something else is mapped into the top 3/4 of that 64K or not.
        !           782:  * Unless the hardware changes, we're limited to using 8K of onboard memory
        !           783:  * and 8-bit transfer mode.
        !           784:  */     
        !           785: 
        !           786: #ifdef SIXTEEN_BIT_MODE
        !           787:     icr = get_icr(base);
        !           788: 
        !           789:     total = (icr.msz ? 16 : 64) * 1024;
        !           790: 
        !           791:     if (total > 16 * 1024)
        !           792:        total = 16 * 1024;
        !           793: #else // SIXTEEN_BIT_MODE
        !           794:     total = 8 * 1024;
        !           795: #endif SIXTEEN_BIT_MODE
        !           796:        
        !           797:     if (total > size)
        !           798:        total = size;
        !           799: 
        !           800: #ifdef DEBUG
        !           801:     IOLog("SMC16: using %d bytes of onboard memory\n",total);
        !           802: #endif DEBUG
        !           803: 
        !           804:     _mconv.address = addr;
        !           805: 
        !           806:     laar = get_laar(base);
        !           807: #ifdef SIXTEEN_BIT_MODE        
        !           808:     laar.zws16 = TRUE;
        !           809:     laar.l16en = TRUE;
        !           810:     laar.m16en = TRUE;
        !           811: #endif SIXTEEN_BIT_MODE
        !           812:     laar.ladr = _mconv.bic_addr.ladr;
        !           813:     put_laar(laar, base);
        !           814:     
        !           815:     msr = get_msr(base);
        !           816:     msr.madr = _mconv.bic_addr.madr;
        !           817:     msr.menb = TRUE;
        !           818:     put_msr(msr, base);
        !           819:  
        !           820:     block_addr = _mconv.nic_addr.block;
        !           821:     put_block_reg(block_addr, base);
        !           822: 
        !           823:     return (total);
        !           824: }
        !           825:        
        !           826: static void
        !           827: startNIC(
        !           828:     IOEISAPortAddress  base,
        !           829:     nic_rcon_reg_t     rcon_reg
        !           830: )
        !           831: {
        !           832:     nic_cmd_reg_t      cmd_reg = { 0 };
        !           833:     nic_enh_reg_t      enh_reg = { 0 };
        !           834:     nic_dcon_reg_t     dcon_reg = { 0 };
        !           835:     nic_tcon_reg_t     tcon_reg = { 0 };
        !           836:     nic_istat_reg_t    istat_reg;
        !           837: 
        !           838:     enh_reg.slot = NIC_SLOT_512_BIT;
        !           839:     enh_reg.wait = 0;
        !           840:     put_enh_reg(enh_reg, base);
        !           841: 
        !           842:     dcon_reg.bsize = NIC_DMA_BURST_8b;
        !           843: #ifdef SIXTEEN_BIT_MODE
        !           844:     dcon_reg.bus16 = TRUE;
        !           845: #endif SIXTEEN_BIT_MODE
        !           846:     put_dcon_reg(dcon_reg, base);
        !           847:     
        !           848:     put_tcon_reg(tcon_reg, base);
        !           849:     
        !           850:     istat_reg = get_istat_reg(base);
        !           851:     put_istat_reg(istat_reg, base);
        !           852:     
        !           853:     cmd_reg.sta = 1;
        !           854:     put_cmd_reg(cmd_reg, base);
        !           855:     
        !           856:     put_rcon_reg(rcon_reg, base);
        !           857: }
        !           858: 
        !           859: static void
        !           860: unmaskInterrupts(
        !           861:     IOEISAPortAddress  base
        !           862: )
        !           863: {
        !           864:     nic_imask_reg_t    imask_reg = { 0 };
        !           865: 
        !           866:     /*
        !           867:      * Receive conditions
        !           868:      */        
        !           869:     imask_reg.prxe = imask_reg.rxee = imask_reg.ovwe = TRUE;
        !           870:     
        !           871:     /*
        !           872:      * Transmit conditions
        !           873:      */        
        !           874:     imask_reg.ptxe = imask_reg.txee = TRUE;
        !           875:     
        !           876:     put_imask_reg(imask_reg, base);
        !           877: }
        !           878: 
        !           879: static SMC16_off_t
        !           880: getCurrentBuffer(
        !           881:     IOEISAPortAddress  base
        !           882: )
        !           883: {
        !           884:     SMC16_off_t                curr;
        !           885:     int                        old_page;
        !           886:     
        !           887:     old_page = sel_reg_page(REG_PAGE1, base);
        !           888:     curr = get_curr_reg(base);
        !           889:     if (old_page != REG_PAGE1)
        !           890:        sel_reg_page(old_page, base);
        !           891:     
        !           892:     return (curr);
        !           893: }
        !           894: 
        !           895: static void
        !           896: startTransmit(
        !           897:     IOEISAPortAddress  base
        !           898: )
        !           899: {
        !           900:     nic_cmd_reg_t      cmd_reg = { 0 };
        !           901:     
        !           902:     cmd_reg.txp = 1;
        !           903:     cmd_reg.sta = 1;
        !           904:     put_cmd_reg(cmd_reg, base);
        !           905: }
        !           906: 
        !           907: static void
        !           908: setIRQ(
        !           909:     int                        irq,
        !           910:     BOOL               enable,
        !           911:     IOEISAPortAddress  base
        !           912: )
        !           913: {
        !           914:     bic_irr_t          irr;
        !           915:     bic_icr_t          icr;
        !           916:     static char                _irx_map[16] = {        -1,
        !           917:                                                -1,
        !           918:                                                -1,
        !           919:                                                BIC_IRX_3,
        !           920:                                                BIC_IRX_4,
        !           921:                                                BIC_IRX_5,
        !           922:                                                -1,
        !           923:                                                BIC_IRX_7,
        !           924:                                                -1,
        !           925:                                                BIC_IRX_9,
        !           926:                                                BIC_IRX_10,
        !           927:                                                BIC_IRX_11,
        !           928:                                                -1,
        !           929:                                                -1,
        !           930:                                                -1,
        !           931:                                                BIC_IRX_15 };
        !           932:     static char                _ir2_map[16] = {        -1,
        !           933:                                                -1,
        !           934:                                                -1,
        !           935:                                                ICR_IR2_3,
        !           936:                                                ICR_IR2_4,
        !           937:                                                ICR_IR2_5,
        !           938:                                                -1,
        !           939:                                                ICR_IR2_7,
        !           940:                                                -1,
        !           941:                                                ICR_IR2_9,
        !           942:                                                ICR_IR2_10,
        !           943:                                                ICR_IR2_11,
        !           944:                                                -1,
        !           945:                                                -1,
        !           946:                                                -1,
        !           947:                                                ICR_IR2_15 };
        !           948: 
        !           949:     irr = get_irr(base);
        !           950:     irr.irx = _irx_map[irq]; 
        !           951:     irr.ien = FALSE;
        !           952:     put_irr(irr, base);
        !           953: 
        !           954:     icr = get_icr(base);
        !           955:     icr.ir2 = _ir2_map[irq];
        !           956:     put_icr(icr, base);
        !           957:     
        !           958:     irr.ien = enable;
        !           959:     put_irr(irr, base);        
        !           960: }

unix.superglobalmegacorp.com

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