Annotation of qemu/roms/ipxe/src/drivers/net/3c5x9.c, revision 1.1

1.1     ! root        1: /**************************************************************************
        !             2: ETHERBOOT -  BOOTP/TFTP Bootstrap Program
        !             3: 
        !             4: Author: Martin Renters.
        !             5:   Date: Mar 22 1995
        !             6: 
        !             7:  This code is based heavily on David Greenman's if_ed.c driver and
        !             8:   Andres Vega Garcia's if_ep.c driver.
        !             9: 
        !            10:  Copyright (C) 1993-1994, David Greenman, Martin Renters.
        !            11:  Copyright (C) 1993-1995, Andres Vega Garcia.
        !            12:  Copyright (C) 1995, Serge Babkin.
        !            13:   This software may be used, modified, copied, distributed, and sold, in
        !            14:   both source and binary form provided that the above copyright and these
        !            15:   terms are retained. Under no circumstances are the authors responsible for
        !            16:   the proper functioning of this software, nor do the authors assume any
        !            17:   responsibility for damages incurred with its use.
        !            18: 
        !            19: 3c509 support added by Serge Babkin ([email protected])
        !            20: 
        !            21: $Id$
        !            22: 
        !            23: ***************************************************************************/
        !            24: 
        !            25: FILE_LICENCE ( BSD2 );
        !            26: 
        !            27: /* #define EDEBUG */
        !            28: 
        !            29: #include <ipxe/ethernet.h>
        !            30: #include "etherboot.h"
        !            31: #include "nic.h"
        !            32: #include <ipxe/isa.h>
        !            33: #include "3c509.h"
        !            34: 
        !            35: static enum { none, bnc, utp } connector = none;       /* for 3C509 */
        !            36: 
        !            37: /**************************************************************************
        !            38: ETH_RESET - Reset adapter
        !            39: ***************************************************************************/
        !            40: void t5x9_disable ( struct nic *nic ) {
        !            41:        /* stop card */
        !            42:        outw(RX_DISABLE, nic->ioaddr + EP_COMMAND);
        !            43:        outw(RX_DISCARD_TOP_PACK, nic->ioaddr + EP_COMMAND);
        !            44:        while (inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS)
        !            45:                ;
        !            46:        outw(TX_DISABLE, nic->ioaddr + EP_COMMAND);
        !            47:        outw(STOP_TRANSCEIVER, nic->ioaddr + EP_COMMAND);
        !            48:        udelay(1000);
        !            49:        outw(RX_RESET, nic->ioaddr + EP_COMMAND);
        !            50:        outw(TX_RESET, nic->ioaddr + EP_COMMAND);
        !            51:        outw(C_INTR_LATCH, nic->ioaddr + EP_COMMAND);
        !            52:        outw(SET_RD_0_MASK, nic->ioaddr + EP_COMMAND);
        !            53:        outw(SET_INTR_MASK, nic->ioaddr + EP_COMMAND);
        !            54:        outw(SET_RX_FILTER, nic->ioaddr + EP_COMMAND);
        !            55: 
        !            56:        /*
        !            57:         * wait for reset to complete
        !            58:         */
        !            59:        while (inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS)
        !            60:                ;
        !            61: 
        !            62:        GO_WINDOW(nic->ioaddr,0);
        !            63: 
        !            64:        /* Disable the card */
        !            65:        outw(0, nic->ioaddr + EP_W0_CONFIG_CTRL);
        !            66: 
        !            67:        /* Configure IRQ to none */
        !            68:        outw(SET_IRQ(0), nic->ioaddr + EP_W0_RESOURCE_CFG);
        !            69: }
        !            70: 
        !            71: static void t509_enable ( struct nic *nic ) {
        !            72:        int i;
        !            73: 
        !            74:        /* Enable the card */
        !            75:        GO_WINDOW(nic->ioaddr,0);
        !            76:        outw(ENABLE_DRQ_IRQ, nic->ioaddr + EP_W0_CONFIG_CTRL);
        !            77: 
        !            78:        GO_WINDOW(nic->ioaddr,2);
        !            79: 
        !            80:        /* Reload the ether_addr. */
        !            81:        for (i = 0; i < ETH_ALEN; i++)
        !            82:                outb(nic->node_addr[i], nic->ioaddr + EP_W2_ADDR_0 + i);
        !            83: 
        !            84:        outw(RX_RESET, nic->ioaddr + EP_COMMAND);
        !            85:        outw(TX_RESET, nic->ioaddr + EP_COMMAND);
        !            86: 
        !            87:        /* Window 1 is operating window */
        !            88:        GO_WINDOW(nic->ioaddr,1);
        !            89:        for (i = 0; i < 31; i++)
        !            90:                inb(nic->ioaddr + EP_W1_TX_STATUS);
        !            91: 
        !            92:        /* get rid of stray intr's */
        !            93:        outw(ACK_INTR | 0xff, nic->ioaddr + EP_COMMAND);
        !            94: 
        !            95:        outw(SET_RD_0_MASK | S_5_INTS, nic->ioaddr + EP_COMMAND);
        !            96: 
        !            97:        outw(SET_INTR_MASK, nic->ioaddr + EP_COMMAND);
        !            98: 
        !            99:        outw(SET_RX_FILTER | FIL_GROUP | FIL_INDIVIDUAL | FIL_BRDCST,
        !           100:             nic->ioaddr + EP_COMMAND);
        !           101: 
        !           102:        /* configure BNC */
        !           103:        if (connector == bnc) {
        !           104:                outw(START_TRANSCEIVER, nic->ioaddr + EP_COMMAND);
        !           105:                udelay(1000);
        !           106:        }
        !           107:        /* configure UTP */
        !           108:        else if (connector == utp) {
        !           109:                GO_WINDOW(nic->ioaddr,4);
        !           110:                outw(ENABLE_UTP, nic->ioaddr + EP_W4_MEDIA_TYPE);
        !           111:                sleep(2);       /* Give time for media to negotiate */
        !           112:                GO_WINDOW(nic->ioaddr,1);
        !           113:        }
        !           114: 
        !           115:        /* start transceiver and receiver */
        !           116:        outw(RX_ENABLE, nic->ioaddr + EP_COMMAND);
        !           117:        outw(TX_ENABLE, nic->ioaddr + EP_COMMAND);
        !           118: 
        !           119:        /* set early threshold for minimal packet length */
        !           120:        outw(SET_RX_EARLY_THRESH | ETH_ZLEN, nic->ioaddr + EP_COMMAND);
        !           121:        outw(SET_TX_START_THRESH | 16, nic->ioaddr + EP_COMMAND);
        !           122: }
        !           123: 
        !           124: static void t509_reset ( struct nic *nic ) {
        !           125:        t5x9_disable ( nic );
        !           126:        t509_enable ( nic );
        !           127: }    
        !           128: 
        !           129: /**************************************************************************
        !           130: ETH_TRANSMIT - Transmit a frame
        !           131: ***************************************************************************/
        !           132: static char padmap[] = {
        !           133:        0, 3, 2, 1};
        !           134: 
        !           135: static void t509_transmit(
        !           136: struct nic *nic,
        !           137: const char *d,                 /* Destination */
        !           138: unsigned int t,                        /* Type */
        !           139: unsigned int s,                        /* size */
        !           140: const char *p)                 /* Packet */
        !           141: {
        !           142:        register unsigned int len;
        !           143:        int pad;
        !           144:        int status;
        !           145: 
        !           146: #ifdef EDEBUG
        !           147:        printf("{l=%d,t=%hX}",s+ETH_HLEN,t);
        !           148: #endif
        !           149: 
        !           150:        /* swap bytes of type */
        !           151:        t= htons(t);
        !           152: 
        !           153:        len=s+ETH_HLEN; /* actual length of packet */
        !           154:        pad = padmap[len & 3];
        !           155: 
        !           156:        /*
        !           157:        * The 3c509 automatically pads short packets to minimum ethernet length,
        !           158:        * but we drop packets that are too large. Perhaps we should truncate
        !           159:        * them instead?
        !           160:        */
        !           161:        if (len + pad > ETH_FRAME_LEN) {
        !           162:                return;
        !           163:        }
        !           164: 
        !           165:        /* drop acknowledgements */
        !           166:        while ((status=inb(nic->ioaddr + EP_W1_TX_STATUS)) & TXS_COMPLETE ) {
        !           167:                if (status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) {
        !           168:                        outw(TX_RESET, nic->ioaddr + EP_COMMAND);
        !           169:                        outw(TX_ENABLE, nic->ioaddr + EP_COMMAND);
        !           170:                }
        !           171:                outb(0x0, nic->ioaddr + EP_W1_TX_STATUS);
        !           172:        }
        !           173: 
        !           174:        while (inw(nic->ioaddr + EP_W1_FREE_TX) < (unsigned short)len + pad + 4)
        !           175:                ; /* no room in FIFO */
        !           176: 
        !           177:        outw(len, nic->ioaddr + EP_W1_TX_PIO_WR_1);
        !           178:        outw(0x0, nic->ioaddr + EP_W1_TX_PIO_WR_1);     /* Second dword meaningless */
        !           179: 
        !           180:        /* write packet */
        !           181:        outsw(nic->ioaddr + EP_W1_TX_PIO_WR_1, d, ETH_ALEN/2);
        !           182:        outsw(nic->ioaddr + EP_W1_TX_PIO_WR_1, nic->node_addr, ETH_ALEN/2);
        !           183:        outw(t, nic->ioaddr + EP_W1_TX_PIO_WR_1);
        !           184:        outsw(nic->ioaddr + EP_W1_TX_PIO_WR_1, p, s / 2);
        !           185:        if (s & 1)
        !           186:                outb(*(p+s - 1), nic->ioaddr + EP_W1_TX_PIO_WR_1);
        !           187: 
        !           188:        while (pad--)
        !           189:                outb(0, nic->ioaddr + EP_W1_TX_PIO_WR_1);       /* Padding */
        !           190: 
        !           191:        /* wait for Tx complete */
        !           192:        while((inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS) != 0)
        !           193:                ;
        !           194: }
        !           195: 
        !           196: /**************************************************************************
        !           197: ETH_POLL - Wait for a frame
        !           198: ***************************************************************************/
        !           199: static int t509_poll(struct nic *nic, int retrieve)
        !           200: {
        !           201:        /* common variables */
        !           202:        /* variables for 3C509 */
        !           203:        short status, cst;
        !           204:        register short rx_fifo;
        !           205: 
        !           206:        cst=inw(nic->ioaddr + EP_STATUS);
        !           207: 
        !           208: #ifdef EDEBUG
        !           209:        if(cst & 0x1FFF)
        !           210:                printf("-%hX-",cst);
        !           211: #endif
        !           212: 
        !           213:        if( (cst & S_RX_COMPLETE)==0 ) {
        !           214:                /* acknowledge  everything */
        !           215:                outw(ACK_INTR| (cst & S_5_INTS), nic->ioaddr + EP_COMMAND);
        !           216:                outw(C_INTR_LATCH, nic->ioaddr + EP_COMMAND);
        !           217: 
        !           218:                return 0;
        !           219:        }
        !           220: 
        !           221:        status = inw(nic->ioaddr + EP_W1_RX_STATUS);
        !           222: #ifdef EDEBUG
        !           223:        printf("*%hX*",status);
        !           224: #endif
        !           225: 
        !           226:        if (status & ERR_RX) {
        !           227:                outw(RX_DISCARD_TOP_PACK, nic->ioaddr + EP_COMMAND);
        !           228:                return 0;
        !           229:        }
        !           230: 
        !           231:        rx_fifo = status & RX_BYTES_MASK;
        !           232:        if (rx_fifo==0)
        !           233:                return 0;
        !           234: 
        !           235:        if ( ! retrieve ) return 1;
        !           236: 
        !           237:                /* read packet */
        !           238: #ifdef EDEBUG
        !           239:        printf("[l=%d",rx_fifo);
        !           240: #endif
        !           241:        insw(nic->ioaddr + EP_W1_RX_PIO_RD_1, nic->packet, rx_fifo / 2);
        !           242:        if(rx_fifo & 1)
        !           243:                nic->packet[rx_fifo-1]=inb(nic->ioaddr + EP_W1_RX_PIO_RD_1);
        !           244:        nic->packetlen=rx_fifo;
        !           245: 
        !           246:        while(1) {
        !           247:                status = inw(nic->ioaddr + EP_W1_RX_STATUS);
        !           248: #ifdef EDEBUG
        !           249:                printf("*%hX*",status);
        !           250: #endif
        !           251:                rx_fifo = status & RX_BYTES_MASK;
        !           252:                if(rx_fifo>0) {
        !           253:                        insw(nic->ioaddr + EP_W1_RX_PIO_RD_1, nic->packet+nic->packetlen, rx_fifo / 2);
        !           254:                        if(rx_fifo & 1)
        !           255:                                nic->packet[nic->packetlen+rx_fifo-1]=inb(nic->ioaddr + EP_W1_RX_PIO_RD_1);
        !           256:                        nic->packetlen+=rx_fifo;
        !           257: #ifdef EDEBUG
        !           258:                        printf("+%d",rx_fifo);
        !           259: #endif
        !           260:                }
        !           261:                if(( status & RX_INCOMPLETE )==0) {
        !           262: #ifdef EDEBUG
        !           263:                        printf("=%d",nic->packetlen);
        !           264: #endif
        !           265:                        break;
        !           266:                }
        !           267:                udelay(1000);   /* if incomplete wait 1 ms */
        !           268:        }
        !           269:        /* acknowledge reception of packet */
        !           270:        outw(RX_DISCARD_TOP_PACK, nic->ioaddr + EP_COMMAND);
        !           271:        while (inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS)
        !           272:                ;
        !           273: #ifdef EDEBUG
        !           274: {
        !           275:        unsigned short type = 0;        /* used by EDEBUG */
        !           276:        type = (nic->packet[12]<<8) | nic->packet[13];
        !           277:        if(nic->packet[0]+nic->packet[1]+nic->packet[2]+nic->packet[3]+nic->packet[4]+
        !           278:            nic->packet[5] == 0xFF*ETH_ALEN)
        !           279:                printf(",t=%hX,b]",type);
        !           280:        else
        !           281:                printf(",t=%hX]",type);
        !           282: }
        !           283: #endif
        !           284:        return (1);
        !           285: }
        !           286: 
        !           287: /**************************************************************************
        !           288: ETH_IRQ - interrupt handling
        !           289: ***************************************************************************/
        !           290: static void t509_irq(struct nic *nic __unused, irq_action_t action __unused)
        !           291: {
        !           292:   switch ( action ) {
        !           293:   case DISABLE :
        !           294:     break;
        !           295:   case ENABLE :
        !           296:     break;
        !           297:   case FORCE :
        !           298:     break;
        !           299:   }
        !           300: }
        !           301: 
        !           302: /*************************************************************************
        !           303:        3Com 509 - specific routines
        !           304: **************************************************************************/
        !           305: 
        !           306: static int eeprom_rdy ( uint16_t ioaddr ) {
        !           307:        int i;
        !           308: 
        !           309:        for (i = 0; is_eeprom_busy(ioaddr) && i < MAX_EEPROMBUSY; i++);
        !           310:        if (i >= MAX_EEPROMBUSY) {
        !           311:                /* printf("3c509: eeprom failed to come ready.\n"); */
        !           312:                /* memory in EPROM is tight */
        !           313:                /* printf("3c509: eeprom busy.\n"); */
        !           314:                return (0);
        !           315:        }
        !           316:        return (1);
        !           317: }
        !           318: 
        !           319: /*
        !           320:  * get_e: gets a 16 bits word from the EEPROM.
        !           321:  */
        !           322: static int get_e ( uint16_t ioaddr, int offset ) {
        !           323:        GO_WINDOW(ioaddr,0);
        !           324:        if (!eeprom_rdy(ioaddr))
        !           325:                return (0xffff);
        !           326:        outw(EEPROM_CMD_RD | offset, ioaddr + EP_W0_EEPROM_COMMAND);
        !           327:        if (!eeprom_rdy(ioaddr))
        !           328:                return (0xffff);
        !           329:        return (inw(ioaddr + EP_W0_EEPROM_DATA));
        !           330: }
        !           331: 
        !           332: static struct nic_operations t509_operations = {
        !           333:        .connect        = dummy_connect,
        !           334:        .poll           = t509_poll,
        !           335:        .transmit       = t509_transmit,
        !           336:        .irq            = t509_irq,
        !           337: };
        !           338: 
        !           339: /**************************************************************************
        !           340: ETH_PROBE - Look for an adapter
        !           341: ***************************************************************************/
        !           342: int t5x9_probe ( struct nic *nic,
        !           343:                 uint16_t prod_id_check, uint16_t prod_id_mask ) {
        !           344:        uint16_t prod_id;
        !           345:        int i,j;
        !           346:        unsigned short *p;
        !           347:        
        !           348:        /* Check product ID */
        !           349:        prod_id = get_e ( nic->ioaddr, EEPROM_PROD_ID );
        !           350:        if ( ( prod_id & prod_id_mask ) != prod_id_check ) {
        !           351:                printf ( "EEPROM Product ID is incorrect (%hx & %hx != %hx)\n",
        !           352:                         prod_id, prod_id_mask, prod_id_check );
        !           353:                return 0;
        !           354:        }
        !           355: 
        !           356:        /* test for presence of connectors */
        !           357:        GO_WINDOW(nic->ioaddr,0);
        !           358:        i = inw(nic->ioaddr + EP_W0_CONFIG_CTRL);
        !           359:        j = (inw(nic->ioaddr + EP_W0_ADDRESS_CFG) >> 14) & 0x3;
        !           360: 
        !           361:        switch(j) {
        !           362:        case 0:
        !           363:                if (i & IS_UTP) {
        !           364:                        printf("10baseT\n");
        !           365:                        connector = utp;
        !           366:                } else {
        !           367:                        printf("10baseT not present\n");
        !           368:                        return 0;
        !           369:                }
        !           370:                break;
        !           371:        case 1:
        !           372:                if (i & IS_AUI) {
        !           373:                        printf("10base5\n");
        !           374:                } else {
        !           375:                        printf("10base5 not present\n");
        !           376:                        return 0;
        !           377:                }
        !           378:                break;
        !           379:        case 3:
        !           380:                if (i & IS_BNC) {
        !           381:                        printf("10base2\n");
        !           382:                        connector = bnc;
        !           383:                } else {
        !           384:                        printf("10base2 not present\n");
        !           385:                        return 0;
        !           386:                }
        !           387:                break;
        !           388:        default:
        !           389:                printf("unknown connector\n");
        !           390:                return 0;
        !           391:        }
        !           392: 
        !           393:        /*
        !           394:        * Read the station address from the eeprom
        !           395:        */
        !           396:        p = (unsigned short *) nic->node_addr;
        !           397:        for (i = 0; i < ETH_ALEN / 2; i++) {
        !           398:                p[i] = htons(get_e(nic->ioaddr,i));
        !           399:                GO_WINDOW(nic->ioaddr,2);
        !           400:                outw(ntohs(p[i]), nic->ioaddr + EP_W2_ADDR_0 + (i * 2));
        !           401:        }
        !           402: 
        !           403:        DBG ( "Ethernet Address: %s\n", eth_ntoa ( nic->node_addr ) );
        !           404: 
        !           405:        t509_reset(nic);
        !           406: 
        !           407:        nic->nic_op = &t509_operations;
        !           408:        return 1;
        !           409: 
        !           410: }
        !           411: 
        !           412: /*
        !           413:  * Local variables:
        !           414:  *  c-basic-offset: 8
        !           415:  * End:
        !           416:  */

unix.superglobalmegacorp.com

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