home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Examples / DriverKit / SMC16 / SMC16_reloc.tproj / SMC16.m < prev    next >
Text File  |  1997-04-25  |  21KB  |  1,056 lines

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