uint8_t sum = 0;
unsigned int i;
- for ( i = 0 ; i < nvo->total_len ; i++ ) {
+ for ( i = 0 ; i < nvo->len ; i++ ) {
sum += *(data++);
}
return sum;
* @ret rc Return status code
*/
static int nvo_load ( struct nvo_block *nvo ) {
- void *data = nvo->data;
- struct nvo_fragment *frag;
int rc;
- /* Read data a fragment at a time */
- for ( frag = nvo->fragments ; frag->len ; frag++ ) {
- if ( ( rc = nvs_read ( nvo->nvs, frag->address, data,
- frag->len ) ) != 0 ) {
- DBGC ( nvo, "NVO %p could not read %zd bytes at "
- "%#04x\n", nvo, frag->len, frag->address );
- return rc;
- }
- data += frag->len;
+ /* Read data */
+ if ( ( rc = nvs_read ( nvo->nvs, nvo->address, nvo->data,
+ nvo->len ) ) != 0 ) {
+ DBGC ( nvo, "NVO %p could not read %zd bytes at %#04x: %s\n",
+ nvo, nvo->len, nvo->address, strerror ( rc ) );
+ return rc;
}
DBGC ( nvo, "NVO %p loaded from non-volatile storage\n", nvo );
* @ret rc Return status code
*/
static int nvo_save ( struct nvo_block *nvo ) {
- void *data = nvo->data;
- uint8_t *checksum = data;
- struct nvo_fragment *frag;
+ uint8_t *checksum = nvo->data;
int rc;
/* Recalculate checksum */
*checksum -= nvo_checksum ( nvo );
- /* Write data a fragment at a time */
- for ( frag = nvo->fragments ; frag->len ; frag++ ) {
- if ( ( rc = nvs_write ( nvo->nvs, frag->address, data,
- frag->len ) ) != 0 ) {
- DBGC ( nvo, "NVO %p could not write %zd bytes at "
- "%#04x\n", nvo, frag->len, frag->address );
- return rc;
- }
- data += frag->len;
+ /* Write data */
+ if ( ( rc = nvs_write ( nvo->nvs, nvo->address, nvo->data,
+ nvo->len ) ) != 0 ) {
+ DBGC ( nvo, "NVO %p could not write %zd bytes at %#04x: %s\n",
+ nvo, nvo->len, nvo->address, strerror ( rc ) );
+ return rc;
}
DBGC ( nvo, "NVO %p saved to non-volatile storage\n", nvo );
/* Steal one byte for the checksum */
options_data = ( nvo->data + 1 );
- options_len = ( nvo->total_len - 1 );
+ options_len = ( nvo->len - 1 );
/* If checksum fails, or options data starts with a zero,
* assume the whole block is invalid. This should capture the
DBGC ( nvo, "NVO %p has checksum %02x and initial byte %02x; "
"assuming empty\n", nvo, nvo_checksum ( nvo ),
options_data[0] );
- memset ( nvo->data, 0, nvo->total_len );
+ memset ( nvo->data, 0, nvo->len );
}
dhcpopt_init ( &nvo->dhcpopts, options_data, options_len,
*
* @v nvo Non-volatile options block
* @v nvs Underlying non-volatile storage device
- * @v fragments List of option-containing fragments, or NULL
+ * @v address Address within NVS device
+ * @v len Length of non-volatile options data
* @v refcnt Containing object reference counter, or NULL
*/
void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs,
- struct nvo_fragment *fragments, struct refcnt *refcnt ) {
+ size_t address, size_t len, struct refcnt *refcnt ) {
nvo->nvs = nvs;
- nvo->fragments = fragments;
+ nvo->address = address;
+ nvo->len = len;
settings_init ( &nvo->settings, &nvo_settings_operations, refcnt, 0 );
}
* @ret rc Return status code
*/
int register_nvo ( struct nvo_block *nvo, struct settings *parent ) {
- struct nvo_fragment *fragment = nvo->fragments;
int rc;
- /* Calculate total length of all fragments, if applicable */
- if ( fragment ) {
- for ( ; fragment->len ; fragment++ )
- nvo->total_len += fragment->len;
- } else {
- nvo->total_len = nvo->nvs->size;
- }
-
- /* Allocate memory for options (and fragment list, if applicable) */
- nvo->data = zalloc ( nvo->total_len +
- ( fragment ? 0 : ( 2 * sizeof ( *fragment ) ) ) );
+ /* Allocate memory for options */
+ nvo->data = zalloc ( nvo->len );
if ( ! nvo->data ) {
DBGC ( nvo, "NVO %p could not allocate %zd bytes\n",
- nvo, nvo->total_len );
+ nvo, nvo->len );
rc = -ENOMEM;
goto err_malloc;
}
- /* Create fragment list, if applicable */
- if ( ! fragment ) {
- fragment = ( nvo->data + nvo->total_len );
- fragment->len = nvo->total_len;
- nvo->fragments = fragment;
- }
-
/* Read data from NVS */
if ( ( rc = nvo_load ( nvo ) ) != 0 )
goto err_load;
*/
struct nvs_device nvs;
- struct nvo_fragment nvo_fragment[2];
struct nvo_block nvo;
+ unsigned int nvo_registered;
/* Cached PCI capability locations. */
priv->nvs.read = myri10ge_nvs_read;
priv->nvs.write = myri10ge_nvs_write;
- /* Build the NonVolatile storage fragment list. We would like
- to use the whole last EEPROM block for this, but we must
- reduce the block size lest malloc fail in
- src/core/nvo.o. */
-
- priv->nvo_fragment[0].address = nvo_fragment_pos;
- priv->nvo_fragment[0].len = 0x200;
-
/* Register the NonVolatile Options storage. */
nvo_init ( &priv->nvo,
&priv->nvs,
- priv->nvo_fragment,
+ nvo_fragment_pos, 0x200,
& myri10ge_netdev (priv) -> refcnt );
rc = register_nvo ( &priv->nvo,
netdev_settings ( myri10ge_netdev ( priv ) ) );
if ( rc ) {
DBG ("register_nvo failed");
- priv->nvo_fragment[0].len = 0;
return rc;
}
+ priv->nvo_registered = 1;
DBG2 ( "NVO supported\n" );
return 0;
}
{
/* Simply return if nonvolatile access is not supported. */
- if ( 0 == priv->nvo_fragment[0].len )
+ if ( 0 == priv->nvo_registered )
return;
unregister_nvo ( &priv->nvo );
.write = rtl_spi_write_bit,
};
-/** Portion of EEPROM available for non-volatile stored options
- *
- * We use offset 0x40 (i.e. address 0x20), length 0x40. This block is
- * marked as VPD in the rtl8139 datasheets, so we use it only if we
- * detect that the card is not supporting VPD.
- */
-static struct nvo_fragment rtl_nvo_fragments[] = {
- { 0x20, 0x40 },
- { 0, 0 }
-};
-
/**
* Set up for EEPROM access
*
}
rtl->eeprom.bus = &rtl->spibit.bus;
- /* Initialise space for non-volatile options, if available */
+ /* Initialise space for non-volatile options, if available
+ *
+ * We use offset 0x40 (i.e. address 0x20), length 0x40. This
+ * block is marked as VPD in the rtl8139 datasheets, so we use
+ * it only if we detect that the card is not supporting VPD.
+ */
vpd = ( inw ( rtl->ioaddr + Config1 ) & VPDEnable );
if ( vpd ) {
DBGC ( rtl, "rtl8139 %p EEPROM in use for VPD; cannot use "
"for options\n", rtl );
} else {
- nvo_init ( &rtl->nvo, &rtl->eeprom.nvs, rtl_nvo_fragments,
+ nvo_init ( &rtl->nvo, &rtl->eeprom.nvs, 0x20, 0x40,
&netdev->refcnt );
}
}
struct nvs_device;
struct refcnt;
-/**
- * A fragment of a non-volatile storage device used for stored options
- */
-struct nvo_fragment {
- /** Starting address of fragment within NVS device */
- unsigned int address;
- /** Length of fragment */
- size_t len;
-};
-
/**
* A block of non-volatile stored options
*/
struct settings settings;
/** Underlying non-volatile storage device */
struct nvs_device *nvs;
- /** List of option-containing fragments
- *
- * The list is terminated by a fragment with a length of zero.
- */
- struct nvo_fragment *fragments;
- /** Total length of option-containing fragments */
- size_t total_len;
+ /** Address within NVS device */
+ unsigned int address;
+ /** Length of options data */
+ size_t len;
/** Option-containing data */
void *data;
/** DHCP options block */
};
extern void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs,
- struct nvo_fragment *fragments, struct refcnt *refcnt );
+ size_t address, size_t len, struct refcnt *refcnt );
extern int register_nvo ( struct nvo_block *nvo, struct settings *parent );
extern void unregister_nvo ( struct nvo_block *nvo );