From 2d8d21fe7416871920c96b53b7d3ae5d02964575 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 4 Dec 2006 19:06:07 +0000 Subject: [PATCH] Added the generic block-splitting code to nvs.c --- src/drivers/net/rtl8139.c | 22 +------------------ src/drivers/nvs/nvs.c | 41 +++++++++++++++++++++++++++++++++++- src/include/gpxe/nvs.h | 9 ++++++-- src/include/gpxe/threewire.h | 2 +- 4 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/drivers/net/rtl8139.c b/src/drivers/net/rtl8139.c index 503cee25..fe4b5ccc 100644 --- a/src/drivers/net/rtl8139.c +++ b/src/drivers/net/rtl8139.c @@ -265,26 +265,6 @@ static struct bit_basher_operations rtl_basher_ops = { rtl->eeprom.bus = &rtl->spibit.bus; } -/** - * Read the MAC address - * - * @v rtl RTL8139 NIC - * @v mac_addr Buffer to contain MAC address (ETH_ALEN bytes) - */ -static void rtl_read_mac ( struct rtl8139_nic *rtl, uint8_t *mac_addr ) { - - struct nvs_device *nvs = &rtl->eeprom.nvs; - int i; - - DBG ( "MAC address is " ); - for ( i = EE_MAC ; i < ( EE_MAC + ( ETH_ALEN / 2 ) ) ; i++ ) { - nvs_read ( nvs, i, mac_addr, 2 ); - DBG ( "%02x%02x", mac_addr[0], mac_addr[1] ); - mac_addr += 2; - } - DBG ( "\n" ); -} - /** * Reset NIC * @@ -531,7 +511,7 @@ static int rtl_probe ( struct pci_device *pci, /* Reset the NIC, set up EEPROM access and read MAC address */ rtl_reset ( rtl ); rtl_init_eeprom ( rtl ); - rtl_read_mac ( rtl, netdev->ll_addr ); + nvs_read ( &rtl->eeprom.nvs, EE_MAC, netdev->ll_addr, ETH_ALEN ); /* Point to NIC specific routines */ // netdev->open = rtl_open; diff --git a/src/drivers/nvs/nvs.c b/src/drivers/nvs/nvs.c index 55cd8283..3f22a0ee 100644 --- a/src/drivers/nvs/nvs.c +++ b/src/drivers/nvs/nvs.c @@ -17,6 +17,7 @@ */ #include +#include #include /** @file @@ -25,7 +26,45 @@ * */ +/** + * Read from non-volatile storage device + * + * @v nvs NVS device + * @v address Address from which to read + * @v data Data buffer + * @v len Length of data buffer + * @ret rc Return status code + */ int nvs_read ( struct nvs_device *nvs, unsigned int address, void *data, size_t len ) { - return nvs->read ( nvs, address, data, len ); + size_t frag_len; + int rc; + + /* We don't even attempt to handle buffer lengths that aren't + * an integral number of words. + */ + assert ( ( len & ( ( 1 << nvs->word_len_log2 ) - 1 ) ) == 0 ); + + while ( len ) { + + /* Calculate space remaining up to next block boundary */ + frag_len = ( ( nvs->block_size - + ( address & ( nvs->block_size - 1 ) ) ) + << nvs->word_len_log2 ); + + /* Limit to space remaining in buffer */ + if ( frag_len > len ) + frag_len = len; + + /* Read this portion of the buffer from the device */ + if ( ( rc = nvs->read ( nvs, address, data, frag_len ) ) != 0 ) + return rc; + + /* Update parameters */ + data += frag_len; + address += ( frag_len >> nvs->word_len_log2 ); + len -= frag_len; + } + + return 0; } diff --git a/src/include/gpxe/nvs.h b/src/include/gpxe/nvs.h index 38bc9c55..b026dd46 100644 --- a/src/include/gpxe/nvs.h +++ b/src/include/gpxe/nvs.h @@ -11,8 +11,13 @@ /** A non-volatile storage device */ struct nvs_device { - /** Word length, in bits */ - unsigned int word_len; + /** Word length + * + * This is expressed as the base-2 logarithm of the word + * length in bytes. A value of 0 therefore translates as + * 8-bit words, and a value of 1 translates as 16-bit words. + */ + unsigned int word_len_log2; /** Device size (in words) */ unsigned int size; /** Data block size (in words) diff --git a/src/include/gpxe/threewire.h b/src/include/gpxe/threewire.h index cbf6180a..d60e1a71 100644 --- a/src/include/gpxe/threewire.h +++ b/src/include/gpxe/threewire.h @@ -32,7 +32,7 @@ extern int threewire_read ( struct nvs_device *nvs, unsigned int address, static inline __attribute__ (( always_inline )) void init_at93cx6 ( struct spi_device *device, unsigned int organisation ) { - device->nvs.word_len = organisation; + device->nvs.word_len_log2 = ( ( organisation == 8 ) ? 0 : 1 ); device->nvs.block_size = 1; device->command_len = 3, device->nvs.read = threewire_read;