mirror of
https://github.com/xcat2/xNBA.git
synced 2024-11-21 17:11:46 +00:00
Merge branch 'master' of https://git.ipxe.org/ipxe
Conflicts: src/config/general.h src/net/netdev_settings.c src/net/tcp.c
This commit is contained in:
commit
dde0935447
@ -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)
|
||||
|
@ -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,$<)),\
|
||||
|
108
src/arch/i386/interface/pcbios/apm.c
Normal file
108
src/arch/i386/interface/pcbios/apm.c
Normal 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 );
|
@ -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 ) );
|
||||
|
@ -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 ) {
|
||||
|
@ -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)
|
||||
|
@ -53,6 +53,8 @@ SECTIONS {
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
KEEP(*(SORT(.tbl.*)))
|
||||
KEEP(*(.provided))
|
||||
KEEP(*(.provided.*))
|
||||
_edata = .;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
*
|
||||
|
272
src/arch/x86/core/cpuid_settings.c
Normal file
272
src/arch/x86/core/cpuid_settings.c
Normal 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,
|
||||
},
|
||||
};
|
@ -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 );
|
||||
}
|
||||
|
@ -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 )
|
||||
|
||||
/** @} */
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -60,6 +60,8 @@
|
||||
#ifndef __MEMCHECK_H
|
||||
#define __MEMCHECK_H
|
||||
|
||||
FILE_LICENCE ( BSD3 );
|
||||
|
||||
|
||||
/* This file is for inclusion into client (your!) code.
|
||||
|
||||
|
@ -73,6 +73,8 @@
|
||||
#ifndef __VALGRIND_H
|
||||
#define __VALGRIND_H
|
||||
|
||||
FILE_LICENCE ( BSD3 );
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* VERSION NUMBER OF VALGRIND */
|
||||
|
@ -55,6 +55,8 @@ SECTIONS {
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
KEEP(*(SORT(.tbl.*))) /* Various tables. See include/tables.h */
|
||||
KEEP(*(.provided))
|
||||
KEEP(*(.provided.*))
|
||||
_edata = .;
|
||||
}
|
||||
|
||||
|
@ -53,6 +53,8 @@ SECTIONS {
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
KEEP(*(SORT(.tbl.*)))
|
||||
KEEP(*(.provided))
|
||||
KEEP(*(.provided.*))
|
||||
_edata = .;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -7,6 +7,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#define UACCESS_EFI
|
||||
#define IOAPI_X86
|
||||
#define PCIAPI_EFI
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
19
src/config/settings.h
Normal 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 */
|
@ -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>
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include <errno.h>
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Error codes
|
||||
|
242
src/core/memmap_settings.c
Normal file
242
src/core/memmap_settings.c
Normal 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,
|
||||
},
|
||||
};
|
@ -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;
|
||||
|
@ -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 );
|
||||
|
@ -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;
|
||||
|
1168
src/core/settings.c
1168
src/core/settings.c
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -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 ) {
|
||||
|
124
src/drivers/bus/pci_settings.c
Normal file
124
src/drivers/bus/pci_settings.c
Normal 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,
|
||||
};
|
@ -20,6 +20,8 @@
|
||||
#ifndef ATH_H
|
||||
#define ATH_H
|
||||
|
||||
FILE_LICENCE ( BSD2 );
|
||||
|
||||
#include <unistd.h>
|
||||
#include <ipxe/net80211.h>
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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},
|
||||
|
@ -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},
|
||||
|
@ -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},
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -20,6 +20,8 @@
|
||||
#ifndef ATH9K_H
|
||||
#define ATH9K_H
|
||||
|
||||
FILE_LICENCE ( BSD2 );
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -20,6 +20,8 @@
|
||||
#ifndef CALIB_H
|
||||
#define CALIB_H
|
||||
|
||||
FILE_LICENCE ( BSD2 );
|
||||
|
||||
#include "hw.h"
|
||||
|
||||
#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3
|
||||
|
@ -17,6 +17,8 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( BSD2 );
|
||||
|
||||
#include "../ath.h"
|
||||
|
||||
#include "hw.h"
|
||||
|
@ -20,6 +20,8 @@
|
||||
#ifndef EEPROM_H
|
||||
#define EEPROM_H
|
||||
|
||||
FILE_LICENCE ( BSD2 );
|
||||
|
||||
#define AR_EEPROM_MODAL_SPURS 5
|
||||
|
||||
#include "../ath.h"
|
||||
|
@ -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 */
|
||||
|
@ -20,6 +20,8 @@
|
||||
#ifndef HW_H
|
||||
#define HW_H
|
||||
|
||||
FILE_LICENCE ( BSD2 );
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "mac.h"
|
||||
|
@ -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) ? \
|
||||
|
@ -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)
|
||||
|
@ -17,6 +17,8 @@
|
||||
#ifndef REG_H
|
||||
#define REG_H
|
||||
|
||||
FILE_LICENCE ( BSD2 );
|
||||
|
||||
#include "../reg.h"
|
||||
|
||||
#define AR_CR 0x0008
|
||||
|
@ -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
|
||||
|
@ -20,6 +20,8 @@
|
||||
#ifndef REGD_H
|
||||
#define REGD_H
|
||||
|
||||
FILE_LICENCE ( BSD2 );
|
||||
|
||||
#include "ath.h"
|
||||
|
||||
enum ctl_group {
|
||||
|
@ -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 ) );
|
||||
}
|
||||
|
||||
|
@ -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++;
|
||||
|
@ -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
787
src/drivers/net/rhine.c
Normal 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
250
src/drivers/net/rhine.h
Normal 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
807
src/drivers/net/velocity.c
Normal 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
356
src/drivers/net/velocity.h
Normal 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
@ -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
|
||||
*
|
||||
|
@ -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 )
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
114
src/hci/commands/pci_cmd.c
Normal 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,
|
||||
},
|
||||
};
|
72
src/hci/commands/poweroff_cmd.c
Normal file
72
src/hci/commands/poweroff_cmd.c
Normal 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,
|
||||
};
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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 )
|
||||
|
||||
|
@ -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
|
||||
|
@ -21,6 +21,8 @@
|
||||
* trailing whitespace.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/* EFI headers rudely redefine NULL */
|
||||
#undef NULL
|
||||
|
||||
|
@ -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 )
|
||||
|
||||
/** @} */
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
/** @} */
|
||||
|
||||
|
@ -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 );
|
||||
|
@ -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 */
|
||||
|
130
src/include/ipxe/linux/linux_pci.h
Normal file
130
src/include/ipxe/linux/linux_pci.h
Normal 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
76
src/include/ipxe/mount.h
Normal 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
157
src/include/ipxe/nfs.h
Normal 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 */
|
12
src/include/ipxe/nfs_open.h
Normal file
12
src/include/ipxe/nfs_open.h
Normal 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
128
src/include/ipxe/oncrpc.h
Normal 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 */
|
102
src/include/ipxe/oncrpc_iob.h
Normal file
102
src/include/ipxe/oncrpc_iob.h
Normal 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 */
|
@ -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 );
|
||||
|
@ -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 );
|
||||
|
@ -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>
|
||||
|
63
src/include/ipxe/portmap.h
Normal file
63
src/include/ipxe/portmap.h
Normal 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 */
|
@ -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 */
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
|
@ -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] != '/' ) );
|
||||
}
|
||||
|
||||
|
@ -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 );
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user