Annotation of Examples/DriverKit/SMC16/SMC16_reloc.tproj/SMC16.m, revision 1.1.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.