Annotation of qemu/roms/ipxe/src/drivers/net/pnic.c, revision 1.1.1.1

1.1       root        1: /**************************************************************************
                      2: Etherboot -  BOOTP/TFTP Bootstrap Program
                      3: Bochs Pseudo NIC driver for Etherboot
                      4: ***************************************************************************/
                      5: 
                      6: /*
                      7:  * This program is free software; you can redistribute it and/or
                      8:  * modify it under the terms of the GNU General Public License as
                      9:  * published by the Free Software Foundation; either version 2, or (at
                     10:  * your option) any later version.
                     11:  *
                     12:  * See pnic_api.h for an explanation of the Bochs Pseudo NIC.
                     13:  */
                     14: 
                     15: FILE_LICENCE ( GPL2_OR_LATER );
                     16: 
                     17: #include <stdint.h>
                     18: #include <stdio.h>
                     19: #include <ipxe/io.h>
                     20: #include <errno.h>
                     21: #include <ipxe/pci.h>
                     22: #include <ipxe/if_ether.h>
                     23: #include <ipxe/ethernet.h>
                     24: #include <ipxe/iobuf.h>
                     25: #include <ipxe/netdevice.h>
                     26: 
                     27: #include "pnic_api.h"
                     28: 
                     29: struct pnic {
                     30:        unsigned short ioaddr;
                     31: };
                     32: 
                     33: /* 
                     34:  * Utility functions: issue a PNIC command, retrieve result.  Use
                     35:  * pnic_command_quiet if you don't want failure codes to be
                     36:  * automatically printed.  Returns the PNIC status code.
                     37:  * 
                     38:  * Set output_length to NULL only if you expect to receive exactly
                     39:  * output_max_length bytes, otherwise it'll complain that you didn't
                     40:  * get enough data (on the assumption that if you not interested in
                     41:  * discovering the output length then you're expecting a fixed amount
                     42:  * of data).
                     43:  */
                     44: 
                     45: static uint16_t pnic_command_quiet ( struct pnic *pnic, uint16_t command,
                     46:                                     const void *input, uint16_t input_length,
                     47:                                     void *output, uint16_t output_max_length,
                     48:                                     uint16_t *output_length ) {
                     49:        uint16_t status;
                     50:        uint16_t _output_length;
                     51: 
                     52:        if ( input != NULL ) {
                     53:                /* Write input length */
                     54:                outw ( input_length, pnic->ioaddr + PNIC_REG_LEN );
                     55:                /* Write input data */
                     56:                outsb ( pnic->ioaddr + PNIC_REG_DATA, input, input_length );
                     57:        }
                     58:        /* Write command */
                     59:        outw ( command, pnic->ioaddr + PNIC_REG_CMD );
                     60:        /* Retrieve status */
                     61:        status = inw ( pnic->ioaddr + PNIC_REG_STAT );
                     62:        /* Retrieve output length */
                     63:        _output_length = inw ( pnic->ioaddr + PNIC_REG_LEN );
                     64:        if ( output_length == NULL ) {
                     65:                if ( _output_length != output_max_length ) {
                     66:                        printf ( "pnic_command %#hx: wrong data length "
                     67:                                 "returned (expected %d, got %d)\n", command,
                     68:                                 output_max_length, _output_length );
                     69:                }
                     70:        } else {
                     71:                *output_length = _output_length;
                     72:        }
                     73:        if ( output != NULL ) {
                     74:                if ( _output_length > output_max_length ) {
                     75:                        printf ( "pnic_command %#hx: output buffer too small "
                     76:                                 "(have %d, need %d)\n", command,
                     77:                                 output_max_length, _output_length );
                     78:                        _output_length = output_max_length;
                     79:                }
                     80:                /* Retrieve output data */
                     81:                insb ( pnic->ioaddr + PNIC_REG_DATA, output, _output_length );
                     82:        }
                     83:        return status;
                     84: }
                     85: 
                     86: static uint16_t pnic_command ( struct pnic *pnic, uint16_t command,
                     87:                               const void *input, uint16_t input_length,
                     88:                               void *output, uint16_t output_max_length,
                     89:                               uint16_t *output_length ) {
                     90:        uint16_t status = pnic_command_quiet ( pnic, command,
                     91:                                               input, input_length,
                     92:                                               output, output_max_length,
                     93:                                               output_length );
                     94:        if ( status == PNIC_STATUS_OK ) return status;
                     95:        printf ( "PNIC command %#hx (len %#hx) failed with status %#hx\n",
                     96:                 command, input_length, status );
                     97:        return status;
                     98: }
                     99: 
                    100: /* Check API version matches that of NIC */
                    101: static int pnic_api_check ( uint16_t api_version ) {
                    102:        if ( api_version != PNIC_API_VERSION ) {
                    103:                printf ( "Warning: API version mismatch! "
                    104:                         "(NIC's is %d.%d, ours is %d.%d)\n",
                    105:                         api_version >> 8, api_version & 0xff,
                    106:                         PNIC_API_VERSION >> 8, PNIC_API_VERSION & 0xff );
                    107:        }
                    108:        if ( api_version < PNIC_API_VERSION ) {
                    109:                printf ( "** You may need to update your copy of Bochs **\n" );
                    110:        }
                    111:        return ( api_version == PNIC_API_VERSION );
                    112: }
                    113: 
                    114: /**************************************************************************
                    115: POLL - Wait for a frame
                    116: ***************************************************************************/
                    117: static void pnic_poll ( struct net_device *netdev ) {
                    118:        struct pnic *pnic = netdev->priv;
                    119:        struct io_buffer *iobuf;
                    120:        uint16_t length;
                    121:        uint16_t qlen;
                    122: 
                    123:        /* Fetch all available packets */
                    124:        while ( 1 ) {
                    125:                if ( pnic_command ( pnic, PNIC_CMD_RECV_QLEN, NULL, 0,
                    126:                                    &qlen, sizeof ( qlen ), NULL )
                    127:                     != PNIC_STATUS_OK )
                    128:                        return;
                    129:                if ( qlen == 0 )
                    130:                        return;
                    131:                iobuf = alloc_iob ( ETH_FRAME_LEN );
                    132:                if ( ! iobuf ) {
                    133:                        DBG ( "could not allocate buffer\n" );
                    134:                        netdev_rx_err ( netdev, NULL, -ENOMEM );
                    135:                        return;
                    136:                }
                    137:                if ( pnic_command ( pnic, PNIC_CMD_RECV, NULL, 0,
                    138:                                    iobuf->data, ETH_FRAME_LEN, &length )
                    139:                     != PNIC_STATUS_OK ) {
                    140:                        netdev_rx_err ( netdev, iobuf, -EIO );
                    141:                        return;
                    142:                }
                    143:                iob_put ( iobuf, length );
                    144:                netdev_rx ( netdev, iobuf );
                    145:        }
                    146: }
                    147: 
                    148: /**************************************************************************
                    149: TRANSMIT - Transmit a frame
                    150: ***************************************************************************/
                    151: static int pnic_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
                    152:        struct pnic *pnic = netdev->priv;
                    153: 
                    154:        /* Pad the packet */
                    155:        iob_pad ( iobuf, ETH_ZLEN );
                    156: 
                    157:        /* Send packet */
                    158:        pnic_command ( pnic, PNIC_CMD_XMIT, iobuf->data, iob_len ( iobuf ),
                    159:                       NULL, 0, NULL );
                    160: 
                    161:        netdev_tx_complete ( netdev, iobuf );
                    162:        return 0;
                    163: }
                    164: 
                    165: /**************************************************************************
                    166: OPEN - Open network device
                    167: ***************************************************************************/
                    168: static int pnic_open ( struct net_device *netdev __unused ) {
                    169:        /* Nothing to do */
                    170:        return 0;
                    171: }
                    172: 
                    173: /**************************************************************************
                    174: CLOSE - Close network device
                    175: ***************************************************************************/
                    176: static void pnic_close ( struct net_device *netdev __unused ) {
                    177:        /* Nothing to do */
                    178: }
                    179: 
                    180: /**************************************************************************
                    181: IRQ - Enable/disable interrupts
                    182: ***************************************************************************/
                    183: static void pnic_irq ( struct net_device *netdev, int enable ) {
                    184:        struct pnic *pnic = netdev->priv;
                    185:        uint8_t mask = ( enable ? 1 : 0 );
                    186:        
                    187:        pnic_command ( pnic, PNIC_CMD_MASK_IRQ, &mask, sizeof ( mask ),
                    188:                       NULL, 0, NULL );
                    189: }
                    190: 
                    191: /**************************************************************************
                    192: OPERATIONS TABLE
                    193: ***************************************************************************/
                    194: static struct net_device_operations pnic_operations = {
                    195:        .open           = pnic_open,
                    196:        .close          = pnic_close,
                    197:        .transmit       = pnic_transmit,
                    198:        .poll           = pnic_poll,
                    199:        .irq            = pnic_irq,
                    200: };
                    201: 
                    202: /**************************************************************************
                    203: DISABLE - Turn off ethernet interface
                    204: ***************************************************************************/
                    205: static void pnic_remove ( struct pci_device *pci ) {
                    206:        struct net_device *netdev = pci_get_drvdata ( pci );
                    207:        struct pnic *pnic = netdev->priv;
                    208: 
                    209:        unregister_netdev ( netdev );
                    210:        pnic_command ( pnic, PNIC_CMD_RESET, NULL, 0, NULL, 0, NULL );
                    211:        netdev_nullify ( netdev );
                    212:        netdev_put ( netdev );
                    213: }
                    214: 
                    215: /**************************************************************************
                    216: PROBE - Look for an adapter, this routine's visible to the outside
                    217: ***************************************************************************/
                    218: static int pnic_probe ( struct pci_device *pci ) {
                    219:        struct net_device *netdev;
                    220:        struct pnic *pnic;
                    221:        uint16_t api_version;
                    222:        uint16_t status;
                    223:        int rc;
                    224: 
                    225:        /* Allocate net device */
                    226:        netdev = alloc_etherdev ( sizeof ( *pnic ) );
                    227:        if ( ! netdev )
                    228:                return -ENOMEM;
                    229:        netdev_init ( netdev, &pnic_operations );
                    230:        pnic = netdev->priv;
                    231:        pci_set_drvdata ( pci, netdev );
                    232:        netdev->dev = &pci->dev;
                    233:        pnic->ioaddr = pci->ioaddr;
                    234: 
                    235:        /* Fix up PCI device */
                    236:        adjust_pci_device ( pci );
                    237:        
                    238:        /* API version check */
                    239:        status = pnic_command_quiet ( pnic, PNIC_CMD_API_VER, NULL, 0,
                    240:                                      &api_version,
                    241:                                      sizeof ( api_version ), NULL );
                    242:        if ( status != PNIC_STATUS_OK ) {
                    243:                printf ( "PNIC failed installation check, code %#hx\n",
                    244:                         status );
                    245:                rc = -EIO;
                    246:                goto err;
                    247:        }
                    248:        pnic_api_check ( api_version );
                    249: 
                    250:        /* Get MAC address */
                    251:        status = pnic_command ( pnic, PNIC_CMD_READ_MAC, NULL, 0,
                    252:                                netdev->hw_addr, ETH_ALEN, NULL );
                    253: 
                    254:        /* Register network device */
                    255:        if ( ( rc = register_netdev ( netdev ) ) != 0 )
                    256:                goto err;
                    257: 
                    258:        /* Mark as link up; PNIC has no concept of link state */
                    259:        netdev_link_up ( netdev );
                    260: 
                    261:        return 0;
                    262: 
                    263:  err:
                    264:        /* Free net device */
                    265:        netdev_nullify ( netdev );
                    266:        netdev_put ( netdev );
                    267:        return rc;
                    268: }
                    269: 
                    270: static struct pci_device_id pnic_nics[] = {
                    271: /* genrules.pl doesn't let us use macros for PCI IDs...*/
                    272: PCI_ROM ( 0xfefe, 0xefef, "pnic", "Bochs Pseudo NIC Adaptor", 0 ),
                    273: };
                    274: 
                    275: struct pci_driver pnic_driver __pci_driver = {
                    276:        .ids = pnic_nics,
                    277:        .id_count = ( sizeof ( pnic_nics ) / sizeof ( pnic_nics[0] ) ),
                    278:        .probe = pnic_probe,
                    279:        .remove = pnic_remove,
                    280: };

unix.superglobalmegacorp.com

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