/** * Transmit packet * * @v netdev Network device * @v iobuf I/O buffer * @ret rc Return status code */ static int nii_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) { struct nii_nic *nii = netdev->priv; PXE_CPB_TRANSMIT cpb; int stat; int rc; /* Defer the packet if there is already a transmission in progress */ if ( nii->txbuf ) { netdev_tx_defer ( netdev, iobuf ); return 0; } /* Construct parameter block */ memset ( &cpb, 0, sizeof ( cpb ) ); cpb.FrameAddr = virt_to_bus ( iobuf->data ); cpb.DataLen = iob_len ( iobuf ); cpb.MediaheaderLen = netdev->ll_protocol->ll_header_len; /* Transmit packet */ if ( ( stat = nii_issue_cpb ( nii, PXE_OPCODE_TRANSMIT, &cpb, sizeof ( cpb ) ) ) < 0 ) { rc = -EIO_STAT ( stat ); DBGC ( nii, "NII %s could not transmit: %s\n", nii->dev.name, strerror ( rc ) ); return rc; } nii->txbuf = iobuf; return 0; }
/** * Set station address * * @v nii NII NIC * @v netdev Network device * @ret rc Return status code */ static int nii_set_station_address ( struct nii_nic *nii, struct net_device *netdev ) { uint32_t implementation = nii->undi->Implementation; PXE_CPB_STATION_ADDRESS cpb; unsigned int op; int stat; int rc; /* Fail if setting station address is unsupported */ if ( ! ( implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE ) ) return -ENOTSUP; /* Construct parameter block */ memset ( &cpb, 0, sizeof ( cpb ) ); memcpy ( cpb.StationAddr, netdev->ll_addr, netdev->ll_protocol->ll_addr_len ); /* Issue command */ op = NII_OP ( PXE_OPCODE_STATION_ADDRESS, PXE_OPFLAGS_STATION_ADDRESS_WRITE ); if ( ( stat = nii_issue_cpb ( nii, op, &cpb, sizeof ( cpb ) ) ) < 0 ) { rc = -EIO_STAT ( stat ); DBGC ( nii, "NII %s could not set station address: %s\n", nii->dev.name, strerror ( rc ) ); return rc; } return 0; }
/** * Set station address * * @v nii NII NIC * @v netdev Network device * @ret rc Return status code */ static int nii_set_station_address ( struct nii_nic *nii, struct net_device *netdev ) { PXE_CPB_STATION_ADDRESS cpb; int stat; int rc; /* Construct parameter block */ memset ( &cpb, 0, sizeof ( cpb ) ); memcpy ( cpb.StationAddr, netdev->ll_addr, netdev->ll_protocol->ll_addr_len ); /* Issue command */ if ( ( stat = nii_issue_cpb ( nii, PXE_OPCODE_STATION_ADDRESS, &cpb, sizeof ( cpb ) ) ) < 0 ) { rc = -EIO_STAT ( stat ); DBGC ( nii, "NII %s could not set station address: %s\n", nii->dev.name, strerror ( rc ) ); return rc; } return 0; }
/** * Start UNDI * * @v nii NII NIC * @ret rc Return status code */ static int nii_start_undi ( struct nii_nic *nii ) { PXE_CPB_START_31 cpb; int stat; int rc; /* Construct parameter block */ memset ( &cpb, 0, sizeof ( cpb ) ); cpb.Delay = ( ( intptr_t ) nii_delay ); cpb.Block = ( ( intptr_t ) nii_block ); cpb.Mem_IO = ( ( intptr_t ) nii_io ); cpb.Unique_ID = ( ( intptr_t ) nii ); /* Issue command */ if ( ( stat = nii_issue_cpb ( nii, PXE_OPCODE_START, &cpb, sizeof ( cpb ) ) ) < 0 ) { rc = -EIO_STAT ( stat ); DBGC ( nii, "NII %s could not start: %s\n", nii->dev.name, strerror ( rc ) ); return rc; } return 0; }