2
0
mirror of https://github.com/xcat2/xNBA.git synced 2024-11-21 17:11:46 +00:00
Conflicts:
	src/config/general.h
	src/net/netdev_settings.c
	src/net/tcp.c
This commit is contained in:
Jarrod Johnson 2013-08-15 14:43:09 -04:00
commit dde0935447
127 changed files with 7846 additions and 6176 deletions

View File

@ -61,7 +61,7 @@ ZLIB_DIR := /usr
SRCDIRS :=
SRCDIRS += libgcc
SRCDIRS += core
SRCDIRS += net net/tcp net/udp net/infiniband net/80211
SRCDIRS += net net/oncrpc net/tcp net/udp net/infiniband net/80211
SRCDIRS += image
SRCDIRS += drivers/bus
SRCDIRS += drivers/net
@ -108,7 +108,7 @@ INCDIRS += include .
# helpfully suggestive message
#
ALL := bin/blib.a bin/ipxe.dsk bin/ipxe.lkrn bin/ipxe.iso \
bin/ipxe.usb bin/undionly.kpxe bin/rtl8139.rom
bin/ipxe.usb bin/ipxe.pxe bin/undionly.kpxe bin/rtl8139.rom
all : $(ALL)
@$(ECHO) '==========================================================='
@$(ECHO)

View File

@ -1011,15 +1011,20 @@ $(BIN)/%.nodeps : $(BIN)/%.tmp
# Get licensing verdict for the specified target
#
define licensable_deps_list
$(filter-out config/local/%.h,$(call deps_list,$(1)))
$(filter-out config/local/%.h,\
$(filter-out $(BIN)/.%.list,\
$(call deps_list,$(1))))
endef
define unlicensed_deps_list
$(shell grep -L FILE_LICENCE $(call licensable_deps_list,$(1)))
endef
define licence_list
$(patsubst __licence_%,%,\
$(filter __licence_%,$(shell $(NM) $(1) | cut -d" " -f3)))
$(sort $(foreach LICENCE,\
$(filter __licence__%,$(shell $(NM) $(1) | cut -d" " -f3)),\
$(word 2,$(subst __, ,$(LICENCE)))))
endef
$(BIN)/%.licence_list : $(BIN)/%.tmp
$(Q)$(ECHO) $(call licence_list,$<)
$(BIN)/%.licence : $(BIN)/%.tmp
$(QM)$(ECHO) " [LICENCE] $@"
$(Q)$(if $(strip $(call unlicensed_deps_list,$<)),\

View File

@ -0,0 +1,108 @@
/*
* Copyright (C) 2013 Marin Hannache <ipxe@mareo.fr>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
FILE_LICENCE ( GPL2_OR_LATER );
/**
* @file
*
* Advanced Power Management
*
*/
#include <errno.h>
#include <realmode.h>
#include <ipxe/reboot.h>
/**
* Power off the computer using APM
*
* @ret rc Return status code
*/
static int apm_poweroff ( void ) {
uint16_t apm_version;
uint16_t apm_signature;
uint16_t apm_flags;
uint16_t carry;
/* APM check */
__asm__ __volatile__ ( REAL_CODE ( "int $0x15\n\t"
"adc %%edx,0\n\t" )
: "=a" ( apm_version ), "=b" ( apm_signature ),
"=c" ( apm_flags ), "=d" ( carry )
: "a" ( 0x5300 ), "b" ( 0x0000 ),
"d" ( 0x0000 ) );
if ( carry ) {
DBG ( "APM not present\n" );
return -ENOTSUP;
}
if ( apm_signature != 0x504d ) { /* signature 'PM' */
DBG ( "APM not present\n" );
return -ENOTSUP;
}
if ( apm_version < 0x0101 ) { /* Need version 1.1+ */
DBG ( "APM 1.1+ not supported\n" );
return -ENOTSUP;
}
if ( ( apm_flags & 0x8 ) == 0x8 ) {
DBG ( "APM power management disabled\n" );
return -EPERM;
}
DBG2 ( "APM check completed\n" );
/* APM initialisation */
__asm__ __volatile__ ( REAL_CODE ( "int $0x15\n\t"
"adc %%edx,0\n\t" )
: "=d" ( carry )
: "a" ( 0x5301 ), "b" ( 0x0000 ),
"d" ( 0x0000 ) );
if ( carry ) {
DBG ( "APM initialisation failed\n" );
return -EIO;
}
DBG2 ( "APM initialisation completed\n" );
/* Set APM driver version */
__asm__ __volatile__ ( REAL_CODE ( "int $0x15\n\t"
"adc %%edx,0\n\t" )
: "=d" ( carry )
: "a" ( 0x530e ), "b" ( 0x0000 ),
"c" ( 0x0101 ), "d" ( 0x0000 ) );
if ( carry ) {
DBG ( "APM setting driver version failed\n" );
return -EIO;
}
DBG2 ( "APM driver version set\n" );
/* Setting power state to off */
__asm__ __volatile__ ( REAL_CODE ( "int $0x15\n\t"
"adc %%edx,0\n\t" )
: "=d" ( carry )
: "a" ( 0x5307 ), "b" ( 0x0001 ),
"c" ( 0x0003 ), "d" ( 0x0000) );
if ( carry ) {
DBG ( "APM setting power state failed\n" );
return -ENOTTY;
}
/* Should never happen */
return -ECANCELED;
}
PROVIDE_REBOOT ( pcbios, poweroff, apm_poweroff );

View File

@ -58,7 +58,7 @@ static int guestinfo_fetch_type ( struct settings *settings,
strlen ( parent_name ) + 1 /* "." */ +
strlen ( setting->name ) + 1 /* "." */ +
( type ? strlen ( type->name ) : 0 ) + 1 /* NUL */ ];
struct setting *named_setting;
struct setting *predefined;
char *info;
int info_len;
int check_len;
@ -82,9 +82,8 @@ static int guestinfo_fetch_type ( struct settings *settings,
/* Determine default type if necessary */
if ( ! type ) {
named_setting = find_setting ( setting->name );
type = ( named_setting ?
named_setting->type : &setting_type_string );
predefined = find_setting ( setting->name );
type = ( predefined ? predefined->type : &setting_type_string );
}
assert ( type != NULL );
@ -115,7 +114,7 @@ static int guestinfo_fetch_type ( struct settings *settings,
settings, &command[9] /* Skip "info-get " */, info );
/* Parse GuestInfo value according to type */
ret = type->parse ( info, data, len );
ret = setting_parse ( type, info, data, len );
if ( ret < 0 ) {
DBGC ( settings, "GuestInfo %p could not parse \"%s\" as %s: "
"%s\n", settings, info, type->name, strerror ( ret ) );

View File

@ -98,6 +98,8 @@ SECTIONS {
*(.data)
*(.data.*)
KEEP(*(SORT(.tbl.*))) /* Various tables. See include/tables.h */
KEEP(*(.provided))
KEEP(*(.provided.*))
_edata16_progbits = .;
}
.bss16 : AT ( _data16_load_offset + __bss16 ) {

View File

@ -109,6 +109,8 @@ SECTIONS {
*(.data)
*(.data.*)
KEEP(*(SORT(.tbl.*))) /* Various tables. See include/tables.h */
KEEP(*(.provided))
KEEP(*(.provided.*))
_mtextdata = .;
} .bss.textdata (NOLOAD) : AT ( _end_lma ) {
*(.bss)

View File

@ -53,6 +53,8 @@ SECTIONS {
*(.data)
*(.data.*)
KEEP(*(SORT(.tbl.*)))
KEEP(*(.provided))
KEEP(*(.provided.*))
_edata = .;
}

View File

@ -33,7 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
*
* @ret is_supported CPUID instruction is supported
*/
static int cpuid_is_supported ( void ) {
int cpuid_is_supported ( void ) {
unsigned long original;
unsigned long inverted;
@ -52,24 +52,6 @@ static int cpuid_is_supported ( void ) {
return ( ( original ^ inverted ) & CPUID_FLAG );
}
/**
* Issue CPUID instruction
*
* @v operation CPUID operation
* @v eax Output via %eax
* @v ebx Output via %ebx
* @v ecx Output via %ecx
* @v edx Output via %edx
*/
static inline __attribute__ (( always_inline )) void
cpuid ( uint32_t operation, uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
uint32_t *edx ) {
__asm__ ( "cpuid"
: "=a" ( *eax ), "=b" ( *ebx ), "=c" ( *ecx ), "=d" ( *edx )
: "0" ( operation ) );
}
/**
* Get Intel-defined x86 CPU features
*

View File

@ -0,0 +1,272 @@
/*
* Copyright (C) 2013 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
FILE_LICENCE ( GPL2_OR_LATER );
#include <string.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/init.h>
#include <ipxe/settings.h>
#include <ipxe/cpuid.h>
/** @file
*
* x86 CPUID settings
*
* CPUID settings are numerically encoded as:
*
* Bit 31 Extended function
* Bits 30-28 Unused
* Bits 27-24 Number of consecutive functions to call, minus one
* Bit 23 Return result as little-endian (used for strings)
* Bits 22-18 Unused
* Bits 17-16 Number of registers in register array, minus one
* Bits 15-8 Array of register indices. First entry in array is in
* bits 9-8. Indices are 0-%eax, 1-%ebx, 2-%ecx, 3-%edx.
* Bits 7-0 Starting function number (excluding "extended" bit)
*
* This encoding scheme is designed to allow the common case of
* extracting a single register from a single function to be encoded
* using "cpuid/<register>.<function>", e.g. "cpuid/2.0x80000001" to
* retrieve the value of %ecx from calling CPUID with %eax=0x80000001.
*/
/** CPUID setting tag register indices */
enum cpuid_registers {
CPUID_EAX = 0,
CPUID_EBX = 1,
CPUID_ECX = 2,
CPUID_EDX = 3,
};
/**
* Construct CPUID setting tag
*
* @v function Starting function number
* @v num_functions Number of consecutive functions
* @v little_endian Return result as little-endian
* @v num_registers Number of registers in register array
* @v register1 First register in register array (or zero, if empty)
* @v register2 Second register in register array (or zero, if empty)
* @v register3 Third register in register array (or zero, if empty)
* @v register4 Fourth register in register array (or zero, if empty)
* @ret tag Setting tag
*/
#define CPUID_TAG( function, num_functions, little_endian, num_registers, \
register1, register2, register3, register4 ) \
( (function) | ( ( (num_functions) - 1 ) << 24 ) | \
( (little_endian) << 23 ) | ( ( (num_registers) - 1) << 16 ) | \
( (register1) << 8 ) | ( (register2) << 10 ) | \
( (register3) << 12 ) | ( (register4) << 14 ) )
/**
* Extract endianness from CPUID setting tag
*
* @v tag Setting tag
* @ret little_endian Result should be returned as little-endian
*/
#define CPUID_LITTLE_ENDIAN( tag ) ( (tag) & 0x00800000UL )
/**
* Extract starting function number from CPUID setting tag
*
* @v tag Setting tag
* @ret function Starting function number
*/
#define CPUID_FUNCTION( tag ) ( (tag) & 0x800000ffUL )
/**
* Extract number of consecutive functions from CPUID setting tag
*
* @v tag Setting tag
* @ret num_functions Number of consecutive functions
*/
#define CPUID_NUM_FUNCTIONS( tag ) ( ( ( (tag) >> 24 ) & 0xf ) + 1 )
/**
* Extract register array from CPUID setting tag
*
* @v tag Setting tag
* @ret registers Register array
*/
#define CPUID_REGISTERS( tag ) ( ( (tag) >> 8 ) & 0xff )
/**
* Extract number of registers from CPUID setting tag
*
* @v tag Setting tag
* @ret num_registers Number of registers within register array
*/
#define CPUID_NUM_REGISTERS( tag ) ( ( ( (tag) >> 16 ) & 0x3 ) + 1 )
/** CPUID settings scope */
static struct settings_scope cpuid_settings_scope;
/**
* Check applicability of CPUID setting
*
* @v settings Settings block
* @v setting Setting
* @ret applies Setting applies within this settings block
*/
static int cpuid_settings_applies ( struct settings *settings __unused,
struct setting *setting ) {
return ( setting->scope == &cpuid_settings_scope );
}
/**
* Fetch value of CPUID setting
*
* @v settings Settings block
* @v setting Setting to fetch
* @v data Buffer to fill with setting data
* @v len Length of buffer
* @ret len Length of setting data, or negative error
*/
static int cpuid_settings_fetch ( struct settings *settings,
struct setting *setting,
void *data, size_t len ) {
uint32_t function;
uint32_t max_function;
uint32_t num_functions;
uint32_t registers;
uint32_t num_registers;
uint32_t buf[4];
uint32_t output;
uint32_t discard_b;
uint32_t discard_c;
uint32_t discard_d;
size_t frag_len;
size_t result_len = 0;
/* Fail unless CPUID is supported */
if ( ! cpuid_is_supported() ) {
DBGC ( settings, "CPUID not supported\n" );
return -ENOTSUP;
}
/* Find highest supported function number within this set */
function = CPUID_FUNCTION ( setting->tag );
cpuid ( function & CPUID_EXTENDED, &max_function, &discard_b,
&discard_c, &discard_d );
/* Fail if maximum function number is meaningless (e.g. if we
* are attempting to call an extended function on a CPU which
* does not support them).
*/
if ( ( max_function & CPUID_AMD_CHECK_MASK ) !=
( function & CPUID_AMD_CHECK_MASK ) ) {
DBGC ( settings, "CPUID invalid maximum function\n" );
return -ENOTSUP;
}
/* Call each function in turn */
num_functions = CPUID_NUM_FUNCTIONS ( setting->tag );
for ( ; num_functions-- ; function++ ) {
/* Fail if this function is not supported */
if ( function > max_function ) {
DBGC ( settings, "CPUID function %#08x not supported\n",
function );
return -ENOTSUP;
}
/* Issue CPUID */
cpuid ( function, &buf[CPUID_EAX], &buf[CPUID_EBX],
&buf[CPUID_ECX], &buf[CPUID_EDX] );
DBGC ( settings, "CPUID %#08x => %#08x:%#08x:%#08x:%#08x\n",
function, buf[0], buf[1], buf[2], buf[3] );
/* Copy results to buffer */
registers = CPUID_REGISTERS ( setting->tag );
num_registers = CPUID_NUM_REGISTERS ( setting->tag );
for ( ; num_registers-- ; registers >>= 2 ) {
output = buf[ registers & 0x3 ];
if ( ! CPUID_LITTLE_ENDIAN ( setting->tag ) )
output = cpu_to_be32 ( output );
frag_len = sizeof ( output );
if ( frag_len > len )
frag_len = len;
memcpy ( data, &output, frag_len );
data += frag_len;
len -= frag_len;
result_len += sizeof ( output );
}
}
/* Set type if not already specified */
if ( ! setting->type )
setting->type = &setting_type_hexraw;
return result_len;
}
/** CPUID settings operations */
static struct settings_operations cpuid_settings_operations = {
.applies = cpuid_settings_applies,
.fetch = cpuid_settings_fetch,
};
/** CPUID settings */
static struct settings cpuid_settings = {
.refcnt = NULL,
.siblings = LIST_HEAD_INIT ( cpuid_settings.siblings ),
.children = LIST_HEAD_INIT ( cpuid_settings.children ),
.op = &cpuid_settings_operations,
.default_scope = &cpuid_settings_scope,
};
/** Initialise CPUID settings */
static void cpuid_settings_init ( void ) {
int rc;
if ( ( rc = register_settings ( &cpuid_settings, NULL,
"cpuid" ) ) != 0 ) {
DBG ( "CPUID could not register settings: %s\n",
strerror ( rc ) );
return;
}
}
/** CPUID settings initialiser */
struct init_fn cpuid_settings_init_fn __init_fn ( INIT_NORMAL ) = {
.initialise = cpuid_settings_init,
};
/** CPUID predefined settings */
struct setting cpuid_predefined_settings[] __setting ( SETTING_HOST_EXTRA ) = {
{
.name = "cpuvendor",
.description = "CPU vendor",
.tag = CPUID_TAG ( CPUID_VENDOR_ID, 1, 1, 3,
CPUID_EBX, CPUID_EDX, CPUID_ECX, 0 ),
.type = &setting_type_string,
.scope = &cpuid_settings_scope,
},
{
.name = "cpumodel",
.description = "CPU model",
.tag = CPUID_TAG ( CPUID_MODEL, 3, 1, 4,
CPUID_EAX, CPUID_EBX, CPUID_ECX, CPUID_EDX ),
.type = &setting_type_string,
.scope = &cpuid_settings_scope,
},
};

View File

@ -37,6 +37,10 @@ int linux_close ( int fd ) {
return linux_syscall ( __NR_close, fd );
}
off_t linux_lseek ( int fd, off_t offset, int whence ) {
return linux_syscall ( __NR_lseek, fd, offset, whence );
}
__kernel_ssize_t linux_read ( int fd, void *buf, __kernel_size_t count ) {
return linux_syscall ( __NR_read, fd, buf, count );
}

View File

@ -19,6 +19,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define ERRFILE_vmware ( ERRFILE_ARCH | ERRFILE_CORE | 0x00080000 )
#define ERRFILE_guestrpc ( ERRFILE_ARCH | ERRFILE_CORE | 0x00090000 )
#define ERRFILE_guestinfo ( ERRFILE_ARCH | ERRFILE_CORE | 0x000a0000 )
#define ERRFILE_apm ( ERRFILE_ARCH | ERRFILE_CORE | 0x000b0000 )
#define ERRFILE_bootsector ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00000000 )
#define ERRFILE_bzimage ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00010000 )
@ -45,6 +46,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define ERRFILE_timer_bios ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00010000 )
#define ERRFILE_cpuid_cmd ( ERRFILE_ARCH | ERRFILE_OTHER | 0x00000000 )
#define ERRFILE_cpuid_settings ( ERRFILE_ARCH | ERRFILE_OTHER | 0x00010000 )
/** @} */

View File

@ -30,6 +30,9 @@ struct x86_features {
/** CPUID support flag */
#define CPUID_FLAG 0x00200000UL
/** CPUID extended function */
#define CPUID_EXTENDED 0x80000000UL
/** Get vendor ID and largest standard function */
#define CPUID_VENDOR_ID 0x00000000UL
@ -48,6 +51,28 @@ struct x86_features {
/** Get extended features */
#define CPUID_AMD_FEATURES 0x80000001UL
/** Get CPU model */
#define CPUID_MODEL 0x80000002UL
/**
* Issue CPUID instruction
*
* @v operation CPUID operation
* @v eax Output via %eax
* @v ebx Output via %ebx
* @v ecx Output via %ecx
* @v edx Output via %edx
*/
static inline __attribute__ (( always_inline )) void
cpuid ( uint32_t operation, uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
uint32_t *edx ) {
__asm__ ( "cpuid"
: "=a" ( *eax ), "=b" ( *ebx ), "=c" ( *ecx ), "=d" ( *edx )
: "0" ( operation ) );
}
extern int cpuid_is_supported ( void );
extern void x86_features ( struct x86_features *features );
#endif /* _IPXE_CPUID_H */

View File

@ -60,6 +60,8 @@
#ifndef __MEMCHECK_H
#define __MEMCHECK_H
FILE_LICENCE ( BSD3 );
/* This file is for inclusion into client (your!) code.

View File

@ -73,6 +73,8 @@
#ifndef __VALGRIND_H
#define __VALGRIND_H
FILE_LICENCE ( BSD3 );
/* ------------------------------------------------------------------ */
/* VERSION NUMBER OF VALGRIND */

View File

@ -55,6 +55,8 @@ SECTIONS {
*(.data)
*(.data.*)
KEEP(*(SORT(.tbl.*))) /* Various tables. See include/tables.h */
KEEP(*(.provided))
KEEP(*(.provided.*))
_edata = .;
}

View File

@ -53,6 +53,8 @@ SECTIONS {
*(.data)
*(.data.*)
KEEP(*(SORT(.tbl.*)))
KEEP(*(.provided))
KEEP(*(.provided.*))
_edata = .;
}

View File

@ -10,6 +10,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <config/general.h>
#include <config/console.h>
#include <config/sideband.h>
#include <config/settings.h>
/** @file
*
@ -128,6 +129,9 @@ REQUIRE_OBJECT ( https );
#ifdef DOWNLOAD_PROTO_FTP
REQUIRE_OBJECT ( ftp );
#endif
#ifdef DOWNLOAD_PROTO_NFS
REQUIRE_OBJECT ( nfs_open );
#endif
#ifdef DOWNLOAD_PROTO_SLAM
REQUIRE_OBJECT ( slam );
#endif
@ -241,6 +245,9 @@ REQUIRE_OBJECT ( lotest_cmd );
#ifdef VLAN_CMD
REQUIRE_OBJECT ( vlan_cmd );
#endif
#ifdef POWEROFF_CMD
REQUIRE_OBJECT ( poweroff_cmd );
#endif
#ifdef REBOOT_CMD
REQUIRE_OBJECT ( reboot_cmd );
#endif
@ -253,6 +260,9 @@ REQUIRE_OBJECT ( sync_cmd );
#ifdef NSLOOKUP_CMD
REQUIRE_OBJECT ( nslookup_cmd );
#endif
#ifdef PCI_CMD
REQUIRE_OBJECT ( pci_cmd );
#endif
/*
* Drag in miscellaneous objects
@ -293,9 +303,22 @@ REQUIRE_OBJECT ( tap );
REQUIRE_OBJECT ( efi_bofm );
#endif /* BOFM_EFI */
#endif /* CONFIG_BOFM */
/*
* Drag in relevant settings sources
*/
#ifdef PCI_SETTINGS
REQUIRE_OBJECT ( pci_settings );
#endif
#ifdef VMWARE_SETTINGS
REQUIRE_OBJECT ( guestinfo );
#endif /* VMWARE_SETTINGS */
#endif
#ifdef CPUID_SETTINGS
REQUIRE_OBJECT ( cpuid_settings );
#endif
#ifdef MEMMAP_SETTINGS
REQUIRE_OBJECT ( memmap_settings );
#endif
/*
* Drag in selected keyboard map

View File

@ -7,6 +7,8 @@
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
#define UACCESS_EFI
#define IOAPI_X86
#define PCIAPI_EFI

View File

@ -7,6 +7,8 @@
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
#define CONSOLE_LINUX
#define TIMER_LINUX
#define UACCESS_LINUX
@ -17,6 +19,7 @@
#define ENTROPY_LINUX
#define TIME_LINUX
#define REBOOT_NULL
#define PCIAPI_LINUX
#define DRIVERS_LINUX

View File

@ -59,6 +59,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define DOWNLOAD_PROTO_HTTPS /* Secure Hypertext Transfer Protocol */
#undef DOWNLOAD_PROTO_FTP /* File Transfer Protocol */
#undef DOWNLOAD_PROTO_SLAM /* Scalable Local Area Multicast */
#undef DOWNLOAD_PROTO_NFS /* Network File System Protocol */
/*
* SAN boot protocols

19
src/config/settings.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef CONFIG_SETTINGS_H
#define CONFIG_SETTINGS_H
/** @file
*
* Configuration settings sources
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
#define PCI_SETTINGS /* PCI device settings */
//#define CPUID_SETTINGS /* CPUID settings */
//#define MEMMAP_SETTINGS /* Memory map settings */
//#define VMWARE_SETTINGS /* VMware GuestInfo settings */
#include <config/local/settings.h>
#endif /* CONFIG_SETTINGS_H */

View File

@ -10,7 +10,6 @@
FILE_LICENCE ( GPL2_OR_LATER );
//#define CONFIG_BOFM /* IBM's BladeCenter Open Fabric Manager */
//#define VMWARE_SETTINGS /* VMware GuestInfo settings */
#include <config/local/sideband.h>

View File

@ -51,15 +51,61 @@ void base16_encode ( const uint8_t *raw, size_t len, char *encoded ) {
char *encoded_bytes = encoded;
size_t remaining = len;
/* Encode each byte */
for ( ; remaining-- ; encoded_bytes += 2 ) {
sprintf ( encoded_bytes, "%02x", *(raw_bytes++) );
}
/* Ensure terminating NUL exists even if length was zero */
*encoded_bytes = '\0';
DBG ( "Base16-encoded to \"%s\":\n", encoded );
DBG_HDA ( 0, raw, len );
assert ( strlen ( encoded ) == base16_encoded_len ( len ) );
}
/**
* Decode hexadecimal string
*
* @v encoded Encoded string
* @v separator Byte separator character, or 0 for no separator
* @v data Buffer
* @v len Length of buffer
* @ret len Length of data, or negative error
*/
int hex_decode ( const char *encoded, char separator, void *data, size_t len ) {
uint8_t *out = data;
unsigned int count = 0;
unsigned int sixteens;
unsigned int units;
while ( *encoded ) {
/* Check separator, if applicable */
if ( count && separator && ( ( *(encoded++) != separator ) ) )
return -EINVAL;
/* Extract digits. Note that either digit may be NUL,
* which would be interpreted as an invalid value by
* strtoul_charval(); there is therefore no need for an
* explicit end-of-string check.
*/
sixteens = strtoul_charval ( *(encoded++) );
if ( sixteens >= 16 )
return -EINVAL;
units = strtoul_charval ( *(encoded++) );
if ( units >= 16 )
return -EINVAL;
/* Store result */
if ( count < len )
out[count] = ( ( sixteens << 4 ) | units );
count++;
}
return count;
}
/**
* Base16-decode data
*
@ -75,33 +121,15 @@ void base16_encode ( const uint8_t *raw, size_t len, char *encoded ) {
* to provide a buffer of the correct size.
*/
int base16_decode ( const char *encoded, uint8_t *raw ) {
const char *encoded_bytes = encoded;
uint8_t *raw_bytes = raw;
char buf[3];
char *endp;
size_t len;
int len;
while ( encoded_bytes[0] ) {
if ( ! encoded_bytes[1] ) {
DBG ( "Base16-encoded string \"%s\" has invalid "
"length\n", encoded );
return -EINVAL;
}
memcpy ( buf, encoded_bytes, 2 );
buf[2] = '\0';
*(raw_bytes++) = strtoul ( buf, &endp, 16 );
if ( *endp != '\0' ) {
DBG ( "Base16-encoded string \"%s\" has invalid "
"byte \"%s\"\n", encoded, buf );
return -EINVAL;
}
encoded_bytes += 2;
}
len = ( raw_bytes - raw );
len = hex_decode ( encoded, 0, raw, -1UL );
if ( len < 0 )
return len;
DBG ( "Base16-decoded \"%s\" to:\n", encoded );
DBG_HDA ( 0, raw, len );
assert ( len <= base16_decoded_max_len ( encoded ) );
return ( len );
return len;
}

View File

@ -1,5 +1,7 @@
#include <errno.h>
FILE_LICENCE ( GPL2_OR_LATER );
/** @file
*
* Error codes

242
src/core/memmap_settings.c Normal file
View File

@ -0,0 +1,242 @@
/*
* Copyright (C) 2013 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
FILE_LICENCE ( GPL2_OR_LATER );
#include <string.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/init.h>
#include <ipxe/settings.h>
#include <ipxe/io.h>
/** @file
*
* Memory map settings
*
* Memory map settings are numerically encoded as:
*
* Bits 31-24 Number of regions, minus one
* Bits 23-16 Starting region
* Bits 15-11 Unused
* Bit 10 Ignore non-existent regions (rather than generating an error)
* Bit 9 Include length
* Bit 8 Include start address
* Bits 7-6 Unused
* Bits 5-0 Scale factor (i.e. right shift count)
*/
/**
* Construct memory map setting tag
*
* @v start Starting region
* @v count Number of regions
* @v include_start Include start address
* @v include_length Include length
* @v ignore Ignore non-existent regions
* @v scale Scale factor
* @ret tag Setting tag
*/
#define MEMMAP_TAG( start, count, include_start, include_length, \
ignore, scale ) \
( ( (start) << 16 ) | ( ( (count) - 1 ) << 24 ) | \
( (ignore) << 10 ) | ( (include_length) << 9 ) | \
( (include_start) << 8 ) | (scale) )
/**
* Extract number of regions from setting tag
*
* @v tag Setting tag
* @ret count Number of regions
*/
#define MEMMAP_COUNT( tag ) ( ( ( (tag) >> 24 ) & 0xff ) + 1 )
/**
* Extract starting region from setting tag
*
* @v tag Setting tag
* @ret start Starting region
*/
#define MEMMAP_START( tag ) ( ( (tag) >> 16 ) & 0xff )
/**
* Extract ignore flag from setting tag
*
* @v tag Setting tag
* @ret ignore Ignore non-existent regions
*/
#define MEMMAP_IGNORE_NONEXISTENT( tag ) ( (tag) & 0x00000400UL )
/**
* Extract length inclusion flag from setting tag
*
* @v tag Setting tag
* @ret include_length Include length
*/
#define MEMMAP_INCLUDE_LENGTH( tag ) ( (tag) & 0x00000200UL )
/**
* Extract start address inclusion flag from setting tag
*
* @v tag Setting tag
* @ret include_start Include start address
*/
#define MEMMAP_INCLUDE_START( tag ) ( (tag) & 0x00000100UL )
/**
* Extract scale factor from setting tag
*
* @v tag Setting tag
* @v scale Scale factor
*/
#define MEMMAP_SCALE( tag ) ( (tag) & 0x3f )
/** Memory map settings scope */
static struct settings_scope memmap_settings_scope;
/**
* Check applicability of memory map setting
*
* @v settings Settings block
* @v setting Setting
* @ret applies Setting applies within this settings block
*/
static int memmap_settings_applies ( struct settings *settings __unused,
struct setting *setting ) {
return ( setting->scope == &memmap_settings_scope );
}
/**
* Fetch value of memory map setting
*
* @v settings Settings block
* @v setting Setting to fetch
* @v data Buffer to fill with setting data
* @v len Length of buffer
* @ret len Length of setting data, or negative error
*/
static int memmap_settings_fetch ( struct settings *settings,
struct setting *setting,
void *data, size_t len ) {
struct memory_map memmap;
struct memory_region *region;
uint64_t result = 0;
unsigned int i;
unsigned int count;
DBGC ( settings, "MEMMAP start %d count %d %s%s%s%s scale %d\n",
MEMMAP_START ( setting->tag ), MEMMAP_COUNT ( setting->tag ),
( MEMMAP_INCLUDE_START ( setting->tag ) ? "start" : "" ),
( ( MEMMAP_INCLUDE_START ( setting->tag ) &&
MEMMAP_INCLUDE_LENGTH ( setting->tag ) ) ? "+" : "" ),
( MEMMAP_INCLUDE_LENGTH ( setting->tag ) ? "length" : "" ),
( MEMMAP_IGNORE_NONEXISTENT ( setting->tag ) ? " ignore" : "" ),
MEMMAP_SCALE ( setting->tag ) );
/* Fetch memory map */
get_memmap ( &memmap );
/* Extract results from memory map */
count = MEMMAP_COUNT ( setting->tag );
for ( i = MEMMAP_START ( setting->tag ) ; count-- ; i++ ) {
/* Check that region exists */
if ( i >= memmap.count ) {
if ( MEMMAP_IGNORE_NONEXISTENT ( setting->tag ) ) {
continue;
} else {
DBGC ( settings, "MEMMAP region %d does not "
"exist\n", i );
return -ENOENT;
}
}
/* Extract results from this region */
region = &memmap.regions[i];
if ( MEMMAP_INCLUDE_START ( setting->tag ) ) {
result += region->start;
DBGC ( settings, "MEMMAP %d start %08llx\n",
i, region->start );
}
if ( MEMMAP_INCLUDE_LENGTH ( setting->tag ) ) {
result += ( region->end - region->start );
DBGC ( settings, "MEMMAP %d length %08llx\n",
i, ( region->end - region->start ) );
}
}
/* Scale result */
result >>= MEMMAP_SCALE ( setting->tag );
/* Return result */
result = cpu_to_be64 ( result );
if ( len > sizeof ( result ) )
len = sizeof ( result );
memcpy ( data, &result, len );
/* Set type if not already specified */
if ( ! setting->type )
setting->type = &setting_type_hexraw;
return sizeof ( result );
}
/** Memory map settings operations */
static struct settings_operations memmap_settings_operations = {
.applies = memmap_settings_applies,
.fetch = memmap_settings_fetch,
};
/** Memory map settings */
static struct settings memmap_settings = {
.refcnt = NULL,
.siblings = LIST_HEAD_INIT ( memmap_settings.siblings ),
.children = LIST_HEAD_INIT ( memmap_settings.children ),
.op = &memmap_settings_operations,
.default_scope = &memmap_settings_scope,
};
/** Initialise memory map settings */
static void memmap_settings_init ( void ) {
int rc;
if ( ( rc = register_settings ( &memmap_settings, NULL,
"memmap" ) ) != 0 ) {
DBG ( "MEMMAP could not register settings: %s\n",
strerror ( rc ) );
return;
}
}
/** Memory map settings initialiser */
struct init_fn memmap_settings_init_fn __init_fn ( INIT_NORMAL ) = {
.initialise = memmap_settings_init,
};
/** Memory map predefined settings */
struct setting memmap_predefined_settings[] __setting ( SETTING_MISC ) = {
{
.name = "memsize",
.description = "Memory size (in MB)",
.tag = MEMMAP_TAG ( 0, 0x100, 0, 1, 1, 20 ),
.type = &setting_type_int32,
.scope = &memmap_settings_scope,
},
};

View File

@ -33,6 +33,19 @@ int inet_aton ( const char *cp, struct in_addr *inp ) {
return 0;
}
unsigned int strtoul_charval ( unsigned int charval ) {
if ( charval >= 'a' ) {
charval = ( charval - 'a' + 10 );
} else if ( charval >= 'A' ) {
charval = ( charval - 'A' + 10 );
} else if ( charval <= '9' ) {
charval = ( charval - '0' );
}
return charval;
}
unsigned long strtoul ( const char *p, char **endp, int base ) {
unsigned long ret = 0;
int negative = 0;

View File

@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
*/
#include <stdio.h>
#include <errno.h>
#include <ipxe/reboot.h>
/**
@ -40,4 +41,15 @@ static void null_reboot ( int warm __unused ) {
while ( 1 ) {}
}
/**
* Power off system
*
* @ret rc Return status code
*/
static int null_poweroff ( void ) {
return -ENOTSUP;
}
PROVIDE_REBOOT ( null, reboot, null_reboot );
PROVIDE_REBOOT ( null, poweroff, null_poweroff );

View File

@ -28,6 +28,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <getopt.h>
#include <ipxe/netdevice.h>
#include <ipxe/menu.h>
#include <ipxe/settings.h>
#include <ipxe/parseopt.h>
/** @file
@ -59,7 +60,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
* @ret value String value
* @ret rc Return status code
*/
int parse_string ( const char *text, const char **value ) {
int parse_string ( char *text, char **value ) {
/* Sanity check */
assert ( text != NULL );
@ -77,7 +78,7 @@ int parse_string ( const char *text, const char **value ) {
* @ret value Integer value
* @ret rc Return status code
*/
int parse_integer ( const char *text, unsigned int *value ) {
int parse_integer ( char *text, unsigned int *value ) {
char *endp;
/* Sanity check */
@ -100,7 +101,7 @@ int parse_integer ( const char *text, unsigned int *value ) {
* @ret netdev Network device
* @ret rc Return status code
*/
int parse_netdev ( const char *text, struct net_device **netdev ) {
int parse_netdev ( char *text, struct net_device **netdev ) {
/* Sanity check */
assert ( text != NULL );
@ -122,7 +123,7 @@ int parse_netdev ( const char *text, struct net_device **netdev ) {
* @ret menu Menu
* @ret rc Return status code
*/
int parse_menu ( const char *text, struct menu **menu ) {
int parse_menu ( char *text, struct menu **menu ) {
/* Find menu */
*menu = find_menu ( text );
@ -145,7 +146,7 @@ int parse_menu ( const char *text, struct menu **menu ) {
* @ret flag Flag to set
* @ret rc Return status code
*/
int parse_flag ( const char *text __unused, int *flag ) {
int parse_flag ( char *text __unused, int *flag ) {
/* Set flag */
*flag = 1;
@ -160,7 +161,7 @@ int parse_flag ( const char *text __unused, int *flag ) {
* @ret key Key
* @ret rc Return status code
*/
int parse_key ( const char *text, unsigned int *key ) {
int parse_key ( char *text, unsigned int *key ) {
/* Interpret single characters as being a literal key character */
if ( text[0] && ! text[1] ) {
@ -172,6 +173,83 @@ int parse_key ( const char *text, unsigned int *key ) {
return parse_integer ( text, key );
}
/**
* Parse settings block name
*
* @v text Text
* @ret value Integer value
* @ret rc Return status code
*/
int parse_settings ( char *text, struct settings **value ) {
/* Sanity check */
assert ( text != NULL );
/* Parse scope name */
*value = find_settings ( text );
if ( ! *value ) {
printf ( "\"%s\": no such scope\n", text );
return -EINVAL;
}
return 0;
}
/**
* Parse setting name
*
* @v text Text
* @v setting Named setting to fill in
* @v get_child Function to find or create child settings block
* @ret rc Return status code
*
* Note that this function modifies the original @c text.
*/
int parse_setting ( char *text, struct named_setting *setting,
get_child_settings_t get_child ) {
int rc;
/* Sanity check */
assert ( text != NULL );
/* Parse setting name */
if ( ( rc = parse_setting_name ( text, get_child, &setting->settings,
&setting->setting ) ) != 0 ) {
printf ( "\"%s\": invalid setting\n", text );
return rc;
}
return 0;
}
/**
* Parse existing setting name
*
* @v text Text
* @v setting Named setting to fill in
* @ret rc Return status code
*
* Note that this function modifies the original @c text.
*/
int parse_existing_setting ( char *text, struct named_setting *setting ) {
return parse_setting ( text, setting, find_child_settings );
}
/**
* Parse and autovivify setting name
*
* @v text Text
* @v setting Named setting to fill in
* @ret rc Return status code
*
* Note that this function modifies the original @c text.
*/
int parse_autovivified_setting ( char *text, struct named_setting *setting ) {
return parse_setting ( text, setting, autovivify_child_settings );
}
/**
* Print command usage message
*
@ -198,7 +276,7 @@ int reparse_options ( int argc, char **argv, struct command_descriptor *cmd,
char shortopts[ cmd->num_options * 3 /* possible "::" */ + 1 /* "h" */
+ 1 /* NUL */ ];
unsigned int shortopt_idx = 0;
int ( * parse ) ( const char *text, void *value );
int ( * parse ) ( char *text, void *value );
void *value;
unsigned int i;
unsigned int j;

File diff suppressed because it is too large Load Diff

View File

@ -116,7 +116,6 @@ static int clientcert_apply_settings ( void ) {
static void *cert = NULL;
static void *key = NULL;
int len;
int rc;
/* Allow client certificate to be overridden only if
* not explicitly specified at build time.
@ -129,14 +128,8 @@ static int clientcert_apply_settings ( void ) {
/* Fetch new client certificate, if any */
free ( cert );
len = fetch_setting_copy ( NULL, &cert_setting, &cert );
if ( len < 0 ) {
rc = len;
DBGC ( &client_certificate, "CLIENTCERT cannot fetch "
"client certificate: %s\n", strerror ( rc ) );
return rc;
}
if ( cert ) {
if ( ( len = fetch_setting_copy ( NULL, &cert_setting,
&cert ) ) >= 0 ) {
client_certificate.data = cert;
client_certificate.len = len;
}
@ -147,14 +140,8 @@ static int clientcert_apply_settings ( void ) {
/* Fetch new client private key, if any */
free ( key );
len = fetch_setting_copy ( NULL, &privkey_setting, &key );
if ( len < 0 ) {
rc = len;
DBGC ( &client_certificate, "CLIENTCERT cannot fetch "
"client private key: %s\n", strerror ( rc ) );
return rc;
}
if ( key ) {
if ( ( len = fetch_setting_copy ( NULL, &privkey_setting,
&key ) ) >= 0 ) {
client_private_key.data = key;
client_private_key.len = len;
}

View File

@ -91,7 +91,6 @@ struct x509_root root_certificates = {
static void rootcert_init ( void ) {
void *external = NULL;
int len;
int rc;
/* Allow trusted root certificates to be overridden only if
* not explicitly specified at build time.
@ -101,21 +100,8 @@ static void rootcert_init ( void ) {
/* Fetch copy of "trust" setting, if it exists. This
* memory will never be freed.
*/
len = fetch_setting_copy ( NULL, &trust_setting, &external );
if ( len < 0 ) {
rc = len;
DBGC ( &root_certificates, "ROOTCERT cannot fetch "
"trusted root certificate fingerprints: %s\n",
strerror ( rc ) );
/* No way to prevent startup; fail safe by
* trusting no certificates.
*/
root_certificates.count = 0;
return;
}
/* Use certificates from "trust" setting, if present */
if ( external ) {
if ( ( len = fetch_setting_copy ( NULL, &trust_setting,
&external ) ) >= 0 ) {
root_certificates.fingerprints = external;
root_certificates.count = ( len / FINGERPRINT_LEN );
}

View File

@ -171,8 +171,20 @@ void adjust_pci_device ( struct pci_device *pci ) {
* @ret rc Return status code
*/
int pci_read_config ( struct pci_device *pci ) {
uint16_t busdevfn;
uint8_t hdrtype;
uint32_t tmp;
/* Ignore all but the first function on non-multifunction devices */
if ( PCI_FUNC ( pci->busdevfn ) != 0 ) {
busdevfn = pci->busdevfn;
pci->busdevfn = PCI_FIRST_FUNC ( pci->busdevfn );
pci_read_config_byte ( pci, PCI_HEADER_TYPE, &hdrtype );
pci->busdevfn = busdevfn;
if ( ! ( hdrtype & 0x80 ) )
return -ENODEV;
}
/* Check for physical device presence */
pci_read_config_dword ( pci, PCI_VENDOR_ID, &tmp );
if ( ( tmp == 0xffffffff ) || ( tmp == 0 ) )
@ -203,6 +215,32 @@ int pci_read_config ( struct pci_device *pci ) {
return 0;
}
/**
* Find next device on PCI bus
*
* @v pci PCI device to fill in
* @v busdevfn Starting bus:dev.fn address
* @ret busdevfn Bus:dev.fn address of next PCI device, or negative error
*/
int pci_find_next ( struct pci_device *pci, unsigned int busdevfn ) {
static unsigned int end;
int rc;
/* Determine number of PCI buses */
if ( ! end )
end = PCI_BUSDEVFN ( pci_num_bus(), 0, 0 );
/* Find next PCI device, if any */
for ( ; busdevfn < end ; busdevfn++ ) {
memset ( pci, 0, sizeof ( *pci ) );
pci_init ( pci, busdevfn );
if ( ( rc = pci_read_config ( pci ) ) == 0 )
return busdevfn;
}
return -ENODEV;
}
/**
* Find driver for PCI device
*
@ -276,14 +314,10 @@ void pci_remove ( struct pci_device *pci ) {
*/
static int pcibus_probe ( struct root_device *rootdev ) {
struct pci_device *pci = NULL;
unsigned int num_bus;
unsigned int busdevfn;
uint8_t hdrtype = 0;
int busdevfn = 0;
int rc;
num_bus = pci_num_bus();
for ( busdevfn = 0 ; busdevfn < PCI_BUSDEVFN ( num_bus, 0, 0 ) ;
busdevfn++ ) {
for ( busdevfn = 0 ; 1 ; busdevfn++ ) {
/* Allocate struct pci_device */
if ( ! pci )
@ -292,22 +326,11 @@ static int pcibus_probe ( struct root_device *rootdev ) {
rc = -ENOMEM;
goto err;
}
memset ( pci, 0, sizeof ( *pci ) );
pci_init ( pci, busdevfn );
/* Skip all but the first function on
* non-multifunction cards
*/
if ( PCI_FUNC ( busdevfn ) == 0 ) {
pci_read_config_byte ( pci, PCI_HEADER_TYPE,
&hdrtype );
} else if ( ! ( hdrtype & 0x80 ) ) {
continue;
}
/* Read device configuration */
if ( ( rc = pci_read_config ( pci ) ) != 0 )
continue;
/* Find next PCI device, if any */
busdevfn = pci_find_next ( pci, busdevfn );
if ( busdevfn < 0 )
break;
/* Look for a driver */
if ( ( rc = pci_find_driver ( pci ) ) != 0 ) {

View File

@ -0,0 +1,124 @@
/*
* Copyright (C) 2013 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
FILE_LICENCE ( GPL2_OR_LATER );
#include <stdio.h>
#include <errno.h>
#include <ipxe/pci.h>
#include <ipxe/settings.h>
#include <ipxe/init.h>
/** @file
*
* PCI device settings
*
*/
/** PCI device settings scope */
static struct settings_scope pci_settings_scope;
/**
* Check applicability of PCI device setting
*
* @v settings Settings block
* @v setting Setting
* @ret applies Setting applies within this settings block
*/
static int pci_settings_applies ( struct settings *settings __unused,
struct setting *setting ) {
return ( setting->scope == &pci_settings_scope );
}
/**
* Fetch value of PCI device setting
*
* @v settings Settings block
* @v setting Setting to fetch
* @v data Buffer to fill with setting data
* @v len Length of buffer
* @ret len Length of setting data, or negative error
*/
static int pci_settings_fetch ( struct settings *settings __unused,
struct setting *setting,
void *data, size_t len ) {
struct pci_device pci;
unsigned int tag_busdevfn;
unsigned int tag_offset;
unsigned int tag_len;
unsigned int i;
/* Extract busdevfn, offset, and length from tag */
tag_busdevfn = ( ( setting->tag >> 16 ) & 0xffff );
tag_offset = ( ( setting->tag >> 8 ) & 0xff );
tag_len = ( ( setting->tag >> 0 ) & 0xff );
/* Locate PCI device */
memset ( &pci, 0, sizeof ( pci ) );
pci_init ( &pci, tag_busdevfn );
DBG ( PCI_FMT " reading %#02x+%#x\n", PCI_ARGS ( &pci ),
tag_offset, tag_len );
/* Read data one byte at a time, in reverse order (since PCI
* is little-endian and iPXE settings are essentially
* big-endian).
*/
tag_offset += tag_len;
for ( i = 0 ; ( ( i < tag_len ) && ( i < len ) ); i++ ) {
pci_read_config_byte ( &pci, --tag_offset, data++ );
}
/* Set type to ":hexraw" if not already specified */
if ( ! setting->type )
setting->type = &setting_type_hexraw;
return tag_len;
}
/** PCI device settings operations */
static struct settings_operations pci_settings_operations = {
.applies = pci_settings_applies,
.fetch = pci_settings_fetch,
};
/** PCI device settings */
static struct settings pci_settings = {
.refcnt = NULL,
.siblings = LIST_HEAD_INIT ( pci_settings.siblings ),
.children = LIST_HEAD_INIT ( pci_settings.children ),
.op = &pci_settings_operations,
.default_scope = &pci_settings_scope,
};
/** Initialise PCI device settings */
static void pci_settings_init ( void ) {
int rc;
if ( ( rc = register_settings ( &pci_settings, NULL, "pci" ) ) != 0 ) {
DBG ( "PCI could not register settings: %s\n",
strerror ( rc ) );
return;
}
}
/** PCI device settings initialiser */
struct init_fn pci_settings_init_fn __init_fn ( INIT_NORMAL ) = {
.initialise = pci_settings_init,
};

View File

@ -20,6 +20,8 @@
#ifndef ATH_H
#define ATH_H
FILE_LICENCE ( BSD2 );
#include <unistd.h>
#include <ipxe/net80211.h>

View File

@ -20,6 +20,8 @@
#ifndef ANI_H
#define ANI_H
FILE_LICENCE ( BSD2 );
#define HAL_PROCESS_ANI 0x00000001
#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI) && ah->curchan)

View File

@ -14,6 +14,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
FILE_LICENCE ( BSD2 );
static const u32 ar5416Modes[][6] = {
{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
{0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},

View File

@ -14,6 +14,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
FILE_LICENCE ( BSD2 );
static const u32 ar5416Modes_9100[][6] = {
{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
{0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},

View File

@ -14,6 +14,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
FILE_LICENCE ( BSD2 );
static const u32 ar9280Modes_9280_2[][6] = {
{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
{0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},

View File

@ -16,6 +16,8 @@
#ifndef AR9002_PHY_H
#define AR9002_PHY_H
FILE_LICENCE ( BSD2 );
#define AR_PHY_TEST 0x9800
#define PHY_AGC_CLR 0x10000000
#define RFSILENT_BB 0x00002000

View File

@ -20,6 +20,8 @@
#ifndef AR9003_EEPROM_H
#define AR9003_EEPROM_H
FILE_LICENCE ( BSD2 );
#define AR9300_EEP_VER 0xD000
#define AR9300_EEP_VER_MINOR_MASK 0xFFF
#define AR9300_EEP_MINOR_VER_1 0x1

View File

@ -20,6 +20,8 @@
#ifndef ATH9K_H
#define ATH9K_H
FILE_LICENCE ( BSD2 );
#include "common.h"
/*

View File

@ -17,6 +17,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
FILE_LICENCE ( BSD2 );
#include "hw.h"
#include "ar5008_initvals.h"
#include "ar9001_initvals.h"

View File

@ -17,6 +17,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
FILE_LICENCE ( BSD2 );
#include <ipxe/malloc.h>
#include <ipxe/pci_io.h>
#include <ipxe/pci.h>

View File

@ -20,6 +20,8 @@
#ifndef CALIB_H
#define CALIB_H
FILE_LICENCE ( BSD2 );
#include "hw.h"
#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3

View File

@ -17,6 +17,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
FILE_LICENCE ( BSD2 );
#include "../ath.h"
#include "hw.h"

View File

@ -20,6 +20,8 @@
#ifndef EEPROM_H
#define EEPROM_H
FILE_LICENCE ( BSD2 );
#define AR_EEPROM_MODAL_SPURS 5
#include "../ath.h"

View File

@ -17,6 +17,8 @@
#ifndef ATH9K_HW_OPS_H
#define ATH9K_HW_OPS_H
FILE_LICENCE ( BSD2 );
#include "hw.h"
/* Hardware core and driver accessible callbacks */

View File

@ -20,6 +20,8 @@
#ifndef HW_H
#define HW_H
FILE_LICENCE ( BSD2 );
#include <errno.h>
#include "mac.h"

View File

@ -20,6 +20,8 @@
#ifndef MAC_H
#define MAC_H
FILE_LICENCE ( BSD2 );
#include <unistd.h>
#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ? \

View File

@ -17,6 +17,8 @@
#ifndef PHY_H
#define PHY_H
FILE_LICENCE ( BSD2 );
#define CHANSEL_DIV 15
#define CHANSEL_2G(_freq) (((_freq) * 0x10000) / CHANSEL_DIV)
#define CHANSEL_5G(_freq) (((_freq) * 0x8000) / CHANSEL_DIV)

View File

@ -17,6 +17,8 @@
#ifndef REG_H
#define REG_H
FILE_LICENCE ( BSD2 );
#include "../reg.h"
#define AR_CR 0x0008

View File

@ -20,6 +20,8 @@
#ifndef ATH_REGISTERS_H
#define ATH_REGISTERS_H
FILE_LICENCE ( BSD2 );
#define AR_MIBC 0x0040
#define AR_MIBC_COW 0x00000001
#define AR_MIBC_FMC 0x00000002

View File

@ -20,6 +20,8 @@
#ifndef REGD_H
#define REGD_H
FILE_LICENCE ( BSD2 );
#include "ath.h"
enum ctl_group {

View File

@ -247,10 +247,15 @@ static int intel_fetch_mac ( struct intel_nic *intel, uint8_t *hw_addr ) {
*/
static void __attribute__ (( unused )) intel_diag ( struct intel_nic *intel ) {
DBGC ( intel, "INTEL %p TDH=%04x TDT=%04x RDH=%04x RDT=%04x\n", intel,
DBGC ( intel, "INTEL %p TX %04x(%02x)/%04x(%02x) "
"RX %04x(%02x)/%04x(%02x)\n", intel,
( intel->tx.cons & 0xffff ),
readl ( intel->regs + intel->tx.reg + INTEL_xDH ),
( intel->tx.prod & 0xffff ),
readl ( intel->regs + intel->tx.reg + INTEL_xDT ),
( intel->rx.cons & 0xffff ),
readl ( intel->regs + intel->rx.reg + INTEL_xDH ),
( intel->rx.prod & 0xffff ),
readl ( intel->regs + intel->rx.reg + INTEL_xDT ) );
}

View File

@ -907,13 +907,15 @@ static void realtek_poll_rx ( struct net_device *netdev ) {
len = ( le16_to_cpu ( rx->length ) & RTL_DESC_SIZE_MASK );
iob_put ( iobuf, ( len - 4 /* strip CRC */ ) );
DBGC2 ( rtl, "REALTEK %p RX %d complete (length %zd)\n",
rtl, rx_idx, len );
/* Hand off to network stack */
if ( rx->flags & cpu_to_le16 ( RTL_DESC_RES ) ) {
DBGC ( rtl, "REALTEK %p RX %d error (length %zd, "
"flags %04x)\n", rtl, rx_idx, len,
le16_to_cpu ( rx->flags ) );
netdev_rx_err ( netdev, iobuf, -EIO );
} else {
DBGC2 ( rtl, "REALTEK %p RX %d complete (length "
"%zd)\n", rtl, rx_idx, len );
netdev_rx ( netdev, iobuf );
}
rtl->rx.cons++;

View File

@ -226,7 +226,8 @@ enum realtek_legacy_status {
#define RTL_NUM_RX_DESC 4
/** Receive buffer length */
#define RTL_RX_MAX_LEN ( ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */ )
#define RTL_RX_MAX_LEN \
( ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */ + 4 /* extra space */ )
/** A Realtek descriptor ring */
struct realtek_ring {

787
src/drivers/net/rhine.c Normal file
View File

@ -0,0 +1,787 @@
/*
* Copyright (C) 2012 Adrian Jamroz <adrian.jamroz@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
FILE_LICENCE ( GPL2_OR_LATER );
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/netdevice.h>
#include <ipxe/ethernet.h>
#include <ipxe/if_ether.h>
#include <ipxe/iobuf.h>
#include <ipxe/malloc.h>
#include <ipxe/pci.h>
#include <ipxe/mii.h>
#include "rhine.h"
/** @file
*
* VIA Rhine network driver
*
*/
/******************************************************************************
*
* MII interface
*
******************************************************************************
*/
/**
* Read from MII register
*
* @v mii MII interface
* @v reg Register address
* @ret value Data read, or negative error
*/
static int rhine_mii_read ( struct mii_interface *mii, unsigned int reg ) {
struct rhine_nic *rhn = container_of ( mii, struct rhine_nic, mii );
unsigned int timeout = RHINE_TIMEOUT_US;
uint8_t cr;
DBGC2 ( rhn, "RHINE %p MII read reg %d\n", rhn, reg );
/* Initiate read */
writeb ( reg, rhn->regs + RHINE_MII_ADDR );
cr = readb ( rhn->regs + RHINE_MII_CR );
writeb ( ( cr | RHINE_MII_CR_RDEN ), rhn->regs + RHINE_MII_CR );
/* Wait for read to complete */
while ( timeout-- ) {
udelay ( 1 );
cr = readb ( rhn->regs + RHINE_MII_CR );
if ( ! ( cr & RHINE_MII_CR_RDEN ) )
return readw ( rhn->regs + RHINE_MII_RDWR );
}
DBGC ( rhn, "RHINE %p MII read timeout\n", rhn );
return -ETIMEDOUT;
}
/**
* Write to MII register
*
* @v mii MII interface
* @v reg Register address
* @v data Data to write
* @ret rc Return status code
*/
static int rhine_mii_write ( struct mii_interface *mii, unsigned int reg,
unsigned int data ) {
struct rhine_nic *rhn = container_of ( mii, struct rhine_nic, mii );
unsigned int timeout = RHINE_TIMEOUT_US;
uint8_t cr;
DBGC2 ( rhn, "RHINE %p MII write reg %d data 0x%04x\n",
rhn, reg, data );
/* Initiate write */
writeb ( reg, rhn->regs + RHINE_MII_ADDR );
writew ( data, rhn->regs + RHINE_MII_RDWR );
cr = readb ( rhn->regs + RHINE_MII_CR );
writeb ( ( cr | RHINE_MII_CR_WREN ), rhn->regs + RHINE_MII_CR );
/* Wait for write to complete */
while ( timeout-- ) {
udelay ( 1 );
cr = readb ( rhn->regs + RHINE_MII_CR );
if ( ! ( cr & RHINE_MII_CR_WREN ) )
return 0;
}
DBGC ( rhn, "RHINE %p MII write timeout\n", rhn );
return -ETIMEDOUT;
}
/** Rhine MII operations */
static struct mii_operations rhine_mii_operations = {
.read = rhine_mii_read,
.write = rhine_mii_write,
};
/**
* Enable auto-polling
*
* @v rhn Rhine device
* @ret rc Return status code
*
* This is voodoo. There seems to be no documentation on exactly what
* we are waiting for, or why we have to do anything other than simply
* turn the feature on.
*/
static int rhine_mii_autopoll ( struct rhine_nic *rhn ) {
unsigned int timeout = RHINE_TIMEOUT_US;
uint8_t addr;
/* Initiate auto-polling */
writeb ( MII_BMSR, rhn->regs + RHINE_MII_ADDR );
writeb ( RHINE_MII_CR_AUTOPOLL, rhn->regs + RHINE_MII_CR );
/* Wait for auto-polling to complete */
while ( timeout-- ) {
udelay ( 1 );
addr = readb ( rhn->regs + RHINE_MII_ADDR );
if ( ! ( addr & RHINE_MII_ADDR_MDONE ) ) {
writeb ( ( MII_BMSR | RHINE_MII_ADDR_MSRCEN ),
rhn->regs + RHINE_MII_ADDR );
return 0;
}
}
DBGC ( rhn, "RHINE %p MII auto-poll timeout\n", rhn );
return -ETIMEDOUT;
}
/******************************************************************************
*
* Device reset
*
******************************************************************************
*/
/**
* Reset hardware
*
* @v rhn Rhine device
* @ret rc Return status code
*
* We're using PIO because this might reset the MMIO enable bit.
*/
static int rhine_reset ( struct rhine_nic *rhn ) {
unsigned int timeout = RHINE_TIMEOUT_US;
uint8_t cr1;
DBGC ( rhn, "RHINE %p reset\n", rhn );
/* Initiate reset */
outb ( RHINE_CR1_RESET, rhn->ioaddr + RHINE_CR1 );
/* Wait for reset to complete */
while ( timeout-- ) {
udelay ( 1 );
cr1 = inb ( rhn->ioaddr + RHINE_CR1 );
if ( ! ( cr1 & RHINE_CR1_RESET ) )
return 0;
}
DBGC ( rhn, "RHINE %p reset timeout\n", rhn );
return -ETIMEDOUT;
}
/**
* Enable MMIO register access
*
* @v rhn Rhine device
* @v revision Card revision
*/
static void rhine_enable_mmio ( struct rhine_nic *rhn, int revision ) {
uint8_t conf;
if ( revision < RHINE_REVISION_OLD ) {
conf = inb ( rhn->ioaddr + RHINE_CHIPCFG_A );
outb ( ( conf | RHINE_CHIPCFG_A_MMIO ),
rhn->ioaddr + RHINE_CHIPCFG_A );
} else {
conf = inb ( rhn->ioaddr + RHINE_CHIPCFG_D );
outb ( ( conf | RHINE_CHIPCFG_D_MMIO ),
rhn->ioaddr + RHINE_CHIPCFG_D );
}
}
/**
* Reload EEPROM contents
*
* @v rhn Rhine device
* @ret rc Return status code
*
* We're using PIO because this might reset the MMIO enable bit.
*/
static int rhine_reload_eeprom ( struct rhine_nic *rhn ) {
unsigned int timeout = RHINE_TIMEOUT_US;
uint8_t eeprom;
/* Initiate reload */
eeprom = inb ( rhn->ioaddr + RHINE_EEPROM_CTRL );
outb ( ( eeprom | RHINE_EEPROM_CTRL_RELOAD ),
rhn->ioaddr + RHINE_EEPROM_CTRL );
/* Wait for reload to complete */
while ( timeout-- ) {
udelay ( 1 );
eeprom = inb ( rhn->ioaddr + RHINE_EEPROM_CTRL );
if ( ! ( eeprom & RHINE_EEPROM_CTRL_RELOAD ) )
return 0;
}
DBGC ( rhn, "RHINE %p EEPROM reload timeout\n", rhn );
return -ETIMEDOUT;
}
/******************************************************************************
*
* Link state
*
******************************************************************************
*/
/**
* Check link state
*
* @v netdev Network device
*/
static void rhine_check_link ( struct net_device *netdev ) {
struct rhine_nic *rhn = netdev->priv;
uint8_t mii_sr;
/* Read MII status register */
mii_sr = readb ( rhn->regs + RHINE_MII_SR );
DBGC ( rhn, "RHINE %p link status %02x\n", rhn, mii_sr );
/* Report link state */
if ( ! ( mii_sr & RHINE_MII_SR_LINKPOLL ) ) {
netdev_link_up ( netdev );
} else if ( mii_sr & RHINE_MII_SR_PHYERR ) {
netdev_link_err ( netdev, -EIO );
} else {
netdev_link_down ( netdev );
}
}
/******************************************************************************
*
* Network device interface
*
******************************************************************************
*/
/**
* Create descriptor ring
*
* @v rhn Rhine device
* @v ring Descriptor ring
* @ret rc Return status code
*/
static int rhine_create_ring ( struct rhine_nic *rhn,
struct rhine_ring *ring ) {
size_t len = ( ring->count * sizeof ( ring->desc[0] ) );
struct rhine_descriptor *next;
physaddr_t address;
unsigned int i;
/* Allocate descriptors */
ring->desc = malloc_dma ( len, RHINE_RING_ALIGN );
if ( ! ring->desc )
return -ENOMEM;
/* Initialise descriptor ring */
memset ( ring->desc, 0, len );
for ( i = 0 ; i < ring->count ; i++ ) {
next = &ring->desc[ ( i + 1 ) % ring->count ];
ring->desc[i].next = cpu_to_le32 ( virt_to_bus ( next ) );
}
/* Program ring address */
address = virt_to_bus ( ring->desc );
writel ( address, rhn->regs + ring->reg );
DBGC ( rhn, "RHINE %p ring %02x is at [%08llx,%08llx)\n",
rhn, ring->reg, ( ( unsigned long long ) address ),
( ( unsigned long long ) address + len ) );
return 0;
}
/**
* Destroy descriptor ring
*
* @v rhn Rhine device
* @v ring Descriptor ring
*/
static void rhine_destroy_ring ( struct rhine_nic *rhn,
struct rhine_ring *ring ) {
size_t len = ( ring->count * sizeof ( ring->desc[0] ) );
/* Clear ring address */
writel ( 0, rhn->regs + ring->reg );
/* Free descriptor ring */
free_dma ( ring->desc, len );
ring->desc = NULL;
ring->prod = 0;
ring->cons = 0;
}
/**
* Refill RX descriptor ring
*
* @v rhn Rhine device
*/
static void rhine_refill_rx ( struct rhine_nic *rhn ) {
struct rhine_descriptor *desc;
struct io_buffer *iobuf;
unsigned int rx_idx;
physaddr_t address;
while ( ( rhn->rx.prod - rhn->rx.cons ) < RHINE_RXDESC_NUM ) {
/* Allocate I/O buffer */
iobuf = alloc_iob ( RHINE_RX_MAX_LEN );
if ( ! iobuf ) {
/* Wait for next refill */
return;
}
/* Populate next receive descriptor */
rx_idx = ( rhn->rx.prod++ % RHINE_RXDESC_NUM );
desc = &rhn->rx.desc[rx_idx];
address = virt_to_bus ( iobuf->data );
desc->buffer = cpu_to_le32 ( address );
desc->des1 =
cpu_to_le32 ( RHINE_DES1_SIZE ( RHINE_RX_MAX_LEN - 1) |
RHINE_DES1_CHAIN | RHINE_DES1_IC );
wmb();
desc->des0 = cpu_to_le32 ( RHINE_DES0_OWN );
/* Record I/O buffer */
rhn->rx_iobuf[rx_idx] = iobuf;
DBGC2 ( rhn, "RHINE %p RX %d is [%llx,%llx)\n", rhn, rx_idx,
( ( unsigned long long ) address ),
( ( unsigned long long ) address + RHINE_RX_MAX_LEN ) );
}
}
/**
* Open network device
*
* @v netdev Network device
* @ret rc Return status code
*/
static int rhine_open ( struct net_device *netdev ) {
struct rhine_nic *rhn = netdev->priv;
int rc;
/* Create transmit ring */
if ( ( rc = rhine_create_ring ( rhn, &rhn->tx ) ) != 0 )
goto err_create_tx;
/* Create receive ring */
if ( ( rc = rhine_create_ring ( rhn, &rhn->rx ) ) != 0 )
goto err_create_rx;
/* Set receive configuration */
writeb ( ( RHINE_RCR_PHYS_ACCEPT | RHINE_RCR_BCAST_ACCEPT |
RHINE_RCR_RUNT_ACCEPT ), rhn->regs + RHINE_RCR );
/* Enable link status monitoring */
if ( ( rc = rhine_mii_autopoll ( rhn ) ) != 0 )
goto err_mii_autopoll;
/* Some cards need an extra delay(observed with VT6102) */
mdelay ( 10 );
/* Enable RX/TX of packets */
writeb ( ( RHINE_CR0_STARTNIC | RHINE_CR0_RXEN | RHINE_CR0_TXEN ),
rhn->regs + RHINE_CR0 );
/* Enable auto polling and full duplex operation */
rhn->cr1 = RHINE_CR1_FDX;
writeb ( rhn->cr1, rhn->regs + RHINE_CR1 );
/* Refill RX ring */
rhine_refill_rx ( rhn );
/* Update link state */
rhine_check_link ( netdev );
return 0;
err_mii_autopoll:
rhine_destroy_ring ( rhn, &rhn->rx );
err_create_rx:
rhine_destroy_ring ( rhn, &rhn->tx );
err_create_tx:
return rc;
}
/**
* Close network device
*
* @v netdev Network device
*/
static void rhine_close ( struct net_device *netdev ) {
struct rhine_nic *rhn = netdev->priv;
unsigned int i;
/* Disable interrupts */
writeb ( 0, RHINE_IMR0 );
writeb ( 0, RHINE_IMR1 );
/* Stop card, clear RXON and TXON bits */
writeb ( RHINE_CR0_STOPNIC, rhn->regs + RHINE_CR0 );
/* Destroy receive ring */
rhine_destroy_ring ( rhn, &rhn->rx );
/* Discard any unused receive buffers */
for ( i = 0 ; i < RHINE_RXDESC_NUM ; i++ ) {
if ( rhn->rx_iobuf[i] )
free_iob ( rhn->rx_iobuf[i] );
rhn->rx_iobuf[i] = NULL;
}
/* Destroy transmit ring */
rhine_destroy_ring ( rhn, &rhn->tx );
}
/**
* Transmit packet
*
* @v netdev Network device
* @v iobuf I/O buffer
* @ret rc Return status code
*/
static int rhine_transmit ( struct net_device *netdev,
struct io_buffer *iobuf ) {
struct rhine_nic *rhn = netdev->priv;
struct rhine_descriptor *desc;
physaddr_t address;
unsigned int tx_idx;
/* Get next transmit descriptor */
if ( ( rhn->tx.prod - rhn->tx.cons ) >= RHINE_TXDESC_NUM )
return -ENOBUFS;
tx_idx = ( rhn->tx.prod++ % RHINE_TXDESC_NUM );
desc = &rhn->tx.desc[tx_idx];
/* Pad and align packet */
iob_pad ( iobuf, ETH_ZLEN );
address = virt_to_bus ( iobuf->data );
/* Populate transmit descriptor */
desc->buffer = cpu_to_le32 ( address );
desc->des1 = cpu_to_le32 ( RHINE_DES1_IC | RHINE_TDES1_STP |
RHINE_TDES1_EDP | RHINE_DES1_CHAIN |
RHINE_DES1_SIZE ( iob_len ( iobuf ) ) );
wmb();
desc->des0 = cpu_to_le32 ( RHINE_DES0_OWN );
wmb();
/* Notify card that there are packets ready to transmit */
writeb ( ( rhn->cr1 | RHINE_CR1_TXPOLL ), rhn->regs + RHINE_CR1 );
DBGC2 ( rhn, "RHINE %p TX %d is [%llx,%llx)\n", rhn, tx_idx,
( ( unsigned long long ) address ),
( ( unsigned long long ) address + iob_len ( iobuf ) ) );
return 0;
}
/**
* Poll for completed packets
*
* @v netdev Network device
*/
static void rhine_poll_tx ( struct net_device *netdev ) {
struct rhine_nic *rhn = netdev->priv;
struct rhine_descriptor *desc;
unsigned int tx_idx;
uint32_t des0;
/* Check for completed packets */
while ( rhn->tx.cons != rhn->tx.prod ) {
/* Get next transmit descriptor */
tx_idx = ( rhn->tx.cons % RHINE_TXDESC_NUM );
desc = &rhn->tx.desc[tx_idx];
/* Stop if descriptor is still in use */
if ( desc->des0 & cpu_to_le32 ( RHINE_DES0_OWN ) )
return;
/* Complete TX descriptor */
des0 = le32_to_cpu ( desc->des0 );
if ( des0 & RHINE_TDES0_TERR ) {
DBGC ( rhn, "RHINE %p TX %d error (DES0 %08x)\n",
rhn, tx_idx, des0 );
netdev_tx_complete_next_err ( netdev, -EIO );
} else {
DBGC2 ( rhn, "RHINE %p TX %d complete\n", rhn, tx_idx );
netdev_tx_complete_next ( netdev );
}
rhn->tx.cons++;
}
}
/**
* Poll for received packets
*
* @v netdev Network device
*/
static void rhine_poll_rx ( struct net_device *netdev ) {
struct rhine_nic *rhn = netdev->priv;
struct rhine_descriptor *desc;
struct io_buffer *iobuf;
unsigned int rx_idx;
uint32_t des0;
size_t len;
/* Check for received packets */
while ( rhn->rx.cons != rhn->rx.prod ) {
/* Get next receive descriptor */
rx_idx = ( rhn->rx.cons % RHINE_RXDESC_NUM );
desc = &rhn->rx.desc[rx_idx];
/* Stop if descriptor is still in use */
if ( desc->des0 & cpu_to_le32 ( RHINE_DES0_OWN ) )
return;
/* Populate I/O buffer */
iobuf = rhn->rx_iobuf[rx_idx];
rhn->rx_iobuf[rx_idx] = NULL;
des0 = le32_to_cpu ( desc->des0 );
len = ( RHINE_DES0_GETSIZE ( des0 ) - 4 /* strip CRC */ );
iob_put ( iobuf, len );
/* Hand off to network stack */
if ( des0 & RHINE_RDES0_RXOK ) {
DBGC2 ( rhn, "RHINE %p RX %d complete (length %zd)\n",
rhn, rx_idx, len );
netdev_rx ( netdev, iobuf );
} else {
DBGC ( rhn, "RHINE %p RX %d error (length %zd, DES0 "
"%08x)\n", rhn, rx_idx, len, des0 );
netdev_rx_err ( netdev, iobuf, -EIO );
}
rhn->rx.cons++;
}
}
/**
* Poll for completed and received packets
*
* @v netdev Network device
*/
static void rhine_poll ( struct net_device *netdev ) {
struct rhine_nic *rhn = netdev->priv;
uint8_t isr0;
uint8_t isr1;
/* Read and acknowledge interrupts */
isr0 = readb ( rhn->regs + RHINE_ISR0 );
isr1 = readb ( rhn->regs + RHINE_ISR1 );
if ( isr0 )
writeb ( isr0, rhn->regs + RHINE_ISR0 );
if ( isr1 )
writeb ( isr1, rhn->regs + RHINE_ISR1 );
/* Report unexpected errors */
if ( ( isr0 & ( RHINE_ISR0_MIBOVFL | RHINE_ISR0_PCIERR |
RHINE_ISR0_RXRINGERR | RHINE_ISR0_TXRINGERR ) ) ||
( isr1 & ( RHINE_ISR1_GPI | RHINE_ISR1_TXABORT |
RHINE_ISR1_RXFIFOOVFL | RHINE_ISR1_RXFIFOUNFL |
RHINE_ISR1_TXFIFOUNFL ) ) ) {
DBGC ( rhn, "RHINE %p unexpected ISR0 %02x ISR1 %02x\n",
rhn, isr0, isr1 );
/* Report as a TX error */
netdev_tx_err ( netdev, NULL, -EIO );
}
/* Poll for TX completions, if applicable */
if ( isr0 & ( RHINE_ISR0_TXDONE | RHINE_ISR0_TXERR ) )
rhine_poll_tx ( netdev );
/* Poll for RX completions, if applicable */
if ( isr0 & ( RHINE_ISR0_RXDONE | RHINE_ISR0_RXERR ) )
rhine_poll_rx ( netdev );
/* Handle RX buffer exhaustion */
if ( isr1 & RHINE_ISR1_RXNOBUF ) {
rhine_poll_rx ( netdev );
netdev_rx_err ( netdev, NULL, -ENOBUFS );
}
/* Check link state, if applicable */
if ( isr1 & RHINE_ISR1_PORTSTATE )
rhine_check_link ( netdev );
/* Refill RX ring */
rhine_refill_rx ( rhn );
}
/**
* Enable or disable interrupts
*
* @v netdev Network device
* @v enable Interrupts should be enabled
*/
static void rhine_irq ( struct net_device *netdev, int enable ) {
struct rhine_nic *nic = netdev->priv;
if ( enable ) {
/* Enable interrupts */
writeb ( 0xff, nic->regs + RHINE_IMR0 );
writeb ( 0xff, nic->regs + RHINE_IMR1 );
} else {
/* Disable interrupts */
writeb ( 0, nic->regs + RHINE_IMR0 );
writeb ( 0, nic->regs + RHINE_IMR1 );
}
}
/** Rhine network device operations */
static struct net_device_operations rhine_operations = {
.open = rhine_open,
.close = rhine_close,
.transmit = rhine_transmit,
.poll = rhine_poll,
.irq = rhine_irq,
};
/******************************************************************************
*
* PCI interface
*
******************************************************************************
*/
/**
* Probe PCI device
*
* @v pci PCI device
* @ret rc Return status code
*/
static int rhine_probe ( struct pci_device *pci ) {
struct net_device *netdev;
struct rhine_nic *rhn;
uint8_t revision;
unsigned int i;
int rc;
/* Allocate and initialise net device */
netdev = alloc_etherdev ( sizeof ( *rhn ) );
if ( ! netdev ) {
rc = -ENOMEM;
goto err_alloc;
}
netdev_init ( netdev, &rhine_operations );
rhn = netdev->priv;
pci_set_drvdata ( pci, netdev );
netdev->dev = &pci->dev;
memset ( rhn, 0, sizeof ( *rhn ) );
rhine_init_ring ( &rhn->tx, RHINE_TXDESC_NUM, RHINE_TXQUEUE_BASE );
rhine_init_ring ( &rhn->rx, RHINE_RXDESC_NUM, RHINE_RXQUEUE_BASE );
/* Fix up PCI device */
adjust_pci_device ( pci );
/* Map registers */
rhn->regs = ioremap ( pci->membase, RHINE_BAR_SIZE );
rhn->ioaddr = pci->ioaddr;
DBGC ( rhn, "RHINE %p regs at %08lx, I/O at %04lx\n", rhn,
pci->membase, pci->ioaddr );
/* Reset the NIC */
if ( ( rc = rhine_reset ( rhn ) ) != 0 )
goto err_reset;
/* Reload EEPROM */
if ( ( rc = rhine_reload_eeprom ( rhn ) ) != 0 )
goto err_reload_eeprom;
/* Read card revision and enable MMIO */
pci_read_config_byte ( pci, PCI_REVISION, &revision );
DBGC ( rhn, "RHINE %p revision %#02x detected\n", rhn, revision );
rhine_enable_mmio ( rhn, revision );
/* Read MAC address */
for ( i = 0 ; i < ETH_ALEN ; i++ )
netdev->hw_addr[i] = readb ( rhn->regs + RHINE_MAC + i );
/* Initialise and reset MII interface */
mii_init ( &rhn->mii, &rhine_mii_operations );
if ( ( rc = mii_reset ( &rhn->mii ) ) != 0 ) {
DBGC ( rhn, "RHINE %p could not reset MII: %s\n",
rhn, strerror ( rc ) );
goto err_mii_reset;
}
DBGC ( rhn, "RHINE PHY vendor %04x device %04x\n",
rhine_mii_read ( &rhn->mii, 0x02 ),
rhine_mii_read ( &rhn->mii, 0x03 ) );
/* Register network device */
if ( ( rc = register_netdev ( netdev ) ) != 0 )
goto err_register_netdev;
/* Set initial link state */
rhine_check_link ( netdev );
return 0;
err_register_netdev:
err_mii_reset:
err_reload_eeprom:
rhine_reset ( rhn );
err_reset:
netdev_nullify ( netdev );
netdev_put ( netdev );
err_alloc:
return rc;
}
/**
* Remove PCI device
*
* @v pci PCI device
*/
static void rhine_remove ( struct pci_device *pci ) {
struct net_device *netdev = pci_get_drvdata ( pci );
struct rhine_nic *nic = netdev->priv;
/* Unregister network device */
unregister_netdev ( netdev );
/* Reset card */
rhine_reset ( nic );
/* Free network device */
netdev_nullify ( netdev );
netdev_put ( netdev );
}
/** Rhine PCI device IDs */
static struct pci_device_id rhine_nics[] = {
PCI_ROM ( 0x1106, 0x3065, "dlink-530tx", "VIA VT6102", 0 ),
PCI_ROM ( 0x1106, 0x3106, "vt6105", "VIA VT6105", 0 ),
PCI_ROM ( 0x1106, 0x3043, "dlink-530tx-old", "VIA VT3043", 0 ),
PCI_ROM ( 0x1106, 0x3053, "vt6105m", "VIA VT6105M", 0 ),
PCI_ROM ( 0x1106, 0x6100, "via-rhine-old", "VIA 86C100A", 0 )
};
/** Rhine PCI driver */
struct pci_driver rhine_driver __pci_driver = {
.ids = rhine_nics,
.id_count = ( sizeof ( rhine_nics ) / sizeof ( rhine_nics[0] ) ),
.probe = rhine_probe,
.remove = rhine_remove,
};

250
src/drivers/net/rhine.h Normal file
View File

@ -0,0 +1,250 @@
#ifndef _RHINE_H
#define _RHINE_H
/** @file
*
* VIA Rhine network driver
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
/** Rhine BAR size */
#define RHINE_BAR_SIZE 256
/** Default timeout */
#define RHINE_TIMEOUT_US 10000
/** Rhine descriptor format */
struct rhine_descriptor {
uint32_t des0;
uint32_t des1;
uint32_t buffer;
uint32_t next;
} __attribute__ (( packed ));
#define RHINE_DES0_OWN (1 << 31) /*< Owned descriptor */
#define RHINE_DES1_IC (1 << 23) /*< Generate interrupt */
#define RHINE_TDES1_EDP (1 << 22) /*< End of packet */
#define RHINE_TDES1_STP (1 << 21) /*< Start of packet */
#define RHINE_TDES1_TCPCK (1 << 20) /*< HW TCP checksum */
#define RHINE_TDES1_UDPCK (1 << 19) /*< HW UDP checksum */
#define RHINE_TDES1_IPCK (1 << 18) /*< HW IP checksum */
#define RHINE_TDES1_TAG (1 << 17) /*< Tagged frame */
#define RHINE_TDES1_CRC (1 << 16) /*< No CRC */
#define RHINE_DES1_CHAIN (1 << 15) /*< Chained descriptor */
#define RHINE_DES1_SIZE(_x) ((_x) & 0x7ff) /*< Frame size */
#define RHINE_DES0_GETSIZE(_x) (((_x) >> 16) & 0x7ff)
#define RHINE_RDES0_RXOK (1 << 15)
#define RHINE_RDES0_VIDHIT (1 << 14)
#define RHINE_RDES0_MAR (1 << 13)
#define RHINE_RDES0_BAR (1 << 12)
#define RHINE_RDES0_PHY (1 << 11)
#define RHINE_RDES0_CHN (1 << 10)
#define RHINE_RDES0_STP (1 << 9)
#define RHINE_RDES0_EDP (1 << 8)
#define RHINE_RDES0_BUFF (1 << 7)
#define RHINE_RDES0_FRAG (1 << 6)
#define RHINE_RDES0_RUNT (1 << 5)
#define RHINE_RDES0_LONG (1 << 4)
#define RHINE_RDES0_FOV (1 << 3)
#define RHINE_RDES0_FAE (1 << 2)
#define RHINE_RDES0_CRCE (1 << 1)
#define RHINE_RDES0_RERR (1 << 0)
#define RHINE_TDES0_TERR (1 << 15)
#define RHINE_TDES0_UDF (1 << 11)
#define RHINE_TDES0_CRS (1 << 10)
#define RHINE_TDES0_OWC (1 << 9)
#define RHINE_TDES0_ABT (1 << 8)
#define RHINE_TDES0_CDH (1 << 7)
#define RHINE_TDES0_COLS (1 << 4)
#define RHINE_TDES0_NCR(_x) ((_x) & 0xf)
#define RHINE_RING_ALIGN 4
/** Rhine descriptor rings sizes */
#define RHINE_RXDESC_NUM 4
#define RHINE_TXDESC_NUM 8
#define RHINE_RX_MAX_LEN 1536
/** Rhine MAC address registers */
#define RHINE_MAC 0x00
/** Receive control register */
#define RHINE_RCR 0x06
#define RHINE_RCR_FIFO_TRSH(_x) (((_x) & 0x7) << 5) /*< RX FIFO threshold */
#define RHINE_RCR_PHYS_ACCEPT (1 << 4) /*< Accept matching PA */
#define RHINE_RCR_BCAST_ACCEPT (1 << 3) /*< Accept broadcast */
#define RHINE_RCR_MCAST_ACCEPT (1 << 2) /*< Accept multicast */
#define RHINE_RCR_RUNT_ACCEPT (1 << 1) /*< Accept runt frames */
#define RHINE_RCR_ERR_ACCEPT (1 << 0) /*< Accept erroneous frames */
/** Transmit control register */
#define RHINE_TCR 0x07
#define RHINE_TCR_LOOPBACK(_x) (((_x) & 0x3) << 1) /*< Transmit loop mode */
#define RHINE_TCR_TAGGING (1 << 0) /*< 802.1P/Q packet tagging */
/** Command 0 register */
#define RHINE_CR0 0x08
#define RHINE_CR0_RXSTART (1 << 6)
#define RHINE_CR0_TXSTART (1 << 5)
#define RHINE_CR0_TXEN (1 << 4) /*< Transmit enable */
#define RHINE_CR0_RXEN (1 << 3) /*< Receive enable */
#define RHINE_CR0_STOPNIC (1 << 2) /*< Stop NIC */
#define RHINE_CR0_STARTNIC (1 << 1) /*< Start NIC */
/** Command 1 register */
#define RHINE_CR1 0x09
#define RHINE_CR1_RESET (1 << 7) /*< Software reset */
#define RHINE_CR1_RXPOLL (1 << 6) /*< Receive poll demand */
#define RHINE_CR1_TXPOLL (1 << 5) /*< Xmit poll demand */
#define RHINE_CR1_AUTOPOLL (1 << 3) /*< Disable autopoll */
#define RHINE_CR1_FDX (1 << 2) /*< Full duplex */
#define RIHNE_CR1_ACCUNI (1 << 1) /*< Disable accept unicast */
/** Transmit queue wake register */
#define RHINE_TXQUEUE_WAKE 0x0a
/** Interrupt service 0 */
#define RHINE_ISR0 0x0c
#define RHINE_ISR0_MIBOVFL (1 << 7)
#define RHINE_ISR0_PCIERR (1 << 6)
#define RHINE_ISR0_RXRINGERR (1 << 5)
#define RHINE_ISR0_TXRINGERR (1 << 4)
#define RHINE_ISR0_TXERR (1 << 3)
#define RHINE_ISR0_RXERR (1 << 2)
#define RHINE_ISR0_TXDONE (1 << 1)
#define RHINE_ISR0_RXDONE (1 << 0)
/** Interrupt service 1 */
#define RHINE_ISR1 0x0d
#define RHINE_ISR1_GPI (1 << 7)
#define RHINE_ISR1_PORTSTATE (1 << 6)
#define RHINE_ISR1_TXABORT (1 << 5)
#define RHINE_ISR1_RXNOBUF (1 << 4)
#define RHINE_ISR1_RXFIFOOVFL (1 << 3)
#define RHINE_ISR1_RXFIFOUNFL (1 << 2)
#define RHINE_ISR1_TXFIFOUNFL (1 << 1)
#define RHINE_ISR1_EARLYRX (1 << 0)
/** Interrupt enable mask register 0 */
#define RHINE_IMR0 0x0e
/** Interrupt enable mask register 1 */
#define RHINE_IMR1 0x0f
/** RX queue descriptor base address */
#define RHINE_RXQUEUE_BASE 0x18
/** TX queue 0 descriptor base address */
#define RHINE_TXQUEUE_BASE 0x1c
/** MII configuration */
#define RHINE_MII_CFG 0x6c
/** MII status register */
#define RHINE_MII_SR 0x6d
#define RHINE_MII_SR_PHYRST (1 << 7) /*< PHY reset */
#define RHINE_MII_SR_LINKNWAY (1 << 4) /*< Link status after N-Way */
#define RHINE_MII_SR_PHYERR (1 << 3) /*< PHY device error */
#define RHINE_MII_SR_DUPLEX (1 << 2) /*< Duplex mode after N-Way */
#define RHINE_MII_SR_LINKPOLL (1 << 1) /*< Link status after poll */
#define RHINE_MII_SR_LINKSPD (1 << 0) /*< Link speed after N-Way */
/** MII bus control 0 register */
#define RHINE_MII_BCR0 0x6e
/** MII bus control 1 register */
#define RHINE_MII_BCR1 0x6f
/** MII control register */
#define RHINE_MII_CR 0x70
#define RHINE_MII_CR_AUTOPOLL (1 << 7) /*< MII auto polling */
#define RHINE_MII_CR_RDEN (1 << 6) /*< PHY read enable */
#define RHINE_MII_CR_WREN (1 << 5) /*< PHY write enable */
#define RHINE_MII_CR_DIRECT (1 << 4) /*< Direct programming mode */
#define RHINE_MII_CR_MDIOOUT (1 << 3) /*< MDIO output enable */
/** MII port address */
#define RHINE_MII_ADDR 0x71
#define RHINE_MII_ADDR_MSRCEN (1 << 6)
#define RHINE_MII_ADDR_MDONE (1 << 5)
/** MII read/write data */
#define RHINE_MII_RDWR 0x72
/** EERPOM control/status register */
#define RHINE_EEPROM_CTRL 0x74
#define RHINE_EEPROM_CTRL_STATUS (1 << 7) /*< EEPROM status */
#define RHINE_EEPROM_CTRL_RELOAD (1 << 5) /*< EEPROM reload */
/** Chip configuration A */
#define RHINE_CHIPCFG_A 0x78
/* MMIO enable. Only valid for Rhine I. Reserved on later boards */
#define RHINE_CHIPCFG_A_MMIO (1 << 5)
/** Chip configuration B */
#define RHINE_CHIPCFG_B 0x79
/** Chip configuation C */
#define RHINE_CHIPCFG_C 0x7a
/** Chip configuration D */
#define RHINE_CHIPCFG_D 0x7b
/* MMIO enable. Only valid on Rhine II and later. GPIOEN on Rhine I */
#define RHINE_CHIPCFG_D_MMIO (1 << 7)
#define RHINE_REVISION_OLD 0x20
/** A VIA Rhine descriptor ring */
struct rhine_ring {
/** Descriptors */
struct rhine_descriptor *desc;
/** Producer index */
unsigned int prod;
/** Consumer index */
unsigned int cons;
/** Number of descriptors */
unsigned int count;
/** Register address */
unsigned int reg;
};
/**
* Initialise descriptor ring
*
* @v ring Descriptor ring
* @v count Number of descriptors (must be a power of 2)
* @v reg Register address
*/
static inline __attribute__ (( always_inline)) void
rhine_init_ring ( struct rhine_ring *ring, unsigned int count,
unsigned int reg ) {
ring->count = count;
ring->reg = reg;
}
/** A VIA Rhine network card */
struct rhine_nic {
/** I/O address (some PIO access is always required) */
unsigned long ioaddr;
/** Registers */
void *regs;
/** Cached value of CR1 (to avoid read-modify-write on fast path) */
uint8_t cr1;
/** MII interface */
struct mii_interface mii;
/** Transmit descriptor ring */
struct rhine_ring tx;
/** Receive descriptor ring */
struct rhine_ring rx;
/** Receive I/O buffers */
struct io_buffer *rx_iobuf[RHINE_RXDESC_NUM];
};
#endif /* _RHINE_H */

807
src/drivers/net/velocity.c Normal file
View File

@ -0,0 +1,807 @@
/*
* Copyright (C) 2012 Adrian Jamróz <adrian.jamroz@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
FILE_LICENCE ( GPL2_OR_LATER );
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/netdevice.h>
#include <ipxe/ethernet.h>
#include <ipxe/if_ether.h>
#include <ipxe/iobuf.h>
#include <ipxe/malloc.h>
#include <ipxe/pci.h>
#include <ipxe/mii.h>
#include "velocity.h"
#define velocity_setbit(_reg, _mask) writeb ( readb ( _reg ) | _mask, _reg )
#define virt_to_le32bus(x) ( cpu_to_le32 ( virt_to_bus ( x ) ) )
/** @file
*
* VIA Velocity network driver
*
*/
/******************************************************************************
*
* MII interface
*
******************************************************************************
*/
/**
* Stop MII auto-polling
*
* @v vlc Velocity device
* @ret rc Return status code
*/
static int velocity_autopoll_stop ( struct velocity_nic *vlc ) {
int timeout = VELOCITY_TIMEOUT_US;
/* Disable MII auto polling */
writeb ( 0, vlc->regs + VELOCITY_MIICR );
/* Wait for disabling to take effect */
while ( timeout-- ) {
udelay ( 1 );
if ( readb ( vlc->regs + VELOCITY_MIISR ) &
VELOCITY_MIISR_IDLE )
return 0;
}
DBGC ( vlc, "MII autopoll stop timeout\n" );
return -ETIMEDOUT;
}
/**
* Start MII auto-polling
*
* @v vlc Velocity device
* @ret rc Return status code
*/
static int velocity_autopoll_start ( struct velocity_nic *vlc ) {
int timeout = VELOCITY_TIMEOUT_US;
/* Enable MII auto polling */
writeb ( VELOCITY_MIICR_MAUTO, vlc->regs + VELOCITY_MIICR );
/* Wait for enabling to take effect */
while ( timeout-- ) {
udelay ( 1 );
if ( ( readb ( vlc->regs + VELOCITY_MIISR ) &
VELOCITY_MIISR_IDLE ) == 0 )
return 0;
}
DBGC ( vlc, "MII autopoll start timeout\n" );
return -ETIMEDOUT;
}
/**
* Read from MII register
*
* @v mii MII interface
* @v reg Register address
* @ret value Data read, or negative error
*/
static int velocity_mii_read ( struct mii_interface *mii, unsigned int reg ) {
struct velocity_nic *vlc =
container_of ( mii, struct velocity_nic, mii );
int timeout = VELOCITY_TIMEOUT_US;
int result;
DBGC2 ( vlc, "VELOCITY %p MII read reg %d\n", vlc, reg );
/* Disable autopolling before we can access MII */
velocity_autopoll_stop ( vlc );
/* Send read command and address */
writeb ( reg, vlc->regs + VELOCITY_MIIADDR );
velocity_setbit ( vlc->regs + VELOCITY_MIICR, VELOCITY_MIICR_RCMD );
/* Wait for read to complete */
while ( timeout-- ) {
udelay ( 1 );
if ( ( readb ( vlc->regs + VELOCITY_MIICR ) &
VELOCITY_MIICR_RCMD ) == 0 ) {
result = readw ( vlc->regs + VELOCITY_MIIDATA );
velocity_autopoll_start ( vlc );
return result;
}
}
/* Restart autopolling */
velocity_autopoll_start ( vlc );
DBGC ( vlc, "MII read timeout\n" );
return -ETIMEDOUT;
}
/**
* Write to MII register
*
* @v mii MII interface
* @v reg Register address
* @v data Data to write
* @ret rc Return status code
*/
static int velocity_mii_write ( struct mii_interface *mii, unsigned int reg,
unsigned int data) {
struct velocity_nic *vlc =
container_of ( mii, struct velocity_nic, mii );
int timeout = VELOCITY_TIMEOUT_US;
DBGC2 ( vlc, "VELOCITY %p MII write reg %d data 0x%04x\n",
vlc, reg, data );
/* Disable autopolling before we can access MII */
velocity_autopoll_stop ( vlc );
/* Send write command, data and destination register */
writeb ( reg, vlc->regs + VELOCITY_MIIADDR );
writew ( data, vlc->regs + VELOCITY_MIIDATA );
velocity_setbit ( vlc->regs + VELOCITY_MIICR, VELOCITY_MIICR_WCMD );
/* Wait for write to complete */
while ( timeout-- ) {
udelay ( 1 );
if ( ( readb ( vlc->regs + VELOCITY_MIICR ) &
VELOCITY_MIICR_WCMD ) == 0 ) {
velocity_autopoll_start ( vlc );
return 0;
}
}
/* Restart autopolling */
velocity_autopoll_start ( vlc );
DBGC ( vlc, "MII write timeout\n" );
return -ETIMEDOUT;
}
/** Velocity MII operations */
static struct mii_operations velocity_mii_operations = {
.read = velocity_mii_read,
.write = velocity_mii_write,
};
/**
* Set Link speed
*
* @v vlc Velocity device
*/
static void velocity_set_link ( struct velocity_nic *vlc ) {
int tmp;
/* Advertise 1000MBit */
tmp = velocity_mii_read ( &vlc->mii, MII_CTRL1000 );
tmp |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
velocity_mii_write ( &vlc->mii, MII_CTRL1000, tmp );
/* Enable GBit operation in MII Control Register */
tmp = velocity_mii_read ( &vlc->mii, MII_BMCR );
tmp |= BMCR_SPEED1000;
velocity_mii_write ( &vlc->mii, MII_BMCR, tmp );
}
/******************************************************************************
*
* Device reset
*
******************************************************************************
*/
/**
* Reload eeprom contents
*
* @v vlc Velocity device
*/
static int velocity_reload_eeprom ( struct velocity_nic *vlc ) {
int timeout = VELOCITY_TIMEOUT_US;
/* Initiate reload */
velocity_setbit ( vlc->regs + VELOCITY_EECSR, VELOCITY_EECSR_RELOAD );
/* Wait for reload to complete */
while ( timeout-- ) {
udelay ( 1 );
if ( ( readb ( vlc->regs + VELOCITY_EECSR ) &
VELOCITY_EECSR_RELOAD ) == 0 )
return 0;
}
DBGC ( vlc, "VELOCITY %p EEPROM reload timeout\n", vlc );
return -ETIMEDOUT;
}
/**
* Reset hardware
*
* @v vlc Velocity device
* @ret rc Return status code
*/
static int velocity_reset ( struct velocity_nic *vlc ) {
int timeout = VELOCITY_TIMEOUT_US;
uint8_t tmp;
DBGC ( vlc, "VELOCITY %p reset\n", vlc );
/* clear sticky Power state bits */
tmp = readb ( vlc->regs + VELOCITY_STICKY );
tmp &= ~( VELOCITY_STICKY_DS0 | VELOCITY_STICKY_DS1 );
writeb ( tmp, vlc->regs + VELOCITY_STICKY );
/* clear PACPI, which might have been enabled by the EEPROM reload */
tmp = readb ( vlc->regs + VELOCITY_CFGA );
tmp &= ~VELOCITY_CFGA_PACPI;
writeb ( tmp, vlc->regs + VELOCITY_CFGA );
velocity_setbit ( vlc->regs + VELOCITY_CRS1, VELOCITY_CR1_SFRST );
/* Wait for reset to complete */
while ( timeout-- ) {
udelay ( 1 );
if ( ( readb ( vlc->regs + VELOCITY_CRS1 ) &
VELOCITY_CR1_SFRST ) == 0 )
return 0;
}
return -EINVAL;
}
/******************************************************************************
*
* Link state
*
******************************************************************************
*/
/**
* Check link state
*
* @v netdev Network device
*/
static void velocity_check_link ( struct net_device *netdev ) {
struct velocity_nic *vlc = netdev->priv;
if ( readb ( vlc->regs + VELOCITY_PHYSTS0 ) & VELOCITY_PHYSTS0_LINK ) {
netdev_link_up ( netdev );
DBGC ( vlc, "VELOCITY %p link up\n", vlc );
} else {
netdev_link_down ( netdev );
DBGC ( vlc, "VELOCITY %p link down\n", vlc );
}
/* The card disables auto-poll after a link change */
velocity_autopoll_start ( vlc );
}
/******************************************************************************
*
* Network device interface
*
******************************************************************************
*/
/**
* Allocate descriptor rings
*
* @v vlc Velocity device
* @ret rc Return status code
*/
static int velocity_alloc_rings ( struct velocity_nic *vlc ) {
int rc = 0;
/* Allocate RX descriptor ring */
vlc->rx_prod = 0;
vlc->rx_cons = 0;
vlc->rx_commit = 0;
vlc->rx_ring = malloc_dma ( VELOCITY_RXDESC_SIZE, VELOCITY_RING_ALIGN );
if ( ! vlc->rx_ring )
return -ENOMEM;
memset ( vlc->rx_ring, 0, VELOCITY_RXDESC_SIZE );
DBGC2 ( vlc, "VELOCITY %p RX ring start address: %p(phys: %#08lx)\n",
vlc, vlc->rx_ring, virt_to_bus ( vlc->rx_ring ) );
/* Allocate TX descriptor ring */
vlc->tx_prod = 0;
vlc->tx_cons = 0;
vlc->tx_ring = malloc_dma ( VELOCITY_TXDESC_SIZE, VELOCITY_RING_ALIGN );
if ( ! vlc->tx_ring ) {
rc = -ENOMEM;
goto err_tx_alloc;
}
memset ( vlc->tx_ring, 0, VELOCITY_TXDESC_SIZE );
/* Send RX ring to the card */
writel ( virt_to_bus ( vlc->rx_ring ),
vlc->regs + VELOCITY_RXDESC_ADDR_LO );
writew ( VELOCITY_RXDESC_NUM - 1, vlc->regs + VELOCITY_RXDESCNUM );
/* Send TX ring to the card */
writel ( virt_to_bus ( vlc->tx_ring ),
vlc->regs + VELOCITY_TXDESC_ADDR_LO0 );
writew ( VELOCITY_TXDESC_NUM - 1, vlc->regs + VELOCITY_TXDESCNUM );
DBGC2 ( vlc, "VELOCITY %p TX ring start address: %p(phys: %#08lx)\n",
vlc, vlc->tx_ring, virt_to_bus ( vlc->tx_ring ) );
return 0;
err_tx_alloc:
free_dma ( vlc->rx_ring, VELOCITY_RXDESC_SIZE );
return rc;
}
/**
* Refill receive descriptor ring
*
* @v vlc Velocity device
*/
static void velocity_refill_rx ( struct velocity_nic *vlc ) {
struct velocity_rx_descriptor *desc;
struct io_buffer *iobuf;
int rx_idx, i = 0;
/* Check for new packets */
while ( ( vlc->rx_prod - vlc->rx_cons ) < VELOCITY_RXDESC_NUM ) {
iobuf = alloc_iob ( VELOCITY_RX_MAX_LEN );
/* Memory pressure: try again next poll */
if ( ! iobuf )
break;
rx_idx = ( vlc->rx_prod++ % VELOCITY_RXDESC_NUM );
desc = &vlc->rx_ring[rx_idx];
/* Set descrptor fields */
desc->des1 = 0;
desc->addr = virt_to_le32bus ( iobuf-> data );
desc->des2 = cpu_to_le32 (
VELOCITY_DES2_SIZE ( VELOCITY_RX_MAX_LEN - 1 ) |
VELOCITY_DES2_IC );
vlc->rx_buffs[rx_idx] = iobuf;
i++;
/* Return RX descriptors in blocks of 4 (hw requirement) */
if ( rx_idx % 4 == 3 ) {
int j;
for (j = 0; j < 4; j++) {
desc = &vlc->rx_ring[rx_idx - j];
desc->des0 = cpu_to_le32 ( VELOCITY_DES0_OWN );
}
vlc->rx_commit += 4;
}
}
wmb();
if ( vlc->rx_commit ) {
writew ( vlc->rx_commit,
vlc->regs + VELOCITY_RXDESC_RESIDUECNT );
vlc->rx_commit = 0;
}
if ( i > 0 )
DBGC2 ( vlc, "VELOCITY %p refilled %d RX descriptors\n",
vlc, i );
}
/**
* Open network device
*
* @v netdev Network device
* @ret rc Return status code
*/
static int velocity_open ( struct net_device *netdev ) {
struct velocity_nic *vlc = netdev->priv;
int rc;
DBGC ( vlc, "VELOCITY %p open\n", vlc );
DBGC ( vlc, "VELOCITY %p regs at: %p\n", vlc, vlc->regs );
/* Allocate descriptor rings */
if ( ( rc = velocity_alloc_rings ( vlc ) ) != 0 )
return rc;
velocity_refill_rx ( vlc );
/* Enable TX/RX queue */
writew ( VELOCITY_TXQCSRS_RUN0, vlc->regs + VELOCITY_TXQCSRS );
writew ( VELOCITY_RXQCSR_RUN | VELOCITY_RXQCSR_WAK,
vlc->regs + VELOCITY_RXQCSRS );
/* Enable interrupts */
writeb ( 0xff, vlc->regs + VELOCITY_IMR0 );
writeb ( 0xff, vlc->regs + VELOCITY_IMR1 );
/* Start MAC */
writeb ( VELOCITY_CR0_STOP, vlc->regs + VELOCITY_CRC0 );
writeb ( VELOCITY_CR1_DPOLL, vlc->regs + VELOCITY_CRC0 );
writeb ( VELOCITY_CR0_START | VELOCITY_CR0_TXON | VELOCITY_CR0_RXON,
vlc->regs + VELOCITY_CRS0 );
/* Receive all packets */
writeb ( 0xff, vlc->regs + VELOCITY_RCR );
/* Set initial link state */
velocity_check_link ( netdev );
velocity_autopoll_start ( vlc );
DBGC2 ( vlc, "VELOCITY %p CR3 %02x\n",
vlc, readb ( vlc->regs + 0x0B ) );
return 0;
}
/**
* Close network device
*
* @v netdev Network device
*/
static void velocity_close ( struct net_device *netdev ) {
struct velocity_nic *vlc = netdev->priv;
int i;
/* Stop NIC */
writeb ( VELOCITY_CR0_TXON | VELOCITY_CR0_RXON,
vlc->regs + VELOCITY_CRC0 );
writeb ( VELOCITY_CR0_STOP, vlc->regs + VELOCITY_CRS0 );
/* Clear RX ring information */
writel ( 0, vlc->regs + VELOCITY_RXDESC_ADDR_LO );
writew ( 0, vlc->regs + VELOCITY_RXDESCNUM );
/* Destroy RX ring */
free_dma ( vlc->rx_ring, VELOCITY_RXDESC_SIZE );
vlc->rx_ring = NULL;
vlc->rx_prod = 0;
vlc->rx_cons = 0;
/* Discard receive buffers */
for ( i = 0 ; i < VELOCITY_RXDESC_NUM ; i++ ) {
if ( vlc->rx_buffs[i] )
free_iob ( vlc->rx_buffs[i] );
vlc->rx_buffs[i] = NULL;
}
/* Clear TX ring information */
writel ( 0, vlc->regs + VELOCITY_TXDESC_ADDR_LO0 );
writew ( 0, vlc->regs + VELOCITY_TXDESCNUM );
/* Destroy TX ring */
free_dma ( vlc->tx_ring, VELOCITY_TXDESC_SIZE );
vlc->tx_ring = NULL;
vlc->tx_prod = 0;
vlc->tx_cons = 0;
}
/**
* Transmit packet
*
* @v netdev Network device
* @v iobuf I/O buffer
* @ret rc Return status code
*/
static int velocity_transmit ( struct net_device *netdev,
struct io_buffer *iobuf ) {
struct velocity_nic *vlc = netdev->priv;
struct velocity_tx_descriptor *desc;
unsigned int tx_idx;
/* Pad packet to minimum length */
iob_pad ( iobuf, ETH_ZLEN );
tx_idx = ( vlc->tx_prod++ % VELOCITY_TXDESC_NUM );
desc = &vlc->tx_ring[tx_idx];
/* Set packet size and transfer ownership to NIC */
desc->des0 = cpu_to_le32 ( VELOCITY_DES0_OWN |
VELOCITY_DES2_SIZE ( iob_len ( iobuf ) ) );
/* Data in first desc fragment, only desc for packet, generate INT */
desc->des1 = cpu_to_le32 ( VELOCITY_DES1_FRAG ( 1 ) |
VELOCITY_DES1_TCPLS |
VELOCITY_DES1_INTR );
desc->frags[0].addr = virt_to_le32bus ( iobuf->data );
desc->frags[0].des2 = cpu_to_le32 (
VELOCITY_DES2_SIZE ( iob_len ( iobuf ) ) );
wmb();
/* Initiate TX */
velocity_setbit ( vlc->regs + VELOCITY_TXQCSRS, VELOCITY_TXQCSRS_WAK0 );
DBGC2 ( vlc, "VELOCITY %p tx_prod=%d desc=%p iobuf=%p len=%zd\n",
vlc, tx_idx, desc, iobuf->data, iob_len ( iobuf ) );
return 0;
}
/**
* Poll for received packets.
*
* @v vlc Velocity device
*/
static void velocity_poll_rx ( struct velocity_nic *vlc ) {
struct velocity_rx_descriptor *desc;
struct io_buffer *iobuf;
int rx_idx;
size_t len;
uint32_t des0;
/* Check for packets */
while ( vlc->rx_cons != vlc->rx_prod ) {
rx_idx = ( vlc->rx_cons % VELOCITY_RXDESC_NUM );
desc = &vlc->rx_ring[rx_idx];
des0 = cpu_to_le32 ( desc->des0 );
/* Return if descriptor still in use */
if ( des0 & VELOCITY_DES0_OWN )
return;
iobuf = vlc->rx_buffs[rx_idx];
/* Get length, strip CRC */
len = VELOCITY_DES0_RMBC ( des0 ) - 4;
iob_put ( iobuf, len );
DBGC2 ( vlc, "VELOCITY %p got packet on idx=%d (prod=%d), len %zd\n",
vlc, rx_idx, vlc->rx_prod % VELOCITY_RXDESC_NUM, len );
if ( des0 & VELOCITY_DES0_RX_ERR ) {
/* Report receive error */
netdev_rx_err ( vlc->netdev, iobuf, -EINVAL );
DBGC ( vlc, "VELOCITY %p receive error, status: %02x\n",
vlc, des0 );
} else if ( des0 & VELOCITY_DES0_RXOK ) {
/* Report receive success */
netdev_rx( vlc->netdev, iobuf );
} else {
/* Card indicated neither success nor failure
* Technically this shouldn't happen, but we saw it
* in debugging once. */
DBGC ( vlc, "VELOCITY %p RX neither ERR nor OK: %04x\n",
vlc, des0 );
DBGC ( vlc, "packet len: %zd\n", len );
DBGC_HD ( vlc, iobuf->data, 64 );
/* we don't know what it is, treat is as an error */
netdev_rx_err ( vlc->netdev, iobuf, -EINVAL );
}
vlc->rx_cons++;
}
}
/**
* Poll for completed packets.
*
* @v vlc Velocity device
*/
static void velocity_poll_tx ( struct velocity_nic *vlc ) {
struct velocity_tx_descriptor *desc;
int tx_idx;
/* Check for packets */
while ( vlc->tx_cons != vlc->tx_prod ) {
tx_idx = ( vlc->tx_cons % VELOCITY_TXDESC_NUM );
desc = &vlc->tx_ring[tx_idx];
/* Return if descriptor still in use */
if ( le32_to_cpu ( desc->des0 ) & VELOCITY_DES0_OWN )
return;
/* Report errors */
if ( le32_to_cpu ( desc->des0 ) & VELOCITY_DES0_TERR ) {
netdev_tx_complete_next_err ( vlc->netdev, -EINVAL );
return;
}
netdev_tx_complete_next ( vlc->netdev );
DBGC2 ( vlc, "VELOCITY %p poll_tx cons=%d prod=%d tsr=%04x\n",
vlc, tx_idx, vlc->tx_prod % VELOCITY_TXDESC_NUM,
( desc->des0 & 0xffff ) );
vlc->tx_cons++;
}
}
/**
* Poll for completed and received packets
*
* @v netdev Network device
*/
static void velocity_poll ( struct net_device *netdev ) {
struct velocity_nic *vlc = netdev->priv;
uint8_t isr1;
isr1 = readb ( vlc->regs + VELOCITY_ISR1 );
/* ACK interrupts */
writew ( 0xFFFF, vlc->regs + VELOCITY_ISR0 );
/* Check for competed packets */
velocity_poll_rx ( vlc );
velocity_poll_tx ( vlc );
if ( isr1 & VELOCITY_ISR1_SRCI ) {
/* Update linkstate */
DBGC2 ( vlc, "VELOCITY %p link status interrupt\n", vlc );
velocity_check_link ( netdev );
}
velocity_refill_rx ( vlc );
/* deal with potential RX stall caused by RX ring underrun */
writew ( VELOCITY_RXQCSR_RUN | VELOCITY_RXQCSR_WAK,
vlc->regs + VELOCITY_RXQCSRS );
}
/**
* Enable or disable interrupts
*
* @v netdev Network device
* @v enable Interrupts should be enabled
*/
static void velocity_irq ( struct net_device *netdev, int enable ) {
struct velocity_nic *vlc = netdev->priv;
DBGC ( vlc, "VELOCITY %p interrupts %s\n", vlc,
enable ? "enable" : "disable" );
if (enable) {
/* Enable interrupts */
writeb ( VELOCITY_CR3_GINTMSK1, vlc->regs + VELOCITY_CRS3 );
} else {
/* Disable interrupts */
writeb ( VELOCITY_CR3_GINTMSK1, vlc->regs + VELOCITY_CRC3 );
}
}
/** Velocity network device operations */
static struct net_device_operations velocity_operations = {
.open = velocity_open,
.close = velocity_close,
.transmit = velocity_transmit,
.poll = velocity_poll,
.irq = velocity_irq,
};
/******************************************************************************
*
* PCI interface
*
******************************************************************************
*/
/**
* Probe PCI device
*
* @v pci PCI device
* @ret rc Return status code
*/
static int velocity_probe ( struct pci_device *pci ) {
struct net_device *netdev;
struct velocity_nic *vlc;
int rc;
/* Allocate and initialise net device */
netdev = alloc_etherdev ( sizeof ( *vlc ) );
if ( ! netdev ) {
rc = -ENOMEM;
goto err_alloc;
}
netdev_init ( netdev, &velocity_operations );
vlc = netdev->priv;
pci_set_drvdata ( pci, netdev );
netdev->dev = &pci->dev;
/* Fix up PCI device */
adjust_pci_device ( pci );
/* Map registers */
vlc->regs = ioremap ( pci->membase, VELOCITY_BAR_SIZE );
vlc->netdev = netdev;
/* Reset the NIC */
if ( ( rc = velocity_reset ( vlc ) ) != 0 )
goto err_reset;
/* Reload EEPROM */
if ( ( rc = velocity_reload_eeprom ( vlc ) ) != 0 )
goto err_reset;
/* Get MAC address */
netdev->hw_addr[0] = readb ( vlc->regs + VELOCITY_MAC0 );
netdev->hw_addr[1] = readb ( vlc->regs + VELOCITY_MAC1 );
netdev->hw_addr[2] = readb ( vlc->regs + VELOCITY_MAC2 );
netdev->hw_addr[3] = readb ( vlc->regs + VELOCITY_MAC3 );
netdev->hw_addr[4] = readb ( vlc->regs + VELOCITY_MAC4 );
netdev->hw_addr[5] = readb ( vlc->regs + VELOCITY_MAC5 );
/* Initialise and reset MII interface */
mii_init ( &vlc->mii, &velocity_mii_operations );
if ( ( rc = mii_reset ( &vlc->mii ) ) != 0 ) {
DBGC ( vlc, "VELOCITY %p could not reset MII: %s\n",
vlc, strerror ( rc ) );
goto err_mii_reset;
}
/* Enable proper link advertising */
velocity_set_link ( vlc );
/* Register network device */
if ( ( rc = register_netdev ( netdev ) ) != 0 )
goto err_register_netdev;
return 0;
err_register_netdev:
err_mii_reset:
velocity_reset ( vlc );
err_reset:
netdev_nullify ( netdev );
netdev_put ( netdev );
err_alloc:
return rc;
}
/**
* Remove PCI device
*
* @v pci PCI device
*/
static void velocity_remove ( struct pci_device *pci ) {
struct net_device *netdev = pci_get_drvdata ( pci );
struct velocity_nic *vlc = netdev->priv;
/* Unregister network device */
unregister_netdev ( netdev );
/* Reset card */
velocity_reset ( vlc );
/* Free network device */
netdev_nullify ( netdev );
netdev_put ( netdev );
}
/** Velocity PCI device IDs */
static struct pci_device_id velocity_nics[] = {
PCI_ROM ( 0x1106, 0x3119, "vt6122", "VIA Velocity", 0 ),
};
/** Velocity PCI driver */
struct pci_driver velocity_driver __pci_driver = {
.ids = velocity_nics,
.id_count = ( sizeof ( velocity_nics ) / sizeof ( velocity_nics[0] ) ),
.probe = velocity_probe,
.remove = velocity_remove,
};

356
src/drivers/net/velocity.h Normal file
View File

@ -0,0 +1,356 @@
#ifndef _VELOCITY_H
#define _VELOCITY_H
/** @file
*
* VIA Velocity network driver
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
/** Skeleton BAR size */
#define VELOCITY_BAR_SIZE 256
/** Default timeout */
#define VELOCITY_TIMEOUT_US 10 * 1000
struct velocity_frag {
uint32_t addr;
uint32_t des2;
} __attribute__ ((packed));
/** Velocity descriptor format */
struct velocity_tx_descriptor {
uint32_t des0;
uint32_t des1;
/* We only use the first fragment, the HW requires us to have 7 */
struct velocity_frag frags[7];
} __attribute__ ((packed));
struct velocity_rx_descriptor {
uint32_t des0;
uint32_t des1;
uint32_t addr;
uint32_t des2;
} __attribute__ ((packed));
#define VELOCITY_DES0_RMBC(_n) (((_n) >> 16) & 0x1fff)
#define VELOCITY_DES0_OWN (1 << 31)
#define VELOCITY_DES0_TERR (1 << 15)
#define VELOCITY_DES0_RXOK (1 << 15)
#define VELOCITY_DES0_FDX (1 << 14)
#define VELOCITY_DES0_GMII (1 << 13)
#define VELOCITY_DES0_LNKFL (1 << 12)
#define VELOCITY_DES0_SHDN (1 << 10)
#define VELOCITY_DES0_CRS (1 << 9)
#define VELOCITY_DES0_CDH (1 << 8)
#define VELOCITY_DES0_ABT (1 << 7)
#define VELOCITY_DES0_OWT (1 << 6)
#define VELOCITY_DES0_OWC (1 << 5)
#define VELOCITY_DES0_COLS (1 << 4)
#define VELOCITY_DES0_RXSHDN (1 << 30)
#define VELOCITY_DES0_RXER (1 << 5)
#define VELOCITY_DES0_RLE (1 << 4)
#define VELOCITY_DES0_CE (1 << 3)
#define VELOCITY_DES0_FAE (1 << 2)
#define VELOCITY_DES0_CRC (1 << 1)
#define VELOCITY_DES0_RX_ERR ( VELOCITY_DES0_RXER | \
VELOCITY_DES0_RLE | \
VELOCITY_DES0_CE | \
VELOCITY_DES0_FAE | \
VELOCITY_DES0_CRC )
/** TX descriptor fragment number */
#define VELOCITY_DES1_FRAG(_n) (((_n + 1) & 0xf) << 28)
#define VELOCITY_DES1_TCPLS ((1 << 24) | (1 << 25))
#define VELOCITY_DES1_INTR (1 << 23)
#define VELOCITY_DES1_PIC (1 << 22)
#define VELOCITY_DES1_VETAG (1 << 21)
#define VELOCITY_DES1_IPCK (1 << 20)
#define VELOCITY_DES1_UDPCK (1 << 19)
#define VELOCITY_DES1_TCPCK (1 << 18)
#define VELOCITY_DES1_JMBO (1 << 17)
#define VELOCITY_DES1_CRC (1 << 16)
#define VELOCITY_DES2_IC (1 << 31)
#define VELOCITY_DES2_SIZE(_n) (((_n) & 0x1fff) << 16)
/** Number of receive descriptors
*
* Must be a multiple of 4 (hardware requirement).
*/
#define VELOCITY_RXDESC_NUM 8
#define VELOCITY_RXDESC_SIZE \
( VELOCITY_RXDESC_NUM * sizeof ( struct velocity_rx_descriptor ) )
/** Number of transmit descriptors */
#define VELOCITY_TXDESC_NUM 8
#define VELOCITY_TXDESC_SIZE \
( VELOCITY_TXDESC_NUM * sizeof ( struct velocity_tx_descriptor ) )
/** Descriptor alignment */
#define VELOCITY_RING_ALIGN 64
/** Receive buffer length */
#define VELOCITY_RX_MAX_LEN 1536
/** MAC address registers */
#define VELOCITY_MAC0 0x00
#define VELOCITY_MAC1 0x01
#define VELOCITY_MAC2 0x02
#define VELOCITY_MAC3 0x03
#define VELOCITY_MAC4 0x04
#define VELOCITY_MAC5 0x05
/** Receive control register */
#define VELOCITY_RCR 0x06
#define RHINE_RCR_SYMERR_ACCEPT (1 << 7) /*< Accept symbol error */
#define RHINE_RCR_FILTER_ACCEPT (1 << 6) /*< Accept based on filter */
#define RHINE_RCR_LONG_ACCEPT (1 << 5) /*< Accept long packets */
#define RHINE_RCR_PROMISC (1 << 4) /*< Promiscuous mode */
#define RHINE_RCR_BCAST_ACCEPT (1 << 3) /*< Accept broadcast */
#define RHINE_RCR_MCAST_ACCEPT (1 << 2) /*< Accept multicast */
#define RHINE_RCR_RUNT_ACCEPT (1 << 1) /*< Accept runt frames */
#define RHINE_RCR_ERR_ACCEPT (1 << 0) /*< Accept erroneous frames */
/** Transmit control register */
#define VELOCITY_TCR 0x07
#define VELOCITY_TCR_LB0 (1 << 0) /*< Loopback control */
#define VELOCITY_TCR_LB1 (1 << 1) /*< Loopback control */
#define VELOCITY_TCR_COLTMC0 (1 << 2) /*< Collision retry control */
#define VELOCITY_TCR_COLTMC1 (1 << 3) /*< Collision retry control */
/** Command register 0 (set) */
#define VELOCITY_CRS0 0x08
#define VELOCITY_CR0_TXON (1 << 3) /*< Transmit enable */
#define VELOCITY_CR0_RXON (1 << 2) /*< Receive enable */
#define VELOCITY_CR0_STOP (1 << 1) /*< Stop NIC */
#define VELOCITY_CR0_START (1 << 0) /*< Start NIC */
/** Command register 1 (set) */
#define VELOCITY_CRS1 0x09
#define VELOCITY_CR1_SFRST (1 << 7) /*< Software reset */
#define VELOCITY_CR1_TM1EN (1 << 6) /*< Perioding software counting */
#define VELOCITY_CR1_TM0EN (1 << 5) /*< Single-shot software counting */
#define VELOCITY_CR1_DPOLL (1 << 3) /*< Disable auto polling */
#define VELOCITY_CR1_DISAU (1 << 0) /*< Unicast reception disable */
/** Command register 2 (set) */
#define VELOCITY_CRS2 0x0A
#define VELOCITY_CR2_XONEN (1 << 7) /*< XON/XOFF mode enable */
#define VELOCITY_CR2_FDXTFCEN (1 << 6) /*< FDX flow control TX */
#define VELOCITY_CR2_FDXRFCEN (1 << 5)
#define VELOCITY_CR2_HDXFCEN (1 << 4)
/** Command register 3 (set) */
#define VELOCITY_CRS3 0x0B
#define VELOCITY_CR3_FOSRST (1 << 6)
#define VELOCITY_CR3_FPHYRST (1 << 5)
#define VELOCITY_CR3_DIAG (1 << 4)
#define VELOCITY_CR3_INTPCTL (1 << 2)
#define VELOCITY_CR3_GINTMSK1 (1 << 1)
#define VELOCITY_CR3_SWPEND (1 << 0)
/** Command register 0 (clear) */
#define VELOCITY_CRC0 0x0C
/** Command register 1 (clear) */
#define VELOCITY_CRC1 0x0D
/** Command register 2 (clear */
#define VELOCITY_CRC2 0x0E
/** Command register 3 (clear */
#define VELOCITY_CRC3 0x0F
#define VELOCITY_CAM0 0x10
#define VELOCITY_CAM1 0x11
#define VELOCITY_CAM2 0x12
#define VELOCITY_CAM3 0x13
#define VELOCITY_CAM4 0x14
#define VELOCITY_CAM5 0x15
#define VELOCITY_CAM6 0x16
#define VELOCITY_CAM7 0x17
#define VELOCITY_TXDESC_HI 0x18 /* Hi part of 64bit txdesc base addr */
#define VELOCITY_DATABUF_HI 0x1D /* Hi part of 64bit data buffer addr */
#define VELOCITY_INTCTL0 0x20 /* interrupt control register */
#define VELOCITY_RXSUPPTHR 0x20
#define VELOCITY_TXSUPPTHR 0x20
#define VELOCITY_INTHOLDOFF 0x20
#define VELOCITY_INTCTL1 0x21 /* interrupt control register */
#define VELOCITY_TXHOSTERR 0x22 /* TX host error status */
#define VELOCITY_RXHOSTERR 0x23 /* RX host error status */
/** Interrupt status register 0 */
#define VELOCITY_ISR0 0x24
#define VELOCITY_ISR0_PTX3 (1 << 7)
#define VELOCITY_ISR0_PTX2 (1 << 6)
#define VELOCITY_ISR0_PTX1 (1 << 5)
#define VELOCITY_ISR0_PTX0 (1 << 4)
#define VELOCITY_ISR0_PTXI (1 << 3)
#define VELOCITY_ISR0_PRXI (1 << 2)
#define VELOCITY_ISR0_PPTXI (1 << 1)
#define VELOCITY_ISR0_PPRXI (1 << 0)
/** Interrupt status register 1 */
#define VELOCITY_ISR1 0x25
#define VELOCITY_ISR1_SRCI (1 << 7)
#define VELOCITY_ISR1_LSTPEI (1 << 6)
#define VELOCITY_ISR1_LSTEI (1 << 5)
#define VELOCITY_ISR1_OVFL (1 << 4)
#define VELOCITY_ISR1_FLONI (1 << 3)
#define VELOCITY_ISR1_RACEI (1 << 2)
/** Interrupt status register 2 */
#define VELOCITY_ISR2 0x26
#define VELOCITY_ISR2_HFLD (1 << 7)
#define VELOCITY_ISR2_UDPI (1 << 6)
#define VELOCITY_ISR2_MIBFI (1 << 5)
#define VELOCITY_ISR2_SHDNII (1 << 4)
#define VELOCITY_ISR2_PHYI (1 << 3)
#define VELOCITY_ISR2_PWEI (1 << 2)
#define VELOCITY_ISR2_TMR1I (1 << 1)
#define VELOCITY_ISR2_TMR0I (1 << 0)
/** Interrupt status register 3 */
#define VELOCITY_ISR3 0x27
/** Interrupt mask register 0 */
#define VELOCITY_IMR0 0x28
/** Interrupt mask register 1 */
#define VELOCITY_IMR1 0x29
/** Interrupt mask register 2 */
#define VELOCITY_IMR2 0x2a
/** Interrupt mask register 3 */
#define VELOCITY_IMR3 0x2b
#define VELOCITY_TXSTS_PORT 0x2C /* Transmit status port (???) */
#define VELOCITY_TXQCSRS 0x30 /* TX queue ctl/status set */
#define VELOCITY_TXQCSRS_DEAD3 (1 << 15)
#define VELOCITY_TXQCSRS_WAK3 (1 << 14)
#define VELOCITY_TXQCSRS_ACT3 (1 << 13)
#define VELOCITY_TXQCSRS_RUN3 (1 << 12)
#define VELOCITY_TXQCSRS_DEAD2 (1 << 11)
#define VELOCITY_TXQCSRS_WAK2 (1 << 10)
#define VELOCITY_TXQCSRS_ACT2 (1 << 9)
#define VELOCITY_TXQCSRS_RUN2 (1 << 8)
#define VELOCITY_TXQCSRS_DEAD1 (1 << 7)
#define VELOCITY_TXQCSRS_WAK1 (1 << 6)
#define VELOCITY_TXQCSRS_ACT1 (1 << 5)
#define VELOCITY_TXQCSRS_RUN1 (1 << 4)
#define VELOCITY_TXQCSRS_DEAD0 (1 << 3)
#define VELOCITY_TXQCSRS_WAK0 (1 << 2)
#define VELOCITY_TXQCSRS_ACT0 (1 << 1)
#define VELOCITY_TXQCSRS_RUN0 (1 << 0)
#define VELOCITY_RXQCSRS 0x32 /* RX queue ctl/status set */
#define VELOCITY_RXQCSRC 0x36
#define VELOCITY_RXQCSR_DEAD (1 << 3)
#define VELOCITY_RXQCSR_WAK (1 << 2)
#define VELOCITY_RXQCSR_ACT (1 << 1)
#define VELOCITY_RXQCSR_RUN (1 << 0)
#define VELOCITY_TXQCSRC 0x34 /* TX queue ctl/status clear */
#define VELOCITY_RXQCSRC 0x36 /* RX queue ctl/status clear */
#define VELOCITY_RXDESC_ADDR_LO 0x38 /* RX desc base addr (lo 32 bits) */
#define VELOCITY_RXDESC_CONSIDX 0x3C /* Current RX descriptor index */
#define VELOCITY_TXQTIMER 0x3E /* TX queue timer pend register */
#define VELOCITY_RXQTIMER 0x3F /* RX queue timer pend register */
#define VELOCITY_TXDESC_ADDR_LO0 0x40 /* TX desc0 base addr (lo 32 bits) */
#define VELOCITY_TXDESC_ADDR_LO1 0x44 /* TX desc1 base addr (lo 32 bits) */
#define VELOCITY_TXDESC_ADDR_LO2 0x48 /* TX desc2 base addr (lo 32 bits) */
#define VELOCITY_TXDESC_ADDR_LO3 0x4C /* TX desc3 base addr (lo 32 bits) */
#define VELOCITY_RXDESCNUM 0x50 /* Size of RX desc ring */
#define VELOCITY_TXDESCNUM 0x52 /* Size of TX desc ring */
#define VELOCITY_TXDESC_CONSIDX0 0x54 /* Current TX descriptor index */
#define VELOCITY_TXDESC_CONSIDX1 0x56 /* Current TX descriptor index */
#define VELOCITY_TXDESC_CONSIDX2 0x58 /* Current TX descriptor index */
#define VELOCITY_TXDESC_CONSIDX3 0x5A /* Current TX descriptor index */
#define VELOCITY_TX_PAUSE_TIMER 0x5C /* TX pause frame timer */
#define VELOCITY_RXDESC_RESIDUECNT 0x5E /* RX descriptor residue count */
#define VELOCITY_FIFOTEST0 0x60 /* FIFO test register */
#define VELOCITY_FIFOTEST1 0x64 /* FIFO test register */
#define VELOCITY_CAMADDR 0x68 /* CAM address register */
#define VELOCITY_CAMCTL 0x69 /* CAM control register */
#define VELOCITY_MIICFG 0x6C /* MII port config register */
#define VELOCITY_MIISR 0x6D /* MII port status register */
#define VELOCITY_MIISR_IDLE (1 << 7)
#define VELOCITY_PHYSTS0 0x6E /* PHY status register */
#define VELOCITY_PHYSTS0_LINK (1 << 6)
#define VELOCITY_PHYSTS1 0x6F /* PHY status register */
#define VELOCITY_MIICR 0x70 /* MII command register */
#define VELOCITY_MIICR_MAUTO (1 << 7)
#define VELOCITY_MIICR_RCMD (1 << 6)
#define VELOCITY_MIICR_WCMD (1 << 5)
#define VELOCITY_MIICR_MDPM (1 << 4)
#define VELOCITY_MIICR_MOUT (1 << 3)
#define VELOCITY_MIICR_MDO (1 << 2)
#define VELOCITY_MIICR_MDI (1 << 1)
#define VELOCITY_MIICR_MDC (1 << 0)
#define VELOCITY_MIIADDR 0x71 /* MII address register */
#define VELOCITY_MIIDATA 0x72 /* MII data register */
#define VELOCITY_SSTIMER 0x74 /* single-shot timer */
#define VELOCITY_PTIMER 0x76 /* periodic timer */
#define VELOCITY_DMACFG0 0x7C /* DMA config 0 */
#define VELOCITY_DMACFG1 0x7D /* DMA config 1 */
#define VELOCITY_RXCFG 0x7E /* MAC RX config */
#define VELOCITY_TXCFG 0x7F /* MAC TX config */
#define VELOCITY_SWEEDATA 0x85 /* EEPROM software loaded data */
/** Chip Configuration Register A */
#define VELOCITY_CFGA 0x78
#define VELOCITY_CFGA_PACPI (1 << 0)
/** Power Management Sticky Register */
#define VELOCITY_STICKY 0x83
#define VELOCITY_STICKY_DS0 (1 << 0)
#define VELOCITY_STICKY_DS1 (1 << 1)
#define VELOCITY_EEWRDAT 0x8C /* EEPROM embedded write */
#define VELOCITY_EECSUM 0x92 /* EEPROM checksum */
#define VELOCITY_EECSR 0x93 /* EEPROM control/status */
#define VELOCITY_EECSR_RELOAD (1 << 5)
#define VELOCITY_EERDDAT 0x94 /* EEPROM embedded read */
#define VELOCITY_EEADDR 0x96 /* EEPROM address */
#define VELOCITY_EECMD 0x97 /* EEPROM embedded command */
/** A Velocity network card */
struct velocity_nic {
/** Registers */
void *regs;
/** MII interface */
struct mii_interface mii;
/** Netdev */
struct net_device *netdev;
/** Receive descriptor ring */
struct velocity_rx_descriptor *rx_ring;
/** Receive I/O buffers */
struct io_buffer *rx_buffs[VELOCITY_RXDESC_NUM];
/** Receive producer index */
unsigned int rx_prod;
/** Receive consumer index */
unsigned int rx_cons;
/** Receive commit number
*
* Used to fullfill the hardware requirement of returning receive buffers
* to the hardware only in blocks of 4.
*/
unsigned int rx_commit;
/** Transmit descriptor ring */
struct velocity_tx_descriptor *tx_ring;
/** Transmit producer index */
unsigned int tx_prod;
/** Transmit consumer index */
unsigned int tx_cons;
};
#endif /* _VELOCITY_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -44,28 +44,6 @@ static struct option_descriptor config_opts[] = {};
static struct command_descriptor config_cmd =
COMMAND_DESC ( struct config_options, config_opts, 0, 1, "[<scope>]" );
/**
* Parse settings scope name
*
* @v text Text
* @ret value Integer value
* @ret rc Return status code
*/
static int parse_settings ( const char *text, struct settings **value ) {
/* Sanity check */
assert ( text != NULL );
/* Parse scope name */
*value = find_settings ( text );
if ( ! *value ) {
printf ( "\"%s\": no such scope\n", text );
return -EINVAL;
}
return 0;
}
/**
* "config" command
*

View File

@ -43,7 +43,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
* @ret port Fibre Channel port
* @ret rc Return status code
*/
static int parse_fc_port ( const char *text, struct fc_port **port ) {
static int parse_fc_port ( char *text, struct fc_port **port ) {
/* Sanity check */
assert ( text != NULL );
@ -65,7 +65,7 @@ static int parse_fc_port ( const char *text, struct fc_port **port ) {
* @ret port_id Fibre Channel port ID
* @ret rc Return status code
*/
static int parse_fc_port_id ( const char *text, struct fc_port_id *port_id ) {
static int parse_fc_port_id ( char *text, struct fc_port_id *port_id ) {
int rc;
/* Sanity check */
@ -87,8 +87,7 @@ static int parse_fc_port_id ( const char *text, struct fc_port_id *port_id ) {
* @ret handler Fibre Channel ELS handler
* @ret rc Return status code
*/
static int parse_fc_els_handler ( const char *text,
struct fc_els_handler **handler ) {
static int parse_fc_els_handler ( char *text, struct fc_els_handler **handler ){
for_each_table_entry ( (*handler), FC_ELS_HANDLERS ) {
if ( strcasecmp ( (*handler)->name, text ) == 0 )

View File

@ -53,6 +53,7 @@ int ifcommon_exec ( int argc, char **argv,
int stop_on_first_success ) {
struct ifcommon_options opts;
struct net_device *netdev;
int i;
int rc;
/* Parse options */
@ -61,11 +62,9 @@ int ifcommon_exec ( int argc, char **argv,
if ( optind != argc ) {
/* Treat arguments as a list of interfaces to try */
while ( optind != argc ) {
if ( ( rc = parse_netdev ( argv[optind++],
&netdev ) ) != 0 ) {
for ( i = optind ; i < argc ; i++ ) {
if ( ( rc = parse_netdev ( argv[i], &netdev ) ) != 0 )
continue;
}
if ( ( ( rc = payload ( netdev ) ) == 0 ) &&
stop_on_first_success ) {
return 0;

View File

@ -39,7 +39,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
/** "img{single}" options */
struct imgsingle_options {
/** Image name */
const char *name;
char *name;
/** Replace image */
int replace;
/** Free image after execution */

View File

@ -84,7 +84,7 @@ static int imgtrust_exec ( int argc, char **argv ) {
/** "imgverify" options */
struct imgverify_options {
/** Required signer common name */
const char *signer;
char *signer;
/** Keep signature after verification */
int keep;
};

View File

@ -41,7 +41,7 @@ FEATURE ( FEATURE_MISC, "Menu", DHCP_EB_FEATURE_MENU, 1 );
/** "menu" options */
struct menu_options {
/** Name */
const char *name;
char *name;
/** Delete */
int delete;
};
@ -107,7 +107,7 @@ static int menu_exec ( int argc, char **argv ) {
/** "item" options */
struct item_options {
/** Menu name */
const char *menu;
char *menu;
/** Shortcut key */
unsigned int key;
/** Use as default */
@ -192,11 +192,11 @@ static int item_exec ( int argc, char **argv ) {
/** "choose" options */
struct choose_options {
/** Menu name */
const char *menu;
char *menu;
/** Timeout */
unsigned int timeout;
/** Default selection */
const char *select;
char *select;
/** Keep menu */
int keep;
};
@ -228,9 +228,9 @@ static struct command_descriptor choose_cmd =
*/
static int choose_exec ( int argc, char **argv ) {
struct choose_options opts;
struct named_setting setting;
struct menu *menu;
struct menu_item *item;
const char *setting;
int rc;
/* Parse options */
@ -238,7 +238,9 @@ static int choose_exec ( int argc, char **argv ) {
goto err_parse_options;
/* Parse setting name */
setting = argv[optind];
if ( ( rc = parse_autovivified_setting ( argv[optind],
&setting ) ) != 0 )
goto err_parse_setting;
/* Identify menu */
if ( ( rc = parse_menu ( opts.menu, &menu ) ) != 0 )
@ -248,11 +250,15 @@ static int choose_exec ( int argc, char **argv ) {
if ( ( rc = show_menu ( menu, opts.timeout, opts.select, &item ) ) != 0)
goto err_show_menu;
/* Apply default type if necessary */
if ( ! setting.setting.type )
setting.setting.type = &setting_type_string;
/* Store setting */
if ( ( rc = storef_named_setting ( setting, &setting_type_string,
item->label ) ) != 0 ) {
if ( ( rc = storef_setting ( setting.settings, &setting.setting,
item->label ) ) != 0 ) {
printf ( "Could not store \"%s\": %s\n",
setting, strerror ( rc ) );
setting.setting.name, strerror ( rc ) );
goto err_store;
}
@ -265,6 +271,7 @@ static int choose_exec ( int argc, char **argv ) {
if ( ! opts.keep )
destroy_menu ( menu );
err_parse_menu:
err_parse_setting:
err_parse_options:
return rc;
}

View File

@ -23,6 +23,7 @@
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <byteswap.h>
#include <ipxe/settings.h>
#include <ipxe/command.h>
#include <ipxe/parseopt.h>
@ -55,31 +56,44 @@ static struct command_descriptor show_cmd =
*/
static int show_exec ( int argc, char **argv ) {
struct show_options opts;
const char *name;
struct named_setting setting;
struct settings *origin;
char name_buf[32];
char value_buf[256];
char *value;
int rc;
/* Parse options */
if ( ( rc = parse_options ( argc, argv, &show_cmd, &opts ) ) != 0 )
return rc;
goto err_parse_options;
/* Parse setting name */
name = argv[optind];
if ( ( rc = parse_existing_setting ( argv[optind], &setting ) ) != 0 )
goto err_parse_setting;
/* Fetch setting */
if ( ( rc = fetchf_named_setting ( name, name_buf, sizeof ( name_buf ),
value_buf,
sizeof ( value_buf ) ) ) < 0 ) {
/* Fetch formatted setting value */
if ( ( rc = fetchf_setting_copy ( setting.settings, &setting.setting,
&value ) ) < 0 ) {
printf ( "Could not find \"%s\": %s\n",
name, strerror ( rc ) );
return rc;
setting.setting.name, strerror ( rc ) );
goto err_fetchf;
}
/* Print setting value */
printf ( "%s = %s\n", name_buf, value_buf );
/* Fetch origin and format fully-qualified name */
origin = fetch_setting_origin ( setting.settings, &setting.setting );
assert ( origin != NULL );
setting_name ( origin, &setting.setting, name_buf, sizeof ( name_buf ));
return 0;
/* Print setting value */
printf ( "%s = %s\n", name_buf, value );
/* Success */
rc = 0;
free ( value );
err_fetchf:
err_parse_setting:
err_parse_options:
return rc;
}
/** "set", "clear", and "read" options */
@ -109,10 +123,10 @@ static struct command_descriptor clear_read_cmd =
*/
static int set_core_exec ( int argc, char **argv,
struct command_descriptor *cmd,
int ( * get_value ) ( const char *name,
int ( * get_value ) ( struct named_setting *setting,
char **args, char **value ) ) {
struct set_core_options opts;
const char *name;
struct named_setting setting;
char *value;
int rc;
@ -121,26 +135,30 @@ static int set_core_exec ( int argc, char **argv,
goto err_parse_options;
/* Parse setting name */
name = argv[optind];
if ( ( rc = parse_autovivified_setting ( argv[optind],
&setting ) ) != 0 )
goto err_parse_setting;
/* Parse setting value */
if ( ( rc = get_value ( name, &argv[ optind + 1 ], &value ) ) != 0 )
if ( ( rc = get_value ( &setting, &argv[ optind + 1 ], &value ) ) != 0 )
goto err_get_value;
/* Determine total length of command line */
if ( ( rc = storef_named_setting ( name, &setting_type_string,
value ) ) != 0 ) {
printf ( "Could not %s \"%s\": %s\n",
argv[0], name, strerror ( rc ) );
/* Apply default type if necessary */
if ( ! setting.setting.type )
setting.setting.type = &setting_type_string;
/* Store setting */
if ( ( rc = storef_setting ( setting.settings, &setting.setting,
value ) ) != 0 ) {
printf ( "Could not store \"%s\": %s\n",
setting.setting.name, strerror ( rc ) );
goto err_store;
}
free ( value );
return 0;
err_store:
free ( value );
err_get_value:
err_parse_setting:
err_parse_options:
return rc;
}
@ -148,12 +166,13 @@ static int set_core_exec ( int argc, char **argv,
/**
* Get setting value for "set" command
*
* @v name Setting name
* @v setting Named setting
* @v args Remaining arguments
* @ret value Setting value
* @ret rc Return status code
*/
static int set_value ( const char *name __unused, char **args, char **value ) {
static int set_value ( struct named_setting *setting __unused,
char **args, char **value ) {
*value = concat_args ( args );
if ( ! *value )
@ -176,13 +195,13 @@ static int set_exec ( int argc, char **argv ) {
/**
* Get setting value for "clear" command
*
* @v name Setting name
* @v setting Named setting
* @v args Remaining arguments
* @ret value Setting value
* @ret rc Return status code
*/
static int clear_value ( const char *name __unused, char **args __unused,
char **value ) {
static int clear_value ( struct named_setting *setting __unused,
char **args __unused, char **value ) {
*value = NULL;
return 0;
@ -202,29 +221,27 @@ static int clear_exec ( int argc, char **argv ) {
/**
* Get setting value for "read" command
*
* @v name Setting name
* @v setting Named setting
* @v args Remaining arguments
* @ret value Setting value
* @ret rc Return status code
*/
static int read_value ( const char *name, char **args __unused, char **value ) {
static int read_value ( struct named_setting *setting, char **args __unused,
char **value ) {
char *existing;
int rc;
/* Read existing value */
if ( ( rc = fetchf_named_setting_copy ( name, &existing ) ) < 0 )
goto err_existing;
/* Read existing value, treating errors as equivalent to an
* empty initial setting.
*/
fetchf_setting_copy ( setting->settings, &setting->setting, &existing );
/* Read new value */
if ( ( rc = readline_history ( NULL, existing, NULL, value ) ) != 0 )
goto err_new;
goto err_readline;
/* Success */
rc = 0;
err_new:
err_readline:
free ( existing );
err_existing:
return rc;
}
@ -239,6 +256,73 @@ static int read_exec ( int argc, char **argv ) {
return set_core_exec ( argc, argv, &clear_read_cmd, read_value );
}
/** "inc" options */
struct inc_options {};
/** "inc" option list */
static struct option_descriptor inc_opts[] = {};
/** "inc" command descriptor */
static struct command_descriptor inc_cmd =
COMMAND_DESC ( struct inc_options, inc_opts, 1, 2,
"<setting> [<increment>]" );
/**
* "inc" command
*
* @v argc Argument count
* @v argv Argument list
* @ret rc Return status code
*/
static int inc_exec ( int argc, char **argv ) {
struct inc_options opts;
struct named_setting setting;
unsigned int increment = 1;
unsigned long value;
int rc;
/* Parse options */
if ( ( rc = parse_options ( argc, argv, &inc_cmd, &opts ) ) != 0 )
goto err_parse_options;
/* Parse setting name */
if ( ( rc = parse_existing_setting ( argv[optind], &setting ) ) != 0 )
goto err_parse_setting;
/* Parse increment (if present) */
if ( ( ( optind + 1 ) < argc ) &&
( ( rc = parse_integer ( argv[ optind + 1 ], &increment ) ) != 0))
goto err_parse_increment;
/* Fetch existing setting value, if any, allowing for the fact
* that numeric settings are big-endian and variable-length.
*/
if ( ( rc = fetchn_setting ( setting.settings, &setting.setting,
&value ) ) != 0 ) {
/* Treat as a non-existent :int32 setting with a zero value */
value = 0;
if ( ! setting.setting.type )
setting.setting.type = &setting_type_int32;
}
/* Increment value */
value += increment;
/* Store updated setting value */
if ( ( rc = storen_setting ( setting.settings, &setting.setting,
value ) ) != 0 ) {
printf ( "Could not store \"%s\": %s\n",
setting.setting.name, strerror ( rc ) );
goto err_store;
}
err_store:
err_parse_increment:
err_parse_setting:
err_parse_options:
return rc;
}
/** Non-volatile option commands */
struct command nvo_commands[] __command = {
{
@ -257,4 +341,8 @@ struct command nvo_commands[] __command = {
.name = "read",
.exec = read_exec,
},
{
.name = "inc",
.exec = inc_exec,
},
};

114
src/hci/commands/pci_cmd.c Normal file
View File

@ -0,0 +1,114 @@
/*
* Copyright (C) 2013 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <stdio.h>
#include <getopt.h>
#include <ipxe/pci.h>
#include <ipxe/command.h>
#include <ipxe/parseopt.h>
FILE_LICENCE ( GPL2_OR_LATER );
/** @file
*
* PCI commands
*
*/
/** "pciscan" options */
struct pciscan_options {};
/** "pciscan" option list */
static struct option_descriptor pciscan_opts[] = {};
/** "pciscan" command descriptor */
static struct command_descriptor pciscan_cmd =
COMMAND_DESC ( struct pciscan_options, pciscan_opts, 1, 1,
"<setting>" );
/**
* "pciscan" command
*
* @v argc Argument count
* @v argv Argument list
* @ret rc Return status code
*/
static int pciscan_exec ( int argc, char **argv ) {
struct pciscan_options opts;
struct named_setting setting;
struct pci_device pci;
unsigned long prev;
int next;
int len;
int rc;
/* Parse options */
if ( ( rc = parse_options ( argc, argv, &pciscan_cmd, &opts ) ) != 0 )
goto err_parse_options;
/* Parse setting name */
if ( ( rc = parse_autovivified_setting ( argv[optind],
&setting ) ) != 0 )
goto err_parse_setting;
/* Determine starting bus:dev.fn address */
if ( ( len = fetch_uint_setting ( setting.settings, &setting.setting,
&prev ) ) < 0 ) {
/* Setting not yet defined: start searching from 00:00.0 */
prev = 0;
} else {
/* Setting is defined: start searching from next location */
prev++;
}
/* Find next existent PCI device */
if ( ( next = pci_find_next ( &pci, prev ) ) < 0 ) {
rc = next;
goto err_find_next;
}
/* Apply default type if necessary. Use ":uint16" rather than
* ":busdevfn" to allow for easy inclusion within a
* "${pci/${location}.x.y}" constructed setting.
*/
if ( ! setting.setting.type )
setting.setting.type = &setting_type_uint16;
/* Store setting */
if ( ( rc = storen_setting ( setting.settings, &setting.setting,
next ) ) != 0 ) {
printf ( "Could not store \"%s\": %s\n",
setting.setting.name, strerror ( rc ) );
goto err_store;
}
err_store:
err_find_next:
err_parse_setting:
err_parse_options:
return rc;
}
/** PCI commands */
struct command pci_commands[] __command = {
{
.name = "pciscan",
.exec = pciscan_exec,
},
};

View File

@ -0,0 +1,72 @@
/*
* Copyright (C) 2013 Marin Hannache <ipxe@mareo.fr>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <ipxe/command.h>
#include <ipxe/parseopt.h>
#include <ipxe/reboot.h>
FILE_LICENCE ( GPL2_OR_LATER );
/** @file
*
* Power off command
*
*/
/** "poweroff" options */
struct poweroff_options {};
/** "poweroff" option list */
static struct option_descriptor poweroff_opts[] = {};
/** "poweroff" command descriptor */
static struct command_descriptor poweroff_cmd =
COMMAND_DESC ( struct poweroff_options, poweroff_opts, 0, 0, "" );
/**
* The "poweroff" command
*
* @v argc Argument count
* @v argv Argument list
* @ret rc Return status code
*/
static int poweroff_exec ( int argc, char **argv ) {
struct poweroff_options opts;
int rc;
/* Parse options */
if ( ( rc = parse_options ( argc, argv, &poweroff_cmd, &opts ) ) != 0 )
return rc;
/* Power off system */
rc = poweroff();
if ( rc != 0 )
printf ( "Could not power off: %s\n", strerror ( rc ) );
return rc;
}
/** "poweroff" command */
struct command poweroff_command __command = {
.name = "poweroff",
.exec = poweroff_exec,
};

View File

@ -441,7 +441,7 @@ static void reveal_setting_row ( struct setting_widget *widget,
static void init_widget ( struct setting_widget *widget,
struct settings *settings ) {
widget->settings = settings;
widget->settings = settings_target ( settings );
widget->num_rows = select_setting_row ( widget, 0 );
widget->first_visible = SETTINGS_LIST_ROWS;
draw_title_row ( widget );
@ -508,13 +508,25 @@ static int main_loop ( struct settings *settings ) {
key = getkey ( 0 );
move = 0;
switch ( key ) {
case KEY_DOWN:
if ( widget.current < ( widget.num_rows - 1 ) )
move = +1;
break;
case KEY_UP:
if ( widget.current > 0 )
move = -1;
move = -1;
break;
case KEY_DOWN:
move = +1;
break;
case KEY_PPAGE:
move = ( widget.first_visible -
widget.current - 1 );
break;
case KEY_NPAGE:
move = ( widget.first_visible - widget.current
+ SETTINGS_LIST_ROWS );
break;
case KEY_HOME:
move = -widget.num_rows;
break;
case KEY_END:
move = +widget.num_rows;
break;
case CTRL_D:
if ( ! widget.row.setting )
@ -545,10 +557,16 @@ static int main_loop ( struct settings *settings ) {
}
if ( move ) {
next = ( widget.current + move );
draw_setting_row ( &widget );
redraw = 1;
reveal_setting_row ( &widget, next );
select_setting_row ( &widget, next );
if ( ( int ) next < 0 )
next = 0;
if ( next >= widget.num_rows )
next = ( widget.num_rows - 1 );
if ( next != widget.current ) {
draw_setting_row ( &widget );
redraw = 1;
reveal_setting_row ( &widget, next );
select_setting_row ( &widget, next );
}
}
}
}

View File

@ -55,44 +55,96 @@ static size_t script_offset;
* @ret rc Return status code
*/
static int process_script ( struct image *image,
int ( * process_line ) ( const char *line ),
int ( * process_line ) ( struct image *image,
size_t offset,
const char *label,
const char *command ),
int ( * terminate ) ( int rc ) ) {
size_t len = 0;
char *line = NULL;
size_t line_offset;
char *label;
char *command;
off_t eol;
size_t len;
char *line;
size_t frag_len;
char *tmp;
int rc;
/* Initialise script and line offsets */
script_offset = 0;
line_offset = 0;
do {
/* Find length of next line, excluding any terminating '\n' */
eol = memchr_user ( image->data, script_offset, '\n',
( image->len - script_offset ) );
if ( eol < 0 )
eol = image->len;
len = ( eol - script_offset );
frag_len = ( eol - script_offset );
/* Allocate buffer for line */
line = zalloc ( len + 1 /* NUL */ );
if ( ! line )
return -ENOMEM;
tmp = realloc ( line, ( len + frag_len + 1 /* NUL */ ) );
if ( ! tmp ) {
rc = -ENOMEM;
goto err_alloc;
}
line = tmp;
/* Copy line */
copy_from_user ( line, image->data, script_offset, len );
DBG ( "$ %s\n", line );
copy_from_user ( ( line + len ), image->data, script_offset,
frag_len );
len += frag_len;
/* Move to next line */
script_offset += ( len + 1 );
/* Move to next line in script */
script_offset += ( frag_len + 1 );
/* Process and free line */
rc = process_line ( line );
free ( line );
/* Strip trailing CR, if present */
if ( len && ( line[ len - 1 ] == '\r' ) )
len--;
/* Handle backslash continuations */
if ( len && ( line[ len - 1 ] == '\\' ) ) {
len--;
rc = -EINVAL;
continue;
}
/* Terminate line */
line[len] = '\0';
/* Split line into (optional) label and command */
command = line;
while ( isspace ( *command ) )
command++;
if ( *command == ':' ) {
label = ++command;
while ( *command && ! isspace ( *command ) )
command++;
if ( *command )
*(command++) = '\0';
} else {
label = NULL;
}
/* Process line */
rc = process_line ( image, line_offset, label, command );
if ( terminate ( rc ) )
return rc;
goto err_process;
/* Free line */
free ( line );
line = NULL;
len = 0;
/* Update line offset */
line_offset = script_offset;
} while ( script_offset < image->len );
err_process:
err_alloc:
free ( line );
return rc;
}
@ -111,18 +163,21 @@ static int terminate_on_exit_or_failure ( int rc ) {
/**
* Execute script line
*
* @v line Line of script
* @v image Script
* @v offset Offset within script
* @v label Label, or NULL
* @v command Command
* @ret rc Return status code
*/
static int script_exec_line ( const char *line ) {
static int script_exec_line ( struct image *image, size_t offset,
const char *label __unused,
const char *command ) {
int rc;
/* Skip label lines */
if ( line[0] == ':' )
return 0;
DBGC ( image, "[%04zx] $ %s\n", offset, command );
/* Execute command */
if ( ( rc = system ( line ) ) != 0 )
if ( ( rc = system ( command ) ) != 0 )
return rc;
return 0;
@ -176,7 +231,7 @@ static int script_probe ( struct image *image ) {
/* Sanity check */
if ( image->len < sizeof ( test ) ) {
DBG ( "Too short to be a script\n" );
DBGC ( image, "Too short to be a script\n" );
return -ENOEXEC;
}
@ -185,7 +240,7 @@ static int script_probe ( struct image *image ) {
if ( ! ( ( ( memcmp ( test, ipxe_magic, sizeof ( test ) - 1 ) == 0 ) ||
( memcmp ( test, gpxe_magic, sizeof ( test ) - 1 ) == 0 )) &&
isspace ( test[ sizeof ( test ) - 1 ] ) ) ) {
DBG ( "Invalid magic signature\n" );
DBGC ( image, "Invalid magic signature\n" );
return -ENOEXEC;
}
@ -219,20 +274,26 @@ static const char *goto_label;
/**
* Check for presence of label
*
* @v line Script line
* @v image Script
* @v offset Offset within script
* @v label Label
* @v command Command
* @ret rc Return status code
*/
static int goto_find_label ( const char *line ) {
size_t len = strlen ( goto_label );
static int goto_find_label ( struct image *image, size_t offset,
const char *label, const char *command __unused ) {
if ( line[0] != ':' )
/* Check label exists */
if ( ! label )
return -ENOENT;
if ( strncmp ( goto_label, &line[1], len ) != 0 )
/* Check label matches */
if ( strcmp ( goto_label, label ) != 0 )
return -ENOENT;
if ( line[ 1 + len ] && ! isspace ( line[ 1 + len ] ) )
return -ENOENT;
/* Update script offset */
script_offset = offset;
DBGC ( image, "[%04zx] Gone to :%s\n", offset, label );
return 0;
}
@ -278,6 +339,8 @@ static int goto_exec ( int argc, char **argv ) {
if ( ( rc = process_script ( current_image, goto_find_label,
terminate_on_label_found ) ) != 0 ) {
script_offset = saved_offset;
DBGC ( current_image, "[%04zx] No such label :%s\n",
script_offset, goto_label );
return rc;
}

View File

@ -1,6 +1,8 @@
#ifndef ETHERBOOT_BIG_BSWAP_H
#define ETHERBOOT_BIG_BSWAP_H
#define htonll(x) (x)
#define ntohll(x) (x)
#define ntohl(x) (x)
#define htonl(x) (x)
#define ntohs(x) (x)

View File

@ -60,12 +60,15 @@
/** Provide a symbol within this object file */
#ifdef ASSEMBLY
#define PROVIDE_SYMBOL( _sym ) \
.section ".provided", "a", @nobits ; \
.hidden _sym ; \
.globl _sym ; \
.comm _sym, 0
_sym: ; \
.previous
#else /* ASSEMBLY */
#define PROVIDE_SYMBOL( _sym ) \
extern char _sym[]; \
char _sym[0]
char _sym[0] \
__attribute__ (( section ( ".provided" ) ))
#endif /* ASSEMBLY */
/** Require a symbol within this object file
@ -652,7 +655,7 @@ int __debug_disable;
* be in the public domain.
*/
#define FILE_LICENCE_PUBLIC_DOMAIN \
PROVIDE_SYMBOL ( __licence_public_domain )
PROVIDE_SYMBOL ( PREFIX_OBJECT ( __licence__public_domain__ ) )
/** Declare a file as being under version 2 (or later) of the GNU GPL
*
@ -661,7 +664,7 @@ int __debug_disable;
* (at your option) any later version".
*/
#define FILE_LICENCE_GPL2_OR_LATER \
PROVIDE_SYMBOL ( __licence_gpl2_or_later )
PROVIDE_SYMBOL ( PREFIX_OBJECT ( __licence__gpl2_or_later__ ) )
/** Declare a file as being under version 2 of the GNU GPL
*
@ -670,7 +673,7 @@ int __debug_disable;
* "or, at your option, any later version" clause.
*/
#define FILE_LICENCE_GPL2_ONLY \
PROVIDE_SYMBOL ( __licence_gpl2_only )
PROVIDE_SYMBOL ( PREFIX_OBJECT ( __licence__gpl2_only__ ) )
/** Declare a file as being under any version of the GNU GPL
*
@ -682,7 +685,7 @@ int __debug_disable;
* version ever published by the Free Software Foundation".
*/
#define FILE_LICENCE_GPL_ANY \
PROVIDE_SYMBOL ( __licence_gpl_any )
PROVIDE_SYMBOL ( PREFIX_OBJECT ( __licence__gpl_any__ ) )
/** Declare a file as being under the three-clause BSD licence
*
@ -707,7 +710,7 @@ int __debug_disable;
* functionally equivalent to the standard three-clause BSD licence.
*/
#define FILE_LICENCE_BSD3 \
PROVIDE_SYMBOL ( __licence_bsd3 )
PROVIDE_SYMBOL ( PREFIX_OBJECT ( __licence__bsd3__ ) )
/** Declare a file as being under the two-clause BSD licence
*
@ -728,7 +731,7 @@ int __debug_disable;
* functionally equivalent to the standard two-clause BSD licence.
*/
#define FILE_LICENCE_BSD2 \
PROVIDE_SYMBOL ( __licence_bsd2 )
PROVIDE_SYMBOL ( PREFIX_OBJECT ( __licence__bsd2__ ) )
/** Declare a file as being under the one-clause MIT-style licence
*
@ -738,7 +741,7 @@ int __debug_disable;
* permission notice appear in all copies.
*/
#define FILE_LICENCE_MIT \
PROVIDE_SYMBOL ( __licence_mit )
PROVIDE_SYMBOL ( PREFIX_OBJECT ( __licence__mit__ ) )
/** Declare a particular licence as applying to a file */
#define FILE_LICENCE( _licence ) FILE_LICENCE_ ## _licence

View File

@ -33,6 +33,8 @@ static inline size_t base16_decoded_max_len ( const char *encoded ) {
}
extern void base16_encode ( const uint8_t *raw, size_t len, char *encoded );
extern int hex_decode ( const char *string, char separator, void *data,
size_t len );
extern int base16_decode ( const char *encoded, uint8_t *raw );
#endif /* _IPXE_BASE16_H */

View File

@ -450,6 +450,18 @@ struct dhcp_netdev_desc {
*/
#define DHCP_EB_REVERSE_PASSWORD DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xc1 )
/** User ID
*
* This will be used as the user id for AUTH_SYS based authentication in NFS.
*/
#define DHCP_EB_UID DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xc2 )
/** Group ID
*
* This will be used as the group id for AUTH_SYS based authentication in NFS.
*/
#define DHCP_EB_GID DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xc3 )
/** iPXE version number */
#define DHCP_EB_VERSION DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xeb )

View File

@ -1,6 +1,8 @@
#ifndef _IPXE_EFI_PROCESSOR_BIND_H
#define _IPXE_EFI_PROCESSOR_BIND_H
FILE_LICENCE ( GPL2_OR_LATER );
/*
* EFI header files rely on having the CPU architecture directory
* present in the search path in order to pick up ProcessorBind.h. We

View File

@ -21,6 +21,8 @@
* trailing whitespace.
*/
FILE_LICENCE ( GPL2_OR_LATER );
/* EFI headers rudely redefine NULL */
#undef NULL

View File

@ -63,6 +63,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define ERRFILE_test ( ERRFILE_CORE | 0x00170000 )
#define ERRFILE_xferbuf ( ERRFILE_CORE | 0x00180000 )
#define ERRFILE_pending ( ERRFILE_CORE | 0x00190000 )
#define ERRFILE_null_reboot ( ERRFILE_CORE | 0x001a0000 )
#define ERRFILE_eisa ( ERRFILE_DRIVER | 0x00000000 )
#define ERRFILE_isa ( ERRFILE_DRIVER | 0x00010000 )
@ -113,8 +114,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define ERRFILE_sundance ( ERRFILE_DRIVER | 0x00410000 )
#define ERRFILE_tlan ( ERRFILE_DRIVER | 0x00420000 )
#define ERRFILE_tulip ( ERRFILE_DRIVER | 0x00430000 )
#define ERRFILE_via_rhine ( ERRFILE_DRIVER | 0x00440000 )
#define ERRFILE_via_velocity ( ERRFILE_DRIVER | 0x00450000 )
#define ERRFILE_rhine ( ERRFILE_DRIVER | 0x00440000 )
#define ERRFILE_velocity ( ERRFILE_DRIVER | 0x00450000 )
#define ERRFILE_w89c840 ( ERRFILE_DRIVER | 0x00460000 )
#define ERRFILE_ipoib ( ERRFILE_DRIVER | 0x00470000 )
#define ERRFILE_e1000_main ( ERRFILE_DRIVER | 0x00480000 )
@ -207,6 +208,12 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define ERRFILE_fcoe ( ERRFILE_NET | 0x002e0000 )
#define ERRFILE_fcns ( ERRFILE_NET | 0x002f0000 )
#define ERRFILE_vlan ( ERRFILE_NET | 0x00300000 )
#define ERRFILE_oncrpc ( ERRFILE_NET | 0x00310000 )
#define ERRFILE_portmap ( ERRFILE_NET | 0x00320000 )
#define ERRFILE_nfs ( ERRFILE_NET | 0x00330000 )
#define ERRFILE_nfs_open ( ERRFILE_NET | 0x00340000 )
#define ERRFILE_mount ( ERRFILE_NET | 0x00350000 )
#define ERRFILE_oncrpc_iob ( ERRFILE_NET | 0x00360000 )
#define ERRFILE_image ( ERRFILE_IMAGE | 0x00000000 )
#define ERRFILE_elf ( ERRFILE_IMAGE | 0x00010000 )
@ -275,6 +282,10 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define ERRFILE_efi_init ( ERRFILE_OTHER | 0x00390000 )
#define ERRFILE_efi_timer ( ERRFILE_OTHER | 0x003a0000 )
#define ERRFILE_efi_umalloc ( ERRFILE_OTHER | 0x003b0000 )
#define ERRFILE_linux_pci ( ERRFILE_OTHER | 0x003c0000 )
#define ERRFILE_pci_settings ( ERRFILE_OTHER | 0x003d0000 )
#define ERRFILE_efi_reboot ( ERRFILE_OTHER | 0x003e0000 )
#define ERRFILE_memmap_settings ( ERRFILE_OTHER | 0x003f0000 )
/** @} */

View File

@ -54,6 +54,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define DHCP_EB_FEATURE_VLAN 0x26 /**< VLAN support */
#define DHCP_EB_FEATURE_MENU 0x27 /**< Menu support */
#define DHCP_EB_FEATURE_SDI 0x28 /**< SDI image support */
#define DHCP_EB_FEATURE_NFS 0x29 /**< NFS protocol */
/** @} */

View File

@ -59,19 +59,22 @@ struct sockaddr_in {
* Always set to @c AF_INET for IPv4 addresses
*/
sa_family_t sin_family;
/** Flags (part of struct @c sockaddr_tcpip) */
uint16_t sin_flags;
/** TCP/IP port (part of struct @c sockaddr_tcpip) */
uint16_t sin_port;
/** IPv4 address */
struct in_addr sin_addr;
/** Padding
*
* This ensures that a struct @c sockaddr_tcpip is large
* enough to hold a socket address for any TCP/IP address
* family.
* This ensures that a struct @c sockaddr_in is large enough
* to hold a socket address for any TCP/IP address family.
*/
char pad[ sizeof ( struct sockaddr ) - sizeof ( sa_family_t )
- sizeof ( uint16_t )
- sizeof ( struct in_addr ) ];
char pad[ sizeof ( struct sockaddr ) -
( sizeof ( sa_family_t ) /* sin_family */ +
sizeof ( uint16_t ) /* sin_flags */ +
sizeof ( uint16_t ) /* sin_port */ +
sizeof ( struct in_addr ) /* sin_addr */ ) ];
} __attribute__ (( may_alias ));
/**
@ -82,12 +85,27 @@ struct sockaddr_in6 {
*
* Always set to @c AF_INET6 for IPv6 addresses
*/
sa_family_t sin_family;
sa_family_t sin6_family;
/** Flags (part of struct @c sockaddr_tcpip) */
uint16_t sin6_flags;
/** TCP/IP port (part of struct @c sockaddr_tcpip) */
uint16_t sin_port;
uint16_t sin6_port;
uint32_t sin6_flowinfo; /* Flow number */
struct in6_addr sin6_addr; /* 128-bit destination address */
uint32_t sin6_scope_id; /* Scope ID */
/** Padding
*
* This ensures that a struct @c sockaddr_in6 is large
* enough to hold a socket address for any TCP/IP address
* family.
*/
char pad[ sizeof ( struct sockaddr ) -
( sizeof ( sa_family_t ) /* sin6_family */ +
sizeof ( uint16_t ) /* sin6_flags */ +
sizeof ( uint16_t ) /* sin6_port */ +
sizeof ( uint32_t ) /* sin6_flowinfo */ +
sizeof ( struct in6_addr ) /* sin6_addr */ +
sizeof ( uint32_t ) /* sin6_scope_id */ ) ];
} __attribute__ (( may_alias ));
extern int inet_aton ( const char *cp, struct in_addr *inp );

View File

@ -30,6 +30,14 @@ FILE_LICENCE(GPL2_OR_LATER);
#include <ipxe/device.h>
#include <ipxe/settings.h>
/**
* Convert a Linux error number to an iPXE status code
*
* @v errno Linux error number
* @ret rc iPXE status code (before negation)
*/
#define ELINUX( errno ) EPLATFORM ( EINFO_EPLATFORM, errno )
/** A linux device */
struct linux_device {
/** Generic device */

View File

@ -0,0 +1,130 @@
#ifndef _IPXE_LINUX_PCI_H
#define _IPXE_LINUX_PCI_H
/** @file
*
* iPXE PCI API for Linux
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
#ifdef PCIAPI_LINUX
#define PCIAPI_PREFIX_linux
#else
#define PCIAPI_PREFIX_linux __linux_
#endif
struct pci_device;
extern int linux_pci_read ( struct pci_device *pci, unsigned long where,
unsigned long *value, size_t len );
extern int linux_pci_write ( struct pci_device *pci, unsigned long where,
unsigned long value, size_t len );
/**
* Read byte from PCI configuration space
*
* @v pci PCI device
* @v where Location within PCI configuration space
* @v value Value read
* @ret rc Return status code
*/
static inline __always_inline int
PCIAPI_INLINE ( linux, pci_read_config_byte ) ( struct pci_device *pci,
unsigned int where,
uint8_t *value ) {
int rc;
unsigned long tmp;
rc = linux_pci_read ( pci, where, &tmp, sizeof ( *value ) );
*value = tmp;
return rc;
}
/**
* Read word from PCI configuration space
*
* @v pci PCI device
* @v where Location within PCI configuration space
* @v value Value read
* @ret rc Return status code
*/
static inline __always_inline int
PCIAPI_INLINE ( linux, pci_read_config_word ) ( struct pci_device *pci,
unsigned int where,
uint16_t *value ) {
int rc;
unsigned long tmp;
rc = linux_pci_read ( pci, where, &tmp, sizeof ( *value ) );
*value = tmp;
return rc;
}
/**
* Read dword from PCI configuration space
*
* @v pci PCI device
* @v where Location within PCI configuration space
* @v value Value read
* @ret rc Return status code
*/
static inline __always_inline int
PCIAPI_INLINE ( linux, pci_read_config_dword ) ( struct pci_device *pci,
unsigned int where,
uint32_t *value ) {
int rc;
unsigned long tmp;
rc = linux_pci_read ( pci, where, &tmp, sizeof ( *value ) );
*value = tmp;
return rc;
}
/**
* Write byte to PCI configuration space
*
* @v pci PCI device
* @v where Location within PCI configuration space
* @v value Value to be written
* @ret rc Return status code
*/
static inline __always_inline int
PCIAPI_INLINE ( linux, pci_write_config_byte ) ( struct pci_device *pci,
unsigned int where,
uint8_t value ) {
return linux_pci_write ( pci, where, value, sizeof ( value ) );
}
/**
* Write word to PCI configuration space
*
* @v pci PCI device
* @v where Location within PCI configuration space
* @v value Value to be written
* @ret rc Return status code
*/
static inline __always_inline int
PCIAPI_INLINE ( linux, pci_write_config_word ) ( struct pci_device *pci,
unsigned int where,
uint16_t value ) {
return linux_pci_write ( pci, where, value, sizeof ( value ) );
}
/**
* Write dword to PCI configuration space
*
* @v pci PCI device
* @v where Location within PCI configuration space
* @v value Value to be written
* @ret rc Return status code
*/
static inline __always_inline int
PCIAPI_INLINE ( linux, pci_write_config_dword ) ( struct pci_device *pci,
unsigned int where,
uint32_t value ) {
return linux_pci_write ( pci, where, value, sizeof ( value ) );
}
#endif /* _IPXE_LINUX_PCI_H */

76
src/include/ipxe/mount.h Normal file
View File

@ -0,0 +1,76 @@
#ifndef _IPXE_MOUNT_H
#define _IPXE_MOUNT_H
#include <ipxe/nfs.h>
/** @file
*
* NFS MOUNT protocol.
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
/** NFS MOUNT protocol number */
#define ONCRPC_MOUNT 100005
/** NFS MOUNT protocol version */
#define MOUNT_VERS 3
/** No error */
#define MNT3_OK 0
/** Not owner */
#define MNT3ERR_PERM 1
/** No such file or directory */
#define MNT3ERR_NOENT 2
/** I/O error */
#define MNT3ERR_IO 5
/** Permission denied */
#define MNT3ERR_ACCES 13
/** Not a directory */
#define MNT3ERR_NOTDIR 20
/** Invalid argument */
#define MNT3ERR_INVAL 22
/** Filename too long */
#define MNT3ERR_NAMETOOLONG 63
/** Operation not supported */
#define MNT3ERR_NOTSUPP 10004
/** A failure on the server */
#define MNT3ERR_SERVERFAULT 10006
/**
* A MOUNT MNT reply
*
*/
struct mount_mnt_reply {
/** Reply status */
uint32_t status;
/** Root file handle */
struct nfs_fh fh;
};
/**
* Prepare an ONC RPC session to be used as a MOUNT session
*
* @v session ONC RPC session
* @v credential ONC RPC credential
*
* The credential parameter must not be NULL, use 'oncrpc_auth_none' if you
* don't want a particular scheme to be used.
*/
static inline void mount_init_session ( struct oncrpc_session *session,
struct oncrpc_cred *credential ) {
oncrpc_init_session ( session, credential, &oncrpc_auth_none,
ONCRPC_MOUNT, MOUNT_VERS );
}
int mount_mnt ( struct interface *intf, struct oncrpc_session *session,
const char *mountpoint );
int mount_umnt ( struct interface *intf, struct oncrpc_session *session,
const char *mountpoint );
int mount_get_mnt_reply ( struct mount_mnt_reply *mnt_reply,
struct oncrpc_reply *reply );
#endif /* _IPXE_MOUNT_H */

157
src/include/ipxe/nfs.h Normal file
View File

@ -0,0 +1,157 @@
#ifndef _IPXE_NFS_H
#define _IPXE_NFS_H
#include <stdint.h>
#include <ipxe/oncrpc.h>
/** @file
*
* Network File System protocol.
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
/** NFS protocol number */
#define ONCRPC_NFS 100003
/** NFS protocol version */
#define NFS_VERS 3
/** No error*/
#define NFS3_OK 0
/** Not owner */
#define NFS3ERR_PERM 1
/** No such file or directory */
#define NFS3ERR_NOENT 2
/** I/O error */
#define NFS3ERR_IO 5
/** No such device or address */
#define NFS3ERR_NXIO 6
/** Permission denied */
#define NFS3ERR_ACCES 13
/** The file specified already exists */
#define NFS3ERR_EXIST 17
/** Attempt to do a cross-device hard link */
#define NFS3ERR_XDEV 18
/** No such device */
#define NFS3ERR_NODEV 19
/** Not a directory */
#define NFS3ERR_NOTDIR 20
/**Is a directory */
#define NFS3ERR_ISDIR 21
/** Invalid argument */
#define NFS3ERR_INVAL 22
/** Filename too long */
#define NFS3ERR_NAMETOOLONG 63
/** Invalid file handle */
#define NFS3ERR_STALE 70
/** Too many levels of remote in path */
#define NFS3ERR_REMOTE 71
/** Illegal NFS file handle */
#define NFS3ERR_BADHANDLE 10001
/** READDIR or READDIRPLUS cookie is stale */
#define NFS3ERR_BAD_COOKIE 10003
/** Operation not supported */
#define NFS3ERR_NOTSUPP 10004
/** Buffer or request is too small */
#define NFS3ERR_TOOSMALL 10005
/** An error occurred on the server which does not map to any of the legal NFS
* version 3 protocol error values */
#define NFS3ERR_SERVERFAULT 10006
/** The server initiated the request, but was not able to complete it in a
* timely fashion */
#define NFS3ERR_JUKEBOX 10008
enum nfs_attr_type {
NFS_ATTR_SYMLINK = 5,
};
/**
* A NFS file handle
*
*/
struct nfs_fh {
uint8_t fh[64];
size_t size;
};
/**
* A NFS LOOKUP reply
*
*/
struct nfs_lookup_reply {
/** Reply status */
uint32_t status;
/** Entity type */
enum nfs_attr_type ent_type;
/** File handle */
struct nfs_fh fh;
};
/**
* A NFS READLINK reply
*
*/
struct nfs_readlink_reply {
/** Reply status */
uint32_t status;
/** File path length */
uint32_t path_len;
/** File path */
char *path;
};
/**
* A NFS READ reply
*
*/
struct nfs_read_reply {
/** Reply status */
uint32_t status;
/** File size */
uint64_t filesize;
/** Bytes read */
uint32_t count;
/** End-of-File indicator */
uint32_t eof;
/** Data length */
uint32_t data_len;
/** Data read */
void *data;
};
size_t nfs_iob_get_fh ( struct io_buffer *io_buf, struct nfs_fh *fh );
size_t nfs_iob_add_fh ( struct io_buffer *io_buf, const struct nfs_fh *fh );
/**
* Prepare an ONC RPC session to be used as a NFS session
*
* @v session ONC RPC session
* @v credential ONC RPC credential
*
* The credential parameter must not be NULL, use 'oncrpc_auth_none' if you
* don't want a particular scheme to be used.
*/
static inline void nfs_init_session ( struct oncrpc_session *session,
struct oncrpc_cred *credential ) {
oncrpc_init_session ( session, credential, &oncrpc_auth_none,
ONCRPC_NFS, NFS_VERS );
}
int nfs_lookup ( struct interface *intf, struct oncrpc_session *session,
const struct nfs_fh *fh, const char *filename );
int nfs_readlink ( struct interface *intf, struct oncrpc_session *session,
const struct nfs_fh *fh );
int nfs_read ( struct interface *intf, struct oncrpc_session *session,
const struct nfs_fh *fh, uint64_t offset, uint32_t count );
int nfs_get_lookup_reply ( struct nfs_lookup_reply *lookup_reply,
struct oncrpc_reply *reply );
int nfs_get_readlink_reply ( struct nfs_readlink_reply *readlink_reply,
struct oncrpc_reply *reply );
int nfs_get_read_reply ( struct nfs_read_reply *read_reply,
struct oncrpc_reply *reply );
#endif /* _IPXE_NFS_H */

View File

@ -0,0 +1,12 @@
#ifndef _IPXE_NFS_OPEN_H
#define _IPXE_NFS_OPEN_H
/** @file
*
* Network File System protocol.
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
#endif /* _IPXE_NFS_OPEN_H */

128
src/include/ipxe/oncrpc.h Normal file
View File

@ -0,0 +1,128 @@
#ifndef _IPXE_ONCRPC_H
#define _IPXE_ONCRPC_H
#include <stdint.h>
#include <ipxe/interface.h>
#include <ipxe/iobuf.h>
/** @file
*
* SUN ONC RPC protocol.
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
/** ONC RCP Version */
#define ONCRPC_VERS 2
/** ONC RPC Null Authentication */
#define ONCRPC_AUTH_NONE 0
/** ONC RPC System Authentication (also called UNIX Authentication) */
#define ONCRPC_AUTH_SYS 1
/** Size of an ONC RPC header */
#define ONCRPC_HEADER_SIZE ( 11 * sizeof ( uint32_t ) )
#define ONCRPC_FIELD( type, value ) { oncrpc_ ## type, { .type = value } }
#define ONCRPC_SUBFIELD( type, args... ) \
{ oncrpc_ ## type, { .type = { args } } }
#define ONCRPC_FIELD_END { oncrpc_none, { } }
/** Enusure that size is a multiple of four */
#define oncrpc_align( size ) ( ( (size) + 3 ) & ~3 )
/**
* Calculate the length of a string, including padding bytes.
*
* @v str String
* @ret size Length of the padded string
*/
#define oncrpc_strlen( str ) ( oncrpc_align ( strlen ( str ) ) + \
sizeof ( uint32_t ) )
struct oncrpc_cred {
uint32_t flavor;
uint32_t length;
};
struct oncrpc_cred_sys {
struct oncrpc_cred credential;
uint32_t stamp;
char *hostname;
uint32_t uid;
uint32_t gid;
uint32_t aux_gid_len;
uint32_t aux_gid[16];
};
struct oncrpc_reply
{
struct oncrpc_cred *verifier;
uint32_t rpc_id;
uint32_t reply_state;
uint32_t accept_state;
uint32_t frame_size;
struct io_buffer *data;
};
struct oncrpc_session {
struct oncrpc_reply pending_reply;
struct oncrpc_cred *credential;
struct oncrpc_cred *verifier;
uint32_t rpc_id;
uint32_t prog_name;
uint32_t prog_vers;
};
enum oncrpc_field_type {
oncrpc_none = 0,
oncrpc_int32,
oncrpc_int64,
oncrpc_str,
oncrpc_array,
oncrpc_intarray,
oncrpc_cred,
};
union oncrpc_field_value {
struct {
size_t length;
const void *ptr;
} array;
struct {
size_t length;
const uint32_t *ptr;
} intarray;
int64_t int64;
int32_t int32;
const char *str;
const struct oncrpc_cred *cred;
};
struct oncrpc_field {
enum oncrpc_field_type type;
union oncrpc_field_value value;
};
extern struct oncrpc_cred oncrpc_auth_none;
int oncrpc_init_cred_sys ( struct oncrpc_cred_sys *auth_sys );
void oncrpc_init_session ( struct oncrpc_session *session,
struct oncrpc_cred *credential,
struct oncrpc_cred *verifier, uint32_t prog_name,
uint32_t prog_vers );
int oncrpc_call ( struct interface *intf, struct oncrpc_session *session,
uint32_t proc_name, const struct oncrpc_field fields[] );
size_t oncrpc_compute_size ( const struct oncrpc_field fields[] );
int oncrpc_get_reply ( struct oncrpc_session *session,
struct oncrpc_reply *reply, struct io_buffer *io_buf );
#endif /* _IPXE_ONCRPC_H */

View File

@ -0,0 +1,102 @@
#ifndef _IPXE_ONCRPC_IOB_H
#define _IPXE_ONCRPC_IOB_H
#include <stdint.h>
#include <string.h>
#include <ipxe/iobuf.h>
#include <ipxe/refcnt.h>
#include <ipxe/oncrpc.h>
/** @file
*
* SUN ONC RPC protocol.
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
/**
* Add a string to the end of an I/O buffer
*
* @v io_buf I/O buffer
* @v val String
* @ret size Size of the data written
*/
#define oncrpc_iob_add_string( buf, str ) \
( { \
const char * _str = (str); \
oncrpc_iob_add_array ( (buf), strlen ( _str ), _str ); \
} )
/**
* Get a 32 bits integer from the beginning of an I/O buffer
*
* @v buf I/O buffer
* @ret int Integer
*/
#define oncrpc_iob_get_int( buf ) \
( { \
uint32_t *_val; \
_val = (buf)->data; \
iob_pull ( (buf), sizeof ( uint32_t ) ); \
ntohl ( *_val ); \
} )
/**
* Get a 64 bits integer from the beginning of an I/O buffer
*
* @v buf I/O buffer
* @ret int Integer
*/
#define oncrpc_iob_get_int64( buf ) \
( { \
uint64_t *_val; \
_val = (buf)->data; \
iob_pull ( (buf), sizeof ( uint64_t ) ); \
ntohll ( *_val ); \
} )
size_t oncrpc_iob_add_fields ( struct io_buffer *io_buf,
const struct oncrpc_field fields[] );
size_t oncrpc_iob_add_array ( struct io_buffer *io_buf, size_t length,
const void *data );
size_t oncrpc_iob_add_intarray ( struct io_buffer *io_buf, size_t length,
const uint32_t *array );
size_t oncrpc_iob_add_cred ( struct io_buffer *io_buf,
const struct oncrpc_cred *cred );
size_t oncrpc_iob_get_cred ( struct io_buffer *io_buf,
struct oncrpc_cred *cred );
/**
* Add a 32 bits integer to the end of an I/O buffer
*
* @v io_buf I/O buffer
* @v val Integer
* @ret size Size of the data written
*/
static inline size_t oncrpc_iob_add_int ( struct io_buffer *io_buf,
uint32_t val ) {
* ( uint32_t * ) iob_put ( io_buf, sizeof ( val ) ) = htonl ( val );
return ( sizeof ( val) );
}
/**
* Add a 64 bits integer to the end of an I/O buffer
*
* @v io_buf I/O buffer
* @v val Integer
* @ret size Size of the data written
*/
static inline size_t oncrpc_iob_add_int64 ( struct io_buffer *io_buf,
uint64_t val ) {
* ( uint64_t * ) iob_put ( io_buf, sizeof ( val ) ) = htonll ( val );
return ( sizeof ( val) );
}
#endif /* _IPXE_ONCRPC_IOB_H */

View File

@ -11,6 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <stdint.h>
#include <stddef.h>
#include <ipxe/settings.h>
struct net_device;
struct menu;
@ -31,7 +32,7 @@ struct option_descriptor {
* @v value Option value to fill in
* @ret rc Return status code
*/
int ( * parse ) ( const char *text, void *value );
int ( * parse ) ( char *text, void *value );
};
/**
@ -43,9 +44,9 @@ struct option_descriptor {
* @ret _parse Generic option parser
*/
#define OPTION_PARSER( _struct, _field, _parse ) \
( ( int ( * ) ( const char *text, void *value ) ) \
( ( int ( * ) ( char *text, void *value ) ) \
( ( ( ( typeof ( _parse ) * ) NULL ) == \
( ( int ( * ) ( const char *text, \
( ( int ( * ) ( char *text, \
typeof ( ( ( _struct * ) NULL )->_field ) * ) ) \
NULL ) ) ? _parse : _parse ) )
@ -114,12 +115,26 @@ struct command_descriptor {
.usage = _usage, \
}
extern int parse_string ( const char *text, const char **value );
extern int parse_integer ( const char *text, unsigned int *value );
extern int parse_netdev ( const char *text, struct net_device **netdev );
extern int parse_menu ( const char *text, struct menu **menu );
extern int parse_flag ( const char *text __unused, int *flag );
extern int parse_key ( const char *text, unsigned int *key );
/** A parsed named setting */
struct named_setting {
/** Settings block */
struct settings *settings;
/** Setting */
struct setting setting;
};
extern int parse_string ( char *text, char **value );
extern int parse_integer ( char *text, unsigned int *value );
extern int parse_netdev ( char *text, struct net_device **netdev );
extern int parse_menu ( char *text, struct menu **menu );
extern int parse_flag ( char *text __unused, int *flag );
extern int parse_key ( char *text, unsigned int *key );
extern int parse_settings ( char *text, struct settings **settings );
extern int parse_setting ( char *text, struct named_setting *setting,
get_child_settings_t get_child );
extern int parse_existing_setting ( char *text, struct named_setting *setting );
extern int parse_autovivified_setting ( char *text,
struct named_setting *setting );
extern void print_usage ( struct command_descriptor *cmd, char **argv );
extern int reparse_options ( int argc, char **argv,
struct command_descriptor *cmd, void *opts );

View File

@ -351,6 +351,7 @@ struct pci_driver {
#define PCI_FUNC( busdevfn ) ( ( (busdevfn) >> 0 ) & 0x07 )
#define PCI_BUSDEVFN( bus, slot, func ) \
( ( (bus) << 8 ) | ( (slot) << 3 ) | ( (func) << 0 ) )
#define PCI_FIRST_FUNC( busdevfn ) ( (busdevfn) & ~0x07 )
#define PCI_BASE_CLASS( class ) ( (class) >> 16 )
#define PCI_SUB_CLASS( class ) ( ( (class) >> 8 ) & 0xff )
@ -385,6 +386,7 @@ extern void adjust_pci_device ( struct pci_device *pci );
extern unsigned long pci_bar_start ( struct pci_device *pci,
unsigned int reg );
extern int pci_read_config ( struct pci_device *pci );
extern int pci_find_next ( struct pci_device *pci, unsigned int busdevfn );
extern int pci_find_driver ( struct pci_device *pci );
extern int pci_probe ( struct pci_device *pci );
extern void pci_remove ( struct pci_device *pci );

View File

@ -44,6 +44,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
/* Include all architecture-independent I/O API headers */
#include <ipxe/efi/efi_pci_api.h>
#include <ipxe/linux/linux_pci.h>
/* Include all architecture-dependent I/O API headers */
#include <bits/pci_io.h>

View File

@ -0,0 +1,63 @@
#ifndef _IPXE_PORTMAP_H
#define _IPXE_PORTMAP_H
#include <stdint.h>
#include <ipxe/oncrpc.h>
/** @file
*
* SUN ONC RPC protocol.
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
/** PORTMAP default port */
#define PORTMAP_PORT 111
/** PORTMAP protocol number */
#define ONCRPC_PORTMAP 100000
/** PORTMAP version */
#define PORTMAP_VERS 2
/** TCP protocol number */
#define PORTMAP_PROTO_TCP 6
/** UDB protocol number */
#define PORTMAP_PROTO_UDP 17
/**
* A PORTMAP GETPORT reply
*
*/
struct portmap_getport_reply {
/** Port returned */
uint32_t port;
};
/**
* Prepare an ONC RPC session to be used as a PORTMAP session
*
* @v session ONC RPC session
* @v credential ONC RPC credential
*
* The credential parameter must not be NULL, use 'oncrpc_auth_none' if you
* don't want a particular scheme to be used.
*/
static inline void portmap_init_session ( struct oncrpc_session *session,
struct oncrpc_cred *credential) {
oncrpc_init_session ( session, credential, &oncrpc_auth_none,
ONCRPC_PORTMAP, PORTMAP_VERS );
}
int portmap_getport ( struct interface *intf, struct oncrpc_session *session,
uint32_t prog, uint32_t vers, uint32_t proto );
int portmap_get_getport_reply ( struct portmap_getport_reply *getport_reply,
struct oncrpc_reply *reply );
#endif /* _IPXE_PORTMAP_H */

View File

@ -55,4 +55,14 @@ FILE_LICENCE ( GPL2_OR_LATER );
*/
void reboot ( int warm );
/**
* Power off system
*
* @ret rc Return status code
*
* This function may fail, since not all systems support being powered
* off by software.
*/
int poweroff ( void );
#endif /* _IPXE_REBOOT_H */

View File

@ -77,6 +77,12 @@ struct setting {
/** Settings block operations */
struct settings_operations {
/** Redirect to underlying settings block (if applicable)
*
* @v settings Settings block
* @ret settings Underlying settings block
*/
struct settings * ( * redirect ) ( struct settings *settings );
/** Check applicability of setting
*
* @v settings Settings block
@ -179,24 +185,47 @@ struct setting_type {
* This is the name exposed to the user (e.g. "string").
*/
const char *name;
/** Parse formatted setting value
/** Parse formatted string to setting value
*
* @v type Setting type
* @v value Formatted setting value
* @v buf Buffer to contain raw value
* @v len Length of buffer
* @ret len Length of raw value, or negative error
*/
int ( * parse ) ( const char *value, void *buf, size_t len );
/** Format setting value
int ( * parse ) ( struct setting_type *type, const char *value,
void *buf, size_t len );
/** Format setting value as a string
*
* @v type Setting type
* @v raw Raw setting value
* @v raw_len Length of raw setting value
* @v buf Buffer to contain formatted value
* @v len Length of buffer
* @ret len Length of formatted value, or negative error
*/
int ( * format ) ( const void *raw, size_t raw_len, char *buf,
size_t len );
int ( * format ) ( struct setting_type *type, const void *raw,
size_t raw_len, char *buf, size_t len );
/** Convert number to setting value
*
* @v type Setting type
* @v value Numeric value
* @v buf Buffer to contain raw value
* @v len Length of buffer
* @ret len Length of raw value, or negative error
*/
int ( * denumerate ) ( struct setting_type *type, unsigned long value,
void *buf, size_t len );
/** Convert setting value to number
*
* @v type Setting type
* @v raw Raw setting value
* @v raw_len Length of raw setting value
* @v value Numeric value to fill in
* @ret rc Return status code
*/
int ( * numerate ) ( struct setting_type *type, const void *raw,
size_t raw_len, unsigned long *value );
};
/** Configuration setting type table */
@ -235,6 +264,9 @@ struct generic_settings {
struct list_head list;
};
/** A child settings block locator function */
typedef struct settings * ( *get_child_settings_t ) ( struct settings *settings,
const char *name );
extern struct settings_operations generic_settings_operations;
extern int generic_settings_store ( struct settings *settings,
struct setting *setting,
@ -248,6 +280,7 @@ extern int register_settings ( struct settings *settings,
struct settings *parent, const char *name );
extern void unregister_settings ( struct settings *settings );
extern struct settings * settings_target ( struct settings *settings );
extern int setting_applies ( struct settings *settings,
struct setting *setting );
extern int store_setting ( struct settings *settings, struct setting *setting,
@ -288,27 +321,35 @@ extern int setting_cmp ( struct setting *a, struct setting *b );
extern struct settings * find_child_settings ( struct settings *parent,
const char *name );
extern struct settings * autovivify_child_settings ( struct settings *parent,
const char *name );
extern const char * settings_name ( struct settings *settings );
extern struct settings * find_settings ( const char *name );
extern struct setting * find_setting ( const char *name );
extern int parse_setting_name ( char *name, get_child_settings_t get_child,
struct settings **settings,
struct setting *setting );
extern int setting_name ( struct settings *settings, struct setting *setting,
char *buf, size_t len );
extern int setting_format ( struct setting_type *type, const void *raw,
size_t raw_len, char *buf, size_t len );
extern int setting_parse ( struct setting_type *type, const char *value,
void *buf, size_t len );
extern int setting_numerate ( struct setting_type *type, const void *raw,
size_t raw_len, unsigned long *value );
extern int setting_denumerate ( struct setting_type *type, unsigned long value,
void *buf, size_t len );
extern int fetchf_setting ( struct settings *settings, struct setting *setting,
char *buf, size_t len );
extern int fetchf_setting_copy ( struct settings *settings,
struct setting *setting, char **value );
extern int storef_setting ( struct settings *settings,
struct setting *setting,
const char *value );
extern int store_named_setting ( const char *name,
struct setting_type *default_type,
const void *data, size_t len );
extern int storef_named_setting ( const char *name,
struct setting_type *default_type,
const char *value );
extern int fetchf_named_setting ( const char *name, char *name_buf,
size_t name_len, char *value_buf,
size_t value_len );
extern int fetchf_named_setting_copy ( const char *name, char **data );
extern int fetchn_setting ( struct settings *settings, struct setting *setting,
unsigned long *value );
extern int storen_setting ( struct settings *settings, struct setting *setting,
unsigned long value );
extern char * expand_settings ( const char *string );
extern struct setting_type setting_type_string __setting_type;
@ -322,7 +363,9 @@ extern struct setting_type setting_type_uint16 __setting_type;
extern struct setting_type setting_type_uint32 __setting_type;
extern struct setting_type setting_type_hex __setting_type;
extern struct setting_type setting_type_hexhyp __setting_type;
extern struct setting_type setting_type_hexraw __setting_type;
extern struct setting_type setting_type_uuid __setting_type;
extern struct setting_type setting_type_busdevfn __setting_type;
extern struct setting ip_setting __setting ( SETTING_IPv4 );
extern struct setting netmask_setting __setting ( SETTING_IPv4 );
@ -384,16 +427,6 @@ static inline int delete_setting ( struct settings *settings,
return store_setting ( settings, setting, NULL, 0 );
}
/**
* Delete named setting
*
* @v name Name of setting
* @ret rc Return status code
*/
static inline int delete_named_setting ( const char *name ) {
return store_named_setting ( name, NULL, NULL, 0 );
}
/**
* Check existence of setting
*

View File

@ -24,6 +24,16 @@ struct net_device;
*/
#define TCPIP_EMPTY_CSUM 0xffff
/** TCP/IP address flags */
enum tcpip_st_flags {
/** Bind to a privileged port (less than 1024)
*
* This value is chosen as 1024 to optimise the calculations
* in tcpip_bind().
*/
TCPIP_BIND_PRIVILEGED = 0x0400,
};
/**
* TCP/IP socket address
*
@ -33,6 +43,8 @@ struct net_device;
struct sockaddr_tcpip {
/** Socket address family (part of struct @c sockaddr) */
sa_family_t st_family;
/** Flags */
uint16_t st_flags;
/** TCP/IP port */
uint16_t st_port;
/** Padding
@ -42,7 +54,9 @@ struct sockaddr_tcpip {
* family.
*/
char pad[ sizeof ( struct sockaddr ) -
( sizeof ( sa_family_t ) + sizeof ( uint16_t ) ) ];
( sizeof ( sa_family_t ) /* st_family */ +
sizeof ( uint16_t ) /* st_flags */ +
sizeof ( uint16_t ) /* st_port */ ) ];
} __attribute__ (( may_alias ));
/**
@ -125,6 +139,8 @@ extern int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip,
extern uint16_t generic_tcpip_continue_chksum ( uint16_t partial,
const void *data, size_t len );
extern uint16_t tcpip_chksum ( const void *data, size_t len );
extern int tcpip_bind ( struct sockaddr_tcpip *st_local,
int ( * available ) ( int port ) );
/* Use generic_tcpip_continue_chksum() if no architecture-specific
* version is available

View File

@ -109,17 +109,27 @@ enum {
* Note that this is a separate concept from a URI with an absolute
* path.
*/
static inline int uri_is_absolute ( struct uri *uri ) {
static inline int uri_is_absolute ( const struct uri *uri ) {
return ( uri->scheme != NULL );
}
/**
* URI has an opaque part
*
* @v uri URI
* @ret has_opaque URI has an opaque part
*/
static inline int uri_has_opaque ( const struct uri *uri ) {
return ( uri->opaque && ( uri->opaque[0] != '\0' ) );
}
/**
* URI has a path
*
* @v uri URI
* @ret has_path URI has a path
*/
static inline int uri_has_path ( struct uri *uri ) {
static inline int uri_has_path ( const struct uri *uri ) {
return ( uri->path && ( uri->path[0] != '\0' ) );
}
@ -133,7 +143,7 @@ static inline int uri_has_path ( struct uri *uri ) {
* concept from an absolute URI. Note also that a URI may not have a
* path at all.
*/
static inline int uri_has_absolute_path ( struct uri *uri ) {
static inline int uri_has_absolute_path ( const struct uri *uri ) {
return ( uri->path && ( uri->path[0] == '/' ) );
}
@ -147,7 +157,7 @@ static inline int uri_has_absolute_path ( struct uri *uri ) {
* this is a separate concept from a relative URI. Note also that a
* URI may not have a path at all.
*/
static inline int uri_has_relative_path ( struct uri *uri ) {
static inline int uri_has_relative_path ( const struct uri *uri ) {
return ( uri->path && ( uri->path[0] != '/' ) );
}

View File

@ -47,11 +47,13 @@ typedef __kernel_loff_t loff_t;
typedef unsigned long nfds_t;
typedef uint32_t useconds_t;
#define MAP_FAILED ( ( void * ) -1 )
#define SEEK_SET 0
extern long linux_syscall ( int number, ... );
extern int linux_open ( const char *pathname, int flags );
extern int linux_close ( int fd );
extern off_t linux_lseek ( int fd, off_t offset, int whence );
extern __kernel_ssize_t linux_read ( int fd, void *buf, __kernel_size_t count );
extern __kernel_ssize_t linux_write ( int fd, const void *buf,
__kernel_size_t count );

View File

@ -3,6 +3,8 @@
FILE_LICENCE ( GPL2_OR_LATER );
#define htonll(x) __bswap_64(x)
#define ntohll(x) __bswap_64(x)
#define ntohl(x) __bswap_32(x)
#define htonl(x) __bswap_32(x)
#define ntohs(x) __bswap_16(x)

Some files were not shown because too many files have changed in this diff Show More