Mercurial > nand-ecoscentric
changeset 195:67850532eebb
Merge from eCos master repository on 2001-11-02-06:43:03-GMT
line wrap: on
line diff
--- a/packages/ChangeLog +++ b/packages/ChangeLog @@ -1,3 +1,8 @@ +2001-10-30 Jonathan Larmour <jlarmour@redhat.com> + + * ecos.db: Added ARM Integrator target including HAL, serial driver, + eth driver and flash driver packages. + 2001-10-19 Lars Lindqvist <Lars.Lindqvist@combitechsystems.com> 2001-10-19 Jonathan Larmour <jlarmour@redhat.com>
--- a/packages/NEWS +++ b/packages/NEWS @@ -1,3 +1,6 @@ +* Incorporated ARM Development board aka INTEGRATOR port from Philippe Robin + at ARM. Includes FLASH, ethernet and serial drivers, along with RedBoot + support. * Added ARM E7T (AEB-2) serial device drivers contributed by Lars Lindqvist at Combitech <Lars.Lindqvist@combitechsystems.com> * Flash driver added for the SH EDK7708 platform.
new file mode 100644 --- /dev/null +++ b/packages/devs/eth/arm/integrator/current/ChangeLog @@ -0,0 +1,31 @@ +2000-08-21 Philippe Robin + * adapted from ebsa285 + +//=========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//=========================================================================== + + +
new file mode 100644 --- /dev/null +++ b/packages/devs/eth/arm/integrator/current/cdl/integrator_eth_drivers.cdl @@ -0,0 +1,149 @@ +# ==================================================================== +# +# integrator_eth_drivers.cdl +# +# Ethernet drivers +# Intel PRO/100+ platform specific support for ARM Integrator +# +# ==================================================================== +#####COPYRIGHTBEGIN#### +# +# ------------------------------------------- +# The contents of this file are subject to the Red Hat eCos Public License +# Version 1.1 (the "License"); you may not use this file except in +# compliance with the License. You may obtain a copy of the License at +# http://www.redhat.com/ +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +# License for the specific language governing rights and limitations under +# the License. +# +# The Original Code is eCos - Embedded Configurable Operating System, +# released September 30, 1998. +# +# The Initial Developer of the Original Code is Red Hat. +# Portions created by Red Hat are +# Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +# All Rights Reserved. +# ------------------------------------------- +# +#####COPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): Philippe Robin +# Original data: hmt +# Contributors: +# Date: November 7, 2000 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_ETH_ARM_INTEGRATOR { + display "Intel PRO/100+ ethernet driver for ARM Integrator" + + parent CYGPKG_IO_ETH_DRIVERS + active_if CYGPKG_IO_ETH_DRIVERS + active_if CYGPKG_HAL_ARM_INTEGRATOR + + implements CYGHWR_NET_DRIVER_ETH0 + implements CYGHWR_NET_DRIVER_ETH1 + # yes, there should be two of these "implement"s + implements CYGHWR_NET_DRIVERS + implements CYGHWR_NET_DRIVERS + include_dir cyg/devs/eth + + # SNMP demands to know stuff; this sadly makes us break the neat + # abstraction of the device having nothing exported. + # The other one is used by other tests: + include_files include/integrator_info.h + # and tell them that it is available + define_proc { + puts $::cdl_system_header \ + "#define CYGBLD_DEVS_ETH_DEVICE_H <pkgconf/devs_eth_arm_integrator.h>" + puts $::cdl_header \ + "#define CYGBLD_DEVS_ETH_INFO_H <cyg/devs/eth/integrator_info.h>" + } + + description "Ethernet driver for Intel PRO/100+ boards on ARM Integrator." + compile -library=libextras.a if_integrator.c + + cdl_option CYGDBG_DEVS_ETH_ARM_INTEGRATOR_CHATTER { + display "Prints ethernet device status info during startup" + default_value 0 + description " + The ethernet device initialization code can print lots of info + to confirm that it has found the devices on the PCI bus, read + the MAC address from EEPROM correctly, and so on, and also + displays the mode (10/100MHz, half/full duplex) of the + connection." + } + + cdl_option CYGNUM_DEVS_ETH_ARM_INTEGRATOR_DEV_COUNT { + display "Number of supported interfaces." + legal_values 1 2 + default_value 1 + flavor data + description " + This option selects the number of PCI ethernet interfaces to + be supported by the driver." + } + + cdl_component CYGDBG_DEVS_ETH_ARM_INTEGRATOR_KEEP_STATISTICS { + display "Keep Ethernet statistics" + default_value 1 + description " + The ethernet device can maintain statistics about the network, + specifically a great variety of error rates which are useful + for network management. SNMP for example uses this + information. There is some performance cost in maintaining + this information; disable this option to recoup that." + + cdl_option CYGDBG_DEVS_ETH_ARM_INTEGRATOR_KEEP_82559_STATISTICS { + display "Keep i82559 Internal statistics" + default_value 1 + description " + The i82559 keeps internal counters, and it is possible to + acquire these. But the i82559 (reputedly) does not service + the network whilst uploading the data to RAM from its + internal registers. If throughput is a problem, disable + this option to acquire only those statistics gathered by + software, so that the i82559 never sleeps." + } + } + + cdl_component CYGPKG_DEVS_ETH_ARM_INTEGRATOR_WRITE_EEPROM { + display "SIOCSIFHWADDR records MAC address in EEPROM" + default_value 0 + description " + The ioctl() socket call with operand SIOCSIFHWADDR sets the + interface hardware address - the MAC address or ethernet + address. This option causes the new MAC address to be written + into the EEPROM associated with the interface, so that the new + MAC address is permanently recorded. Doing this should be a + carefully chosen decision, hence this option." + } + + cdl_component CYGPKG_DEVS_ETH_ARM_INTEGRATOR_OPTIONS { + display "Intel PRO/100+ ethernet driver build options for ARM Integrator" + flavor none + no_define + + cdl_option CYGPKG_DEVS_ETH_ARM_INTEGRATOR_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "-D_KERNEL -D__ECOS" } + description " + This option modifies the set of compiler flags for + building the Intel EBSA285 with PRO/100+ ethernet driver + package. These flags are used in addition to the set of + global flags." + } + } + +} + +# EOF integrator_eth_drivers.cdl
new file mode 100644 --- /dev/null +++ b/packages/devs/eth/arm/integrator/current/include/integrator_info.h @@ -0,0 +1,206 @@ +#ifndef CYGONCE_DEVS_ETH_ARM_INTEGRATOR_INTEGRATOR_INFO_H +#define CYGONCE_DEVS_ETH_ARM_INTEGRATOR_INTEGRATOR_INFO_H +/*========================================================================== +// +// integrator_info.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Philippe Robin +// Original data: hmt +// Contributors: +// Date: November 7, 2000 +// Description: +// +//####DESCRIPTIONEND#### +*/ + +#include <pkgconf/devs_eth_arm_integrator.h> + +#undef CYGHWR_HAL_ARM_INTEGRATOR_PCI_MEM_MAP_SIZE +#define CYGHWR_HAL_ARM_INTEGRATOR_PCI_MEM_MAP_SIZE 0x100000 + +#ifdef CYGDBG_DEVS_ETH_ARM_INTEGRATOR_KEEP_STATISTICS +# define KEEP_STATISTICS +# define nDISPLAY_STATISTICS +# define nDISPLAY_82559_STATISTICS +#else +# define nKEEP_STATISTICS +# define nDISPLAY_STATISTICS +# define nDISPLAY_82559_STATISTICS +#endif + + +// ------------------------------------------------------------------------ +// +// STATISTICAL COUNTER STRUCTURE +// +// ------------------------------------------------------------------------ +#ifdef KEEP_STATISTICS +typedef struct { +/* 0 */ cyg_uint32 tx_good; +/* 4 */ cyg_uint32 tx_max_collisions; +/* 8 */ cyg_uint32 tx_late_collisions; +/* 12 */ cyg_uint32 tx_underrun; +/* 16 */ cyg_uint32 tx_carrier_loss; +/* 20 */ cyg_uint32 tx_deferred; +/* 24 */ cyg_uint32 tx_single_collisions; +/* 28 */ cyg_uint32 tx_mult_collisions; +/* 32 */ cyg_uint32 tx_total_collisions; +/* 36 */ cyg_uint32 rx_good; +/* 40 */ cyg_uint32 rx_crc_errors; +/* 44 */ cyg_uint32 rx_align_errors; +/* 48 */ cyg_uint32 rx_resource_errors; +/* 52 */ cyg_uint32 rx_overrun_errors; +/* 56 */ cyg_uint32 rx_collisions; // Always 0 +/* 60 */ cyg_uint32 rx_short_frames; +// In this setup; can also be flow-control counts after. +// If these are to be used, a config command (as in set promiscuous mode) +// must be issued at start, to let those stats escape. Params are in +// comments around the config command setup... +/* 64 */ cyg_uint32 done; +} I82559_COUNTERS; + + +typedef struct { + cyg_uint32 interrupts; + cyg_uint32 rx_count; + cyg_uint32 rx_deliver; + cyg_uint32 rx_resource; + cyg_uint32 rx_restart; + cyg_uint32 tx_count; + cyg_uint32 tx_complete; + cyg_uint32 tx_dropped; +} STATISTICS; + + +extern STATISTICS statistics[2]; +#ifdef CYGDBG_DEVS_ETH_ARM_INTEGRATOR_KEEP_82559_STATISTICS +extern I82559_COUNTERS i82559_counters[2]; +#endif + +#endif // KEEP_STATISTICS + +// ------------------------------------------------------------------------ +// +// DEVICES AND PACKET QUEUES +// +// ------------------------------------------------------------------------ +// The system seems to work OK with as few as 8 of RX and TX descriptors. +// It limps very painfully with only 4. +// Performance is better with more than 8. +// But the size of non-cached (so useless for anything else) +// memory window is 1Mb, so we might as well use it all. +// +// 128 for these uses the whole 1Mb, near enough. + +#ifndef MAX_RX_DESCRIPTORS +#define MAX_RX_DESCRIPTORS 8 // number of Rx descriptors 128 +#endif +#ifndef MAX_TX_DESCRIPTORS +#define MAX_TX_DESCRIPTORS 8 // number of Tx descriptors +#endif + + +typedef struct i82559 { + cyg_uint8 // (split up for atomic byte access) + found:1, // was hardware discovered? + mac_addr_ok:1, // can we bring up? + active:1, // has this if been brung up? + spare1:5; + cyg_uint8 + spare2:8; + cyg_uint8 + tx_in_progress:1, // transmit in progress flag + tx_queue_full:1, // all Tx descriptors used flag + spare3:6; + cyg_uint8 index; // 0 or 1 or whatever + cyg_uint32 devid; // PCI device id + cyg_uint32 memory_address; // PCI memory address + cyg_uint32 io_address; // memory mapped I/O address + cyg_uint8 mac_address[6]; // mac (hardware) address + void *ndp; // Network Device Pointer + + int next_rx_descriptor; // descriptor index for RFDs + struct rfd *rx_ring[MAX_RX_DESCRIPTORS]; // location of Rx descriptors + + int tx_descriptor_add; // descriptor index for additions + int tx_descriptor_active; // descriptor index for active tx + int tx_descriptor_remove; // descriptor index for remove + + struct txcb *tx_ring[MAX_TX_DESCRIPTORS]; // location of Tx descriptors + unsigned long tx_keys[MAX_TX_DESCRIPTORS]; + // keys for tx q management + + // Interrupt handling stuff + cyg_vector_t vector; // interrupt vector + cyg_handle_t interrupt_handle; // handle for int.handler + cyg_interrupt interrupt_object; + +#ifdef KEEP_STATISTICS + void *p_statistics; // pointer to statistical counters +#endif + +} I82559; + + + +// ------------------------------------------------------------------------ +// +// 82559 GENERAL STATUS REGISTER +// +// ------------------------------------------------------------------------ +#define GEN_STATUS_FDX 0x04 // 1 = full duplex, 0 = half +#define GEN_STATUS_100MBPS 0x02 // 1 = 100 Mbps, 0 = 10 Mbps +#define GEN_STATUS_LINK 0x01 // 1 = link up, 0 = link down + +extern int i82559_status( struct eth_drv_sc *sc ); + +// ------------------------------------------------------------------------ + +#ifdef KEEP_STATISTICS +void update_statistics(struct i82559* p_i82559); +#endif + + +#ifdef CYGDBG_DEVS_ETH_ARM_INTEGRATOR_KEEP_82559_STATISTICS +#define ETH_STATS_INIT( p ) \ + update_statistics( (struct i82559 *)((p)->driver_private) ) +#else +#define ETH_STATS_INIT( p ) // otherwise do nothing +#endif + +#define CYGDAT_DEVS_ETH_DESCRIPTION "Intel EtherPRO 10/100+ (i82559)" + +#define ETH_DEV_DOT3STATSETHERCHIPSET 1,3,6,1,2,1,10,7,8,2,5 + +#endif /* ifndef CYGONCE_DEVS_ETH_ARM_INTEGRATOR_INTEGRATOR_INFO_H */ + +/* EOF integrator_info.h */ +
new file mode 100644 --- /dev/null +++ b/packages/devs/eth/arm/integrator/current/src/if_integrator.c @@ -0,0 +1,2712 @@ +//========================================================================== +// +// if_integrator.c +// +// Ethernet drivers +// ARM Integrator with Intel PRO/100+ platform specific support +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####BSDCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from OpenBSD or other sources, +// and are covered by the appropriate copyright disclaimers included herein. +// +// ------------------------------------------- +// +//####BSDCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt, gthomas +// Contributors: Ron Spence, Philippe Robin +// Date: November 7, 2000 +// Purpose: +// Description: hardware driver for 82559 Intel PRO/100+ ethernet and +// ARM INTEGRATOR development boards +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/system.h> +#include <pkgconf/devs_eth_arm_integrator.h> +#include <cyg/infra/cyg_type.h> +#include <cyg/infra/cyg_ass.h> +#include <cyg/hal/hal_arch.h> +#include <cyg/hal/hal_intr.h> +#include <cyg/infra/diag.h> +#include <cyg/hal/drv_api.h> +#include <netdev.h> +#include <eth_drv.h> + +#ifdef CYGPKG_NET +#include <pkgconf/net.h> +#include <net/if.h> /* Needed for struct ifnet */ +#else +#include <cyg/hal/hal_if.h> +#endif + +#ifdef CYGPKG_IO_PCI +#include <cyg/io/pci.h> +// So we can check the validity of the PCI window against the MLTs opinion, +// and thereby what the malloc heap consumes willy-nilly: +#include CYGHWR_MEMORY_LAYOUT_H +#else +#error "Need PCI package here" +#endif + +// Exported statistics and the like +#include <cyg/devs/eth/integrator_info.h> +#include <eth_drv_stats.h> + +// ------------------------------------------------------------------------ + +#ifdef CYGDBG_DEVS_ETH_ARM_INTEGRATOR_CHATTER +#define noDEBUG_82559 // This one prints stuff as packets come and go +#define DEBUG // Startup printing mainly +#define DEBUG_EE // Some EEPROM specific retries &c +#endif + +#define os_printf diag_printf +#define db_printf diag_printf + +// ------------------------------------------------------------------------ +// I/O access macros as inlines for type safety + +static inline void OUTB(cyg_uint8 value, cyg_uint32 io_address) +{ *((volatile cyg_uint8 *)io_address) = value; } + +static inline void OUTW(cyg_uint16 value, cyg_uint32 io_address) +{ *((volatile cyg_uint16 *)io_address) = value; } + +static inline void OUTL(cyg_uint32 value, cyg_uint32 io_address) +{ *((volatile cyg_uint32 *)io_address) = value; } + +static inline cyg_uint8 INB(cyg_uint32 io_address) +{ return *((volatile cyg_uint8 *)io_address); } + +static inline cyg_uint16 INW(cyg_uint32 io_address) +{ return *((volatile cyg_uint16 *)io_address); } + +static inline cyg_uint32 INL(cyg_uint32 io_address) +{ return *((volatile cyg_uint32 *)io_address); } + +#define VIRT_TO_BUS( _x_ ) virt_to_bus((cyg_uint32)(_x_)) +static inline cyg_uint32 virt_to_bus(cyg_uint32 p_memory) +{ return (p_memory); } + +#define BUS_TO_VIRT( _x_ ) bus_to_virt((cyg_uint32)(_x_)) +static inline cyg_uint32 bus_to_virt(cyg_uint32 p_memory) +{ return (p_memory); } + + +// ------------------------------------------------------------------------ +// +// 82559 REGISTER OFFSETS (I/O SPACE) +// +// ------------------------------------------------------------------------ +#define SCBStatus 0 // Rx/Command Unit command and status. +#define SCBCmd 2 // Rx/Command Unit command and status. +#define SCBPointer 4 // General purpose pointer. +#define SCBPort 8 // Misc. commands and operands. +#define SCBflash 12 // Flash memory control. +#define SCBeeprom 14 // EEPROM memory control. +#define SCBCtrlMDI 16 // MDI interface control. +#define SCBEarlyRx 20 // Early receive byte count. +#define SCBGenControl 28 // 82559 General Control Register +#define SCBGenStatus 29 // 82559 General Status register + + +// ------------------------------------------------------------------------ +// +// 82559 SCB STATUS WORD DEFNITIONS +// +// ------------------------------------------------------------------------ +#define SCB_STATUS_CX 0x8000 // CU finished command (transmit) +#define SCB_STATUS_FR 0x4000 // frame received +#define SCB_STATUS_CNA 0x2000 // CU left active state +#define SCB_STATUS_RNR 0x1000 // receiver left ready state +#define SCB_STATUS_MDI 0x0800 // MDI read/write cycle done +#define SCB_STATUS_SWI 0x0400 // software generated interrupt +#define SCB_STATUS_FCP 0x0100 // flow control pause interrupt + +#define SCB_INTACK_MASK 0xFD00 // all the above + +#define SCB_INTACK_TX (SCB_STATUS_CX | SCB_STATUS_CNA) +#define SCB_INTACK_RX (SCB_STATUS_FR | SCB_STATUS_RNR) + +// ------------------------------------------------------------------------ +// +// 82559 PORT INTERFACE COMMANDS +// +// ------------------------------------------------------------------------ +#define I82559_RESET 0x00000000 // software reset +#define I82559_SELFTEST 0x00000001 // 82559 selftest command +#define I82559_SELECTIVE_RESET 0x00000002 +#define I82559_DUMP 0x00000003 +#define I82559_DUMP_WAKEUP 0x00000007 + + + +// ------------------------------------------------------------------------ +// +// 82559 EEPROM INTERFACE +// +// ------------------------------------------------------------------------ +// EEPROM_Ctrl bits. +#define EE_SHIFT_CLK 0x01 // EEPROM shift clock. +#define EE_CS 0x02 // EEPROM chip select. +#define EE_DATA_WRITE 0x04 // EEPROM chip data in. +#define EE_DATA_READ 0x08 // EEPROM chip data out. +#define EE_ENB (0x4800 | EE_CS) + +// Delay between EEPROM clock transitions. +#define eeprom_delay(usec) udelay(usec); + +// The EEPROM commands include the always-set leading bit. +#define EE_WRITE_CMD(a) (5 << (a)) +#define EE_READ_CMD(a) (6 << (a)) +#define EE_ERASE_CMD(a) (7 << (a)) +#define EE_WRITE_EN_CMD(a) (19 << ((a)-2)) +#define EE_WRITE_DIS_CMD(a) (16 << ((a)-2)) +#define EE_ERASE_ALL_CMD(a) (18 << ((a)-2)) + +#define EE_TOP_CMD_BIT(a) ((a)+2) // Counts down to zero +#define EE_TOP_DATA_BIT (15) // Counts down to zero + +#define EEPROM_ENABLE_DELAY (10) // Delay at chip select + +#define EEPROM_SK_DELAY (2) // Delay between clock edges *and* data + // read or transition; 3 of these per bit. +#define EEPROM_DONE_DELAY (100) // Delay when all done + + +// ------------------------------------------------------------------------ +// +// SYSTEM CONTROL BLOCK COMMANDS +// +// ------------------------------------------------------------------------ +// CU COMMANDS +#define CU_NOP 0x0000 +#define CU_START 0x0010 +#define CU_RESUME 0x0020 +#define CU_STATSADDR 0x0040 // Load Dump Statistics ctrs addr +#define CU_SHOWSTATS 0x0050 // Dump statistics counters. +#define CU_ADDR_LOAD 0x0060 // Base address to add to CU commands +#define CU_DUMPSTATS 0x0070 // Dump then reset stats counters. + +// RUC COMMANDS +#define RUC_NOP 0x0000 +#define RUC_START 0x0001 +#define RUC_RESUME 0x0002 +#define RUC_ABORT 0x0004 +#define RUC_ADDR_LOAD 0x0006 // (seems not to clear on acceptance) +#define RUC_RESUMENR 0x0007 + +#define SCB_M 0x0100 // 0 = enable interrupt, 1 = disable +#define SCB_SI 0x0200 // 1 - cause device to interrupt + +#define CU_STATUS_MASK 0x00C0 +#define RU_STATUS_MASK 0x003C + +#define RU_STATUS_IDLE (0<<2) +#define RU_STATUS_SUS (1<<2) +#define RU_STATUS_NORES (2<<2) +#define RU_STATUS_READY (4<<2) +#define RU_STATUS_NO_RBDS_SUS ((1<<2)|(8<<2)) +#define RU_STATUS_NO_RBDS_NORES ((2<<2)|(8<<2)) +#define RU_STATUS_NO_RBDS_READY ((4<<2)|(8<<2)) + + + +#define MAX_MEM_RESERVED_IOCTL 1000 + +// ------------------------------------------------------------------------ +// +// RECEIVE FRAME DESCRIPTORS +// +// ------------------------------------------------------------------------ +typedef struct rfd { + volatile union { + cyg_uint32 u32_status; // result of receive operation + cyg_uint16 u16_status[2]; + } u_status; + volatile cyg_uint32 link; // offset from RU base to next RFD + volatile cyg_uint32 rdb_address; // pointer to Rx data buffer + volatile cyg_uint32 count:14, // number of bytes received + + f:1, // + EOF & F flags + eof:1, + size:16; // size of the data buffer + volatile cyg_uint8 buffer[0]; // data buffer (simple mode) +} RFD; + +// The status is split into two shorts to get atomic access to the EL bit; +// the upper word is not written by the device, so we can just hit it, +// leaving the lower word (which the device updates) alone. Otherwise +// there's a race condition between software moving the end-of-list (EL) +// bit round and the device writing into the previous slot. + +#define rxstatus u_status.u32_status +#define rxstatus_hi u_status.u16_status[1] +#define rxstatus_lo u_status.u16_status[0] + +#define RFD_STATUS_EL 0x80000000 // 1=last RFD in RFA +#define RFD_STATUS_S 0x40000000 // 1=suspend RU after receiving frame +#define RFD_STATUS_H 0x00100000 // 1=RFD is a header RFD +#define RFD_STATUS_SF 0x00080000 // 0=simplified, 1=flexible mode +#define RFD_STATUS_C 0x00008000 // completion of received frame +#define RFD_STATUS_OK 0x00002000 // frame received with no errors + +#define RFD_STATUS_HI_EL 0x8000 // 1=last RFD in RFA +#define RFD_STATUS_HI_S 0x4000 // 1=suspend RU after receiving frame +#define RFD_STATUS_HI_H 0x0010 // 1=RFD is a header RFD +#define RFD_STATUS_HI_SF 0x0008 // 0=simplified, 1=flexible mode + +#define RFD_STATUS_LO_C 0x8000 // completion of received frame +#define RFD_STATUS_LO_OK 0x2000 // frame received with no errors + +#define RFD_RX_CRC 0x00000800 // crc error +#define RFD_RX_ALIGNMENT 0x00000400 // alignment error +#define RFD_RX_RESOURCE 0x00000200 // out of space, no resources +#define RFD_RX_DMA_OVER 0x00000100 // DMA overrun +#define RFD_RX_SHORT 0x00000080 // short frame error +#define RFD_RX_LENGTH 0x00000020 // +#define RFD_RX_ERROR 0x00000010 // receive error +#define RFD_RX_NO_ADR_MATCH 0x00000004 // no address match +#define RFD_RX_IA_MATCH 0x00000002 // individual address does not match +#define RFD_RX_TCO 0x00000001 // TCO indication + + +typedef struct rbd { + volatile cyg_uint32 count:14, // bytes used in buffer + f:1, // buffer has been used (filled) + eof:1; // last receive buffer in frame + volatile cyg_uint32 next_rbd; // next RBD (RU base relative) + volatile cyg_uint32 buffer_address; // address of receive data buffer + volatile cyg_uint32 size:15, // size of the associated buffer + el:1; // buffer of this RBD is last +} RBD; + + +// ------------------------------------------------------------------------ +// +// TRANSMIT FRAME DESCRIPTORS +// +// ------------------------------------------------------------------------ +typedef struct txcb { + volatile cyg_uint32 txstatus:16, // result of transmit operation + command:16; // transmit command + volatile cyg_uint32 link; // offset from RU base to next RFD + volatile cyg_uint32 tbd_address; // pointer to Rx data buffer + volatile cyg_uint32 count:15, // number of bytes in transmit buffer + eof:1, + tx_threshold:8, + tbd_number:8; + volatile cyg_uint8 buffer[0]; // data buffer (simple mode) +} TxCB; + + +#define TxCB_CMD_TRANSMIT 0x0004 // transmit command +#define TxCB_CMD_SF 0x0008 // 0=simplified, 1=flexible mode +#define TxCB_CMD_NC 0x0010 // 0=CRC insert by controller +#define TxCB_CMD_I 0x2000 // generate interrupt on completion +#define TxCB_CMD_S 0x4000 // suspend on completion +#define TxCB_CMD_EL 0x8000 // last command block in CBL + + +// ------------------------------------------------------------------------ +// +// STRUCTURES ADDED FOR PROMISCUOUS MODE +// +// ------------------------------------------------------------------------ +typedef struct { + cyg_uint32 cb_status_word:13, + cb_ok:1, + cb_dc:1, + cb_complete:1, + cb_cmd:3, + cb_cmd_word:10, + cb_int:1, + cb_suspend:1, + cb_el:1; + cyg_uint32 cb_link_offset; +} CB_STRUCT; + + +typedef struct { + CB_STRUCT cb_entry; + cyg_uint8 config_bytes[24]; +} CONFIG_CMD_STRUCT; + +// ------------------------------------------------------------------------ +// +// STATISTICAL COUNTER STRUCTURE +// +// ------------------------------------------------------------------------ +#ifdef KEEP_STATISTICS +STATISTICS statistics[2]; +I82559_COUNTERS i82559_counters[2]; +#endif // KEEP_STATISTICS + +// ------------------------------------------------------------------------ +// +// DEVICES AND PACKET QUEUES +// +// ------------------------------------------------------------------------ + +#define MAX_RX_PACKET_SIZE 1536 // maximum Rx packet size +#define MAX_TX_PACKET_SIZE 1536 // maximum Tx packet size + + +// This is encapsulated here so that a change to > 2 interfaces can +// easily be accommodated. + +#define IF_BAD_82559( _p_ ) \ + CYG_ASSERT( (&i82559[0] == (_p_)) || (&i82559[1] == (_p_)), \ + "Bad pointer-to-i82559" ); \ + if ( (&i82559[0] != (_p_)) && (&i82559[1] != (_p_)) ) + +// ------------------------------------------------------------------------ +// Instantiate the interfaces that we have: + +// number of interfaces +#define MAX_82559 CYGNUM_DEVS_ETH_ARM_INTEGRATOR_DEV_COUNT + +I82559 i82559[MAX_82559]; // i82559 device info. structure + +// eth0 + +ETH_DRV_SC(integrator_sc0, + &i82559[0], // Driver specific data + "eth0", // Name for this interface + i82559_start, + i82559_stop, + i82559_ioctl, + i82559_can_send, + i82559_send, + i82559_recv, + i82559_deliver, + i82559_poll, + i82559_int_vector); + +NETDEVTAB_ENTRY(integrator_netdev0, + "integrator-0", + integrator_i82559_init, + &integrator_sc0); + +#if (MAX_82559 > 1) + +// eth1 + +ETH_DRV_SC(integrator_sc1, + &i82559[1], // Driver specific data + "eth1", // Name for this interface + i82559_start, + i82559_stop, + i82559_ioctl, + i82559_can_send, + i82559_send, + i82559_recv, + i82559_deliver, + i82559_poll, + i82559_int_vector); + +NETDEVTAB_ENTRY(integrator_netdev1, + "integrator-1", + integrator_i82559_init, + &integrator_sc1); + +#else +int integrator_netdev1 = -1; // for asserts about valid addresses +int integrator_sc1 = -1; +#endif // eth1 is included + +// This is in a macro so that if more devices arrive it can easily be changed +#define CHECK_NDP_SC_LINK() CYG_MACRO_START \ + CYG_ASSERT( ((void *)ndp == (void *)&integrator_netdev0) || \ + ((void *)ndp == (void *)&integrator_netdev1), "Bad ndp" ); \ + CYG_ASSERT( ((void *)sc == (void *)&integrator_sc0) || \ + ((void *)sc == (void *)&integrator_sc1), "Bad sc" ); \ + CYG_ASSERT( (void *)p_i82559 == sc->driver_private, "sc pointer bad" );\ +CYG_MACRO_END + +// ------------------------------------------------------------------------ +// +// Managing the memory that is windowed onto the PCI bus +// +// ------------------------------------------------------------------------ + +static cyg_uint32 i82559_heap_size; +static cyg_uint8 *i82559_heap_base; +static cyg_uint8 *i82559_heap_free; + +static void *mem_reserved_ioctl = (void*)0; +// uncacheable memory reserved for ioctl calls + +static int mux_device_index = 0; + +// ------------------------------------------------------------------------ +// +// FUNCTION PROTOTYPES +// +// ------------------------------------------------------------------------ + +static int pci_init_find_82559s(void); + +static void i82559_reset(struct i82559* p_i82559); + +static void InitRxRing(struct i82559* p_i82559); +static void ResetRxRing(struct i82559* p_i82559); +static void InitTxRing(struct i82559* p_i82559); +static void ResetTxRing(struct i82559* p_i82559); + +#ifdef CYGPKG_DEVS_ETH_ARM_INTEGRATOR_WRITE_EEPROM +static void program_eeprom(cyg_uint32 , cyg_uint32 , cyg_uint8 * ); +#endif +#ifdef CYGPKG_NET +static int eth_set_promiscuous_mode(struct i82559* p_i82559); +#endif + +// debugging/logging only: +void dump_txcb(TxCB *p_txcb); +void DisplayStatistics(void); +void update_statistics(struct i82559* p_i82559); +void dump_rfd(RFD *p_rfd, int anyway ); +void dump_all_rfds( int intf ); +void dump_packet(cyg_uint8 *p_buffer, int length); + +// ------------------------------------------------------------------------ +// utilities +// ------------------------------------------------------------------------ + +static // inline +void wait_for_cmd_done(long scb_ioaddr) +{ + register int CSRstatus; + register int wait = 0x100000; + do CSRstatus = INB(scb_ioaddr + SCBCmd) ; + while( CSRstatus && --wait >= 0); + CYG_ASSERT( wait > 0, "wait_for_cmd_done" ); +} + +static inline void Mask82559Interrupt(struct i82559* p_i82559) +{ + cyg_drv_interrupt_mask(p_i82559->vector); +} + +static inline void UnMask82559Interrupt(struct i82559* p_i82559) +{ + cyg_drv_interrupt_unmask(p_i82559->vector); +} + +#ifdef CYGDBG_USE_ASSERTS // an indication of a debug build +static int acknowledge82559interrupt_compensating = 0; +#endif + +static void Acknowledge82559Interrupt(struct i82559* p_i82559) +{ + cyg_uint32 sources, mask; + cyg_uint32 ioaddr; + cyg_uint16 status; + int loops = 64; + + cyg_drv_interrupt_acknowledge(p_i82559->vector); + + // It appears that some time can be taken before the interrupt source + // *really* quietens down... this is ugly, but effective. + // Without it, we get "Spurious Interrupt!" failures. + ioaddr = p_i82559->io_address; // get I/O address for 82559 + mask = (1 << p_i82559->vector); // Do not include the MUX vector or we + sources = *(cyg_uint32 *)INTEGRATOR_IRQCONT_IRQSTATUS; //...get hung on the other 82559 + status = INW(ioaddr + SCBStatus); + + while ( ((0 != (sources & mask)) || (0 != (status & SCB_INTACK_MASK))) + && --loops >= 0) { + OUTW( status & SCB_INTACK_MASK, ioaddr + SCBStatus); + cyg_drv_interrupt_acknowledge(p_i82559->vector); + +#ifdef CYGDBG_USE_ASSERTS + acknowledge82559interrupt_compensating++; // verify this is executed +#endif + sources = *(cyg_uint32 *)INTEGRATOR_IRQCONT_IRQSTATUS; + status = INW(ioaddr + SCBStatus); + } + CYG_ASSERT( loops >= 0, "Acknowledge82559Interrupt" ); +} + + +static void udelay(int delay) +{ + int i; + // the loop is going to take 3 ticks. At 228 MHz, to give uS, multiply + // by 228/3 = 76 near enough. No volatile is needed on i; gcc recognizes + // delay loops and does NOT elide them. + for ( i = 76 * delay; i ; i--) + ; +} + +// ------------------------------------------------------------------------ +// Memory management +// +// Simply carve off from the front of the PCI mapped window into real memory + +static void *pciwindow_mem_alloc(int size) +{ + void *p_memory; + + CYG_ASSERT( + (CYGHWR_HAL_ARM_INTEGRATOR_PCI_MEM_MAP_BASE <= (int)i82559_heap_free) + && + ((CYGHWR_HAL_ARM_INTEGRATOR_PCI_MEM_MAP_BASE + + CYGHWR_HAL_ARM_INTEGRATOR_PCI_MEM_MAP_SIZE) > (int)i82559_heap_free) + && + (0 < i82559_heap_size) + && + (CYGHWR_HAL_ARM_INTEGRATOR_PCI_MEM_MAP_SIZE >= i82559_heap_size) + && + (CYGHWR_HAL_ARM_INTEGRATOR_PCI_MEM_MAP_BASE == (int)i82559_heap_base), + "Heap variables corrupted" ); + + p_memory = (void *)0; + size = (size + 3) & ~3; + if ( (i82559_heap_free + size) < (i82559_heap_base + i82559_heap_size) ) { + cyg_uint32 *p; + p_memory = (void *)i82559_heap_free; + i82559_heap_free += size; + for ( p = (cyg_uint32 *)p_memory; size > 0; size -= 4 ) + *p++ = 0; + } + + return p_memory; +} + +// ------------------------------------------------------------------------ +// +// GET EEPROM SIZE +// +// ------------------------------------------------------------------------ +static int get_eeprom_size(long ioaddr) +{ + unsigned short retval = 0; + int ee_addr = ioaddr + SCBeeprom; + int i, addrbits; + + // Should already be not-selected, but anyway: + OUTW(EE_ENB & ~EE_CS, ee_addr); + eeprom_delay(EEPROM_ENABLE_DELAY); + OUTW(EE_ENB, ee_addr); + eeprom_delay(EEPROM_ENABLE_DELAY); + + // Shift the read command bits out. + for (i = 2; i >= 0; i--) { + short dataval = (6 & (1 << i)) ? EE_DATA_WRITE : 0; + OUTW(EE_ENB | dataval , ee_addr); + eeprom_delay(EEPROM_SK_DELAY); + OUTW(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); + eeprom_delay(EEPROM_SK_DELAY); + OUTW(EE_ENB | dataval , ee_addr); + eeprom_delay(EEPROM_SK_DELAY); + } + // Now clock out address zero, looking for the dummy 0 data bit + for ( i = 1; i <= 12; i++ ) { + OUTW(EE_ENB , ee_addr); + eeprom_delay(EEPROM_SK_DELAY); + OUTW(EE_ENB | EE_SHIFT_CLK, ee_addr); + eeprom_delay(EEPROM_SK_DELAY); + OUTW(EE_ENB , ee_addr); + eeprom_delay(EEPROM_SK_DELAY); + retval = INW(ee_addr) & EE_DATA_READ; + if ( 0 == retval ) + break; // The dummy zero est arrive' + } + +#ifdef DEBUG_EE + os_printf( "eeprom data bits %d (ioaddr %x)\n", i, ee_addr ); +#endif + if ( 6 != i && 8 != i ) { +#ifdef DEBUG_EE + os_printf( "*****EEPROM data bits not 6 or 8*****\n" ); +#endif + i = 6; + } + addrbits = i; + + // clear the dataval, leave the clock low to read in the data regardless + OUTW(EE_ENB, ee_addr); + eeprom_delay(1); + + retval = INW(ee_addr); + if ( (EE_DATA_READ & retval) != 0 ) { +#ifdef DEBUG_EE + os_printf( "Size EEPROM: Dummy data bit not 0, reg %x\n" , retval ); +#endif + } + eeprom_delay(1); + + for (i = EE_TOP_DATA_BIT; i >= 0; i--) { + OUTW(EE_ENB | EE_SHIFT_CLK, ee_addr); + eeprom_delay(EEPROM_SK_DELAY); + retval = INW(ee_addr); + eeprom_delay(EEPROM_SK_DELAY); + OUTW(EE_ENB, ee_addr); + eeprom_delay(EEPROM_SK_DELAY); + } + + // Terminate the EEPROM access. + OUTW(EE_ENB & ~EE_CS, ee_addr); + eeprom_delay(EEPROM_DONE_DELAY); + + return addrbits; +} + + +// ------------------------------------------------------------------------ +// +// READ EEPROM +// +// ------------------------------------------------------------------------ +static int read_eeprom(long ioaddr, int location, int addr_len) +{ + unsigned short retval = 0; + int ee_addr = ioaddr + SCBeeprom; + int read_cmd = location | EE_READ_CMD(addr_len); + int i, tries = 10; + + try_again: + // Should already be not-selected, but anyway: + OUTW(EE_ENB & ~EE_CS, ee_addr); + eeprom_delay(EEPROM_ENABLE_DELAY); + OUTW(EE_ENB, ee_addr); + eeprom_delay(EEPROM_ENABLE_DELAY); + + // Shift the read command bits out, changing only one bit per time. + for (i = EE_TOP_CMD_BIT(addr_len); i >= 0; i--) { + short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + OUTW(EE_ENB | dataval , ee_addr); + eeprom_delay(EEPROM_SK_DELAY); + OUTW(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); + eeprom_delay(EEPROM_SK_DELAY); + OUTW(EE_ENB | dataval , ee_addr); + eeprom_delay(EEPROM_SK_DELAY); + } + + // clear the dataval, leave the clock low + OUTW(EE_ENB, ee_addr); + eeprom_delay(1); + + retval = INW(ee_addr); + // This should show a zero in the data read bit to confirm that the + // address transfer is compelete. If not, go to the start and try + // again! + if ( (0 != (retval & EE_DATA_READ)) && (tries-- > 0) ) { + // Terminate the EEPROM access. + OUTW(EE_ENB & ~EE_CS, ee_addr); + eeprom_delay(EEPROM_DONE_DELAY); +#ifdef DEBUG_EE + os_printf( "Warning: Retrying EEPROM read word %d, address %x, try %d\n", + location, ee_addr, tries+1 ); +#endif + goto try_again; + } + + // This fires with one device on one of the customer boards! + // (but is OK on all other h/w. Worrying huh.) + if ( (EE_DATA_READ & retval) != 0 ) { +#ifdef DEBUG_EE + os_printf( "Read EEPROM: Dummy data bit not 0, reg %x\n" , retval ); +#endif + } + eeprom_delay(1); + retval = 0; + + for (i = EE_TOP_DATA_BIT; i >= 0; i--) { + OUTW(EE_ENB | EE_SHIFT_CLK, ee_addr); + eeprom_delay(EEPROM_SK_DELAY); + retval = (retval << 1) | ((INW(ee_addr) & EE_DATA_READ) ? 1 : 0); + eeprom_delay(EEPROM_SK_DELAY); + OUTW(EE_ENB, ee_addr); + eeprom_delay(EEPROM_SK_DELAY); + } + + // Terminate the EEPROM access. + OUTW(EE_ENB & ~EE_CS, ee_addr); + eeprom_delay(EEPROM_DONE_DELAY); + + return retval; +} + + +// ------------------------------------------------------------------------ +// +// NETWORK INTERFACE INITIALIZATION +// +// Function : Init82559 +// +// Description : +// This routine resets, configures, and initializes the chip. +// It also clears the ethernet statistics structure, and selects +// which statistics are supported by this driver. +// +// ------------------------------------------------------------------------ +static bool +integrator_i82559_init(struct cyg_netdevtab_entry * ndp) +{ + static int initialized = 0; // only probe PCI et al *once* + + struct eth_drv_sc *sc; + cyg_uint32 selftest; + volatile cyg_uint32 *p_selftest; + cyg_uint32 ioaddr; + cyg_uint16 checksum; + int count; + int i; + int addr_length; + cyg_uint8 mac_address[6]; + struct i82559 *p_i82559; + +#ifdef DEBUG + db_printf("integrator_i82559_init\n"); +#endif + + sc = (struct eth_drv_sc *)(ndp->device_instance); + p_i82559 = (struct i82559 *)(sc->driver_private); + + IF_BAD_82559( p_i82559 ) { +#ifdef DEBUG + os_printf( "Bad device private pointer %x\n", sc->driver_private ); +#endif + return 0; + } + + CHECK_NDP_SC_LINK(); + + if ( 0 == initialized++ ) { + // then this is the first time ever: + if ( ! pci_init_find_82559s() ) { +#ifdef DEBUG + os_printf( "pci_init_find_82559s failed" ); +#endif + return 0; + } + } + + if ( ! p_i82559->found ) // no device on PCI bus + return (0); + + ioaddr = p_i82559->io_address; // get I/O address for 82559 + +#ifdef DEBUG + os_printf("Init82559 %d @ %x\n82559 Self Test\n", + p_i82559->index, (int)ndp); +#endif + + Mask82559Interrupt(p_i82559); + + wait_for_cmd_done(ioaddr); // make sure no command operating + + i82559_reset(p_i82559); + + // Perform a system self-test. (get enough mem to round address) + if ( (selftest = (cyg_uint32)pciwindow_mem_alloc(32) ) == 0) + return (0); + + p_selftest = (cyg_uint32 *) ((selftest + 15) & ~0xf); + p_selftest[0] = p_selftest[1] = -1; + + OUTL( (VIRT_TO_BUS(p_selftest)) | I82559_SELFTEST, ioaddr + SCBPort); + count = 0x7FFFF; // Timeout for self-test. + do { + udelay(10); + } while ( (p_selftest[1] == -1) && (--count >= 0) ); + + Acknowledge82559Interrupt(p_i82559); + UnMask82559Interrupt(p_i82559); + + if (count < 0) { + // Test timed out. +#ifdef DEBUG + os_printf("Self test failed\n"); +#endif + return (0); + } +#ifdef DEBUG + os_printf(" General self-test: %s.\n" + " Serial sub-system self-test: %s.\n" + " Internal registers self-test: %s.\n" + " ROM checksum self-test: %s (%08X).\n", + p_selftest[1] & 0x1000 ? "failed" : "passed", + p_selftest[1] & 0x0020 ? "failed" : "passed", + p_selftest[1] & 0x0008 ? "failed" : "passed", + p_selftest[1] & 0x0004 ? "failed" : "passed", + p_selftest[0]); +#endif + + // read eeprom and get 82559's mac address + addr_length = get_eeprom_size(ioaddr); + // (this is the length of the *EEPROM*s address, not MAC address) + + for (checksum = 0, i = 0, count = 0; count < 64; count++) { + cyg_uint16 value; + // read word from eeprom + value = read_eeprom(ioaddr, count, addr_length); +#ifdef DEBUG_EE + // os_printf( "%2d: %04x\n", count, value ); +#endif + checksum += value; + if (count < 3) { + mac_address[i++] = value & 0xFF; + mac_address[i++] = (value >> 8) & 0xFF; + } + } + + // If the EEPROM checksum is wrong, the MAC address read from the + // EEPROM is probably wrong as well. In that case, we don't set + // mac_addr_ok, but continue the initialization. If then somebody calls + // i82559_start without calling eth_set_mac_address() first, we refuse + // to bring up the interface, because running with an invalid MAC + // address is not a very brilliant idea. + + if ((checksum & 0xFFFF) != 0xBABA) { + // selftest verified checksum, verify again +#ifdef DEBUG_EE + os_printf( "Warning: Invalid EEPROM checksum %04X for device %d\n", + checksum, p_i82559->index); +#endif + } else { + p_i82559->mac_addr_ok = 1; +#ifdef DEBUG_EE + os_printf("Valid EEPROM checksum %x\n", checksum); +#endif + } +#ifdef DEBUG + os_printf("MAC Address = %02X %02X %02X %02X %02X %02X\n", + mac_address[0], mac_address[1], mac_address[2], mac_address[3], + mac_address[4], mac_address[5]); +#endif + + // record the MAC address in the device structure + p_i82559->mac_address[0] = mac_address[0]; + p_i82559->mac_address[1] = mac_address[1]; + p_i82559->mac_address[2] = mac_address[2]; + p_i82559->mac_address[3] = mac_address[3]; + p_i82559->mac_address[4] = mac_address[4]; + p_i82559->mac_address[5] = mac_address[5]; + + // and record the net dev pointer + p_i82559->ndp = (void *)ndp; + + InitRxRing(p_i82559); + InitTxRing(p_i82559); + + // Initialize upper level driver + if ( p_i82559->mac_addr_ok ) + (sc->funs->eth_drv->init)(sc, &(p_i82559->mac_address[0]) ); + else + (sc->funs->eth_drv->init)(sc, 0 ); + + return (1); +} + +// ------------------------------------------------------------------------ +// +// Function : i82559_start +// +// ------------------------------------------------------------------------ +static void i82559_start( struct eth_drv_sc *sc, + unsigned char *enaddr, int flags ) +{ + struct i82559 *p_i82559; + cyg_uint32 ioaddr; +#ifdef KEEP_STATISTICS + void *p_statistics; +#endif +#ifdef CYGPKG_NET + struct ifnet *ifp = &sc->sc_arpcom.ac_if; +#endif + + p_i82559 = (struct i82559 *)sc->driver_private; + + IF_BAD_82559( p_i82559 ) { +#ifdef DEBUG + os_printf( "i82559_start: Bad device pointer %x\n", p_i82559 ); +#endif + return; + } + + if ( ! p_i82559->mac_addr_ok ) { +#ifdef DEBUG + os_printf("i82559_start %d: invalid MAC address, " + "can't bring up interface\n", + p_i82559->index ); +#endif + return; + } + + if ( p_i82559->active ) + i82559_stop( sc ); + + ioaddr = p_i82559->io_address; // get 82559's I/O address + +#ifdef KEEP_STATISTICS +#ifdef CYGDBG_DEVS_ETH_ARM_INTEGRATOR_KEEP_82559_STATISTICS + p_i82559->p_statistics = + p_statistics = pciwindow_mem_alloc(sizeof(I82559_COUNTERS)); + memset(p_statistics, 0xFFFFFFFF, sizeof(I82559_COUNTERS)); + wait_for_cmd_done(ioaddr); // make sure no command operating + // set statistics dump address + OUTL(VIRT_TO_BUS(p_statistics), ioaddr + SCBPointer); + OUTW(SCB_M | CU_STATSADDR, ioaddr + SCBCmd); + + wait_for_cmd_done(ioaddr); // make sure no command operating + OUTW(SCB_M | CU_DUMPSTATS, ioaddr + SCBCmd); // start register dump +#endif +#endif + + // Set the base address + wait_for_cmd_done(ioaddr); + OUTL(0, ioaddr + SCBPointer); // load ru base address = 0 + OUTW(SCB_M | RUC_ADDR_LOAD, ioaddr + SCBCmd); + udelay( 1000 ); // load pointer to Rx Ring + OUTL(VIRT_TO_BUS(p_i82559->rx_ring[0]), ioaddr + SCBPointer); + OUTW(RUC_START, ioaddr + SCBCmd); + + p_i82559->active = 1; + +#ifdef CYGPKG_NET + if (( 0 +#ifdef ETH_DRV_FLAGS_PROMISC_MODE + != (flags & ETH_DRV_FLAGS_PROMISC_MODE) +#endif + ) || (ifp->if_flags & IFF_PROMISC) + ) { + eth_set_promiscuous_mode(p_i82559); + } +#endif + +#ifdef DEBUG + { + int status = i82559_status( sc ); + os_printf("i82559_start %d flg %x Link = %s, %s Mbps, %s Duplex\n", + p_i82559->index, + *(int *)p_i82559, + status & GEN_STATUS_LINK ? "Up" : "Down", + status & GEN_STATUS_100MBPS ? "100" : "10", + status & GEN_STATUS_FDX ? "Full" : "Half"); + } +#endif +} + +// ------------------------------------------------------------------------ +// +// Function : i82559_status +// +// ------------------------------------------------------------------------ +int i82559_status( struct eth_drv_sc *sc ) +{ + int status; + struct i82559 *p_i82559; + cyg_uint32 ioaddr; + p_i82559 = (struct i82559 *)sc->driver_private; + + IF_BAD_82559( p_i82559 ) { +#ifdef DEBUG + os_printf( "i82559_status: Bad device pointer %x\n", p_i82559 ); +#endif + return 0; + } + + ioaddr = p_i82559->io_address; // get 82559's I/O address + + status = INB(ioaddr + SCBGenStatus); + + return status; +} + +// ------------------------------------------------------------------------ +// +// Function : BringDown82559 +// +// ------------------------------------------------------------------------ + +static void i82559_stop( struct eth_drv_sc *sc ) +{ + struct i82559 *p_i82559; + + p_i82559 = (struct i82559 *)sc->driver_private; + + IF_BAD_82559( p_i82559 ) { +#ifdef DEBUG + os_printf( "i82559_stop: Bad device pointer %x\n", p_i82559 ); +#endif + return; + } + +#ifdef DEBUG + os_printf("i82559_stop %d flg %x\n", p_i82559->index, *(int *)p_i82559 ); +#endif + + p_i82559->active = 0; // stop people tormenting it + i82559_reset(p_i82559); // that should stop it + + ResetRxRing( p_i82559 ); + ResetTxRing( p_i82559 ); +} + + +// ------------------------------------------------------------------------ +// +// Function : InitRxRing +// +// ------------------------------------------------------------------------ +static void InitRxRing(struct i82559* p_i82559) +{ + int i, j; + RFD *rfd; + RFD *p_rfd = 0; +#ifdef DEBUG_82559 + os_printf("InitRxRing %d\n", p_i82559->index); +#endif + for ( i = 0; i < MAX_RX_DESCRIPTORS; i++ ) { + rfd = (RFD *)pciwindow_mem_alloc(sizeof(RFD) + MAX_RX_PACKET_SIZE); + p_i82559->rx_ring[i] = rfd; + if ( i ) + p_rfd->link = VIRT_TO_BUS(rfd); + p_rfd = (RFD *)rfd; + } + // link last RFD to first: + p_rfd->link = VIRT_TO_BUS(p_i82559->rx_ring[0]); + + ResetRxRing( p_i82559 ); +} + +// ------------------------------------------------------------------------ +// +// Function : ResetRxRing +// +// ------------------------------------------------------------------------ +static void ResetRxRing(struct i82559* p_i82559) +{ + RFD *p_rfd; + int i; +#ifdef DEBUG_82559 + os_printf("ResetRxRing %d\n", p_i82559->index); +#endif + for ( i = 0; i < MAX_RX_DESCRIPTORS; i++ ) { + p_rfd = p_i82559->rx_ring[i]; + CYG_ASSERT( (cyg_uint8 *)p_rfd >= i82559_heap_base, "rfd under" ); + CYG_ASSERT( (cyg_uint8 *)p_rfd < i82559_heap_free, "rfd over" ); + CYG_ASSERT( p_i82559->rx_ring[ + ( i ? (i-1) : (MAX_RX_DESCRIPTORS-1) ) + ]->link == VIRT_TO_BUS(p_rfd), "rfd linked list broken" ); + p_rfd->rxstatus = 0; + p_rfd->count = 0; + p_rfd->f = 0; + p_rfd->eof = 0; + p_rfd->rdb_address = 0xFFFFFFFF; + p_rfd->size = MAX_RX_PACKET_SIZE; + } + p_i82559->next_rx_descriptor = 0; + // And set an end-of-list marker in the previous one. + p_rfd->rxstatus = RFD_STATUS_EL; +} + +// ------------------------------------------------------------------------ +// +// Function : PacketRxReady (Called from delivery thread) +// +// ------------------------------------------------------------------------ +static void PacketRxReady(struct i82559* p_i82559) +{ + RFD *p_rfd; + int next_descriptor; + int length; + struct cyg_netdevtab_entry *ndp; + struct eth_drv_sc *sc; + cyg_uint32 ioaddr; + cyg_uint16 status; + + ndp = (struct cyg_netdevtab_entry *)(p_i82559->ndp); + sc = (struct eth_drv_sc *)(ndp->device_instance); + + CHECK_NDP_SC_LINK(); + + ioaddr = p_i82559->io_address; + + next_descriptor = p_i82559->next_rx_descriptor; + p_rfd = p_i82559->rx_ring[next_descriptor]; + + CYG_ASSERT( (cyg_uint8 *)p_rfd >= i82559_heap_base, "rfd under" ); + CYG_ASSERT( (cyg_uint8 *)p_rfd < i82559_heap_free, "rfd over" ); + + while ( p_rfd->rxstatus & RFD_STATUS_C ) { + p_rfd->rxstatus_hi |= RFD_STATUS_HI_EL; + length = p_rfd->count; + +#ifdef DEBUG_82559 + os_printf( "Device %d (eth%d), rx descriptor %d:\n", + p_i82559->index, p_i82559->index, next_descriptor ); +// dump_rfd( p_rfd, 1 ); +#endif + + p_i82559->next_rx_descriptor = next_descriptor; + // Check for bogusly short packets; can happen in promisc mode: + // Asserted against and checked by upper layer driver. +#ifdef CYGPKG_NET + if ( length > sizeof( struct ether_header ) ) + // then it is acceptable; offer the data to the network stack +#endif + (sc->funs->eth_drv->recv)( sc, length ); + + p_rfd->count = 0; + p_rfd->f = 0; + p_rfd->eof = 0; + p_rfd->rxstatus_lo = 0; + + // The just-emptied slot is now ready for re-use and already marked EL; + // we can now remove the EL marker from the previous one. + if ( 0 == next_descriptor ) + p_rfd = p_i82559->rx_ring[ MAX_RX_DESCRIPTORS-1 ]; + else + p_rfd = p_i82559->rx_ring[ next_descriptor-1 ]; + // The previous one: check it *was* marked before clearing. + CYG_ASSERT( p_rfd->rxstatus_hi & RFD_STATUS_HI_EL, "No prev EL" ); + p_rfd->rxstatus_hi = 0; // that word is not written by the device. + +#ifdef KEEP_STATISTICS + statistics[p_i82559->index].rx_deliver++; +#endif + if (++next_descriptor >= MAX_RX_DESCRIPTORS) + next_descriptor = 0; + p_rfd = p_i82559->rx_ring[next_descriptor]; + + CYG_ASSERT( (cyg_uint8 *)p_rfd >= i82559_heap_base, "rfd under" ); + CYG_ASSERT( (cyg_uint8 *)p_rfd < i82559_heap_free, "rfd over" ); + } + + // See if the RU has gone idle (usually because of out of resource + // condition) and restart it if needs be. + Mask82559Interrupt(p_i82559); + status = INW(ioaddr + SCBStatus); + + if ( RU_STATUS_READY != (status & RU_STATUS_MASK) ) { + // Acknowledge the RX INT sources + OUTW( SCB_INTACK_RX, ioaddr + SCBStatus); + // (see pages 6-10 & 6-90) + +#ifdef KEEP_STATISTICS + statistics[p_i82559->index].rx_restart++; +#endif + // There's an end-of-list marker out there somewhere... + // So mop it up; it takes a little time but this is infrequent. + ResetRxRing( p_i82559 ); + next_descriptor = 0; // re-initialize next desc. + // wait for SCB command complete + wait_for_cmd_done(ioaddr); + // load pointer to Rx Ring + OUTL(VIRT_TO_BUS(p_i82559->rx_ring[0]), + ioaddr + SCBPointer); + OUTW(RUC_START, ioaddr + SCBCmd); + Acknowledge82559Interrupt(p_i82559); + } + UnMask82559Interrupt(p_i82559); + + p_i82559->next_rx_descriptor = next_descriptor; +} + +// and the callback function + +static void i82559_recv( struct eth_drv_sc *sc, + struct eth_drv_sg *sg_list, int sg_len ) +{ + struct i82559 *p_i82559; + RFD *p_rfd; + int next_descriptor; + int total_len; + struct eth_drv_sg *last_sg; + volatile cyg_uint8 *from_p; + + p_i82559 = (struct i82559 *)sc->driver_private; + + IF_BAD_82559( p_i82559 ) { +#ifdef DEBUG + os_printf( "i82559_recv: Bad device pointer %x\n", p_i82559 ); +#endif + return; + } + + next_descriptor = p_i82559->next_rx_descriptor; + p_rfd = p_i82559->rx_ring[next_descriptor]; + + CYG_ASSERT( (cyg_uint8 *)p_rfd >= i82559_heap_base, "rfd under" ); + CYG_ASSERT( (cyg_uint8 *)p_rfd < i82559_heap_free, "rfd over" ); + + CYG_ASSERT( p_rfd->rxstatus & RFD_STATUS_C, "No complete frame" ); + CYG_ASSERT( p_rfd->rxstatus & RFD_STATUS_EL, "No marked frame" ); + + CYG_ASSERT( p_rfd->rxstatus_lo & RFD_STATUS_LO_C, "No complete frame 2" ); + CYG_ASSERT( p_rfd->rxstatus_hi & RFD_STATUS_HI_EL, "No marked frame 2" ); + + if ( 0 == (p_rfd->rxstatus & RFD_STATUS_C) ) + return; + + total_len = p_rfd->count; + +#ifdef DEBUG_82559 + os_printf("Rx %d %x (status %x): %d sg's, %d bytes\n", + p_i82559->index, (int)p_i82559, p_rfd->rxstatus, sg_len, total_len); +#endif + + // Copy the data to the network stack + from_p = &p_rfd->buffer[0]; + + // check we have memory to copy into; we would be called even if + // caller was out of memory in order to maintain our state. + if ( 0 == sg_len || 0 == sg_list ) + return; // caller was out of mbufs + + CYG_ASSERT( 0 < sg_len, "sg_len underflow" ); + CYG_ASSERT( MAX_ETH_DRV_SG >= sg_len, "sg_len overflow" ); + + for ( last_sg = &sg_list[sg_len]; sg_list < last_sg; sg_list++ ) { + cyg_uint8 *to_p; + int l; + + to_p = (cyg_uint8 *)(sg_list->buf); + l = sg_list->len; + + CYG_ASSERT( 0 <= l, "sg length -ve" ); + + if ( 0 >= l || 0 == to_p ) + return; // caller was out of mbufs + + if ( l > total_len ) + l = total_len; + + memcpy( to_p, (unsigned char *)from_p, l ); + from_p += l; + total_len -= l; + } + + CYG_ASSERT( 0 == total_len, "total_len mismatch in rx" ); + CYG_ASSERT( last_sg == sg_list, "sg count mismatch in rx" ); + CYG_ASSERT( &p_rfd->buffer[0] < from_p, "from_p wild in rx" ); + CYG_ASSERT( &p_rfd->buffer[0] + MAX_RX_PACKET_SIZE >= from_p, + "from_p overflow in rx" ); +} + + +// ------------------------------------------------------------------------ +// +// Function : InitTxRing +// +// ------------------------------------------------------------------------ +static void InitTxRing(struct i82559* p_i82559) +{ + int i, j; + cyg_uint32 ioaddr; + +#ifdef DEBUG_82559 + os_printf("InitTxRing %d\n", p_i82559->index); +#endif + ioaddr = p_i82559->io_address; + for ( i = 0; i < MAX_TX_DESCRIPTORS; i++) { + p_i82559->tx_ring[i] = (TxCB *)pciwindow_mem_alloc( + sizeof(TxCB) + MAX_TX_PACKET_SIZE); + } + ResetTxRing(p_i82559); +} + +// ------------------------------------------------------------------------ +// +// Function : ResetTxRing +// +// ------------------------------------------------------------------------ +static void ResetTxRing(struct i82559* p_i82559) +{ + int i; + cyg_uint32 ioaddr; + +#ifdef DEBUG_82559 + os_printf("ResetTxRing %d\n", p_i82559->index); +#endif + ioaddr = p_i82559->io_address; + p_i82559->tx_descriptor_add = + p_i82559->tx_descriptor_active = + p_i82559->tx_descriptor_remove = 0; + p_i82559->tx_in_progress = + p_i82559->tx_queue_full = 0; + + for ( i = 0; i < MAX_TX_DESCRIPTORS; i++) { + TxCB *p_txcb = p_i82559->tx_ring[i]; + CYG_ASSERT( (cyg_uint8 *)p_txcb >= i82559_heap_base, "txcb under" ); + CYG_ASSERT( (cyg_uint8 *)p_txcb < i82559_heap_free, "txcb over" ); + + p_txcb->txstatus = 0; + p_txcb->command = 0; + p_txcb->link = VIRT_TO_BUS((cyg_uint32)p_txcb); + p_txcb->tbd_address = 0xFFFFFFFF; + p_txcb->tbd_number = 0; + p_txcb->tx_threshold = 16; + p_txcb->eof = 1; + p_txcb->count = 0; + p_i82559->tx_keys[i] = 0; + } + + wait_for_cmd_done(ioaddr); + OUTL(0, ioaddr + SCBPointer); + OUTW(SCB_M | CU_ADDR_LOAD, ioaddr + SCBCmd); +} + +// ------------------------------------------------------------------------ +// +// Function : TxMachine (Called from FG & ISR) +// +// This steps the Tx Machine onto the next record if necessary - allowing +// for missed interrupts, and so on. +// ------------------------------------------------------------------------ + +static void TxMachine(struct i82559* p_i82559) +{ + int tx_descriptor_active; + cyg_uint32 ioaddr; + + tx_descriptor_active = p_i82559->tx_descriptor_active; + ioaddr = p_i82559->io_address; + + // See if the CU is idle when we think it isn't; this is the only place + // tx_descriptor_active is advanced. (Also recovers from a dropped intr) + if ( p_i82559->tx_in_progress ) { + cyg_uint16 status; + status = INW(ioaddr + SCBStatus); + if ( 0 == (status & CU_STATUS_MASK) ) { + // It is idle. So ack the TX interrupts + OUTW( SCB_INTACK_TX, ioaddr + SCBStatus); + // (see pages 6-10 & 6-90) + + // and step on to the next queued tx. + p_i82559->tx_in_progress = 0; + if ( ++tx_descriptor_active >= MAX_TX_DESCRIPTORS ) + tx_descriptor_active = 0; + p_i82559->tx_descriptor_active = tx_descriptor_active; + } + } + + // is the CU idle, and there a next tx to set going? + if ( ( ! p_i82559->tx_in_progress ) + && p_i82559->tx_descriptor_add != tx_descriptor_active ) { + TxCB *p_txcb; + p_txcb = p_i82559->tx_ring[tx_descriptor_active]; + CYG_ASSERT( (cyg_uint8 *)p_txcb >= i82559_heap_base, "txcb under" ); + CYG_ASSERT( (cyg_uint8 *)p_txcb < i82559_heap_free, "txcb over" ); +#ifdef DEBUG_82559 + os_printf("Tx %d %x: Starting Engines\n", + p_i82559->index, (int)p_i82559); +#endif + // make sure no command operating + wait_for_cmd_done(ioaddr); + // start Tx operation + OUTL(VIRT_TO_BUS(p_txcb), ioaddr + SCBPointer); + OUTW(CU_START, ioaddr + SCBCmd); + p_i82559->tx_in_progress = 1; + } +} + +// ------------------------------------------------------------------------ +// +// Function : TxDone (Called from delivery thread) +// +// This returns Tx's from the Tx Machine to the stack (ie. reports +// completion) - allowing for missed interrupts, and so on. +// ------------------------------------------------------------------------ + +static void TxDone(struct i82559* p_i82559) +{ + struct cyg_netdevtab_entry *ndp; + struct eth_drv_sc *sc; + int tx_descriptor_remove = p_i82559->tx_descriptor_remove; + + ndp = (struct cyg_netdevtab_entry *)(p_i82559->ndp); + sc = (struct eth_drv_sc *)(ndp->device_instance); + + CHECK_NDP_SC_LINK(); + + // "Done" txen are from here to active, OR + // the remove one if the queue is full AND its status is nonzero: + while ( (tx_descriptor_remove != p_i82559->tx_descriptor_active) || + ( p_i82559->tx_queue_full && + (0 != p_i82559->tx_ring[ tx_descriptor_remove ]->txstatus) ) ) { + unsigned long key = p_i82559->tx_keys[ tx_descriptor_remove ]; +#ifdef DEBUG_82559 + os_printf("TxDone %d %x: KEY %x\n", + p_i82559->index, (int)p_i82559, key ); +#endif + (sc->funs->eth_drv->tx_done)( sc, key, 1 /* status */ ); + + if ( ++tx_descriptor_remove >= MAX_TX_DESCRIPTORS ) + tx_descriptor_remove = 0; + p_i82559->tx_descriptor_remove = tx_descriptor_remove; + p_i82559->tx_queue_full = 0; + } +} + + +// ------------------------------------------------------------------------ +// +// Function : i82559_can_send +// +// ------------------------------------------------------------------------ + +static int +i82559_can_send(struct eth_drv_sc *sc) +{ + struct i82559 *p_i82559; + + p_i82559 = (struct i82559 *)sc->driver_private; + + IF_BAD_82559( p_i82559 ) { +#ifdef DEBUG + os_printf( "i82559_send: Bad device pointer %x\n", p_i82559 ); +#endif + return 0; + } + + // Advance TxMachine atomically + Mask82559Interrupt(p_i82559); + TxMachine(p_i82559); + Acknowledge82559Interrupt(p_i82559); + PacketRxReady(p_i82559); /* FIX: 16/07/01 added from ebsa */ + UnMask82559Interrupt(p_i82559); + + return ! p_i82559->tx_queue_full; +} + +// ------------------------------------------------------------------------ +// +// Function : i82559_send +// +// ------------------------------------------------------------------------ + +static void +i82559_send(struct eth_drv_sc *sc, + struct eth_drv_sg *sg_list, int sg_len, int total_len, + unsigned long key) +{ + struct i82559 *p_i82559; + int tx_descriptor_add; + TxCB *p_txcb; + cyg_uint32 ioaddr; + + p_i82559 = (struct i82559 *)sc->driver_private; + + IF_BAD_82559( p_i82559 ) { +#ifdef DEBUG + os_printf( "i82559_send: Bad device pointer %x\n", p_i82559 ); +#endif + return; + } + +#ifdef DEBUG_82559 + os_printf("Tx %d %x: %d sg's, %d bytes, KEY %x = %d\n", + p_i82559->index, (int)p_i82559, sg_len, total_len, key, *(int *)key); +#endif + + if ( ! p_i82559->active ) + return; // device inactive, no return + +#ifdef KEEP_STATISTICS + statistics[p_i82559->index].tx_count++; +#endif + ioaddr = p_i82559->io_address; // get device I/O address + + if ( p_i82559->tx_queue_full ) { +#ifdef KEEP_STATISTICS + statistics[p_i82559->index].tx_dropped++; +#endif +#ifdef DEBUG_82559 + os_printf( "i82559_send: Queue full, device %x, key %x\n", + p_i82559, key ); +#endif + } else { + struct eth_drv_sg *last_sg; + volatile cyg_uint8 *to_p; + + tx_descriptor_add = p_i82559->tx_descriptor_add; + + p_i82559->tx_keys[tx_descriptor_add] = key; + + p_txcb = p_i82559->tx_ring[tx_descriptor_add]; + + CYG_ASSERT( (cyg_uint8 *)p_txcb >= i82559_heap_base, "txcb under" ); + CYG_ASSERT( (cyg_uint8 *)p_txcb < i82559_heap_free, "txcb over" ); + + p_txcb->txstatus = 0; + p_txcb->command = TxCB_CMD_TRANSMIT | TxCB_CMD_S + | TxCB_CMD_I | TxCB_CMD_EL; + p_txcb->link = VIRT_TO_BUS((cyg_uint32)p_txcb); + p_txcb->tbd_address = 0xFFFFFFFF; + p_txcb->tbd_number = 0; + p_txcb->tx_threshold = 16; + p_txcb->eof = 1; + p_txcb->count = total_len; + + // Copy from the sglist into the txcb + to_p = &p_txcb->buffer[0]; + + CYG_ASSERT( 0 < sg_len, "sg_len underflow" ); + CYG_ASSERT( MAX_ETH_DRV_SG >= sg_len, "sg_len overflow" ); + + for ( last_sg = &sg_list[sg_len]; sg_list < last_sg; sg_list++ ) { + cyg_uint8 *from_p; + int l; + + from_p = (cyg_uint8 *)(sg_list->buf); + l = sg_list->len; + + if ( l > total_len ) + l = total_len; + + memcpy( (unsigned char *)to_p, from_p, l ); + to_p += l; + total_len -= l; + + if ( 0 > total_len ) + break; // Should exit via sg_last normally + } + + CYG_ASSERT( 0 == total_len, "length mismatch in tx" ); + CYG_ASSERT( last_sg == sg_list, "sg count mismatch in tx" ); + CYG_ASSERT( &p_txcb->buffer[0] < to_p, "to_p wild in tx" ); + CYG_ASSERT( &p_txcb->buffer[0] + MAX_TX_PACKET_SIZE >= to_p, + "to_p overflow in tx" ); + + // Next descriptor + if ( ++tx_descriptor_add >= MAX_TX_DESCRIPTORS) + tx_descriptor_add = 0; + p_i82559->tx_descriptor_add = tx_descriptor_add; + + // From this instant, interrupts can advance the world and start, + // even complete, this tx request... + + if ( p_i82559->tx_descriptor_remove == tx_descriptor_add ) + p_i82559->tx_queue_full = 1; + } + + // Try advancing the Tx Machine regardless + + // no more interrupts until started + Mask82559Interrupt(p_i82559); + + // Check that either: + // tx is already active, there is other stuff queued, + // OR this tx just added is the current active one + // OR this tx just added is already complete + CYG_ASSERT( + // The machine is busy: + (p_i82559->tx_in_progress == 1) || + // or: The machine is idle and this just added is the next one + (((p_i82559->tx_descriptor_add-1) == p_i82559->tx_descriptor_active) + || ((0 == p_i82559->tx_descriptor_add) && + ((MAX_TX_DESCRIPTORS-1) == p_i82559->tx_descriptor_active))) || + // or: This tx is already complete + (p_i82559->tx_descriptor_add == p_i82559->tx_descriptor_active), + "Active/add mismatch" ); + + // Advance TxMachine atomically + TxMachine(p_i82559); + Acknowledge82559Interrupt(p_i82559); + PacketRxReady(p_i82559); /* FIX: 16/07/01 added from ebsa */ + UnMask82559Interrupt(p_i82559); +} + +// ------------------------------------------------------------------------ +// +// Function : i82559_reset +// +// ------------------------------------------------------------------------ +static void i82559_reset(struct i82559* p_i82559) +{ + cyg_uint32 ioaddr; + int count; + + ioaddr = p_i82559->io_address; + // make sure no command operating + wait_for_cmd_done(ioaddr); + + OUTL(I82559_SELECTIVE_RESET, ioaddr + SCBPort); + + for (count = 10 ; count-- ; ) { + udelay(1000); + } + + OUTL(I82559_RESET, ioaddr + SCBPort); + + for (count = 10 ; count-- ; ) { + udelay(1000); + } +} + + +// ------------------------------------------------------------------------ +// +// INTERRUPT HANDLERS +// +// ------------------------------------------------------------------------ + +static cyg_uint32 eth_isr(cyg_vector_t vector, cyg_addrword_t data) +{ + struct i82559* p_i82559 = (struct i82559 *)data; + cyg_uint16 status; + cyg_uint32 ioaddr; + + IF_BAD_82559( p_i82559 ) { +#ifdef DEBUG + os_printf( "i82559_isr: Bad device pointer %x\n", (cyg_uint8 *)p_i82559 ); +#endif + return 0; + } + + ioaddr = p_i82559->io_address; + status = INW(ioaddr + SCBStatus); + + // Acknowledge all INT sources that were active + OUTW( status & SCB_INTACK_MASK, ioaddr + SCBStatus); + // (see pages 6-10 & 6-90) + +#ifdef KEEP_STATISTICS + statistics[p_i82559->index].interrupts++; + + // receiver left ready state ? + if ( status & SCB_STATUS_RNR ) + statistics[p_i82559->index].rx_resource++; + + // frame receive interrupt ? + if ( status & SCB_STATUS_FR ) + statistics[p_i82559->index].rx_count++; + + // transmit interrupt ? + if ( status & SCB_STATUS_CX ) + statistics[p_i82559->index].tx_complete++; +#endif + + // Advance the Tx Machine regardless + TxMachine(p_i82559); + + // it should have settled down now... + Acknowledge82559Interrupt(p_i82559); + + return CYG_ISR_CALL_DSR; // schedule DSR +} + + +// ------------------------------------------------------------------------ +static +void eth_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +{ + struct i82559* p_i82559 = (struct i82559 *)data; + struct cyg_netdevtab_entry *ndp = + (struct cyg_netdevtab_entry *)(p_i82559->ndp); + struct eth_drv_sc *sc = (struct eth_drv_sc *)(ndp->device_instance); + + // but here, it must be a *sc: + eth_drv_dsr( vector, count, (cyg_addrword_t)sc ); +} + +// ------------------------------------------------------------------------ +// This is called from the function below (used to be uni-DSR) +static inline void +uni_deliver(struct i82559* p_i82559) +{ + // First pass any rx data up the stack + PacketRxReady(p_i82559); + + // Then scan for completed Txen and inform the stack + TxDone(p_i82559); +} + +// ------------------------------------------------------------------------ + +void i82559_deliver(struct eth_drv_sc *sc) +{ + struct i82559* p_i82559; + int device_index = mux_device_index; + + // Since this must mux both devices, the incoming arg is ignored. + mux_device_index ^= 1; // look at the other one first next time. + do { + p_i82559 = &i82559[device_index]; + if ( p_i82559->active ) + uni_deliver( p_i82559 ); + device_index ^= 1; + } while ( device_index == mux_device_index ); +} + +// ------------------------------------------------------------------------ +// Device table entry to operate the chip in a polled mode. + +void i82559_poll(struct eth_drv_sc *sc) +{ + struct i82559 *p_i82559; + p_i82559 = (struct i82559 *)sc->driver_private; + + IF_BAD_82559( p_i82559 ) { +#ifdef DEBUG + os_printf( "i82559_poll: Bad device pointer %x\n", p_i82559 ); +#endif + return; + } +/**/ + // Do these atomically + Mask82559Interrupt(p_i82559); +/**/ + // As it happens, this driver always requests the DSR to be called: + (void)eth_isr( p_i82559->vector, (cyg_addrword_t)p_i82559 ); + + i82559_deliver( p_i82559 ); +/**/ + Acknowledge82559Interrupt(p_i82559); + UnMask82559Interrupt(p_i82559); +/**/ +} + +// ------------------------------------------------------------------------ +// Determine interrupt vector used by a device - for attaching GDB stubs +// packet handler. +int +i82559_int_vector(struct eth_drv_sc *sc) +{ + struct i82559 *p_i82559; + p_i82559 = (struct i82559 *)sc->driver_private; + return (p_i82559->vector); +} + +// ------------------------------------------------------------------------ +// +// Function : pci_init_find_82559s +// +// This is called exactly once at the start of time to: +// o scan the PCI bus for objects +// o record them in the device table +// o acquire all the info needed for the driver to access them +// o instantiate interrupts for them +// o attach those interrupts appropriately +// ------------------------------------------------------------------------ +static int +pci_init_find_82559s( void ) +{ + cyg_pci_device_id devid; + cyg_pci_device dev_info; + cyg_uint16 cmd; + int device_index; + +#ifdef DEBUG + db_printf("pci_init_find_82559s()\n"); +#endif + + // allocate memory to be used in ioctls later + if (mem_reserved_ioctl != (void*)0) { +#ifdef DEBUG + db_printf("pci_init_find_82559s() called > once\n"); +#endif + return 0; + } + + // First initialize the heap in PCI window'd memory + i82559_heap_size = CYGHWR_HAL_ARM_INTEGRATOR_PCI_MEM_MAP_SIZE; + i82559_heap_base = (cyg_uint8 *)CYGHWR_HAL_ARM_INTEGRATOR_PCI_MEM_MAP_BASE; + i82559_heap_free = i82559_heap_base; + + mem_reserved_ioctl = pciwindow_mem_alloc(MAX_MEM_RESERVED_IOCTL); + + cyg_pci_init(); + + devid = CYG_PCI_NULL_DEVID; + + for (device_index = 0; device_index < MAX_82559; device_index++) { + struct i82559 *p_i82559 = &i82559[device_index]; + p_i82559->index = device_index; + + if (cyg_pci_find_device(0x8086, 0x1229, &devid) ) { +#ifdef DEBUG + db_printf("eth%d = 82559\n", device_index); +#endif + cyg_pci_get_device_info(devid, &dev_info); + + if (cyg_pci_translate_interrupt(&dev_info, &p_i82559->vector)) { +#ifdef DEBUG + db_printf(" Wired to HAL vector %d\n", p_i82559->vector); +#endif + cyg_drv_interrupt_create( + p_i82559->vector, + 0, // Priority - unused + (CYG_ADDRWORD)p_i82559, // Data item passed to ISR & DSR + eth_isr, // ISR + eth_dsr, // DSR + &p_i82559->interrupt_handle, // handle to intr obj + &p_i82559->interrupt_object ); // space for int obj + + cyg_drv_interrupt_attach(p_i82559->interrupt_handle); + + // Don't unmask the interrupt yet, that could get us into a + // race. + } else { + p_i82559->vector=0; +#ifdef DEBUG + db_printf(" Does not generate interrupts.\n"); +#endif + } + + if (cyg_pci_configure_device(&dev_info)) { +#ifdef DEBUG + int i; + db_printf("Found device on bus %d, devfn 0x%02x:\n", + CYG_PCI_DEV_GET_BUS(devid), + CYG_PCI_DEV_GET_DEVFN(devid)); + + if (dev_info.command & CYG_PCI_CFG_COMMAND_ACTIVE) { + db_printf(" Note that board is active. Probed" + " sizes and CPU addresses invalid!\n"); + } + db_printf(" Vendor 0x%04x", dev_info.vendor); + db_printf("\n Device 0x%04x", dev_info.device); + db_printf("\n Command 0x%04x, Status 0x%04x\n", + dev_info.command, dev_info.status); + + db_printf(" Class/Rev 0x%08x", dev_info.class_rev); + db_printf("\n Header 0x%02x\n", dev_info.header_type); + + db_printf(" SubVendor 0x%04x, Sub ID 0x%04x\n", + dev_info.header.normal.sub_vendor, + dev_info.header.normal.sub_id); + + for(i = 0; i < CYG_PCI_MAX_BAR; i++) { + db_printf(" BAR[%d] 0x%08x /", i, dev_info.base_address[i]); + db_printf(" probed size 0x%08x / CPU addr 0x%08x\n", + dev_info.base_size[i], dev_info.base_map[i]); + } + db_printf(" eth%d configured\n", device_index); +#endif + p_i82559->found = 1; + p_i82559->active = 0; + p_i82559->devid = devid; + p_i82559->memory_address = dev_info.base_map[0]; + p_i82559->io_address = dev_info.base_map[1]; +#ifdef DEBUG + db_printf(" memory address = 0x%08x\n", dev_info.base_map[0]); + db_printf(" I/O address = 0x%08x\n", dev_info.base_map[1]); +#endif + + // Don't use cyg_pci_set_device_info since it clears + // some of the fields we want to print out below. + cyg_pci_read_config_uint16(dev_info.devid, CYG_PCI_CFG_COMMAND, &cmd); + cmd |= CYG_PCI_CFG_COMMAND_IO // enable I/O space + | CYG_PCI_CFG_COMMAND_MEMORY // enable memory space + | CYG_PCI_CFG_COMMAND_MASTER; // enable bus master + cyg_pci_write_config_uint16(dev_info.devid, CYG_PCI_CFG_COMMAND, cmd); + + // Now the PCI part of the device is configured, reset it. This + // should make it safe to enable the interrupt + i82559_reset(p_i82559); + + if (p_i82559->vector != 0) { + cyg_drv_interrupt_acknowledge(p_i82559->vector); + cyg_drv_interrupt_unmask(p_i82559->vector); + } +#ifdef DEBUG + db_printf(" **** Device enabled for I/O and Memory and Bus Master\n"); +#endif + } + else { + p_i82559->found = 0; + p_i82559->active = 0; +#ifdef DEBUG + db_printf("Failed to configure device %d\n",device_index); +#endif + } + } + else { + p_i82559->found = 0; + p_i82559->active = 0; +#ifdef DEBUG + db_printf("eth%d not found\n", device_index); +#endif + } + } + + // Now a delay to ensure the hardware has "come up" before you try to + // use it. Yes, really, the full 2 seconds. It's only really + // necessary if DEBUG is off - otherwise all that printout wastes + // enough time. No kidding. + udelay( 20000 ); + return 1; +} + +#ifdef CYGPKG_NET +// ------------------------------------------------------------------------ +// +// Function : eth_set_promiscuous_mode +// +// Return : 0 = It worked. +// non0 = It failed. +// ------------------------------------------------------------------------ + +static int eth_set_promiscuous_mode(struct i82559* p_i82559) +{ + cyg_uint32 ioaddr; + volatile CONFIG_CMD_STRUCT *ccs; + + IF_BAD_82559( p_i82559 ) { +#ifdef DEBUG + os_printf( "eth_set_promiscuos_mode: Bad device pointer %x\n", + p_i82559 ); +#endif + return -1; + } + + ioaddr = p_i82559->io_address; + wait_for_cmd_done(ioaddr); + // load cu base address = 0 */ + OUTL(0, ioaddr + SCBPointer); + // 32 bit linear addressing used + + OUTW(SCB_M | CU_ADDR_LOAD, ioaddr + SCBCmd); + // wait for SCB command complete + wait_for_cmd_done(ioaddr); + + ccs = (CONFIG_CMD_STRUCT *)mem_reserved_ioctl; + + // Check the malloc we did earlier worked + if (ccs == (void*)0) + return 2; // Failed + + ccs->cb_entry.cb_cmd=0x2; + ccs->cb_entry.cb_cmd_word=0x0; + ccs->cb_entry.cb_status_word=0x0; + ccs->cb_entry.cb_int=0; + ccs->cb_entry.cb_suspend=1; + ccs->cb_entry.cb_el=1; + ccs->cb_entry.cb_complete=0; + ccs->cb_entry.cb_link_offset=VIRT_TO_BUS((cyg_uint32)&ccs); + + // Default values from the Intel Manual + ccs->config_bytes[0]=0x13; + ccs->config_bytes[1]=0x8; + ccs->config_bytes[2]=0x0; + ccs->config_bytes[3]=0x0; + ccs->config_bytes[4]=0x0; + ccs->config_bytes[5]=0x0; + ccs->config_bytes[6]=0xb2; // (promisc ? 0x80 : 0) | 0x32 for small stats, + ccs->config_bytes[7]=0x0; // \ ditto | 0x12 for stats with PAUSE stats + ccs->config_bytes[8]=0x0; // \ ditto | 0x16 for PAUSE + TCO stats + ccs->config_bytes[9]=0x0; + ccs->config_bytes[10]=0x28; + ccs->config_bytes[11]=0x0; + ccs->config_bytes[12]=0x60; + ccs->config_bytes[13]=0x0; // arp + ccs->config_bytes[14]=0x0; // arp + + ccs->config_bytes[15]=0x81; // promiscuous mode set + // \ or 0x80 for normal mode. + ccs->config_bytes[16]=0x0; + ccs->config_bytes[17]=0x40; + ccs->config_bytes[18]=0x72; // Keep the Padding Enable bit + + // wait for SCB command complete + wait_for_cmd_done(ioaddr); + + OUTL(VIRT_TO_BUS(ccs), ioaddr + SCBPointer); + OUTW(SCB_M | CU_START, ioaddr + SCBCmd); + + udelay(10000); + + // now check for result ... + wait_for_cmd_done(ioaddr); + + if ( (!ccs->cb_entry.cb_ok) || (!ccs->cb_entry.cb_complete) ) + return 1; // Failed + + wait_for_cmd_done(ioaddr); + /* load pointer to Rx Ring */ + + OUTL(VIRT_TO_BUS(p_i82559->rx_ring[0]), + ioaddr + SCBPointer); + OUTW(RUC_START, ioaddr + SCBCmd); + + return 0; // OK +} +#endif + +// ------------------------------------------------------------------------ +// We use this as a templete when writing a new MAC address into the +// eeproms. The MAC address in the first few bytes is over written +// with the correct MAC address and then the whole lot is programmed +// into the serial EEPROM. The checksum is calculated on the fly and +// sent instead of the last two bytes. +// The values are copied from the Intel EtherPro10/100+ &c devices +// in the Integrator boards. + +#ifdef CYGPKG_DEVS_ETH_ARM_INTEGRATOR_WRITE_EEPROM + +#define ee00 0x00, 0x00 // shorthand + +static char eeprom_burn[126] = { +/* halfword addresses! */ +/* 0: */ 0x00, 0x90, 0x27, 0x8c, 0x57, 0x82, 0x03, 0x02, +/* 4: */ ee00 , 0x01, 0x02, 0x01, 0x47, ee00 , +/* 8: */ 0x13, 0x72, 0x06, 0x83, 0xa2, 0x40, 0x0c, 0x00, +/* C: */ 0x86, 0x80, ee00 , ee00 , ee00 , +/* 10: */ ee00 , ee00 , ee00 , ee00 , +/* 14: */ ee00 , ee00 , ee00 , ee00 , +/* 18: */ ee00 , ee00 , ee00 , ee00 , +/* 1C: */ ee00 , ee00 , ee00 , ee00 , +/* 20: */ ee00 , ee00 , ee00 , ee00 , +/* 24: */ ee00 , ee00 , ee00 , ee00 , +/* 28: */ ee00 , ee00 , ee00 , ee00 , +/* 2C: */ ee00 , ee00 , ee00 , ee00 , +/* 30: */ 0x28, 0x01, ee00 , ee00 , ee00 , +/* 34: */ ee00 , ee00 , ee00 , ee00 , +/* 38: */ ee00 , ee00 , ee00 , ee00 , +/* 3C: */ ee00 , ee00 , ee00 +}; +#undef ee00 + +#endif + +// ------------------------------------------------------------------------ +// +// Function : eth_set_mac_address +// +// Return : 0 = It worked. +// non0 = It failed. +// ------------------------------------------------------------------------ +static int eth_set_mac_address(struct i82559* p_i82559, char *addr) +{ +#ifdef CYGPKG_DEVS_ETH_ARM_INTEGRATOR_WRITE_EEPROM + int checksum, i, count; + // (this is the length of the *EEPROM*s address, not MAC address) + int addr_length; +#endif + cyg_uint32 ioaddr; + volatile CONFIG_CMD_STRUCT *ccs; + + IF_BAD_82559( p_i82559 ) { +#ifdef DEBUG + os_printf( "eth_set_mac_address : Bad device pointer %x\n", + p_i82559 ); +#endif + return -1; + } + + ioaddr = p_i82559->io_address; + + wait_for_cmd_done(ioaddr); + + ccs = (CONFIG_CMD_STRUCT *)mem_reserved_ioctl; + if (ccs == (void*)0) + return 2; + + ccs->cb_entry.cb_cmd=0x1; + ccs->cb_entry.cb_cmd_word=0x0; + ccs->cb_entry.cb_status_word=0x0; + ccs->cb_entry.cb_int=0; + ccs->cb_entry.cb_suspend=1; + ccs->cb_entry.cb_el=1; + + memcpy((char *)(ccs->config_bytes),addr,6); + + ccs->config_bytes[6]=0x0; + ccs->config_bytes[7]=0x0; + + ioaddr = p_i82559->io_address; + + OUTL(VIRT_TO_BUS(ccs), ioaddr + SCBPointer); + OUTW(SCB_M | CU_START, ioaddr + SCBCmd); + // Next delay seems to be required, otherwise, + // cb_ok/cb_complete won't be set later. + + udelay(1000); + wait_for_cmd_done(ioaddr); + + // now check for result ... + if ( (!ccs->cb_entry.cb_ok) || (!ccs->cb_entry.cb_complete) ) + return 3; + +#ifdef CYGPKG_DEVS_ETH_ARM_INTEGRATOR_WRITE_EEPROM + + addr_length = get_eeprom_size( ioaddr ); + + // now set this address in the device eeprom .... + (void)memcpy(eeprom_burn,addr,6); + + // No idea what these were for... + // eeprom_burn[20] &= 0xfe; + // eeprom_burn[20] |= p_i82559->index; + + program_eeprom( ioaddr, addr_length, eeprom_burn ); + + // update 82559 driver data structure ... + udelay( 100000 ); + + // by reading EEPROM to get the mac address back + for (checksum = 0, i = 0, count = 0; count < 64; count++) { + cyg_uint16 value; + // read word from eeprom + value = read_eeprom(ioaddr, count, addr_length); + checksum += value; + if (count < 3) { + p_i82559->mac_address[i++] = value & 0xFF; + p_i82559->mac_address[i++] = (value >> 8) & 0xFF; + } + } + +#ifdef DEBUG + os_printf("MAC Address = %02X %02X %02X %02X %02X %02X\n", + p_i82559->mac_address[0], p_i82559->mac_address[1], + p_i82559->mac_address[2], p_i82559->mac_address[3], + p_i82559->mac_address[4], p_i82559->mac_address[5]); +#endif + + p_i82559->mac_addr_ok = 1; + + for ( i = 0, count = 0; i < 6; i++ ) + if ( p_i82559->mac_address[i] != addr[i] ) + count++; + + if ( count ) { +#ifdef DEBUG + os_printf( "Warning: MAC Address read back wrong! %d bytes differ.\n", + count ); +#endif + p_i82559->mac_addr_ok = 0; + } + + // If the EEPROM checksum is wrong, the MAC address read from the + // EEPROM is probably wrong as well. In that case, we don't set + // mac_addr_ok. + if ((checksum & 0xFFFF) != 0xBABA) { +#ifdef DEBUG + os_printf( "Warning: Invalid EEPROM checksum %04X for device %d\n", + checksum, p_i82559->index); +#endif + p_i82559->mac_addr_ok = 0; + } +#else + p_i82559->mac_addr_ok = 1; +#endif // ! CYGPKG_DEVS_ETH_ARM_INTEGRATOR_WRITE_EEPROM + + return p_i82559->mac_addr_ok ? 0 : 1; +} + +#ifdef CYGPKG_DEVS_ETH_ARM_INTEGRATOR_WRITE_EEPROM +// ------------------------------------------------------------------------ +static void +write_eeprom(long ioaddr, int location, int addr_len, unsigned short value) +{ + int ee_addr = ioaddr + SCBeeprom; + int write_cmd = location | EE_WRITE_CMD(addr_len); + int i; + + OUTW(EE_ENB & ~EE_CS, ee_addr); + eeprom_delay( 100 ); + OUTW(EE_ENB, ee_addr); + eeprom_delay( 100 ); + +// os_printf("\n write_eeprom : write_cmd : %x",write_cmd); +// os_printf("\n addr_len : %x value : %x ",addr_len,value); + + /* Shift the write command bits out. */ + for (i = (addr_len+2); i >= 0; i--) { + short dataval = (write_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + OUTW(EE_ENB | dataval, ee_addr); + eeprom_delay(100); + OUTW(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); + eeprom_delay(150); + } + OUTW(EE_ENB, ee_addr); + + for (i = 15; i >= 0; i--) { + short dataval = (value & (1 << i)) ? EE_DATA_WRITE : 0; + OUTW(EE_ENB | dataval, ee_addr); + eeprom_delay(100); + OUTW(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); + eeprom_delay(150); + } + + /* Terminate the EEPROM access. */ + OUTW(EE_ENB & ~EE_CS, ee_addr); + eeprom_delay(150000); // let the write take effect +} + +// ------------------------------------------------------------------------ +static int write_enable_eeprom(long ioaddr, int addr_len) +{ + int ee_addr = ioaddr + SCBeeprom; + int write_en_cmd = EE_WRITE_EN_CMD(addr_len); + int i; + + OUTW(EE_ENB & ~EE_CS, ee_addr); + OUTW(EE_ENB, ee_addr); + +#ifdef DEBUG_82559 + os_printf("write_en_cmd : %x",write_en_cmd); +#endif + + // Shift the wr/er enable command bits out. + for (i = (addr_len+2); i >= 0; i--) { + short dataval = (write_en_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + OUTW(EE_ENB | dataval, ee_addr); + eeprom_delay(100); + OUTW(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); + eeprom_delay(150); + } + + // Terminate the EEPROM access. + OUTW(EE_ENB & ~EE_CS, ee_addr); + eeprom_delay(EEPROM_DONE_DELAY); +} + + +// ------------------------------------------------------------------------ +static void +program_eeprom(cyg_uint32 ioaddr, cyg_uint32 eeprom_size, cyg_uint8 *data) +{ + cyg_uint32 i; + cyg_uint16 checksum = 0; + cyg_uint16 value; + + // First enable erase/write operations on the eeprom. + // This is done through the EWEN instruction. + write_enable_eeprom( ioaddr, eeprom_size ); + + for (i=0 ; i< 63 ; i++) { + value = ((unsigned short *)data)[i]; + checksum += value; +#ifdef DEBUG_82559 + os_printf("\n i : %x ... value to be written : %x",i,value); +#endif + write_eeprom( ioaddr, i, eeprom_size, value); +#ifdef DEBUG_82559 + os_printf("\n val read : %x ",read_eeprom(ioaddr,i,eeprom_size)); +#endif + } + value = 0xBABA - checksum; +#ifdef DEBUG_82559 + os_printf("\n i : %x ... checksum adjustment val to be written : %x",i,value); +#endif + write_eeprom( ioaddr, i, eeprom_size, value ); +} + +// ------------------------------------------------------------------------ +#endif // ! CYGPKG_DEVS_ETH_ARM_INTEGRATOR_WRITE_EEPROM + + +// ------------------------------------------------------------------------ +// +// Function : eth_get_mac_address +// +// ------------------------------------------------------------------------ +#ifdef ETH_DRV_GET_MAC_ADDRESS +static int eth_get_mac_address(struct i82559* p_i82559, char *addr) +{ + IF_BAD_82559( p_i82559 ) { +#ifdef DEBUG + os_printf( "eth_get_mac_address : Bad device pointer %x\n", + p_i82559 ); +#endif + return -1; + } + + memcpy( addr, (char *)(&p_i82559->mac_address[0]), 6 ); + return 0; +} +#endif +// ------------------------------------------------------------------------ +// +// Function : i82559_ioctl +// +// ------------------------------------------------------------------------ +static int i82559_ioctl(struct eth_drv_sc *sc, unsigned long key, + void *data, int data_length) +{ + struct i82559 *p_i82559; + + p_i82559 = (struct i82559 *)sc->driver_private; + + IF_BAD_82559( p_i82559 ) { +#ifdef DEBUG + os_printf( "i82559_ioctl/control: Bad device pointer %x\n", p_i82559 ); +#endif + return -1; + } + +#ifdef DEBUG + db_printf( "i82559_ioctl: device eth%d at %x; key is 0x%x, data at %x[%d]\n", + p_i82559->index, p_i82559, key, data, data_length ); +#endif + + switch ( key ) { + +#ifdef ETH_DRV_SET_MAC_ADDRESS + case ETH_DRV_SET_MAC_ADDRESS: + if ( 6 != data_length ) + return -2; + return eth_set_mac_address( p_i82559, data ); +#endif + +#ifdef ETH_DRV_GET_MAC_ADDRESS + case ETH_DRV_GET_MAC_ADDRESS: + return eth_get_mac_address( p_i82559, data ); +#endif +#ifdef ETH_DRV_GET_IF_STATS_UD + case ETH_DRV_GET_IF_STATS_UD: // UD == UPDATE + ETH_STATS_INIT( sc ); // so UPDATE the statistics structure +#endif + // drop through +#ifdef ETH_DRV_GET_IF_STATS + case ETH_DRV_GET_IF_STATS: +#endif +#if defined(ETH_DRV_GET_IF_STATS) || defined (ETH_DRV_GET_IF_STATS_UD) + { + struct ether_drv_stats *p = (struct ether_drv_stats *)data; + int i; + static unsigned char my_chipset[] + = { ETH_DEV_DOT3STATSETHERCHIPSET }; + + strcpy( p->description, CYGDAT_DEVS_ETH_DESCRIPTION ); + CYG_ASSERT( 48 > strlen(p->description), "Description too long" ); + + for ( i = 0; i < SNMP_CHIPSET_LEN; i++ ) + if ( 0 == (p->snmp_chipset[i] = my_chipset[i]) ) + break; + + i = i82559_status( sc ); + + if ( !( i & GEN_STATUS_LINK) ) { + p->operational = 2; // LINK DOWN + p->duplex = 1; // UNKNOWN + p->speed = 0; + } + else { + p->operational = 3; // LINK UP + p->duplex = (i & GEN_STATUS_FDX) ? 3 : 2; // 2 = SIMPLEX, 3 = DUPLEX + p->speed = ((i & GEN_STATUS_100MBPS) ? 100 : 10) * 1000000; + } + +#ifdef KEEP_STATISTICS + { + I82559_COUNTERS *pc = &i82559_counters[ p_i82559->index ]; + STATISTICS *ps = &statistics[ p_i82559->index ]; + + // Admit to it... + p->supports_dot3 = true; + + // Those commented out are not available on this chip. + + p->tx_good = pc->tx_good ; + p->tx_max_collisions = pc->tx_max_collisions ; + p->tx_late_collisions = pc->tx_late_collisions ; + p->tx_underrun = pc->tx_underrun ; + p->tx_carrier_loss = pc->tx_carrier_loss ; + p->tx_deferred = pc->tx_deferred ; + //p->tx_sqetesterrors = pc->tx_sqetesterrors ; + p->tx_single_collisions = pc->tx_single_collisions; + p->tx_mult_collisions = pc->tx_mult_collisions ; + p->tx_total_collisions = pc->tx_total_collisions ; + p->rx_good = pc->rx_good ; + p->rx_crc_errors = pc->rx_crc_errors ; + p->rx_align_errors = pc->rx_align_errors ; + p->rx_resource_errors = pc->rx_resource_errors ; + p->rx_overrun_errors = pc->rx_overrun_errors ; + p->rx_collisions = pc->rx_collisions ; + p->rx_short_frames = pc->rx_short_frames ; + //p->rx_too_long_frames = pc->rx_too_long_frames ; + //p->rx_symbol_errors = pc->rx_symbol_errors ; + + p->interrupts = ps->interrupts ; + p->rx_count = ps->rx_count ; + p->rx_deliver = ps->rx_deliver ; + p->rx_resource = ps->rx_resource ; + p->rx_restart = ps->rx_restart ; + p->tx_count = ps->tx_count ; + p->tx_complete = ps->tx_complete ; + p->tx_dropped = ps->tx_dropped ; + } +#endif // KEEP_STATISTICS + + p->tx_queue_len = MAX_TX_DESCRIPTORS; + + return 0; // OK + } +#endif + + default: + break; + } + return -1; +} + +// ------------------------------------------------------------------------ +// +// Statistics update... +// +// ------------------------------------------------------------------------ + +#ifdef KEEP_STATISTICS +#ifdef CYGDBG_DEVS_ETH_ARM_INTEGRATOR_KEEP_82559_STATISTICS +void update_statistics(struct i82559* p_i82559) +{ + I82559_COUNTERS *p_statistics; + cyg_uint32 *p_counter; + cyg_uint32 *p_register; + int reg_count; + + Mask82559Interrupt(p_i82559); + + // This points to the sthared memory stats area/command block + p_statistics = (I82559_COUNTERS *)(p_i82559->p_statistics); + + if ( (p_statistics->done & 0xFFFF) == 0xA007 ) { + p_counter = (cyg_uint32 *)&i82559_counters[ p_i82559->index ]; + p_register = (cyg_uint32 *)p_statistics; + for ( reg_count = 0; + reg_count < sizeof( I82559_COUNTERS ) / sizeof( cyg_uint32 ) - 1; + reg_count++ ) { + *p_counter += *p_register; + p_counter++; + p_register++; + } + p_statistics->done = 0; + // make sure no command operating + wait_for_cmd_done(p_i82559->io_address); + // start register dump + OUTW(CU_DUMPSTATS, p_i82559->io_address + SCBCmd); + } + Acknowledge82559Interrupt(p_i82559); + UnMask82559Interrupt(p_i82559); +} +#endif +#endif // KEEP_STATISTICS + +// ------------------------------------------------------------------------ +// +// +// CODE FOR DEBUGGING PURPOSES ONLY +// +// +// ------------------------------------------------------------------------ +void dump_txcb(TxCB *p_txcb) +{ + os_printf("TxCB @ %x\n", (int)p_txcb); + os_printf("status = %04X ", p_txcb->txstatus); + os_printf("command = %04X ", p_txcb->command); + os_printf("link = %08X ", p_txcb->link); + os_printf("tbd = %08X ", p_txcb->tbd_address); + os_printf("count = %d ", p_txcb->count); + os_printf("eof = %x ", p_txcb->eof); + os_printf("threshold = %d ", p_txcb->tx_threshold); + os_printf("tbd number = %d\n", p_txcb->tbd_number); +} + +// This is intended to be the body of a THREAD that prints stuff every 10 +// seconds or so: +#ifdef KEEP_STATISTICS +#ifdef DISPLAY_STATISTICS +void DisplayStatistics(void) +{ + int i; + I82559_COUNTERS *p_statistics; + cyg_uint32 *p_counter; + cyg_uint32 *p_register; + int reg_count; + int status; + + while ( 1 ) { +#ifdef DISPLAY_82559_STATISTICS + for ( i = 0; i < 2; i ++ ) { + p_statistics = (I82559_COUNTERS *)i82559[i].p_statistics; + if ( (p_statistics->done & 0xFFFF) == 0xA007 ) { + p_counter = (cyg_uint32 *)&i82559_counters[i]; + p_register = (cyg_uint32 *)&p_statistics->tx_good; + for ( reg_count = 20; reg_count != 0; reg_count--) { + *p_counter += *p_register; + p_counter++; + p_register++; + } + p_statistics->done = 0; + // make sure no command operating + wait_for_cmd_done(i82559[i].io_address); + // start register dump + OUTW(CU_DUMPSTATS, i82559[i].io_address + SCBCmd); + } + } +#endif + os_printf("\nRx\nPackets = %d %d\n", + statistics[0].rx_count, statistics[1].rx_count); + os_printf("Deliver %d %d\n", + statistics[0].rx_deliver, statistics[1].rx_deliver); + os_printf("Resource %d %d\n", + statistics[0].rx_resource, statistics[1].rx_resource); + os_printf("Restart %d %d\n", + statistics[0].rx_restart, statistics[1].rx_restart); + +#ifdef DISPLAY_82559_STATISTICS + os_printf("Count %d %d\n", + i82559_counters[0].rx_good, i82559_counters[1].rx_good); + os_printf("CRC %d %d\n", + i82559_counters[0].rx_crc_errors, i82559_counters[1].rx_crc_errors); + os_printf("Align %d %d\n", + i82559_counters[0].rx_align_errors, i82559_counters[1].rx_align_errors); + os_printf("Resource %d %d\n", + i82559_counters[0].rx_resource_errors, i82559_counters[1].rx_resource_errors); + os_printf("Overrun %d %d\n", + i82559_counters[0].rx_overrun_errors, i82559_counters[1].rx_overrun_errors); + os_printf("Collision %d %d\n", + i82559_counters[0].rx_collisions, i82559_counters[1].rx_collisions); + os_printf("Short %d %d\n", + i82559_counters[0].rx_short_frames, i82559_counters[1].rx_short_frames); +#endif + os_printf("\nTx\nPackets = %d %d\n", + statistics[0].tx_count, statistics[1].tx_count); + os_printf("Complete %d %d\n", + statistics[0].tx_complete, statistics[1].tx_complete); + os_printf("Dropped %d %d\n", + statistics[0].tx_dropped, statistics[1].tx_dropped); + os_printf("Count %d %d\n", + i82559_counters[0].tx_good, i82559_counters[1].tx_good); +#ifdef DISPLAY_82559_STATISTICS + os_printf("Collision %d %d\n", + i82559_counters[0].tx_max_collisions,i82559_counters[1].tx_max_collisions); + os_printf("Late Col. %d %d\n", + i82559_counters[0].tx_late_collisions,i82559_counters[1].tx_late_collisions); + os_printf("Underrun %d %d\n", + i82559_counters[0].tx_underrun,i82559_counters[1].tx_underrun); + os_printf("Carrier %d %d\n", + i82559_counters[0].tx_carrier_loss,i82559_counters[1].tx_carrier_loss); + os_printf("Deferred %d %d\n", + i82559_counters[0].tx_deferred, i82559_counters[1].tx_deferred); + os_printf("1 Col %d %d\n", + i82559_counters[0].tx_single_collisions, i82559_counters[0].tx_single_collisions); + os_printf("Mult. Col %d %d\n", + i82559_counters[0].tx_mult_collisions, i82559_counters[0].tx_mult_collisions); + os_printf("Total Col %d %d\n", + i82559_counters[0].tx_total_collisions, i82559_counters[0].tx_total_collisions); +#endif + status = INB(i82559[0].io_address + SCBGenStatus); + os_printf("Interface 0 Link = %s, %s Mbps, %s Duplex\n", + status & GEN_STATUS_LINK ? "Up" : "Down", + status & GEN_STATUS_100MBPS ? "100" : "10", + status & GEN_STATUS_FDX ? "Full" : "Half"); + + status = INB(i82559[1].io_address + SCBGenStatus); + os_printf("Interface 1 Link = %s, %s Mbps, %s Duplex\n", + status & GEN_STATUS_LINK ? "Up" : "Down", + status & GEN_STATUS_100MBPS ? "100" : "10", + status & GEN_STATUS_FDX ? "Full" : "Half"); + + cyg_thread_delay(1000); + } +} +#endif // DISPLAY_STATISTICS +#endif // KEEP_STATISTICS + +void dump_rfd(RFD *p_rfd, int anyway ) +{ + if ( (0 != p_rfd->rxstatus) || anyway ) { + os_printf("RFD @ %x = ", (int)p_rfd); + os_printf("status = %x ", p_rfd->rxstatus); + os_printf("link = %x ", p_rfd->link); +// os_printf("rdb_address = %x ", p_rfd->rdb_address); + os_printf("count = %x ", p_rfd->count); + os_printf("f = %x ", p_rfd->f); + os_printf("eof = %x ", p_rfd->eof); + os_printf("size = %x\n", p_rfd->size); + os_printf("[%04x %04x %04x] ", + *((cyg_uint16 *)(&(p_rfd->buffer[0]))), + *((cyg_uint16 *)(&(p_rfd->buffer[2]))), + *((cyg_uint16 *)(&(p_rfd->buffer[4]))) ); + os_printf("[%04x %04x %04x] %04x : ", + *((cyg_uint16 *)(&(p_rfd->buffer[6]))), + *((cyg_uint16 *)(&(p_rfd->buffer[8]))), + *((cyg_uint16 *)(&(p_rfd->buffer[10]))), + *((cyg_uint16 *)(&(p_rfd->buffer[12]))) ); + os_printf("(%04x %04x %04x %04x) ", + *((cyg_uint16 *)(&(p_rfd->buffer[14]))), + *((cyg_uint16 *)(&(p_rfd->buffer[16]))), + *((cyg_uint16 *)(&(p_rfd->buffer[18]))), + *((cyg_uint16 *)(&(p_rfd->buffer[20]))) ); + os_printf("[%04x %04x %04x] ", + *((cyg_uint16 *)(&(p_rfd->buffer[22]))), + *((cyg_uint16 *)(&(p_rfd->buffer[24]))), + *((cyg_uint16 *)(&(p_rfd->buffer[26]))) ); + os_printf("%d.%d.%d.%d ", + *((cyg_uint8 *)(&(p_rfd->buffer[28]))), + *((cyg_uint8 *)(&(p_rfd->buffer[29]))), + *((cyg_uint8 *)(&(p_rfd->buffer[30]))), + *((cyg_uint8 *)(&(p_rfd->buffer[31]))) ); + os_printf("[%04x %04x %04x] ", + *((cyg_uint16 *)(&(p_rfd->buffer[32]))), + *((cyg_uint16 *)(&(p_rfd->buffer[34]))), + *((cyg_uint16 *)(&(p_rfd->buffer[36]))) ); + os_printf("%d.%d.%d.%d ...\n", + *((cyg_uint8 *)(&(p_rfd->buffer[38]))), + *((cyg_uint8 *)(&(p_rfd->buffer[39]))), + *((cyg_uint8 *)(&(p_rfd->buffer[40]))), + *((cyg_uint8 *)(&(p_rfd->buffer[41]))) ); + } +} + +void dump_all_rfds( int intf ) +{ + struct i82559* p_i82559 = &i82559[intf]; + int i, j; + j = p_i82559->next_rx_descriptor; + os_printf("rx descriptors for interface %d (eth%d):\n", intf, intf ); + for ( i = 0; i < MAX_RX_DESCRIPTORS; i++ ) + dump_rfd( p_i82559->rx_ring[i], (i > (j-3) && (i <= j)) ); + os_printf("next rx descriptor = %x\n\n", j); +} + + +void dump_packet(cyg_uint8 *p_buffer, int length) +{ + int count; + + count = 0; + while ( length > 0 ) { + if ( count == 0 ) + os_printf("\n"); + count = (count + 1) & 0x0F; + os_printf("%02X ", *p_buffer++); + length--; + } + os_printf("\n"); +} + +// ------------------------------------------------------------------------ + +// EOF if_integrator.c
--- a/packages/devs/flash/amd/am29xxxxx/current/ChangeLog +++ b/packages/devs/flash/amd/am29xxxxx/current/ChangeLog @@ -1,3 +1,14 @@ +2001-10-31 Jesper Skov <jskov@redhat.com> + + * include/flash_am29xxxxx_parts.inl: Removed fix me comments - + description is accurate. + +2001-10-30 Jesper Skov <jskov@redhat.com> + From Gary: + * include/flash_am29xxxxx_parts.inl: Added preliminary AM29LV640 + support. Still needs some tweaks. + * cdl/flash_amd_am29xxxxx.cdl: Same. + 2001-09-26 Gary Thomas <gthomas@redhat.com> * include/flash_am29xxxxx.inl (flash_erase_block):
--- a/packages/devs/flash/amd/am29xxxxx/current/cdl/flash_amd_am29xxxxx.cdl +++ b/packages/devs/flash/amd/am29xxxxx/current/cdl/flash_amd_am29xxxxx.cdl @@ -77,6 +77,16 @@ cdl_package CYGPKG_DEVS_FLASH_AMD_AM29XX part in the family." } + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29LV640 { + display "AMD AM29LV640 flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AMD29LV640 + part in the family." + } + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29DL324D { display "AMD AM29DL324D flash memory support" default_value 0
--- a/packages/devs/flash/amd/am29xxxxx/current/include/flash_am29xxxxx_parts.inl +++ b/packages/devs/flash/amd/am29xxxxx/current/include/flash_am29xxxxx_parts.inl @@ -362,6 +362,18 @@ }, #endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29LV640 + { // MBM29LV640xx + device_id : FLASHWORD(0x22d7), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 128, + device_size: 0x800000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x800000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : false, + banked : false + }, +#endif + #endif // 16 bit devices #endif // CYGONCE_DEVS_FLASH_AMD_AM29XXXXX_PARTS_INL
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/integrator/current/ChangeLog @@ -0,0 +1,30 @@ +2001-10-30 Philippe Robin <Philippe.Robin@arm.com> +2001-10-30 Jonathan Larmour <jlarmour@redhat.com> + + * Initial version of ARM Integrator flash driver. + +//=========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//===========================================================================
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/integrator/current/cdl/flash_integrator.cdl @@ -0,0 +1,84 @@ +# ==================================================================== +# +# flash_integrator.cdl +# +# FLASH memory - Hardware support on ARM INTEGRATOR +# +# ==================================================================== +#####COPYRIGHTBEGIN#### +# +# ------------------------------------------- +# The contents of this file are subject to the Red Hat eCos Public License +# Version 1.1 (the "License"); you may not use this file except in +# compliance with the License. You may obtain a copy of the License at +# http://www.redhat.com/ +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +# License for the specific language governing rights and limitations under +# the License. +# +# The Original Code is eCos - Embedded Configurable Operating System, +# released September 30, 1998. +# +# The Initial Developer of the Original Code is Red Hat. +# Portions created by Red Hat are +# Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +# All Rights Reserved. +# ------------------------------------------- +# +#####COPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): Philippe Robin +# Original data: gthomas +# Contributors: +# Date: November 7, 2000 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_FLASH_INTEGRATOR { + display "ARM INTEGRATOR FLASH memory support" + + parent CYGPKG_IO_FLASH + active_if CYGPKG_IO_FLASH + active_if CYGPKG_HAL_ARM_INTEGRATOR + requires { CYGNUM_FLASH_WORKSPACE_SIZE == 0x10000 } + + implements CYGINT_REDBOOT_ARM_FLASH_SIB_SUPPORTED + implements CYGHWR_IO_FLASH_DEVICE + + include_dir . +# include_files ; # none _exported_ whatsoever + description "FLASH memory device support for ARM INTEGRATOR" + compile integrator_flash.c + + make -priority 1 { + flash_erase_block.o: $(REPOSITORY)/$(PACKAGE)/src/flash_erase_block.c + $(CC) -S $(INCLUDE_PATH) $(CFLAGS) -g0 -fno-function-sections $(REPOSITORY)/$(PACKAGE)/src/flash_erase_block.c + echo " .globl flash_erase_block_end" >>flash_erase_block.s + echo "flash_erase_block_end:" >>flash_erase_block.s + $(CC) -c -o flash_erase_block.o flash_erase_block.s + $(AR) rcs $(PREFIX)/lib/libtarget.a flash_erase_block.o + } + make -priority 1 { + flash_program_buf.o: $(REPOSITORY)/$(PACKAGE)/src/flash_program_buf.c + $(CC) -S $(INCLUDE_PATH) $(CFLAGS) -g0 -fno-function-sections $(REPOSITORY)/$(PACKAGE)/src/flash_program_buf.c + echo " .globl flash_program_buf_end" >>flash_program_buf.s + echo "flash_program_buf_end:" >>flash_program_buf.s + $(CC) -c -o flash_program_buf.o flash_program_buf.s + $(AR) rcs $(PREFIX)/lib/libtarget.a flash_program_buf.o + } + make -priority 1 { + flash_query.o: $(REPOSITORY)/$(PACKAGE)/src/flash_query.c + $(CC) -S $(INCLUDE_PATH) $(CFLAGS) -g0 -fno-function-sections $(REPOSITORY)/$(PACKAGE)/src/flash_query.c + echo " .globl flash_query_end" >>flash_query.s + echo "flash_query_end:" >>flash_query.s + $(CC) -c -o flash_query.o flash_query.s + $(AR) rcs $(PREFIX)/lib/libtarget.a flash_query.o + } +} +
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/integrator/current/src/flash.h @@ -0,0 +1,65 @@ +//========================================================================== +// +// flash.h +// +// Flash programming - device constants, etc. +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: Philippe Robin +// Date: November 7, 2000 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#ifndef _FLASH_HWR_H_ +#define _FLASH_HWR_H_ + +// INTEGRATOR FLASH layout +// 4x 28F008SA, one device per byte-lane +// each device is 16x64k blocks + +#define FLASH_Read_ID 0x90909090 +#define FLASH_Read_Status 0x70707070 +#define FLASH_Clear_Status 0x50505050 +#define FLASH_Status_Ready 0x80808080 +#define FLASH_Program 0x10101010 +#define FLASH_Block_Erase 0x20202020 +#define FLASH_Confirm 0xD0D0D0D0 +#define FLASH_Reset 0xFFFFFFFF + +#define FLASH_BLOCK_SIZE 0x20000 + +#define FLASH_Intel_code 0x89 +#define FLASH_28F320 0xD4 + +#endif // _FLASH_HWR_H_
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/integrator/current/src/flash_erase_block.c @@ -0,0 +1,92 @@ +//========================================================================== +// +// flash_erase_block.c +// +// Flash programming +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: Philippe Robin +// Date: November 7, 2000 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include "flash.h" + +#include <pkgconf/hal.h> +#include <cyg/hal/hal_arch.h> +#include <cyg/hal/hal_cache.h> +#include <cyg/hal/hal_integrator.h> + +// +// CAUTION! This code must be copied to RAM before execution. Therefore, +// it must not contain any code which might be position dependent! +// + +int +flash_erase_block(volatile cyg_uint32 *block) +{ + volatile cyg_uint32 stat = 0; + int timeout = 5000000; + int cache_on; + + HAL_DCACHE_IS_ENABLED(cache_on); + if (cache_on) { + HAL_DCACHE_SYNC(); + HAL_DCACHE_DISABLE(); + } + + HAL_FLASH_WRITE_ENABLE(); + // Clear any error conditions + *block = FLASH_Clear_Status; + + // Set to erase + *block = FLASH_Block_Erase; + *block = FLASH_Confirm; + while((stat & FLASH_Status_Ready) != FLASH_Status_Ready) { + *block = FLASH_Read_Status; + stat = *block; + if (--timeout == 0) break; + } + + // Restore ROM to "normal" mode + *block = FLASH_Reset; + + HAL_FLASH_WRITE_DISABLE(); + + if (cache_on) { + HAL_DCACHE_ENABLE(); + } + + return stat; +}
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/integrator/current/src/flash_program_buf.c @@ -0,0 +1,99 @@ +//========================================================================== +// +// flash_program_buf.c +// +// Flash programming +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: Philippe Robin +// Date: November 7, 2000 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include "flash.h" + +#include <pkgconf/hal.h> +#include <cyg/hal/hal_arch.h> +#include <cyg/hal/hal_cache.h> +#include <cyg/hal/hal_integrator.h> + +// +// CAUTION! This code must be copied to RAM before execution. Therefore, +// it must not contain any code which might be position dependent! +// + +int +flash_program_buf(volatile unsigned long *addr, unsigned long *data, int len) +{ + unsigned long stat; + int timeout = 5000000; + int cache_on; + volatile unsigned long *orig_addr = addr; + + HAL_DCACHE_IS_ENABLED(cache_on); + if (cache_on) { + HAL_DCACHE_SYNC(); + HAL_DCACHE_DISABLE(); + } + + HAL_FLASH_WRITE_ENABLE(); + + // Clear any error conditions + *addr = FLASH_Clear_Status; + + while (len > 0) { + *addr = FLASH_Program; + *addr = *data++; + timeout = 5000000; + while(((stat = *addr) & FLASH_Status_Ready) != FLASH_Status_Ready) { + if (--timeout == 0) { + goto bad; + } + } + addr++; + len -= sizeof(unsigned long); + } + + // Restore ROM to "normal" mode + bad: + *orig_addr = FLASH_Reset; + + HAL_FLASH_WRITE_DISABLE(); + + if (cache_on) { + HAL_DCACHE_ENABLE(); + } + + return stat; +}
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/integrator/current/src/flash_query.c @@ -0,0 +1,93 @@ +//========================================================================== +// +// flash_query.c +// +// Flash programming - query device +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: Philippe Robin +// Date: November 7, 2000 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include "flash.h" + +#include <pkgconf/hal.h> +#include <cyg/hal/hal_arch.h> +#include <cyg/hal/hal_cache.h> +#include <cyg/hal/hal_integrator.h> + +// +// CAUTION! This code must be copied to RAM before execution. Therefore, +// it must not contain any code which might be position dependent! +// + +#define CNT 20*1000*10 // Approx 200ms + +int +flash_query(unsigned char *data) +{ + volatile unsigned long *lROM; + volatile unsigned char *cROM; + int i, cnt; + int cache_on; + volatile cyg_uint8 *ptr = 0x24000000; + cyg_uint8 val; + + HAL_DCACHE_IS_ENABLED(cache_on); + if (cache_on) { + HAL_DCACHE_SYNC(); + HAL_DCACHE_DISABLE(); + } + + HAL_FLASH_WRITE_ENABLE(); + + lROM = 0x24000000; + cROM = 0x24000000; + + lROM[0] = FLASH_Read_ID; + for (cnt = CNT; cnt > 0; cnt--) ; + for (i = 0; i < 8; i++) { + *data++ = cROM[i]; + } + lROM[0] = FLASH_Reset; + + HAL_FLASH_WRITE_DISABLE(); + + if (cache_on) { + HAL_DCACHE_ENABLE(); + } + + return 0; +}
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/integrator/current/src/integrator_flash.c @@ -0,0 +1,1016 @@ +//========================================================================== +// +// integrator_flash.c +// +// Flash programming +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: Philippe Robin +// Date: November 7, 2000 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/hal.h> +#include <cyg/hal/hal_arch.h> +#include <cyg/hal/hal_cache.h> + +#define _FLASH_PRIVATE_ +#include <cyg/io/flash.h> + +#include "flash.h" + +#define ARM_INTEGRATOR_FLASH + +extern int strncmp(const char *s1, const char *s2, int len); + +#define INTEGRATOR_NUM_REGIONS 256 + +int +flash_hwr_init(void) +{ + unsigned char data[96]; + extern char flash_query, flash_query_end; + typedef int code_fun(unsigned char *); + code_fun *_flash_query; + int code_len, stat, num_regions, region_size; + + // Copy 'program' code to RAM for execution + code_len = (unsigned long)&flash_query_end - (unsigned long)&flash_query; + _flash_query = (code_fun *)flash_info.work_space; + memcpy(_flash_query, &flash_query, code_len); + HAL_DCACHE_SYNC(); // Should guarantee this code will run + HAL_ICACHE_DISABLE(); // is also required to avoid old contents + + stat = (*_flash_query)(data); + + HAL_ICACHE_ENABLE(); + + if ( data[4] == FLASH_28F320 ) { + num_regions = INTEGRATOR_NUM_REGIONS; + region_size = FLASH_BLOCK_SIZE; + flash_info.block_size = region_size; + flash_info.blocks = num_regions; + flash_info.start = (void *)0x24000000; + flash_info.end = (void *)(0x24000000+(num_regions*region_size)); + return FLASH_ERR_OK; + } else { + diag_printf("Can't identify FLASH, sorry\n"); + diag_dump_buf(data, sizeof(data)); + return FLASH_ERR_HWR; + } +} + +// Map a hardware status to a package error +int +flash_hwr_map_error(int err) +{ + if (err & 0x7E) { + if (err & 0x10) { + return FLASH_ERR_PROGRAM; + } else + if (err & 0x20) { + return FLASH_ERR_ERASE; + } else + return FLASH_ERR_HWR; // FIXME + } else { + return FLASH_ERR_OK; + } +} + +// See if a range of FLASH addresses overlaps currently running code +bool +flash_code_overlaps(void *start, void *end) +{ + extern char _stext, _etext; + + return ((((unsigned long)&_stext >= (unsigned long)start) && + ((unsigned long)&_stext < (unsigned long)end)) || + (((unsigned long)&_etext >= (unsigned long)start) && + ((unsigned long)&_etext < (unsigned long)end))); +} + + +#ifdef ARM_INTEGRATOR_FLASH +#define FLASH_BASE 0x24000000 +#define FLASH_SIZE 0x02000000 + +/* type information :- + * 0xffff ffff - deleted (usual flash erased value) + * 0x0000 xxxx - Reserved for ARM usage: + * Bit 0 - ARM Executable Image + * Bit 1 - System Information Block + * Bit 2 - File System Block + * 0xyyyy 0000 - Available for customers (y != 0) + */ +#define TYPE_DELETED 0xFFFFFFFF +#define TYPE_ARM_MASK 0x0000FFFF +#define TYPE_CUSTOM_MASK 0xFFFF0000 +#define TYPE_ARM_EXEC 0x00000001 +#define TYPE_ARM_SIB 0x00000002 +#define TYPE_ARM_SYSBLOCK 0x00000004 + +/* Filetypes */ + +#define UNKNOWN_FILE 0x00000000 +#define MOT_S_RECORD 0x00000001 +#define INTEL_HEX 0x00000002 +#define ELF 0x00000004 +#define DWARF 0x00000008 +#define ARM_AOF 0x00000010 +#define ARM_AIF 0x00000020 +#define PLAIN_BINARY 0x00000040 +#define ARM_AIF_BIN 0x00000080 +#define MCS_TYPE 0x00000100 + +#define CONVERT_TYPE (MOT_S_RECORD | INTEL_HEX | MCS_TYPE | ELF) + +#define SIB_OWNER_STRING_SIZE 32 +#define MAX_SIB_SIZE 512 +#define MAX_SIB_INDEX 64 + +#define NoOfElements(array) (sizeof(array) / sizeof(array[0])) +#define AddressToBlock(address) ((((cyg_uint32)(address)) - FLASH_BASE) / FLASH_BLOCK_SIZE) +#define BlockToAddress(block) (((block) * FLASH_BLOCK_SIZE) + FLASH_BASE) +#define BlockBaseAddress(address) (((cyg_uint32)(address)) & ~(FLASH_BLOCK_SIZE - 1)) +#define FooterAddress(block) ((tFooter *)((BlockToAddress(block) + FLASH_BLOCK_SIZE) \ + - sizeof (tFooter))) +#define InFlash(address) ((((cyg_uint32)(address)) >= FLASH_BASE) && (((cyg_uint32)(address))\ + < (FLASH_BASE + FLASH_SIZE))) + +#define NO_OF_BLOCKS (FLASH_SIZE / FLASH_BLOCK_SIZE) + +#define SIB_HEADER_SIGNATURE 0xA00FFF9F /* This is an invalid instruction - MULGE pc,pc,pc */ +#define FLASH_FOOTER_SIGNATURE 0xA0FFFF9F /* This is an invalid instruction - SMULALGES pc,pc,pc */ + + +typedef struct SIBType { + cyg_uint32 signature; + cyg_uint32 size; + char owner[SIB_OWNER_STRING_SIZE]; + cyg_uint32 index; + cyg_uint32 revision; + cyg_uint32 checksum; +} tSIB; + +typedef struct SIBInfoType { + cyg_uint32 SIB_number; /* Unique number of SIB Block */ + cyg_uint32 SIB_Extension; /* Base of SIB Flash Block */ + char Label[16]; /* String space for ownership string */ + cyg_uint32 checksum; /* SIB Image checksum */ +} tSIBInfo; + +typedef struct FooterType { + void *infoBase; /* Address of first word of ImageFooter */ + char *blockBase; /* Start of area reserved by this footer */ + cyg_uint32 signature; /* 'Magic' number proves it's a footer */ + cyg_uint32 type; /* Area type: ARM Image, SIB, customer */ + cyg_uint32 checksum; /* Just this structure */ +} tFooter ; + +typedef struct ImageInfoType { + cyg_uint32 bootFlags; /* Boot flags, compression etc. */ + cyg_uint32 imageNumber; /* Unique number, selects for boot etc. */ + char *loadAddress; /* Address program should be loaded to */ + cyg_uint32 length; /* Actual size of image */ + char *address; /* Image is executed from here */ + char name[16]; /* Null terminated */ + char *headerBase; /* Flash Address of any stripped header */ + cyg_uint32 header_length; /* Length of header in memory */ + cyg_uint32 headerType; /* AIF, RLF, s-record etc. */ + cyg_uint32 checksum; /* Image checksum (inc. this struct) */ +} tImageInfo; + +/* globals */ + +static tFooter *active_flash_footers[NO_OF_BLOCKS]; +static tSIB *active_sibs[MAX_SIB_INDEX]; +static char active_id_string[SIB_OWNER_STRING_SIZE]; +static cyg_uint32 buffer[MAX_SIB_SIZE / sizeof(cyg_uint32)]; +static cyg_uint32 *free_ptr; +static cyg_uint32 free_space; + +// +// find_free_space() +// +// This routine searches backwards from the end of flash, this is to ensure +// that any SIB's are at the end of flash and therefore less likely to be +// overwritten by the boot monitor loader. +// +// RETURNS: NULL or pointer on area of free space + +static cyg_uint32 * +find_free_space(int size) +{ + tFooter *footer; + int required_blocks; + int free_blocks; + + //Calculate the number of blocks required. + required_blocks = (size / FLASH_BLOCK_SIZE) + 1; + + // Get a pointer to the last possible footer in flash. + footer = (tFooter *)(FLASH_BASE + FLASH_SIZE - sizeof(tFooter)); + + free_blocks = 0; + + while (free_blocks < required_blocks) { + // Skip pass any allocated blocks + while (footer->signature == FLASH_FOOTER_SIGNATURE) { + footer = (tFooter *)(footer->blockBase - sizeof (tFooter)); + + if ((cyg_uint32)footer < FLASH_BASE) + return NULL; + } + + // Count free blocks + free_blocks = 0; + + while (footer->signature != FLASH_FOOTER_SIGNATURE) { + free_blocks++; + + // Have we found enough. + if (free_blocks >= required_blocks) + break; + + footer = (tFooter *)((cyg_uint32)footer - FLASH_BLOCK_SIZE); + + if ((cyg_uint32)footer < FLASH_BASE) + return NULL; + } + } + + // Return the address of the first location of the free space. + return (cyg_uint32 *)BlockBaseAddress(footer); +} + +// +// arm_fis_find_free() +// + +bool +arm_fis_find_free(cyg_uint32 *addr, cyg_uint32 size) +{ + tFooter *footer; + int required_blocks; + int free_blocks; + + //Calculate the number of blocks required. + required_blocks = (size / FLASH_BLOCK_SIZE) + 1; + + footer = FooterAddress(AddressToBlock(*addr)); + free_blocks = 0; + + while (free_blocks < required_blocks) { + // Skip pass any allocated blocks + while (footer->signature == FLASH_FOOTER_SIGNATURE) { + footer = (tFooter *)((cyg_uint32)footer + FLASH_BLOCK_SIZE); + + if ((cyg_uint32)footer > (FLASH_BASE + FLASH_SIZE)) + return 0; + } + + // Count free blocks + free_blocks = 0; + *addr = (tFooter *)((cyg_uint32)footer + sizeof(tFooter) - FLASH_BLOCK_SIZE); + + while (footer->signature != FLASH_FOOTER_SIGNATURE) { + free_blocks++; + + // Have we found enough. + if (free_blocks >= required_blocks) + break; + + footer = (tFooter *)((cyg_uint32)footer + FLASH_BLOCK_SIZE); + + if ((cyg_uint32)footer > (FLASH_BASE + FLASH_SIZE)) + return 0; + } + } + + // Return the address of the first location of the free space. + return 1; +} + +// +// sib_checksum() - calculate SIB checksum. +// + +static cyg_uint32 +sib_checksum(tSIB *sib) +{ + cyg_uint32 checksum; + cyg_uint32 *ptr; + int size; + + checksum = 0; + size = sib->size; + ptr = (cyg_uint32 *)sib; + + while (size > 0) { + cyg_uint32 word; + + word = *ptr++; + + if (word > ~checksum) checksum++; + + checksum += word; + size -= sizeof (word); + } + + return ~checksum; +} + +// footer_checksum() - calculate the footer checksum. +static cyg_uint32 +footer_checksum(tFooter *footer) +{ + cyg_uint32 checksum; + cyg_uint32 *ptr; + int size; + + checksum = 0; + size = sizeof (tFooter); + ptr = (cyg_uint32 *)footer; + + while (size > 0) { + cyg_uint32 word; + + word = *ptr++; + + if (word > ~checksum) checksum++; + + checksum += word; + size -= sizeof (word); + } + + return ~checksum; +} + +// write_sib() - internal routine to write a SIB to flash. +// +// RETURN: -1 if error 0 otherwise + +static int +write_sib(tSIB *sib) +{ + cyg_uint32 *ptr; + + // Is there space available for this SIB. + if (sib->size > free_space) { + int required_space; + int count; + int block; + tFooter footer; + tFooter *footer_ptr; + + // If not then we need to allocate a new area in flash. + // + // First calculate the size required for the new area by + // adding up the size of all the active SIB's. + // + required_space = sib->size; + + for (count = 0; count < MAX_SIB_INDEX; count++) { + tSIB *sib2; + + sib2 = active_sibs[count]; + + if (sib2 != NULL) required_space += sib2->size; + } + + // Get a pointer to the free space. + free_ptr = find_free_space (required_space); + + // Build a flash footer to describe this area. + footer.blockBase = (char *)BlockBaseAddress(free_ptr); + footer.infoBase = NULL; + footer.type = TYPE_ARM_SIB; + footer.signature = FLASH_FOOTER_SIGNATURE; + footer.checksum = 0; + footer.checksum = footer_checksum (&footer); + + // Calculate the address where the footer will live in flash + // and write it to flash. + block = AddressToBlock((cyg_uint32)free_ptr + required_space + sizeof (tFooter)); + + footer_ptr = FooterAddress(block); + +#ifdef TO_CHECK + if (sysFlashWrite(FLASH_CAST(&footer), sizeof(tFooter), + ((cyg_uint32)footer_ptr - FLASH_BASE), + flashType, 0) != OK) + return -1; +#endif + if (flash_program_buf(footer_ptr, (unsigned long *)&footer, sizeof(tFooter)) < 0 ) + return -1; + + // Update the free space global varible. + free_space = ((AddressToBlock(footer_ptr) - block + 1) * FLASH_BLOCK_SIZE) + - sizeof (tFooter); + } + + // If the SIB that we are writing is already in flash then it need to + // be copied into memory as it may become unreadable when we start + // programming the flash (if it is in the same flash part). + if (InFlash(sib)) { + cyg_uint32 *src; + cyg_uint32 *dest; + int size; + tSIB *tmp_sib; + + size = sib->size; + src = (cyg_uint32 *)sib; + dest = buffer; + + while (size > 0) { + *dest++ = *src++; + size -= sizeof (cyg_uint32); + } + + // Increment the revision count. + tmp_sib = (tSIB *)buffer; + tmp_sib->revision = sib->revision + 1; + + ptr = buffer; + } else + ptr = (cyg_uint32 *)sib; + + // Write the SIB to flash. +#ifdef TO_CHECK + if (sysFlashWrite(FLASH_CAST(ptr), sib->size, (int)((cyg_uint32)free_ptr - FLASH_BASE), + flashType, 0) != OK) + return -1; +#endif + + if (flash_program_buf((cyg_uint32)free_ptr, ptr, sib->size) < 0 ) + return -1; + + // Update the free space, free pointer and active SIB's varibles + // to reflect this write. + free_space -= sib->size; + free_ptr = (cyg_uint32 *)((cyg_uint32)free_ptr - sib->size); + + active_sibs[sib->index] = sib; + + return 0; +} + +// delete_sib() - delete a SIB. +// +// This will delete at least a whole flash block and therefore any active +// SIB's will need to be rewritten. + +static int +delete_sib (tSIB *sib_to_delete) +{ + int block; + tFooter *footer; + tSIB *sib; + int delete_size; + + // Calculate the first address of this flash block and the + // first possible footer location. + // + block = AddressToBlock(sib_to_delete); + footer = FooterAddress(block); + + // Search for the footer for this block. + while (footer->signature != FLASH_FOOTER_SIGNATURE) + footer = (tFooter *)((cyg_uint32)footer + FLASH_BLOCK_SIZE); + + if (footer_checksum (footer) != 0) + return -1; + + // Now get the a pointer to the first SIB. + sib = (tSIB *)footer->blockBase; + + // Now search through all the SIB's. + while (sib->signature == SIB_HEADER_SIGNATURE) { + if (sib_checksum (sib) != 0) + break; + + // Any valid and active SIB will need to be rewritten. + if (sib->index < MAX_SIB_INDEX) { + if ((active_sibs[sib->index] == NULL) || + (sib->revision > active_sibs[sib->index]->revision)) { + write_sib (sib); + } + } + + // Move onto next SIB. + sib = (tSIB *)((cyg_uint32)sib + sib->size); + } + + // Calculate how much space needs to be deleted, it may be multiple + // blocks, and delete it. + delete_size = (AddressToBlock(footer) - block + 1) * FLASH_BLOCK_SIZE; + + // !! must add code for cases where (delete_size > block_size) +#ifdef TO_CHECK + return sysFlashEraseBlock((cyg_uint32 *)footer->blockBase, sysFlashTypeGet()); +#endif + return flash_erase_block((cyg_uint32 *)footer->blockBase); + } + +// SIB_Open() - Open all SIB's with the owner by 'id_string'. +// +// RETURN: -1 if error 0 otherwise + +int +SIB_Open(char *id_string, int *sib_count, int private_flag) +{ + int count; + tFooter *footer; + int no_of_sibs; + + // Initialize various globals. + memset(active_id_string, 0, SIB_OWNER_STRING_SIZE); + free_ptr = NULL; + free_space = 0; + *sib_count = 0; + + // Find all the active footers. + fLib_FindFooter((cyg_uint32 *)FLASH_BASE, FLASH_SIZE, active_flash_footers); + + // Initialise the active SIB array. + for (count = 0; count < MAX_SIB_INDEX; count++) + active_sibs[count] = NULL; + + // Populate the active SIB array with all the active SIB found in flash. + count = 0; + no_of_sibs = 0; + + while ((footer = active_flash_footers[count++]) != NULL) { + tSIB *sib; + + if (footer->type != TYPE_ARM_SIB) + continue; + + sib = (tSIB *)footer->blockBase; + + while (sib->signature == SIB_HEADER_SIGNATURE) { + char c; + char *ptr1; + char *ptr2; + + if (sib_checksum (sib) != 0) + return -1; + + ptr1 = id_string; + ptr2 = sib->owner; + + while ((c = *ptr1++) != '\0') { + if (c != *ptr2++) + break; + } + + if (c == '\0') { + // If two SIB's have the same name and index the one with the + // highest revision is considered to be the active one. + if (sib->index < MAX_SIB_INDEX) { + tSIB *current_sib; + + current_sib = active_sibs[sib->index]; + + if (current_sib == NULL) { + active_sibs[sib->index] = sib; + } else if (sib->revision > current_sib->revision) { + delete_sib(current_sib); + active_sibs[sib->index] = sib; + } else { + tSIB *old_sib; + + old_sib = sib; + sib = (tSIB *)((cyg_uint32)sib + sib->size); + + delete_sib(old_sib); + + continue; + } + } else + return -1; + + no_of_sibs++; + } + + sib = (tSIB *)((cyg_uint32)sib + sib->size); + } + } + + memcpy(active_id_string, id_string, SIB_OWNER_STRING_SIZE); + + *sib_count = no_of_sibs; + + return 0; +} + +// SIB_Close() - close access to SIBs + +int +SIB_Close(void) +{ + int count; + + memset(active_id_string, 0, SIB_OWNER_STRING_SIZE); + + // Initialise the active SIB array. + for (count = 0; count < MAX_SIB_INDEX; count++) + active_sibs[count] = NULL; + + return 0; +} + + +// SIB_GetSize() - Get the size of the user data in a SIB. + +int +SIB_GetSize(int sib_index, int *data_size) +{ + tSIB *sib; + + sib = active_sibs[sib_index]; + + if (sib == NULL) { + *data_size = 0; + return -1; + } + + *data_size = sib->size = sizeof(tSIB); + + return 0; +} + +// SIB_Program() - create or update a SIB with new user data. +// +// Return: 0 if OK -1 otherwise + +int +SIB_Program(int sib_index, void *data_block, int data_size) +{ + tSIB *old_sib; + tSIB *new_sib; + int sib_size; + cyg_uint32 *src; + cyg_uint32 *dest; + + // Calculate the size of the SIB as a whole. + sib_size = data_size + sizeof(tSIB); + + if (sib_size > MAX_SIB_SIZE) + return -1; + + // Create the new SIB in local memory + new_sib = (tSIB *)&buffer; + + new_sib->signature = SIB_HEADER_SIGNATURE; + new_sib->size = sib_size; + new_sib->index = sib_index; + + memcpy(new_sib->owner, active_id_string, SIB_OWNER_STRING_SIZE); + + // Increment the revision number if this is updating a SIB. + old_sib = active_sibs[sib_index]; + + if (old_sib == NULL) + new_sib->revision = 0; + else + new_sib->revision = old_sib->revision + 1; + + // Copy the user data into the SIB. + src = (cyg_uint32 *)data_block; + dest = (cyg_uint32 *)((cyg_uint32)new_sib + sizeof(tSIB)); + + while (data_size > 0) { + *dest++ = *src++; + data_size -= sizeof (cyg_uint32); + } + + // Finally calculate the checksum and call write_sib. + new_sib->checksum = 0; + new_sib->checksum = sib_checksum (new_sib); + + if (write_sib (new_sib) != 0) + return -1; + + // Delete the SIB that this one replaces if there is one. + if (old_sib != NULL) + delete_sib (old_sib); + + return 0; +} + +// SIB_Erase() - erase a SIB +// +// Return: -1 if error 0 otherwise + +int +SIB_Erase(int sib_index) +{ + tSIB *sib; + + sib = active_sibs[sib_index]; + + active_sibs[sib_index] = NULL; + + return delete_sib (sib); +} + +// fLib_FindFooter() - find footer in flash memory +// +// Scan the flash memory from start for size bytes, returning a list of pointers to the +// image footers. Pointer list should point to an area of ram supplied by the application +// and should be large enough to contain a pointer to each logical block of flash in the +// specified area. +// If the size is defined as zero, only the address of the next footer found is returned. +// Parameters: +// cyg_uint32 *start +// pointer to the address of the flash memory to be scanned +// cyg_uint32 size +// size of the flash memory in bytes +// tFooter **list +// pointer to a list of pointers to footers +// +// Returns: number of flash footers found. +// + +cyg_uint32 +fLib_FindFooter(cyg_uint32 *start, cyg_uint32 size, tFooter *list[]) +{ + cyg_uint32 *end ; + cyg_uint32 count = 0; + cyg_uint32 logical_block = FLASH_BLOCK_SIZE; + cyg_uint32 block_mask; + tFooter *test; + + end = flash_info.end; + + // Start looking at each block boundary to see if there is a + // structured footer there if so that is a footer to put in the footer list + // + // Initially we must get the nearest logical block boundary to the + // initial address + block_mask = logical_block - 1; + + start = (cyg_uint32*)((int)start | block_mask); + + test = (tFooter*)(start - (sizeof(tFooter) >> 2) ); + test = (tFooter*) ((char*)test + 1); + + // Now test should be at the first available footer location + + for ( ; (cyg_uint32*)test < end; test = (tFooter*)((char*)test + logical_block)) { + // initial check is to see if the type is deleted (ie empty block) + if (TYPE_DELETED != test->type) { + // next check for a signature in the footer + + if (FLASH_FOOTER_SIGNATURE == test->signature) { + cyg_uint32 check = 0; + cyg_uint32 *check_ptr = (cyg_uint32 *)test; + count = (sizeof(tFooter) - 4) >> 2; // sizeof will return bytes + + // We're pretty certain by now but lets check the checksum to make fully sure + for ( ; count > 0; count--) { + if (*check_ptr > ~check) + check++; + check += *check_ptr++; + } + + if (test->checksum == ~check) { + if (size != 0 ) + *list++ = test; + else { + // If the size was set at 0 - return only the first found footer + *list = test; + return 1; + } + } + } + } + // This should carry on through checking each logical block boundary to end */ + } + + // tidy up the array/list + *list = NULL; + return count; +} + +// +// fLib_DeleteImage(tFooter *foot, tFlash *flash) +// +// Delete the image in flash as detailed by the specified image footer. We will have to +// define the flash device to access the relevant flash delete routines +// Parameters +// tFooter *foot +// pointer to the footer which defines the image to be deleted +// +// Returns: 0 if successful, otherwise -1. +// + +static int +fLib_DeleteImage(tFooter *foot) +{ + cyg_uint32 delete_size , block_mask = flash_info.block_size; + cyg_uint8 *erase_addr = foot->blockBase; + cyg_uint8 complete_flag = 0; + + // presume that the erase size is chosen to cover the boundary size + block_mask -= 1; + + delete_size = ((tImageInfo*)foot->infoBase)->length + + ((tImageInfo*)foot->infoBase)->header_length + + sizeof (tImageInfo) + sizeof (tFooter); + delete_size |= block_mask; + delete_size += 1; /* for the boundary */ + + while (!complete_flag ) { + if ( delete_size > flash_info.block_size) { + delete_size -= flash_info.block_size; + } else + complete_flag = 1; + + flash_erase_block(erase_addr); + erase_addr += flash_info.block_size; + } + return 0; +} + +// +// fLib_FindImage(tFooter **list, cyg_uint32 imageNo, tFooter *foot) +// +// Scan the list of flash footers looking for a footer with an imageNumber which +// matches the specified number. +// If the specified footer pointer is not NULL, the footer is copied from flash. +// Parameters: +// tFooter **list +// pointer to a list of pointers to footers +// unsigned32 imageNo +// number of image to be located +// tFooter *foot +// pointer to where the found footer should be copied +// +// Returns: 1 if successful, otherwise 0 +// + +static int +fLib_FindImage(tFooter **list, char *name, tFooter *foot) +{ + // Initially, if there are no images in the flash we can just return so check + if (*list == NULL) + return 0; + + // Now we can start checking for the images that are in flash + while (*list != NULL) { + tImageInfo *im = (tImageInfo *)(*list)->infoBase; + if (strncmp(name, im->name, 16) == 0 ) { + *foot = **list; + return 1; + } + list++; + } + + return 0; +} + +#define FLASH_ADRS 0x23000000 + +int +markBlock() +{ + tFooter footer; + tFooter *current; + cyg_uint32 writeOffset; + + // Build a flash footer to describe this area. + footer.blockBase = (char *)FLASH_ADRS; + footer.infoBase = NULL; + footer.type = 0x10000; //TYPE_WRS_SIB; + footer.signature = FLASH_FOOTER_SIGNATURE; + footer.checksum = 0; + footer.checksum = footer_checksum (&footer); + + current = (tFooter *)(FLASH_ADRS + FLASH_BLOCK_SIZE - sizeof (tFooter)); + + if ( current->type == TYPE_ARM_SIB) + return 1; + + writeOffset = FLASH_ADRS + FLASH_BLOCK_SIZE - sizeof (tFooter); + + if (flash_program_buf(writeOffset, (unsigned long *)&footer, sizeof(tFooter)) < 0 ) + return 0; + +#ifdef TO_CHECK + if (sysFlashWrite(FLASH_CAST(&footer), sizeof(tFooter), + writeOffset, + flashType, 0) != OK) + return 0; +#endif +} + +void +arm_fis_list(void) +{ + int count = 0; + tFooter *footer; + + fLib_FindFooter((cyg_uint32 *)FLASH_BASE, FLASH_SIZE, active_flash_footers); + + diag_printf("Name FLASH addr Mem addr Length Entry point\n"); + while ((footer = active_flash_footers[count++]) != NULL) { + if (footer->type == TYPE_ARM_EXEC) { + diag_printf("%-16s 0x%08lX 0x%08lX 0x%06lX 0x%08lX\n", + ((tImageInfo *)footer->infoBase)->name, + FLASH_BASE, footer->blockBase, + ((tImageInfo *)footer->infoBase)->length, + ((tImageInfo *)footer->infoBase)->loadAddress); + } + } +} + +void +arm_fis_delete(char *name) +{ + tFooter footer; + + if ( name == NULL ) return; + + fLib_FindFooter((cyg_uint32 *)FLASH_BASE, FLASH_SIZE, active_flash_footers); + + if ( fLib_FindImage(active_flash_footers, name, &footer) ) { + diag_printf("Found Image %s, base 0x%x\n", name, footer.blockBase); + fLib_DeleteImage(&footer); + } +} + +static void +SIB_test(void) +{ + int count; + tFooter *footer; + + fLib_FindFooter((cyg_uint32 *)FLASH_BASE, FLASH_SIZE, active_flash_footers); + + + // Find everything that looks like a SIB. + count = 0; + + diag_printf("\n"); + while ((footer = active_flash_footers[count++]) != NULL) { + if (footer->type == TYPE_ARM_EXEC) { + diag_printf("Blk: %d Image Nb: %3d Name: %s Load address: 0x%x Length 0x%x\n\n", + AddressToBlock(footer->blockBase), + ((tImageInfo *) footer->infoBase)->imageNumber, + ((tImageInfo *)footer->infoBase)->name, + ((tImageInfo *)footer->infoBase)->loadAddress, + ((tImageInfo *)footer->infoBase)->length); + } else if (footer->type == TYPE_ARM_SIB) { + tSIB *sib; + + sib = (tSIB *)footer->blockBase; + diag_printf("SIB Address Owner Size Idx Rev\n"); + diag_printf("----------- ----- ---- --- ---\n"); + while (sib->signature == SIB_HEADER_SIGNATURE) { + if (sib_checksum (sib) == 0) { + diag_printf("0x%08X %-32s %4d %4d %4d\n\n", + (int)sib, sib->owner, sib->size, sib->index, sib->revision); + sib = (tSIB *)((cyg_uint32)sib + sib->size); + } else { + diag_printf("0x%08X *** Bad Checksum ***\n", (int)sib); + break; + } + } + + } + } +} +#endif // ARM_INTEGRATOR_FLASH
new file mode 100644 --- /dev/null +++ b/packages/devs/serial/arm/integrator/current/ChangeLog @@ -0,0 +1,31 @@ +2001-10-30 Philippe Robin <Philippe.Robin@arm.com> +2001-10-30 Jonathan Larmour <jlarmour@redhat.com> + + * New package for ARM Integrator serial driver derived from + ARM PID serial driver. + +//=========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//===========================================================================
new file mode 100644 --- /dev/null +++ b/packages/devs/serial/arm/integrator/current/cdl/ser_arm_integrator.cdl @@ -0,0 +1,170 @@ +# ==================================================================== +# +# ser_arm_integrator.cdl +# +# eCos serial ARM/INTEGRATOR configuration data +# +# ==================================================================== +#####COPYRIGHTBEGIN#### +# +# ------------------------------------------- +# The contents of this file are subject to the Red Hat eCos Public License +# Version 1.1 (the "License"); you may not use this file except in +# compliance with the License. You may obtain a copy of the License at +# http://www.redhat.com/ +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +# License for the specific language governing rights and limitations under +# the License. +# +# The Original Code is eCos - Embedded Configurable Operating System, +# released September 30, 1998. +# +# The Initial Developer of the Original Code is Red Hat. +# Portions created by Red Hat are +# Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +# All Rights Reserved. +# ------------------------------------------- +# +#####COPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): David A Rusling +# Original data: David A Rusling +# Contributors: Philippe Robin +# Date: November 7, 2000 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + + +cdl_package CYGPKG_IO_SERIAL_ARM_INTEGRATOR { + display "ARM INTEGRATOR serial device drivers" + + parent CYGPKG_IO_SERIAL_DEVICES + active_if CYGPKG_IO_SERIAL + active_if CYGPKG_HAL_ARM_INTEGRATOR + + requires CYGPKG_ERROR + include_dir cyg/io + description " + This option enables the serial device drivers for the + ARM INTEGRATOR." + doc redirect/ecos-device-drivers.html + + compile -library=libextras.a integrator_serial_with_ints.c + + define_proc { + puts $::cdl_system_header "/***** serial driver proc output start *****/" + puts $::cdl_system_header "#define CYGDAT_IO_SERIAL_DEVICE_HEADER <pkgconf/io_serial_arm_integrator.h>" + puts $::cdl_system_header "/***** serial driver proc output end *****/" + } + + cdl_component CYGPKG_IO_SERIAL_ARM_INTEGRATOR_SERIAL0 { + display "ARM INTEGRATOR serial port 0 driver" + flavor bool + default_value 1 + description " + This option includes the serial device driver for the ARM INTEGRATOR + port 0." + + cdl_option CYGDAT_IO_SERIAL_ARM_INTEGRATOR_SERIAL0_NAME { + display "Device name for ARM INTEGRATOR serial port 0 driver" + flavor data + default_value {"\"/dev/ser0\""} + description " + This option specifies the name of the serial device for the + ARM INTEGRATOR port 0." + } + + cdl_option CYGNUM_IO_SERIAL_ARM_INTEGRATOR_SERIAL0_BAUD { + display "Baud rate for the ARM INTEGRATOR serial port 0 driver" + flavor data + legal_values { 50 75 110 "134_5" 150 200 300 600 1200 1800 2400 3600 + 4800 7200 9600 14400 19200 38400 57600 115200 234000 + } + default_value 38400 + description " + This option specifies the default baud rate (speed) for the + ARM INTEGRATOR port 0." + } + + cdl_option CYGNUM_IO_SERIAL_ARM_INTEGRATOR_SERIAL0_BUFSIZE { + display "Buffer size for the ARM INTEGRATOR serial port 0 driver" + flavor data + legal_values 0 to 8192 + default_value 128 + description " + This option specifies the size of the internal buffers used + for the ARM INTEGRATOR port 0." + } + } + + cdl_component CYGPKG_IO_SERIAL_ARM_INTEGRATOR_SERIAL1 { + display "ARM INTEGRATOR serial port 1 driver" + flavor bool + default_value 1 + description " + This option includes the serial device driver for the ARM INTEGRATOR + port 1." + + cdl_option CYGDAT_IO_SERIAL_ARM_INTEGRATOR_SERIAL1_NAME { + display "Device name for ARM INTEGRATOR serial port 1 driver" + flavor data + default_value {"\"/dev/ser1\""} + description " + This option specifies the name of the serial device for the + ARM INTEGRATOR port 1." + } + + cdl_option CYGNUM_IO_SERIAL_ARM_INTEGRATOR_SERIAL1_BAUD { + display "Baud rate for the ARM INTEGRATOR serial port 1 driver" + flavor data + legal_values { 50 75 110 "134_5" 150 200 300 600 1200 1800 2400 3600 + 4800 7200 9600 14400 19200 38400 57600 115200 234000 + } + default_value 38400 + description " + This option specifies the default baud rate (speed) for the + ARM INTEGRATOR port 1." + } + } + + cdl_option CYGNUM_IO_SERIAL_ARM_INTEGRATOR_SERIAL1_BUFSIZE { + display "Buffer size for the ARM INTEGRATOR serial port 1 driver" + flavor data + legal_values 0 to 8192 + default_value 128 + description " + This option specifies the size of the internal buffers used + for the ARM INTEGRATOR port 1." + } + + cdl_component CYGPKG_IO_SERIAL_ARM_INTEGRATOR_TESTING { + display "Testing parameters" + flavor bool + calculated 1 + active_if CYGPKG_IO_SERIAL_ARM_INTEGRATOR_SERIAL0 + +# FIXME: I have no idea what the integrator hardware doesn't support -Jifl +# implements CYGINT_IO_SERIAL_TEST_SKIP_9600 +# implements CYGINT_IO_SERIAL_TEST_SKIP_115200 +# implements CYGINT_IO_SERIAL_TEST_SKIP_PARITY_EVEN + + cdl_option CYGPRI_SER_TEST_SER_DEV { + display "Serial device used for testing" + flavor data + default_value { CYGDAT_IO_SERIAL_ARM_INTEGRATOR_SERIAL0_NAME } + } + + define_proc { + puts $::cdl_header "#define CYGPRI_SER_TEST_CRASH_ID \"arminteg\"" + puts $::cdl_header "#define CYGPRI_SER_TEST_TTY_DEV \"/dev/tty0\"" + } + } +} + +# EOF ser_arm_integrator.cdl
new file mode 100644 --- /dev/null +++ b/packages/devs/serial/arm/integrator/current/src/integrator_serial.h @@ -0,0 +1,205 @@ +#ifndef CYGONCE_ARM_INTEGRATOR_SERIAL_H +#define CYGONCE_ARM_INTEGRATOR_SERIAL_H + +// ==================================================================== +// +// integrator_serial.h +// +// Device I/O - Description of ARM INTEGRATOR serial hardware +// +// ==================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +// ==================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): David A Rusling +// Contributors: Philippe Robin +// Date: November 7, 2000 +// Purpose: Internal interfaces for serial I/O drivers +// Description: +// +//####DESCRIPTIONEND#### +// +// ==================================================================== + +// Description of serial ports on ARM INTEGRATOR7T + +struct serial_port { + unsigned char _byte[32]; +}; + +// Little-endian version +#if (CYG_BYTEORDER == CYG_LSBFIRST) + +#define reg(n) _byte[n*4] + +#else // Big-endian version + +#define reg(n) _byte[(n*4)^3] + +#endif + +/* ------------------------------------------------------------------------------- + * From AMBA UART (PL010) Block Specification (ARM-0001-CUST-DSPC-A03) + * ------------------------------------------------------------------------------- + * UART Register Offsets. + * + */ +#define AMBA_UARTDR 0x00 /* Data read or written from the interface. */ +#define AMBA_UARTRSR 0x04 /* Receive status register (Read). */ +#define AMBA_UARTECR 0x04 /* Error clear register (Write). */ +#define AMBA_UARTLCR_H 0x08 /* Line control register, high byte. */ +#define AMBA_UARTLCR_M 0x0C /* Line control register, middle byte. */ +#define AMBA_UARTLCR_L 0x10 /* Line control register, low byte. */ +#define AMBA_UARTCR 0x14 /* Control register. */ +#define AMBA_UARTFR 0x18 /* Flag register (Read only). */ +#define AMBA_UARTIIR 0x1C /* Interrupt indentification register (Read). */ +#define AMBA_UARTICR 0x1C /* Interrupt clear register (Write). */ +#define AMBA_UARTILPR 0x20 /* IrDA low power counter register. */ + +#define AMBA_UARTRSR_OE 0x08 +#define AMBA_UARTRSR_BE 0x04 +#define AMBA_UARTRSR_PE 0x02 +#define AMBA_UARTRSR_FE 0x01 + +#define AMBA_UARTFR_TXFF 0x20 +#define AMBA_UARTFR_RXFE 0x10 +#define AMBA_UARTFR_BUSY 0x08 +#define AMBA_UARTFR_TMSK (AMBA_UARTFR_TXFF + AMBA_UARTFR_BUSY) + +#define AMBA_UARTCR_RTIE 0x40 +#define AMBA_UARTCR_TIE 0x20 +#define AMBA_UARTCR_RIE 0x10 +#define AMBA_UARTCR_MSIE 0x08 +#define AMBA_UARTCR_IIRLP 0x04 +#define AMBA_UARTCR_SIREN 0x02 +#define AMBA_UARTCR_UARTEN 0x01 + +#define AMBA_UARTLCR_H_WLEN_8 0x60 +#define AMBA_UARTLCR_H_WLEN_7 0x40 +#define AMBA_UARTLCR_H_WLEN_6 0x20 +#define AMBA_UARTLCR_H_WLEN_5 0x00 +#define AMBA_UARTLCR_H_FEN 0x10 +#define AMBA_UARTLCR_H_STP2 0x08 +#define AMBA_UARTLCR_H_EPS 0x04 +#define AMBA_UARTLCR_H_PEN 0x02 +#define AMBA_UARTLCR_H_BRK 0x01 + +#define AMBA_UARTIIR_RTIS 0x08 +#define AMBA_UARTIIR_TIS 0x04 +#define AMBA_UARTIIR_RIS 0x02 +#define AMBA_UARTIIR_MIS 0x01 + +#define ARM_BAUD_460800 1 +#define ARM_BAUD_230400 3 +#define ARM_BAUD_115200 7 +#define ARM_BAUD_57600 15 +#define ARM_BAUD_38400 23 +#define ARM_BAUD_19200 47 +#define ARM_BAUD_14400 63 +#define ARM_BAUD_9600 95 +#define ARM_BAUD_4800 191 +#define ARM_BAUD_2400 383 +#define ARM_BAUD_1200 767 + +// Interrupt Enable Register +#define IER_RCV 0x01 +#define IER_XMT 0x02 +#define IER_LS 0x04 +#define IER_MS 0x08 + +// Line Control Register +#define LCR_WL5 0x00 // Word length +#define LCR_WL6 0x20 +#define LCR_WL7 0x40 +#define LCR_WL8 0x60 + +#define LCR_SB1 0x00 // Number of stop bits +#define LCR_SB1_5 0x00 // 1.5 -> only valid with 5 bit words +#define LCR_SB2 0x08 + +#define LCR_PN 0x00 // Parity mode - none +#define LCR_PE 0x06 // Parity mode - even +#define LCR_PO 0x02 // Parity mode - odd +#define LCR_PM 0x00 // Forced "mark" parity +#define LCR_PS 0x00 // Forced "space" parity + +// Line Status Register +#define LSR_RSR 0x01 +#define LSR_THE 0x20 + +// Modem Control Register +#define MCR_DTR 0x01 +#define MCR_RTS 0x02 +#define MCR_INT 0x08 // Enable interrupts + +static unsigned short select_baud[] = { + 0, // Unused + 0, // 50 + 0, // 75 + 0, // 110 + 0, // 134.5 + 0, // 150 + 0, // 200 + 0, // 300 + 0, // 600 + ARM_BAUD_1200, // 1200 + 0, // 1800 + ARM_BAUD_2400, // 2400 + 0, // 3600 + ARM_BAUD_4800, // 4800 + 0, // 7200 + ARM_BAUD_9600, // 9600 + ARM_BAUD_14400, // 14400 + ARM_BAUD_19200, // 19200 + ARM_BAUD_38400, // 38400 + ARM_BAUD_57600, // 57600 + ARM_BAUD_115200, // 115200 + ARM_BAUD_230400, // 230400 +}; + +static unsigned char select_word_length[] = { + LCR_WL5, // 5 bits / word (char) + LCR_WL6, + LCR_WL7, + LCR_WL8 +}; + +static unsigned char select_stop_bits[] = { + 0, + LCR_SB1, // 1 stop bit + LCR_SB1_5, // 1.5 stop bit + LCR_SB2 // 2 stop bits +}; + +static unsigned char select_parity[] = { + LCR_PN, // No parity + LCR_PE, // Even parity + LCR_PO, // Odd parity + LCR_PM, // Mark parity + LCR_PS, // Space parity +}; + +#endif // CYGONCE_ARM_INTEGRATOR_SERIAL_H
new file mode 100644 --- /dev/null +++ b/packages/devs/serial/arm/integrator/current/src/integrator_serial_with_ints.c @@ -0,0 +1,402 @@ +//========================================================================== +// +// io/serial/arm/integrator_serial_with_ints.c +// +// ARM INTEGRATOR Serial I/O Interface Module (interrupt driven) +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): David A Rusling +// Contributors: Philippe Robin +// Date: November 7, 2000 +// Purpose: INTEGRATOR Serial I/O module (interrupt driven) +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/system.h> +#include <pkgconf/io.h> +#include <pkgconf/io_serial.h> +#include <cyg/io/io.h> +#include <cyg/hal/hal_intr.h> +#include <cyg/io/devtab.h> +#include <cyg/io/serial.h> +#include <cyg/infra/diag.h> + +#ifdef CYGPKG_IO_SERIAL_ARM_INTEGRATOR +#include "integrator_serial.h" + +typedef struct integrator_serial_info { + CYG_ADDRWORD base; + CYG_WORD int_num; + cyg_interrupt serial_interrupt; + cyg_handle_t serial_interrupt_handle; +} integrator_serial_info; + +static bool integrator_serial_init(struct cyg_devtab_entry *tab); +static bool integrator_serial_putc(serial_channel *chan, unsigned char c); +static Cyg_ErrNo integrator_serial_lookup(struct cyg_devtab_entry **tab, + struct cyg_devtab_entry *sub_tab, + const char *name); +static unsigned char integrator_serial_getc(serial_channel *chan); +static Cyg_ErrNo integrator_serial_set_config(serial_channel *chan, cyg_uint32 key, + const void *xbuf, cyg_uint32 *len); +static void integrator_serial_start_xmit(serial_channel *chan); +static void integrator_serial_stop_xmit(serial_channel *chan); + +static cyg_uint32 integrator_serial_ISR(cyg_vector_t vector, cyg_addrword_t data); +static void integrator_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data); + +static SERIAL_FUNS(integrator_serial_funs, + integrator_serial_putc, + integrator_serial_getc, + integrator_serial_set_config, + integrator_serial_start_xmit, + integrator_serial_stop_xmit + ); + +#ifdef CYGPKG_IO_SERIAL_ARM_INTEGRATOR_SERIAL0 +#define INTEGRATOR_UART0_BASE 0x16000000 /* UART 0 */ +static integrator_serial_info integrator_serial_info0 = {INTEGRATOR_UART0_BASE, CYGNUM_HAL_INTERRUPT_UARTINT0}; +#if CYGNUM_IO_SERIAL_ARM_INTEGRATOR_SERIAL0_BUFSIZE > 0 +static unsigned char integrator_serial_out_buf0[CYGNUM_IO_SERIAL_ARM_INTEGRATOR_SERIAL0_BUFSIZE]; +static unsigned char integrator_serial_in_buf0[CYGNUM_IO_SERIAL_ARM_INTEGRATOR_SERIAL0_BUFSIZE]; + +static SERIAL_CHANNEL_USING_INTERRUPTS(integrator_serial_channel0, + integrator_serial_funs, + integrator_serial_info0, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_INTEGRATOR_SERIAL0_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT, + &integrator_serial_out_buf0[0], sizeof(integrator_serial_out_buf0), + &integrator_serial_in_buf0[0], sizeof(integrator_serial_in_buf0) + ); +#else +static SERIAL_CHANNEL(integrator_serial_channel0, + integrator_serial_funs, + integrator_serial_info0, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_INTEGRATOR_SERIAL0_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT + ); +#endif + +DEVTAB_ENTRY(integrator_serial_io0, + CYGDAT_IO_SERIAL_ARM_INTEGRATOR_SERIAL0_NAME, + 0, // Does not depend on a lower level interface + &cyg_io_serial_devio, + integrator_serial_init, + integrator_serial_lookup, // Serial driver may need initializing + &integrator_serial_channel0 + ); +#endif // CYGPKG_IO_SERIAL_ARM_INTEGRATOR_SERIAL0 + +#ifdef CYGPKG_IO_SERIAL_ARM_INTEGRATOR_SERIAL1 +#define INTEGRATOR_UART1_BASE 0x17000000 /* UART 1 */ +static integrator_serial_info integrator_serial_info1 = {INTEGRATOR_UART1_BASE, CYGNUM_HAL_INTERRUPT_UARTINT1}; +#if CYGNUM_IO_SERIAL_ARM_INTEGRATOR_SERIAL1_BUFSIZE > 0 +static unsigned char integrator_serial_out_buf1[CYGNUM_IO_SERIAL_ARM_INTEGRATOR_SERIAL1_BUFSIZE]; +static unsigned char integrator_serial_in_buf1[CYGNUM_IO_SERIAL_ARM_INTEGRATOR_SERIAL1_BUFSIZE]; + +static SERIAL_CHANNEL_USING_INTERRUPTS(integrator_serial_channel1, + integrator_serial_funs, + integrator_serial_info1, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_INTEGRATOR_SERIAL1_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT, + &integrator_serial_out_buf1[0], sizeof(integrator_serial_out_buf1), + &integrator_serial_in_buf1[0], sizeof(integrator_serial_in_buf1) + ); +#else +static SERIAL_CHANNEL(integrator_serial_channel1, + integrator_serial_funs, + integrator_serial_info1, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_INTEGRATOR_SERIAL1_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT + ); +#endif + +DEVTAB_ENTRY(integrator_serial_io1, + CYGDAT_IO_SERIAL_ARM_INTEGRATOR_SERIAL1_NAME, + 0, // Does not depend on a lower level interface + &cyg_io_serial_devio, + integrator_serial_init, + integrator_serial_lookup, // Serial driver may need initializing + &integrator_serial_channel1 + ); +#endif // CYGPKG_IO_SERIAL_ARM_INTEGRATOR_SERIAL1 + +#define GET_INTERRUPT_STATUS(p) IO_READ((p) + AMBA_UARTIIR) +#define GET_STATUS(p) (IO_READ((p) + AMBA_UARTFR)) +#define GET_CHAR(p) (IO_READ((p) + AMBA_UARTDR)) +#define PUT_CHAR(p, c) (IO_WRITE(((p) + AMBA_UARTDR), (c))) +#define IO_READ(p) ((*(volatile unsigned int *)(p)) & 0xFF) +#define IO_WRITE(p, c) (*(unsigned int *)(p) = (c)) +#define RX_DATA(s) (((s) & AMBA_UARTFR_RXFE) == 0) +#define TX_READY(s) (((s) & AMBA_UARTFR_TXFF) == 0) +#define TX_EMPTY(p) ((GET_STATUS(p) & AMBA_UARTFR_TMSK) == 0) + +// debugging help +static int chars_rx = 0 ; +static int chars_tx = 0 ; + +// Internal function to actually configure the hardware to desired baud rate, etc. +static bool +integrator_serial_config_port(serial_channel *chan, cyg_serial_info_t *new_config, bool init) +{ + integrator_serial_info *integrator_chan = (integrator_serial_info *)chan->dev_priv; + unsigned int port = (unsigned int)integrator_chan->base; + unsigned short baud_divisor = select_baud[new_config->baud]; + unsigned char _lcr ; + + // don't do this baud rate... + if (baud_divisor == 0) return false; // Invalid configuration + + // first, disable everything + IO_WRITE(port + AMBA_UARTCR, 0x0); + + // Set baud rate + IO_WRITE(port + AMBA_UARTLCR_M, ((baud_divisor & 0xf00) >> 8)); + IO_WRITE(port + AMBA_UARTLCR_L, (baud_divisor & 0xff)); + + // ----------v----------v----------v----------v---------- + // NOTE: MUST BE WRITTEN LAST (AFTER UARTLCR_M & UARTLCR_L) + // ----------^----------^----------^----------^---------- + _lcr = + select_word_length[new_config->word_length - CYGNUM_SERIAL_WORD_LENGTH_5] | + select_stop_bits[new_config->stop] | + select_parity[new_config->parity] | AMBA_UARTLCR_H_FEN ; + IO_WRITE(port + AMBA_UARTLCR_H, _lcr); + + // finally, enable the uart + IO_WRITE(port + AMBA_UARTCR, (AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE | AMBA_UARTCR_UARTEN)); + + // save the configuration + if (new_config != &chan->config) { + chan->config = *new_config; + } + + // success + return true; +} + +// Function to initialize the device. Called at bootstrap time. +static bool +integrator_serial_init(struct cyg_devtab_entry *tab) +{ + serial_channel *chan = (serial_channel *)tab->priv; + integrator_serial_info *integrator_chan = (integrator_serial_info *)chan->dev_priv; +#ifdef CYGDBG_IO_INIT + diag_printf("INTEGRATOR SERIAL init - dev: %x.%d\n", integrator_chan->base, integrator_chan->int_num); +#endif + (chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices + if (chan->out_cbuf.len != 0) { + cyg_drv_interrupt_create(integrator_chan->int_num, + 99, // Priority - what goes here? + (cyg_addrword_t)chan, // Data item passed to interrupt handler + integrator_serial_ISR, + integrator_serial_DSR, + &integrator_chan->serial_interrupt_handle, + &integrator_chan->serial_interrupt); + cyg_drv_interrupt_attach(integrator_chan->serial_interrupt_handle); + cyg_drv_interrupt_unmask(integrator_chan->int_num); + } + integrator_serial_config_port(chan, &chan->config, true); + return true; +} + +// This routine is called when the device is "looked" up (i.e. attached) +static Cyg_ErrNo +integrator_serial_lookup(struct cyg_devtab_entry **tab, + struct cyg_devtab_entry *sub_tab, + const char *name) +{ + serial_channel *chan = (serial_channel *)(*tab)->priv; + (chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices + return ENOERR; +} + +// Send a character to the device output buffer. +// Return 'true' if character is sent to device +static bool +integrator_serial_putc(serial_channel *chan, unsigned char c) +{ + integrator_serial_info *integrator_chan = (integrator_serial_info *)chan->dev_priv; + unsigned int status = GET_STATUS(integrator_chan->base) ; + + if (TX_READY(status)) { +// Transmit buffer is empty + PUT_CHAR(integrator_chan->base, c) ; + chars_tx++ ; + return true; + } else { +// No space + return false; + } +} + +// Fetch a character from the device input buffer, waiting if necessary +static unsigned char +integrator_serial_getc(serial_channel *chan) +{ + unsigned char c; + integrator_serial_info *integrator_chan = (integrator_serial_info *)chan->dev_priv; + unsigned int status ; + + do { + status = GET_STATUS(integrator_chan->base) ; + } while (!RX_DATA(status)) ; // Wait for char + + chars_rx++ ; + + // get it + c = GET_CHAR(integrator_chan->base) ; + return c; +} + +// Set up the device characteristics; baud rate, etc. +static Cyg_ErrNo +integrator_serial_set_config(serial_channel *chan, cyg_uint32 key, const void *xbuf, + cyg_uint32 *len) +{ + integrator_serial_info *integrator_chan = (integrator_serial_info *)chan->dev_priv; + + switch (key) { + case CYG_IO_SET_CONFIG_SERIAL_INFO: + { + cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf; + if ( *len < sizeof(cyg_serial_info_t) ) { + return -EINVAL; + } + *len = sizeof(cyg_serial_info_t); + if ( true != integrator_serial_config_port(chan, config, false) ) + return -EINVAL; + } + break; +#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_HW +#ifdef FIXME + case CYG_IO_SET_CONFIG_SERIAL_HW_RX_FLOW_THROTTLE: + { + volatile struct serial_port *port = (volatile struct serial_port *)integrator_chan->base; + cyg_uint8 *f = (cyg_uint8 *)xbuf; + unsigned char mask=0; + if ( *len < *f ) + return -EINVAL; + + if ( chan->config.flags & CYGNUM_SERIAL_FLOW_RTSCTS_RX ) + mask = MCR_RTS; + if ( chan->config.flags & CYGNUM_SERIAL_FLOW_DSRDTR_RX ) + mask |= MCR_DTR; + if (*f) // we should throttle + port->REG_mcr &= ~mask; + else // we should no longer throttle + port->REG_mcr |= mask; + } + break; + case CYG_IO_SET_CONFIG_SERIAL_HW_FLOW_CONFIG: + // Nothing to do because we do support both RTSCTS and DSRDTR flow + // control. + // Other targets would clear any unsupported flags here. + // We just return ENOERR. + break; +#else +#error "Flow control for Integrator not integrated!" +#endif +#endif + default: + return -EINVAL; + } + return ENOERR; +} + +// Enable the transmitter on the device +static void +integrator_serial_start_xmit(serial_channel *chan) +{ + integrator_serial_info *integrator_chan = (integrator_serial_info *)chan->dev_priv; + + IO_WRITE(integrator_chan->base + AMBA_UARTCR, + IO_READ(integrator_chan->base + AMBA_UARTCR) | AMBA_UARTCR_TIE); +} + +// Disable the transmitter on the device +static void +integrator_serial_stop_xmit(serial_channel *chan) +{ + integrator_serial_info *integrator_chan = (integrator_serial_info *)chan->dev_priv; + + IO_WRITE(integrator_chan->base + AMBA_UARTCR, + IO_READ(integrator_chan->base + AMBA_UARTCR) & ~AMBA_UARTCR_TIE); +} + +// Serial I/O - low level interrupt handler (ISR) +static cyg_uint32 +integrator_serial_ISR(cyg_vector_t vector, cyg_addrword_t data) +{ + serial_channel *chan = (serial_channel *)data; + integrator_serial_info *integrator_chan = (integrator_serial_info *)chan->dev_priv; + + cyg_drv_interrupt_mask(integrator_chan->int_num); + cyg_drv_interrupt_acknowledge(integrator_chan->int_num); + return CYG_ISR_CALL_DSR; // Cause DSR to be run +} + +// Serial I/O - high level interrupt handler (DSR) +static void +integrator_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +{ + serial_channel *chan = (serial_channel *)data; + integrator_serial_info *integrator_chan = (integrator_serial_info *)chan->dev_priv; + volatile unsigned char isr = GET_INTERRUPT_STATUS(integrator_chan->base) ; + + while ((isr & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_TIS | AMBA_UARTIIR_RIS)) != 0) { + if (isr & AMBA_UARTIIR_TIS) { + (chan->callbacks->xmt_char)(chan); + } else if (isr & AMBA_UARTIIR_RTIS) { + chars_rx++ ; + (chan->callbacks->rcv_char)(chan, GET_CHAR(integrator_chan->base)); + } else if (isr & AMBA_UARTIIR_RIS) { + chars_rx++ ; + (chan->callbacks->rcv_char)(chan, GET_CHAR(integrator_chan->base)); + } + isr = GET_INTERRUPT_STATUS(integrator_chan->base) ; + } + cyg_drv_interrupt_unmask(integrator_chan->int_num); +} +#endif
--- a/packages/ecos.db +++ b/packages/ecos.db @@ -132,6 +132,7 @@ package CYGPKG_DEVS_FLASH_INTEL_BOOTBLOC This package contains hardware support for Intel boot block flash memory." } + package CYGPKG_DEVS_FLASH_AMD_AM29XXXXX { alias { "Support for AMD AM29xxxxx flash memory" flash_amd_am29xxxxx } directory devs/flash/amd/am29xxxxx @@ -303,6 +304,16 @@ package CYGPKG_DEVS_FLASH_IQ80310 { on the Cyclone IQ80310 platform." } +package CYGPKG_DEVS_FLASH_INTEGRATOR { + alias { "FLASH memory support for ARM INTEGRATOR" flash_integrator } + directory devs/flash/arm/integrator + script flash_integrator.cdl + hardware + description " + This package contains hardware support for FLASH memory + on the ARM INTEGRATOR platform." +} + package CYGPKG_DEVS_FLASH_MBX { alias { "FLASH memory support for Motorola PowerPC/860 MBX" flash_mbx } directory devs/flash/powerpc/mbx @@ -433,6 +444,15 @@ package CYGPKG_IO_SERIAL_ARM_E7T { description "ARM AEB-2 (E7T) serial device drivers" } +package CYGPKG_IO_SERIAL_ARM_INTEGRATOR { + alias { "ARM INTEGRATOR serial device drivers" + devs_serial_arm_integrator integrator_serial_driver } + hardware + directory devs/serial/arm/integrator + script ser_arm_integrator.cdl + description "ARM INTEGRATOR serial device drivers" +} + package CYGPKG_IO_SERIAL_ARM_AT91 { alias { "Atmel AT91 evaluation board (EB40)" devs_serial_arm_at91 at91_serial_driver } @@ -713,6 +733,15 @@ package CYGPKG_DEVS_ETH_ARM_FLEXANET { ethernet device on the Flexanet board." } +package CYGPKG_DEVS_ETH_ARM_INTEGRATOR { + alias { "ARM INTEGRATOR with Intel PRO/100+ ethernet driver" + devs_eth_arm_integrator integrator_eth_driver } + hardware + directory devs/eth/arm/integrator + script integrator_eth_drivers.cdl + description "Ethernet driver for Intel PRO/100+ boards on ARM INTEGRATOR." +} + package CYGPKG_DEVS_ETH_POWERPC_QUICC { alias { "QUICC ethernet driver" quicc_eth_driver } hardware @@ -1179,6 +1208,16 @@ The e7t HAL package provides the support Evaluator7T board (aka the AEB-2)." } +package CYGPKG_HAL_ARM_INTEGRATOR { + alias { "ARM development board (INTEGRATOR)" hal_arm_integrator arm_integrator_hal } + directory hal/arm/integrator + script hal_arm_integrator.cdl + hardware + description " + The INTEGRATOR HAL package provides the support needed to + run eCos on a ARM INTEGRATOR eval board." +} + package CYGPKG_HAL_ARM_AT91 { alias { "Atmel evaluation board (EB40)" hal_arm_at91 arm_at91_hal } directory hal/arm/at91 @@ -1209,6 +1248,7 @@ package CYGPKG_HAL_ARM_ARM9 { eCos on a ARM9 based systems." } + package CYGPKG_HAL_ARM_SA11X0 { alias { "Intel SA11X0 Chipset" hal_arm_sa11x0 } directory hal/arm/sa11x0/var @@ -1929,6 +1969,21 @@ The aeb target provides the packages nee Evaluator7T board (aka AEB-2)." } +target integrator { + alias { "ARM development board (INTEGRATOR)" INTEGRATOR } + packages { CYGPKG_HAL_ARM + CYGPKG_HAL_ARM_INTEGRATOR + CYGPKG_IO_PCI + CYGPKG_DEVS_ETH_ARM_INTEGRATOR + CYGPKG_IO_SERIAL_ARM_INTEGRATOR + CYGPKG_DEVS_FLASH_INTEGRATOR + } + description " + The INTEGRATOR target provides the packages needed to + run eCos on an ARM development board (formerly known + as INTEGRATOR)." +} + target at91 { alias { "Atmel evaluation board (EB40)" eb40 } packages { CYGPKG_HAL_ARM @@ -1956,6 +2011,7 @@ target ebsa285 { eCos on an Intel EBSA285 StrongARM board." } + target assabet { alias { "Intel StrongARM SA1110 board" assabet } packages { CYGPKG_HAL_ARM
--- a/packages/hal/arm/arch/current/ChangeLog +++ b/packages/hal/arm/arch/current/ChangeLog @@ -1,3 +1,9 @@ +2001-10-29 Hugo Tyson <hmt@redhat.com> + + * src/arm.ld (SECTION_rom_vectors): Define symbols used for ROMRAM + startup; for some reason these were not in the trunk. They are: + __rom_vectors_vma and __rom_vectors_lma + 2001-10-24 Gary Thomas <gthomas@redhat.com> * src/hal_misc.c (hal_msbindex): Fix calculation.
--- a/packages/hal/arm/arch/current/src/arm.ld +++ b/packages/hal/arm/arch/current/src/arm.ld @@ -87,8 +87,10 @@ OUTPUT_FORMAT(elf32-bigarm) #define SECTION_rom_vectors(_region_, _vma_, _lma_) \ .rom_vectors _vma_ : _lma_ \ - { FORCE_OUTPUT; KEEP (*(.vectors)) } \ - > _region_ + { __rom_vectors_vma = ABSOLUTE(.); \ + FORCE_OUTPUT; KEEP (*(.vectors)) } \ + > _region_ \ + __rom_vectors_lma = LOADADDR(.rom_vectors); #define SECTION_text(_region_, _vma_, _lma_) \ .text _vma_ : _lma_ \
--- a/packages/hal/arm/arm9/var/current/ChangeLog +++ b/packages/hal/arm/arm9/var/current/ChangeLog @@ -1,3 +1,13 @@ +2001-11-01 Jesper Skov <jskov@redhat.com> + + * src/arm9_misc.c (cyg_hal_arm9_soft_reset): Attempt at soft + reset. Doesn't quite work though, and it's unclear why. + +2001-10-28 Gary Thomas <gthomas@redhat.com> + + * include/hal_cache.h: Fix DATA cache flush for 920,922. This was + off-by-one, leaving part of the cache unflushed. + 2001-08-13 Jesper Skov <jskov@redhat.com> * include/hal_cache.h: Support ARM variants 920, 922, 925 and 940.
--- a/packages/hal/arm/arm9/var/current/include/hal_cache.h +++ b/packages/hal/arm/arm9/var/current/include/hal_cache.h @@ -72,7 +72,7 @@ # define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX # define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX_STEP 0x20 -# define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX_LIMIT 0xe0 +# define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX_LIMIT 0x100 #elif defined(CYGPKG_HAL_ARM_ARM9_ARM922T) # define HAL_ICACHE_SIZE 0x2000 @@ -89,7 +89,7 @@ # define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX # define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX_STEP 0x20 -# define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX_LIMIT 0x60 +# define CYGHWR_HAL_ARM_ARM9_CLEAN_DCACHE_INDEX_LIMIT 0x80 #elif defined(CYGPKG_HAL_ARM_ARM9_ARM925T) # define HAL_ICACHE_SIZE 0x4000
--- a/packages/hal/arm/arm9/var/current/src/arm9_misc.c +++ b/packages/hal/arm/arm9/var/current/src/arm9_misc.c @@ -75,5 +75,26 @@ void hal_hardware_init(void) #endif } +void +cyg_hal_arm9_soft_reset(CYG_ADDRESS entry) +{ + + /* It would probably make more sense to have the + clear/drain/invalidate after disabling the cache and MMU, but + then we'd have to know the (unmapped) address of this code. */ + asm volatile ("mov r1, #0;" + "mcr p15,0,r1,c7,c7,0;" /* clear I+DCache */ + "mcr p15,0,r1,c7,c10,4;" /* Drain Write Buffer */ + "mcr p15,0,r1,c8,c7,0;" /* Invalidate TLBs */ + "mrc p15,0,r1,c1,c0,0;" + "bic r1,r1,#0x1000;" /* disable ICache */ + "bic r1,r1,#0x0007;" /* disable DCache, MMU and alignment faults */ + "mcr p15,0,r1,c1,c0,0;" + "nop;" /* delay 1 */ + "mov pc, %0;" /* delay 2 - next instruction should be fetched flat */ + : : "r" (entry) : "r1"); + for(;;); +} + /*------------------------------------------------------------------------*/ // EOF arm9_misc.c
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/ChangeLog @@ -0,0 +1,29 @@ +2001-10-30 Philippe Robin <Philippe.Robin@arm.com> + + * Initial version of integrator package. + +//=========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//===========================================================================
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/cdl/hal_arm_integrator.cdl @@ -0,0 +1,457 @@ +# ==================================================================== +# +# hal_arm_integrator.cdl +# +# INTEGRATOR board HAL package configuration data +# +# ==================================================================== +#####COPYRIGHTBEGIN#### +# +# ------------------------------------------- +# The contents of this file are subject to the Red Hat eCos Public License +# Version 1.1 (the "License"); you may not use this file except in +# compliance with the License. You may obtain a copy of the License at +# http://www.redhat.com/ +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +# License for the specific language governing rights and limitations under +# the License. +# +# The Original Code is eCos - Embedded Configurable Operating System, +# released September 30, 1998. +# +# The Initial Developer of the Original Code is Red Hat. +# Portions created by Red Hat are +# Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +# All Rights Reserved. +# ------------------------------------------- +# +#####COPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): David A Rusling +# Original data: gthomas +# Contributors: Philippe Robin +# Date: November 7, 2000 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_HAL_ARM_INTEGRATOR { + display "ARM INTEGRATOR evaluation board" + parent CYGPKG_HAL_ARM + define_header hal_arm_integrator.h + include_dir cyg/hal + hardware + description " + The integrator HAL package provides the support needed to run + eCos on an ARM INTEGRATOR evaluation board." + + compile hal_diag.c integrator_misc.c + + implements CYGINT_HAL_DEBUG_GDB_STUBS + implements CYGINT_HAL_DEBUG_GDB_STUBS_BREAK + implements CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT + implements CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT_NOT_GUARANTEED + implements CYGINT_HAL_ARM_THUMB_ARCH + implements CYGINT_HAL_ARM_BIGENDIAN + implements CYGINT_HAL_ARM_ARCH_ARM7 + implements CYGINT_HAL_ARM_ARCH_ARM9 + + define_proc { + puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H <pkgconf/hal_arm.h>" + puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_H <pkgconf/hal_arm_integrator.h>" + puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_IO_H <cyg/hal/plf_io.h>" + puts $::cdl_header "" + puts $::cdl_header "#define HAL_PLATFORM_CPU \"ARM 7TDMI\"" + puts $::cdl_header "#define HAL_PLATFORM_BOARD \"INTEGRATOR\"" + puts $::cdl_header "#define HAL_PLATFORM_EXTRA \"\"" + puts $::cdl_header "" + } + + + cdl_component CYG_HAL_STARTUP { + display "Startup type" + flavor data + legal_values {"RAM" "ROM"} + default_value {"RAM"} + no_define + define -file system.h CYG_HAL_STARTUP + description " + When targetting the INTEGRATOR eval board it is possible to build + the system for either RAM bootstrap or ROM bootstrap(s). Select + 'ram' when building programs to load into RAM using onboard + debug software such as Angel or eCos GDB stubs. Select 'rom' + when building a stand-alone application which will be put + into ROM." + + } + + cdl_option CYGHWR_HAL_ARM_INTEGRATOR_PCI_MEM_MAP_BASE { + display "Base of memory accessible via PCI space" + flavor data + legal_values 0 to 0x80000000 + default_value 0x80000000 + active_if CYGPKG_IO_PCI + description " + This option determines the base of the INTEGRATOR memory + which can be accessed via the PCI bus. Change in 256kB + increments." + } + + cdl_option CYGHWR_HAL_ARM_INTEGRATOR_PCI_MEM_MAP_SIZE { + display "Size of memory accessible via PCI space" + flavor data + legal_values 0 to 0x100000 + default_value 0x100000 + active_if CYGPKG_IO_PCI + description " + This option determines the size of the INTEGRATOR memory + which can be accessed via the PCI bus. Change in 256kB + increments." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_DEFAULT { + display "Default console channel." + flavor data + calculated 0 + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD { + display "Diagnostic serial port baud rate" + flavor data + legal_values 9600 19200 38400 115200 + default_value 38400 + description " + This option selects the baud rate used for the diagnostic port. + Note: this should match the value chosen for the GDB port if the + diagnostic and GDB port are the same." + } + + cdl_option CYGHWR_HAL_ARM_INTEGRATOR_GDB_PORT { + display "GDB serial port" + flavor data + legal_values 0 1 + default_value 1 + description " + The INTEGRATOR board has two separate serial ports. This option + chooses which of these ports will be used to connect to a host + running GDB." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD { + display "GDB serial port baud rate" + flavor data + legal_values 9600 19200 38400 115200 + default_value 38400 + description " + This option controls the baud rate used for the GDB connection." + } + + cdl_option CYGHWR_HAL_ARM_INTEGRATOR_DIAG_LEDS { + display "Enable use of PPx LEDs" + default_value 1 + description " + Enabling this option causes eCos to flash the LEDs during + early board initialization. See vectors.S for + details. Before calling cyg_start, PP0 is switched on, + PP1-3 are switched off. The application code can use the + function hal_diag_led() to control the LEDs after this + point." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS { + display "Number of communication channels on the board" + flavor data + calculated 2 + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL { + display "Debug serial port" + active_if CYGPRI_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_CONFIGURABLE + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 1 + description " + The INTEGRATOR board has two serial ports. This option + chooses which port will be used to connect to a host + running GDB." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL { + display "Diagnostic serial port" + active_if CYGPRI_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_CONFIGURABLE + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + The INTEGRATOR board has two serial ports. This option + chooses which port will be used for diagnostic output." + } + + # Real-time clock/counter specifics + cdl_component CYGNUM_HAL_RTC_CONSTANTS { + display "Real-time clock constants" + flavor none + + cdl_option CYGNUM_HAL_RTC_NUMERATOR { + display "Real-time clock numerator" + flavor data + calculated 1000000000 + } + cdl_option CYGNUM_HAL_RTC_DENOMINATOR { + display "Real-time clock denominator" + flavor data + calculated 100 + } + cdl_option CYGNUM_HAL_RTC_PERIOD { + display "Real-time clock period" + flavor data + calculated 12500 + } + } + + cdl_component CYGBLD_GLOBAL_OPTIONS { + display "Global build options" + flavor none + parent CYGPKG_NONE + description " + Global build options including control over + compiler flags, linker flags and choice of toolchain." + + + cdl_option CYGBLD_GLOBAL_COMMAND_PREFIX { + display "Global command prefix" + flavor data + no_define + default_value { CYGHWR_THUMB ? "thumb-elf" : "arm-elf" } + description " + This option specifies the command prefix used when + invoking the build tools." + } + + cdl_option CYGBLD_GLOBAL_CFLAGS { + display "Global compiler flags" + flavor data + no_define + default_value { (CYGBLD_ARM_ENABLE_THUMB_INTERWORK && CYGHWR_HAL_ARM_BIGENDIAN) ? "-mthumb-interwork -mbig-endian -Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority" : + CYGBLD_ARM_ENABLE_THUMB_INTERWORK ? "-mthumb-interwork -Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority" : + (CYGHWR_HAL_ARM_CPU_FAMILY == "ARM9") && CYGHWR_HAL_ARM_BIGENDIAN ? "-mcpu=arm9 -mbig-endian -Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority" : + (CYGHWR_HAL_ARM_CPU_FAMILY == "ARM9") && ! CYGHWR_HAL_ARM_BIGENDIAN ? "-mcpu=arm9 -Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority" : + (CYGHWR_HAL_ARM_CPU_FAMILY != "ARM9") && CYGHWR_HAL_ARM_BIGENDIAN ? "-mcpu=arm7tdmi -mbig-endian -Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority" : + "-mcpu=arm7tdmi -Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority" } + description " + This option controls the global compiler flags which are used to + compile all packages by default. Individual packages may define + options which override these global flags." + } + + cdl_option CYGBLD_GLOBAL_LDFLAGS { + display "Global linker flags" + flavor data + no_define + default_value { ((CYGHWR_THUMB || CYGSEM_HAL_ROM_MONITOR) && CYGHWR_HAL_ARM_BIGENDIAN) ? "-mthumb-interwork -mbig-endian -g -nostdlib -Wl,--gc-sections -Wl,-static" : + (CYGHWR_THUMB || CYGSEM_HAL_ROM_MONITOR) ? "-mthumb-interwork -g -nostdlib -Wl,--gc-sections -Wl,-static" : + (CYGHWR_HAL_ARM_CPU_FAMILY == "ARM9") && CYGHWR_HAL_ARM_BIGENDIAN ? "-mcpu=arm9 -mbig-endian -g -nostdlib -Wl,--gc-sections -Wl,-static" : + (CYGHWR_HAL_ARM_CPU_FAMILY == "ARM9") && ! CYGHWR_HAL_ARM_BIGENDIAN ? "-mcpu=arm9 -g -nostdlib -Wl,--gc-sections -Wl,-static" : + (CYGHWR_HAL_ARM_CPU_FAMILY != "ARM9") && CYGHWR_HAL_ARM_BIGENDIAN ? "-mcpu=arm7tdmi -mbig-endian -g -nostdlib -Wl,--gc-sections -Wl,-static" : + "-mcpu=arm7tdmi -g -nostdlib -Wl,--gc-sections -Wl,-static" } + description " + This option controls the global linker flags. Individual + packages may define options which override these global flags." + } + + cdl_option CYGBLD_BUILD_GDB_STUBS { + display "Build GDB stub ROM image" + default_value 0 + requires CYGBLD_BUILD_COMMON_GDB_STUBS + requires { CYG_HAL_STARTUP == "ROM" } + requires CYGSEM_HAL_ROM_MONITOR + requires CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + requires CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + requires CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT + requires ! CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT + requires ! CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM + no_define + description " + This option enables the building of the GDB stubs for the + board. The address of the ELF headers in the image are + adjusted to ensure loading at an address in memory used + by the flash tool." + + make -priority 320 { + <PREFIX>/bin/gdb_module.bin : <PREFIX>/bin/gdb_module.img + @mv $< $(<:.img=.elf) + $(OBJCOPY) --strip-debug --change-addresses=0xFC060000 $(<:.img=.elf) $< + $(OBJCOPY) -O binary $(<:.img=.elf) $@ + } + } + + cdl_option CYGBLD_BUILD_FLASH_TOOL { + display "Build flash programming tool" + default_value 0 + requires { CYG_HAL_STARTUP == "RAM" } + requires CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == 1 + requires CYGPKG_LIBC + requires CYGPKG_KERNEL + no_define + description "This option enables the building of the flash programming tool for copying the GDB stubs into flash memory." + make -priority 320 { + <PREFIX>/bin/prog_flash.img : <PACKAGE>/src/prog_flash.c + @sh -c "mkdir -p src $(dir $@)" + $(CC) -c $(INCLUDE_PATH) -Wp,-MD,deps.tmp -I$(dir $<) $(CFLAGS) -o src/prog_flash.o $< + @echo $@ ": \\" > $(notdir $@).deps + @echo $(wildcard $(PREFIX)/lib/*) " \\" >> $(notdir $@).deps + @tail +2 deps.tmp >> $(notdir $@).deps + @echo >> $(notdir $@).deps + @rm deps.tmp + $(CC) $(LDFLAGS) -L$(PREFIX)/lib -Ttarget.ld -o $@ src/prog_flash.o + } + } + + cdl_option CYGBLD_BUILD_FLASH_TOOL_BE { + display "Build flash programming tool for BE images on LE boards" + default_value 0 + requires { CYG_HAL_STARTUP == "RAM" } + requires CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == 1 + requires CYGPKG_LIBC + requires CYGPKG_KERNEL + no_define + description "This option enables the building of the flash + programming tool for copying the GDB stubs + into flash memory. The tool built by enabling + this option must be used when programming BE + images on LE boards." + make -priority 320 { + <PREFIX>/bin/prog_flash_BE_image_LE_system.img : <PACKAGE>/src/prog_flash.c + @sh -c "mkdir -p src $(dir $@)" + $(CC) -DBE_IMAGE -c $(INCLUDE_PATH) -Wp,-MD,deps.tmp -I$(dir $<) $(CFLAGS) -o src/prog_flash_be.o $< + @echo $@ ": \\" > $(notdir $@).deps + @echo $(wildcard $(PREFIX)/lib/*) " \\" >> $(notdir $@).deps + @tail +2 deps.tmp >> $(notdir $@).deps + @echo >> $(notdir $@).deps + @rm deps.tmp + $(CC) $(LDFLAGS) -L$(PREFIX)/lib -Ttarget.ld -o $@ src/prog_flash_be.o + } + } + } + + cdl_component CYGHWR_MEMORY_LAYOUT { + display "Memory layout" + flavor data + no_define + calculated { CYG_HAL_STARTUP == "RAM" ? "arm_integrator_ram" : \ + "arm_integrator_rom" } + + cdl_option CYGHWR_MEMORY_LAYOUT_LDI { + display "Memory layout linker script fragment" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_LDI + calculated { CYG_HAL_STARTUP == "RAM" ? "<pkgconf/mlt_arm_integrator_ram.ldi>" : \ + "<pkgconf/mlt_arm_integrator_rom.ldi>" } + } + + cdl_option CYGHWR_MEMORY_LAYOUT_H { + display "Memory layout header file" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_H + calculated { CYG_HAL_STARTUP == "RAM" ? "<pkgconf/mlt_arm_integrator_ram.h>" : \ + "<pkgconf/mlt_arm_integrator_rom.h>" } + } + } + + + cdl_option CYGSEM_HAL_ROM_MONITOR { + display "Behave as a ROM monitor" + flavor bool + default_value 0 + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "ROM" } + description " + Enable this option if this program is to be used as a ROM monitor, + i.e. applications will be loaded into RAM on the board, and this + ROM monitor may process exceptions or interrupts generated from the + application. This enables features such as utilizing a separate + interrupt stack when exceptions are generated." + } + + cdl_component CYGPKG_CYGMON_HAL_OPTIONS { + display "CygMon HAL options" + flavor none + no_define + parent CYGPKG_CYGMON + active_if CYGPKG_CYGMON + description " + This option also lists the target's requirements for a valid CygMon + configuration." + + cdl_option CYGBLD_BUILD_CYGMON_BIN { + display "Build CygMon ROM binary image" + active_if CYGBLD_BUILD_CYGMON + default_value 1 + no_define + description "This option enables the conversion of the CygMon ELF + image to a binary image suitable for ROM programming." + + make -priority 325 { + <PREFIX>/bin/cygmon.bin : <PREFIX>/bin/cygmon.elf + $(OBJCOPY) --strip-debug --change-addresses=0xFC060000 $< $(@:.bin=.img) + $(OBJCOPY) -O srec $< $(@:.bin=.srec) + $(OBJCOPY) -O binary $< $@ + } + } + } + + cdl_option CYGSEM_HAL_USE_ROM_MONITOR { + display "Work with a ROM monitor" + flavor booldata + legal_values { "Generic" "GDB_stubs" } + default_value { CYG_HAL_STARTUP == "RAM" ? "GDB_stubs" : 0 } + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "RAM" } + description " + Support can be enabled for different varieties of ROM monitor. + This support changes various eCos semantics such as the encoding + of diagnostic output, or the overriding of hardware interrupt + vectors. + Firstly there is \"Generic\" support which prevents the HAL + from overriding the hardware vectors that it does not use, to + instead allow an installed ROM monitor to handle them. This is + the most basic support which is likely to be common to most + implementations of ROM monitor. + \"GDB_stubs\" provides support when GDB stubs are included in + the ROM monitor or boot ROM." + } + + cdl_component CYGPKG_REDBOOT_HAL_OPTIONS { + display "Redboot HAL options" + flavor none + no_define + parent CYGPKG_REDBOOT + active_if CYGPKG_REDBOOT + description " + This option lists the target's requirements for a valid Redboot + configuration." + + cdl_option CYGBLD_BUILD_REDBOOT_BIN { + display "Build Redboot ROM binary image" + active_if CYGBLD_BUILD_REDBOOT + default_value 1 + no_define + description "This option enables the conversion of the Redboot ELF + image to a binary image suitable for ROM programming." + + make -priority 325 { + <PREFIX>/bin/redboot.bin : <PREFIX>/bin/redboot.elf + $(OBJCOPY) --strip-debug $< $(@:.bin=.img) + $(OBJCOPY) -O srec $< $(@:.bin=.srec) + $(OBJCOPY) -O binary $< $@ + } + } + } +}
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/include/hal_cache.h @@ -0,0 +1,174 @@ +#ifndef CYGONCE_HAL_CACHE_H +#define CYGONCE_HAL_CACHE_H + +//============================================================================= +// +// hal_cache.h +// +// HAL cache control API +// +//============================================================================= +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): David A Rusling +// Contributors: Philippe Robin +// Date: November 7, 2000 +// Purpose: Cache control API +// Description: The macros defined here provide the HAL APIs for handling +// cache control operations. +// Usage: +// #include <cyg/hal/hal_cache.h> +// ... +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include <cyg/infra/cyg_type.h> + +//----------------------------------------------------------------------------- +// Cache dimensions + +// Data cache +#define HAL_DCACHE_SIZE 0 // Size of data cache in bytes +#define HAL_DCACHE_LINE_SIZE 0 // Size of a data cache line +#define HAL_DCACHE_WAYS 0 // Associativity of the cache + +// Instruction cache +#define HAL_ICACHE_SIZE 0 // Size of cache in bytes +#define HAL_ICACHE_LINE_SIZE 0 // Size of a cache line +#define HAL_ICACHE_WAYS 0 // Associativity of the cache + +#define HAL_DCACHE_SETS (HAL_DCACHE_SIZE/(HAL_DCACHE_LINE_SIZE*HAL_DCACHE_WAYS)) +#define HAL_ICACHE_SETS (HAL_ICACHE_SIZE/(HAL_ICACHE_LINE_SIZE*HAL_ICACHE_WAYS)) + +//----------------------------------------------------------------------------- +// Global control of data cache + +// Enable the data cache +#define HAL_DCACHE_ENABLE() + +// Disable the data cache +#define HAL_DCACHE_DISABLE() + +// Invalidate the entire cache +#define HAL_DCACHE_INVALIDATE_ALL() + +// Synchronize the contents of the cache with memory. +#define HAL_DCACHE_SYNC() + +// Query the state of the data cache +#define HAL_DCACHE_IS_ENABLED(_state_) 0 + +// Purge contents of data cache +#define HAL_DCACHE_PURGE_ALL() + +// Set the data cache refill burst size +//#define HAL_DCACHE_BURST_SIZE(_size_) + +// Set the data cache write mode +//#define HAL_DCACHE_WRITE_MODE( _mode_ ) + +//#define HAL_DCACHE_WRITETHRU_MODE 0 +//#define HAL_DCACHE_WRITEBACK_MODE 1 + +// Load the contents of the given address range into the data cache +// and then lock the cache so that it stays there. +//#define HAL_DCACHE_LOCK(_base_, _size_) + +// Undo a previous lock operation +//#define HAL_DCACHE_UNLOCK(_base_, _size_) + +// Unlock entire cache +//#define HAL_DCACHE_UNLOCK_ALL() + +//----------------------------------------------------------------------------- +// Data cache line control + +// Allocate cache lines for the given address range without reading its +// contents from memory. +//#define HAL_DCACHE_ALLOCATE( _base_ , _size_ ) + +// Write dirty cache lines to memory and invalidate the cache entries +// for the given address range. +//#define HAL_DCACHE_FLUSH( _base_ , _size_ ) + +// Invalidate cache lines in the given range without writing to memory. +//#define HAL_DCACHE_INVALIDATE( _base_ , _size_ ) + +// Write dirty cache lines to memory for the given address range. +//#define HAL_DCACHE_STORE( _base_ , _size_ ) + +// Preread the given range into the cache with the intention of reading +// from it later. +//#define HAL_DCACHE_READ_HINT( _base_ , _size_ ) + +// Preread the given range into the cache with the intention of writing +// to it later. +//#define HAL_DCACHE_WRITE_HINT( _base_ , _size_ ) + +// Allocate and zero the cache lines associated with the given range. +//#define HAL_DCACHE_ZERO( _base_ , _size_ ) + +//----------------------------------------------------------------------------- +// Global control of Instruction cache + +// Enable the instruction cache +#define HAL_ICACHE_ENABLE() + +// Disable the instruction cache +#define HAL_ICACHE_DISABLE() + +// Invalidate the entire cache +#define HAL_ICACHE_INVALIDATE_ALL() + +// Synchronize the contents of the cache with memory. +#define HAL_ICACHE_SYNC() + +// Set the instruction cache refill burst size +//#define HAL_ICACHE_BURST_SIZE(_size_) + +// Load the contents of the given address range into the instruction cache +// and then lock the cache so that it stays there. +//#define HAL_ICACHE_LOCK(_base_, _size_) + +// Undo a previous lock operation +//#define HAL_ICACHE_UNLOCK(_base_, _size_) + +// Unlock entire cache +//#define HAL_ICACHE_UNLOCK_ALL() + +//----------------------------------------------------------------------------- +// Instruction cache line control + +// Invalidate cache lines in the given range without writing to memory. +//#define HAL_ICACHE_INVALIDATE( _base_ , _size_ ) + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_HAL_CACHE_H +// End of hal_cache.h
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/include/hal_diag.h @@ -0,0 +1,86 @@ +#ifndef CYGONCE_HAL_DIAG_H +#define CYGONCE_HAL_DIAG_H + +/*============================================================================= +// +// hal_diag.h +// +// HAL Support for Kernel Diagnostic Routines +// +//============================================================================= +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): David A Rusling +// Contributors: Philippe Robin +// Date: November 7, 2000 +// Purpose: HAL Support for Kernel Diagnostic Routines +// Description: Diagnostic routines for use during kernel development. +// Usage: #include <cyg/hal/hal_diag.h> +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +#include <pkgconf/hal.h> + +#include <cyg/infra/cyg_type.h> + +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) + +#include <cyg/hal/hal_if.h> + +#define HAL_DIAG_INIT() hal_if_diag_init() +#define HAL_DIAG_WRITE_CHAR(_c_) hal_if_diag_write_char(_c_) +#define HAL_DIAG_READ_CHAR(_c_) hal_if_diag_read_char(&_c_) + +#else // everything by steam + +/*---------------------------------------------------------------------------*/ +/* functions implemented in hal_diag.c */ + +externC void hal_diag_init(void); +externC void hal_diag_write_char(char c); +externC void hal_diag_read_char(char *c); + +/*---------------------------------------------------------------------------*/ + +#define HAL_DIAG_INIT() hal_diag_init() + +#define HAL_DIAG_WRITE_CHAR(_c_) hal_diag_write_char(_c_) + +#define HAL_DIAG_READ_CHAR(_c_) hal_diag_read_char(&_c_) + +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG + +/*---------------------------------------------------------------------------*/ +// LED + +externC void hal_diag_led(int n); + +/*---------------------------------------------------------------------------*/ +/* end of hal_diag.h */ +#endif /* CYGONCE_HAL_DIAG_H */
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/include/hal_integrator.h @@ -0,0 +1,433 @@ +#ifndef CYGONCE_HAL_INTEGRATOR_H +#define CYGONCE_HAL_INTEGRATOR_H + +/*============================================================================= +// +// hal_integrator.h +// +// HAL Description of INTEGRATOR board +// +//============================================================================= +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Philippe Robin +// Contributors: +// Date: November 7, 2000 +// Purpose: +// Description: +// Usage: #include <cyg/hal/hal_integrator.h> +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + + +#define INTEGRATOR_HDR_BASE 0x10000000 +#define INTEGRATOR_HDR_CTRL_OFFSET 0x0C +#define INTEGRATOR_HDR_CTRL_REMAP 0x04 + +#define INTEGRATOR_BOOT_ROM_BASE 0x20000000 +#define INTEGRATOR_HDR0_SDRAM_BASE 0x80000000 + +#define INTEGRATOR_DBG_ALPHA_OFFSET 0x00 +#define INTEGRATOR_DBG_LEDS_OFFSET 0x04 +#define INTEGRATOR_DBG_SWITCH_OFFSET 0x08 + +#define INTEGRATOR_DBG_BASE 0x1A000000 +#define INTEGRATOR_DBG_ALPHA (INTEGRATOR_DBG_BASE + INTEGRATOR_DBG_ALPHA_OFFSET) +#define INTEGRATOR_DBG_LEDS (INTEGRATOR_DBG_BASE + INTEGRATOR_DBG_LEDS_OFFSET) +#define INTEGRATOR_DBG_SWITCH (INTEGRATOR_DBG_BASE + INTEGRATOR_DBG_SWITCH_OFFSET) + +#define INTEGRATOR_UART0_BASE 0x16000000 /* UART 0 */ +#define INTEGRATOR_UART1_BASE 0x17000000 /* UART 1 */ + +#define INTEGRATOR_IRQCONT_BASE 0x14000000 + +#define INTEGRATOR_IRQSTATUS 0x00 +#define INTEGRATOR_IRQRAWSTATUS 0x04 +#define INTEGRATOR_IRQENABLE 0x08 +#define INTEGRATOR_IRQENABLESET 0x08 +#define INTEGRATOR_IRQENABLECLEAR 0x0C + +#define INTEGRATOR_IRQSOFT 0x10 +#define INTEGRATOR_IRQSOFTSET 0x10 +#define INTEGRATOR_IRQSOFTCLEAR 0x14 + +#define INTEGRATOR_FIQSTATUS 0x20 +#define INTEGRATOR_FIQRAWSTATUS 0x24 +#define INTEGRATOR_FIQENABLE 0x28 +#define INTEGRATOR_FIQENABLESET 0x28 +#define INTEGRATOR_FIQENABLECLEAR 0x2C + +#define INTEGRATOR_IRQCONT_IRQSTATUS (INTEGRATOR_IRQCONT_BASE + INTEGRATOR_IRQSTATUS) +#define INTEGRATOR_IRQCONT_IRQRAWSTATUS (INTEGRATOR_IRQCONT_BASE + INTEGRATOR_IRQRAWSTATUS) +#define INTEGRATOR_IRQCONT_IRQENABLE (INTEGRATOR_IRQCONT_BASE + INTEGRATOR_IRQENABLE) +#define INTEGRATOR_IRQCONT_IRQENABLESET (INTEGRATOR_IRQCONT_BASE + INTEGRATOR_IRQENABLESET) +#define INTEGRATOR_IRQCONT_IRQENABLECLEAR (INTEGRATOR_IRQCONT_BASE + INTEGRATOR_IRQENABLECLEAR) +#define INTEGRATOR_IRQCONT_IRQSOFT (INTEGRATOR_IRQCONT_BASE + INTEGRATOR_IRQSOFT) +#define INTEGRATOR_IRQCONT_IRQSOFTSET (INTEGRATOR_IRQCONT_BASE + INTEGRATOR_IRQSOFTSET) +#define INTEGRATOR_IRQCONT_IRQSOFTCLEAR (INTEGRATOR_IRQCONT_BASE + INTEGRATOR_IRQSOFTCLEAR) +#define INTEGRATOR_IRQCONT_FIQSTATUS (INTEGRATOR_IRQCONT_BASE + INTEGRATOR_FIQSTATUS) +#define INTEGRATOR_IRQCONT_FIQRAWSTATUS (INTEGRATOR_IRQCONT_BASE + INTEGRATOR_FIQRAWSTATUS) +#define INTEGRATOR_IRQCONT_FIQENABLE (INTEGRATOR_IRQCONT_BASE + INTEGRATOR_FIQENABLE) +#define INTEGRATOR_IRQCONT_FIQENABLESET (INTEGRATOR_IRQCONT_BASE + INTEGRATOR_FIQENABLESET) +#define INTEGRATOR_IRQCONT_FIQENABLECLEAR (INTEGRATOR_IRQCONT_BASE + INTEGRATOR_FIQENABLECLEAR) +#define INTEGRATOR_IRQCONT_FIQSOFT (INTEGRATOR_IRQCONT_BASE + INTEGRATOR_FIQSOFT) + +// Interrupt controller registers +#define CYG_DEVICE_ICTL_BASE INTEGRATOR_IRQCONT_BASE +#define CYG_DEVICE_IRQ_Status \ + ((volatile cyg_uint32 *) (CYG_DEVICE_ICTL_BASE + INTEGRATOR_IRQSTATUS)) + // Current status, read only +#define CYG_DEVICE_IRQ_Enable \ + ((volatile cyg_uint32 *) (CYG_DEVICE_ICTL_BASE + INTEGRATOR_IRQENABLE)) + // Enable status, read only +#define CYG_DEVICE_IRQ_EnableSet \ + ((volatile cyg_uint32 *) (CYG_DEVICE_ICTL_BASE + INTEGRATOR_IRQENABLESET)) + // Enable (1's only), write only +#define CYG_DEVICE_IRQ_EnableClear \ + ((volatile cyg_uint32 *) (CYG_DEVICE_ICTL_BASE + INTEGRATOR_IRQENABLECLEAR)) + // Disable (1's only), write only + +// Timer registers +#define INTEGRATOR_CT_BASE 0x13000000 /* Counter/Timers */ + +#define INTEGRATOR_TIMER0_BASE INTEGRATOR_CT_BASE +#define INTEGRATOR_TIMER1_BASE (INTEGRATOR_CT_BASE + 0x100) +#define INTEGRATOR_TIMER2_BASE (INTEGRATOR_CT_BASE + 0x200) + +#define CYG_DEVICE_TIMER_BASE INTEGRATOR_TIMER2_BASE + +#define CYG_DEVICE_TIMER_LOAD \ + ((volatile cyg_uint32 *) (CYG_DEVICE_TIMER_BASE + 0x00)) + // Load value, read/write +#define CYG_DEVICE_TIMER_CURRENT \ + ((volatile cyg_uint32 *) (CYG_DEVICE_TIMER_BASE + 0x04)) + // Current value, read +#define CYG_DEVICE_TIMER_CONTROL \ + ((volatile cyg_uint32 *) (CYG_DEVICE_TIMER_BASE + 0x08)) + // Control register, read/write +#define CYG_DEVICE_TIMER_CLEAR \ + ((volatile cyg_uint32 *) (CYG_DEVICE_TIMER_BASE + 0x0C)) + // Clears interrrupt, write only + +// Clock/timer control register +#define CTL_ENABLE 0x80 // Bit 7: 1 - counter enabled +#define CTL_DISABLE 0x00 // 0 - counter disabled +#define CTL_FREERUN 0x00 // Bit 6: 0 - free running counter +#define CTL_PERIODIC 0x40 // 1 - periodic timer mode +#define CTL_SCALE_1 0x00 // Bits 32: 00 - Scale clock by 1 +#define CTL_SCALE_16 0x04 // 01 - Scale by 16 +#define CTL_SCALE_256 0x08 // 10 - Scale by 256 + // 12.8us/tick +/*------------------------------------------------------------------------------- + * From AMBA UART (PL010) Block Specification (ARM-0001-CUST-DSPC-A03) + * ------------------------------------------------------------------------------- + * UART Register Offsets. + */ +#define AMBA_UARTDR 0x00 /* Data read or written from the interface. */ +#define AMBA_UARTRSR 0x04 /* Receive status register (Read). */ +#define AMBA_UARTECR 0x04 /* Error clear register (Write). */ +#define AMBA_UARTLCR_H 0x08 /* Line control register, high byte. */ +#define AMBA_UARTLCR_M 0x0C /* Line control register, middle byte. */ +#define AMBA_UARTLCR_L 0x10 /* Line control register, low byte. */ +#define AMBA_UARTCR 0x14 /* Control register. */ +#define AMBA_UARTFR 0x18 /* Flag register (Read only). */ +#define AMBA_UARTIIR 0x1C /* Interrupt indentification register (Read). */ +#define AMBA_UARTICR 0x1C /* Interrupt clear register (Write). */ +#define AMBA_UARTILPR 0x20 /* IrDA low power counter register. */ + +#define AMBA_UARTRSR_OE 0x08 +#define AMBA_UARTRSR_BE 0x04 +#define AMBA_UARTRSR_PE 0x02 +#define AMBA_UARTRSR_FE 0x01 + +#define AMBA_UARTFR_TXFF 0x20 +#define AMBA_UARTFR_RXFE 0x10 +#define AMBA_UARTFR_BUSY 0x08 +#define AMBA_UARTFR_TMSK (AMBA_UARTFR_TXFF + AMBA_UARTFR_BUSY) + +#define AMBA_UARTCR_RTIE 0x40 +#define AMBA_UARTCR_TIE 0x20 +#define AMBA_UARTCR_RIE 0x10 +#define AMBA_UARTCR_MSIE 0x08 +#define AMBA_UARTCR_IIRLP 0x04 +#define AMBA_UARTCR_SIREN 0x02 +#define AMBA_UARTCR_UARTEN 0x01 + +#define AMBA_UARTLCR_H_WLEN_8 0x60 +#define AMBA_UARTLCR_H_WLEN_7 0x40 +#define AMBA_UARTLCR_H_WLEN_6 0x20 +#define AMBA_UARTLCR_H_WLEN_5 0x00 +#define AMBA_UARTLCR_H_FEN 0x10 +#define AMBA_UARTLCR_H_STP2 0x08 +#define AMBA_UARTLCR_H_EPS 0x04 +#define AMBA_UARTLCR_H_PEN 0x02 +#define AMBA_UARTLCR_H_BRK 0x01 + +#define AMBA_UARTIIR_RTIS 0x08 +#define AMBA_UARTIIR_TIS 0x04 +#define AMBA_UARTIIR_RIS 0x02 +#define AMBA_UARTIIR_MIS 0x01 + +#define ARM_BAUD_460800 1 +#define ARM_BAUD_230400 3 +#define ARM_BAUD_115200 7 +#define ARM_BAUD_57600 15 +#define ARM_BAUD_38400 23 +#define ARM_BAUD_19200 47 +#define ARM_BAUD_14400 63 +#define ARM_BAUD_9600 95 +#define ARM_BAUD_4800 191 +#define ARM_BAUD_2400 383 +#define ARM_BAUD_1200 767 + +// PCI Base area +#define INTEGRATOR_PCI_BASE 0x40000000 +#define INTEGRATOR_PCI_SIZE 0x3FFFFFFF + +// memory map as seen by the CPU on the local bus +#define CPU_PCI_IO_ADRS 0x60000000 // PCI I/O space base +#define CPU_PCI_IO_SIZE 0x10000 + +#define CPU_PCI_CNFG_ADRS 0x61000000 // PCI config space +#define CPU_PCI_CNFG_SIZE 0x1000000 + +#define PCI_MEM_BASE 0x40000000 // 512M to xxx +// unused 256M from A0000000-AFFFFFFF might be used for I2O ??? +#define PCI_IO_BASE 0x60000000 // 16M to xxx +// unused (128-16)M from B1000000-B7FFFFFF +#define PCI_CONFIG_BASE 0x61000000 // 16M to xxx +// unused ((128-16)M - 64K) from XXX + +#define PCI_V3_BASE 0x62000000 + +// V3 PCI bridge controller +#define V3_BASE 0x62000000 // V360EPC registers + +#define V3_PCI_VENDOR 0x00000000 +#define V3_PCI_DEVICE 0x00000002 +#define V3_PCI_CMD 0x00000004 +#define V3_PCI_STAT 0x00000006 +#define V3_PCI_CC_REV 0x00000008 +#define V3_PCI_HDR_CF 0x0000000C +#define V3_PCI_IO_BASE 0x00000010 +#define V3_PCI_BASE0 0x00000014 +#define V3_PCI_BASE1 0x00000018 +#define V3_PCI_SUB_VENDOR 0x0000002C +#define V3_PCI_SUB_ID 0x0000002E +#define V3_PCI_ROM 0x00000030 +#define V3_PCI_BPARAM 0x0000003C +#define V3_PCI_MAP0 0x00000040 +#define V3_PCI_MAP1 0x00000044 +#define V3_PCI_INT_STAT 0x00000048 +#define V3_PCI_INT_CFG 0x0000004C +#define V3_LB_BASE0 0x00000054 +#define V3_LB_BASE1 0x00000058 +#define V3_LB_MAP0 0x0000005E +#define V3_LB_MAP1 0x00000062 +#define V3_LB_BASE2 0x00000064 +#define V3_LB_MAP2 0x00000066 +#define V3_LB_SIZE 0x00000068 +#define V3_LB_IO_BASE 0x0000006E +#define V3_FIFO_CFG 0x00000070 +#define V3_FIFO_PRIORITY 0x00000072 +#define V3_FIFO_STAT 0x00000074 +#define V3_LB_ISTAT 0x00000076 +#define V3_LB_IMASK 0x00000077 +#define V3_SYSTEM 0x00000078 +#define V3_LB_CFG 0x0000007A +#define V3_PCI_CFG 0x0000007C +#define V3_DMA_PCI_ADR0 0x00000080 +#define V3_DMA_PCI_ADR1 0x00000090 +#define V3_DMA_LOCAL_ADR0 0x00000084 +#define V3_DMA_LOCAL_ADR1 0x00000094 +#define V3_DMA_LENGTH0 0x00000088 +#define V3_DMA_LENGTH1 0x00000098 +#define V3_DMA_CSR0 0x0000008B +#define V3_DMA_CSR1 0x0000009B +#define V3_DMA_CTLB_ADR0 0x0000008C +#define V3_DMA_CTLB_ADR1 0x0000009C +#define V3_DMA_DELAY 0x000000E0 +#define V3_MAIL_DATA 0x000000C0 +#define V3_PCI_MAIL_IEWR 0x000000D0 +#define V3_PCI_MAIL_IERD 0x000000D2 +#define V3_LB_MAIL_IEWR 0x000000D4 +#define V3_LB_MAIL_IERD 0x000000D6 +#define V3_MAIL_WR_STAT 0x000000D8 +#define V3_MAIL_RD_STAT 0x000000DA +#define V3_QBA_MAP 0x000000DC + +// SYSTEM register bits +#define V3_SYSTEM_M_RST_OUT (1 << 15) +#define V3_SYSTEM_M_LOCK (1 << 14) + +// PCI_CFG bits +#define V3_PCI_CFG_M_RETRY_EN (1 << 10) +#define V3_PCI_CFG_M_AD_LOW1 (1 << 9) +#define V3_PCI_CFG_M_AD_LOW0 (1 << 8) + +// PCI MAP register bits (PCI -> Local bus) +#define V3_PCI_MAP_M_MAP_ADR 0xFFF00000 +#define V3_PCI_MAP_M_RD_POST_INH (1 << 15) +#define V3_PCI_MAP_M_ROM_SIZE (1 << 11 | 1 << 10) +#define V3_PCI_MAP_M_SWAP (1 << 9 | 1 << 8) +#define V3_PCI_MAP_M_ADR_SIZE 0x000000F0 +#define V3_PCI_MAP_M_REG_EN (1 << 1) +#define V3_PCI_MAP_M_ENABLE (1 << 0) + +// 9 => 512M window size +#define V3_PCI_MAP_M_ADR_SIZE_512M 0x00000090 + +// A => 1024M window size +#define V3_PCI_MAP_M_ADR_SIZE_1024M 0x000000A0 + +// LB_BASE register bits (Local bus -> PCI) +#define V3_LB_BASE_M_MAP_ADR 0xFFF00000 +#define V3_LB_BASE_M_SWAP (1 << 8 | 1 << 9) +#define V3_LB_BASE_M_ADR_SIZE 0x000000F0 +#define V3_LB_BASE_M_PREFETCH (1 << 3) +#define V3_LB_BASE_M_ENABLE (1 << 0) + +// PCI COMMAND REGISTER bits +#define V3_COMMAND_M_FBB_EN (1 << 9) +#define V3_COMMAND_M_SERR_EN (1 << 8) +#define V3_COMMAND_M_PAR_EN (1 << 6) +#define V3_COMMAND_M_MASTER_EN (1 << 2) +#define V3_COMMAND_M_MEM_EN (1 << 1) +#define V3_COMMAND_M_IO_EN (1 << 0) + +#define INTEGRATOR_SC_BASE 0x11000000 +#define INTEGRATOR_SC_PCIENABLE_OFFSET 0x18 +#define INTEGRATOR_SC_PCIENABLE \ + (INTEGRATOR_SC_BASE + INTEGRATOR_SC_PCIENABLE_OFFSET) + + + +#define SZ_256M 0x10000000 + +// Integrator EBI register definitions + +#define INTEGRATOR_EBI_BASE 0x12000000 + +#define INTEGRATOR_EBI_CSR0_OFFSET 0x00 +#define INTEGRATOR_EBI_CSR1_OFFSET 0x04 +#define INTEGRATOR_EBI_CSR2_OFFSET 0x08 +#define INTEGRATOR_EBI_CSR3_OFFSET 0x0C +#define INTEGRATOR_EBI_LOCK_OFFSET 0x20 + +#define INTEGRATOR_EBI_CSR0 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR0_OFFSET) +#define INTEGRATOR_EBI_CSR1 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR1_OFFSET) +#define INTEGRATOR_EBI_CSR2 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR2_OFFSET) +#define INTEGRATOR_EBI_CSR3 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR3_OFFSET) +#define INTEGRATOR_EBI_LOCK (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_LOCK_OFFSET) + +#define INTEGRATOR_EBI_8_BIT 0x00 +#define INTEGRATOR_EBI_16_BIT 0x01 +#define INTEGRATOR_EBI_32_BIT 0x02 +#define INTEGRATOR_EBI_WRITE_ENABLE 0x04 +#define INTEGRATOR_EBI_SYNC 0x08 +#define INTEGRATOR_EBI_WS_2 0x00 +#define INTEGRATOR_EBI_WS_3 0x10 +#define INTEGRATOR_EBI_WS_4 0x20 +#define INTEGRATOR_EBI_WS_5 0x30 +#define INTEGRATOR_EBI_WS_6 0x40 +#define INTEGRATOR_EBI_WS_7 0x50 +#define INTEGRATOR_EBI_WS_8 0x60 +#define INTEGRATOR_EBI_WS_9 0x70 +#define INTEGRATOR_EBI_WS_10 0x80 +#define INTEGRATOR_EBI_WS_11 0x90 +#define INTEGRATOR_EBI_WS_12 0xA0 +#define INTEGRATOR_EBI_WS_13 0xB0 +#define INTEGRATOR_EBI_WS_14 0xC0 +#define INTEGRATOR_EBI_WS_15 0xD0 +#define INTEGRATOR_EBI_WS_16 0xE0 +#define INTEGRATOR_EBI_WS_17 0xF0 + +#define FL_SC_CONTROL 0x06 // Enable Flash Write and Vpp + +/* + * System Controller + * + */ +#define INTEGRATOR_SC_ID_OFFSET 0x00 +#define INTEGRATOR_SC_OSC_OFFSET 0x04 +#define INTEGRATOR_SC_CTRLS_OFFSET 0x08 +#define INTEGRATOR_SC_CTRLC_OFFSET 0x0C +#define INTEGRATOR_SC_DEC_OFFSET 0x10 +#define INTEGRATOR_SC_ARB_OFFSET 0x14 +#define INTEGRATOR_SC_PCIENABLE_OFFSET 0x18 +#define INTEGRATOR_SC_LOCK_OFFSET 0x1C + +#define INTEGRATOR_SC_BASE 0x11000000 +#define INTEGRATOR_SC_ID (INTEGRATOR_SC_BASE + INTEGRATOR_SC_ID_OFFSET) +#define INTEGRATOR_SC_OSC (INTEGRATOR_SC_BASE + INTEGRATOR_SC_OSC_OFFSET) +#define INTEGRATOR_SC_CTRLS (INTEGRATOR_SC_BASE + INTEGRATOR_SC_CTRLS_OFFSET) +#define INTEGRATOR_SC_CTRLC (INTEGRATOR_SC_BASE + INTEGRATOR_SC_CTRLC_OFFSET) +#define INTEGRATOR_SC_DEC (INTEGRATOR_SC_BASE + INTEGRATOR_SC_DEC_OFFSET) +#define INTEGRATOR_SC_ARB (INTEGRATOR_SC_BASE + INTEGRATOR_SC_ARB_OFFSET) +#define INTEGRATOR_SC_PCIENABLE (INTEGRATOR_SC_BASE + INTEGRATOR_SC_PCIENABLE_OFFSET) +#define INTEGRATOR_SC_LOCK (INTEGRATOR_SC_BASE + INTEGRATOR_SC_LOCK_OFFSET) + + +#define HAL_FLASH_WRITE_ENABLE() \ + { \ + volatile cyg_uint32 *ebi_csr1 = (volatile cyg_uint32 *)INTEGRATOR_EBI_CSR1; \ + \ + /* allow write access to EBI_CSR1 area (Flash) */ \ + *ebi_csr1 |= INTEGRATOR_EBI_WRITE_ENABLE; \ + \ + if (!(*ebi_csr1 & INTEGRATOR_EBI_WRITE_ENABLE)) { \ + *(volatile cyg_uint32 *)INTEGRATOR_EBI_LOCK = 0xA05F; \ + *ebi_csr1 |= INTEGRATOR_EBI_WRITE_ENABLE; \ + *(volatile cyg_uint32 *)INTEGRATOR_EBI_LOCK = 0; \ + } \ + \ + /* Enable Vpp and allow write access to Flash in system controller */ \ + *(volatile unsigned int *)INTEGRATOR_SC_CTRLS = FL_SC_CONTROL; \ + } + +#define HAL_FLASH_WRITE_DISABLE() \ + { \ + volatile cyg_uint32 *ebi_csr1 = (volatile cyg_uint32 *)INTEGRATOR_EBI_CSR1; \ + \ + /* disable write access to EBI_CSR1 area (Flash) */ \ + *ebi_csr1 &= ~INTEGRATOR_EBI_WRITE_ENABLE; \ + \ + if (*ebi_csr1 & INTEGRATOR_EBI_WRITE_ENABLE) { \ + *(volatile cyg_uint32 *)INTEGRATOR_EBI_LOCK = 0xA05F; \ + *ebi_csr1 &= ~INTEGRATOR_EBI_WRITE_ENABLE; \ + *(volatile cyg_uint32 *)INTEGRATOR_EBI_LOCK = 1; \ + } \ + \ + /* Disable Vpp and disable write access to Flash in system controller */ \ + *(volatile unsigned int *)INTEGRATOR_SC_CTRLS = 0; \ + } + + +#endif //CYGONCE_HAL_INTEGRATOR_H +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/include/hal_platform_ints.h @@ -0,0 +1,90 @@ +#ifndef CYGONCE_HAL_PLATFORM_INTS_H +#define CYGONCE_HAL_PLATFORM_INTS_H +//========================================================================== +// +// hal_platform_ints.h +// +// HAL Interrupt and clock support +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): David A Rusling +// Contributors: Philippe Robin +// Date: November 7, 2000 +// Purpose: Define Interrupt support +// Description: The interrupt details for the INTEGRATOR are defined here. +// Usage: +// #include <cyg/hal/hal_platform_ints.h> +// ... +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#define CYGNUM_HAL_INTERRUPT_SOFTINT 0 +#define CYGNUM_HAL_INTERRUPT_UARTINT0 1 +#define CYGNUM_HAL_INTERRUPT_UARTINT1 2 +#define CYGNUM_HAL_INTERRUPT_KMIINT0 3 +#define CYGNUM_HAL_INTERRUPT_KMIINT1 4 +#define CYGNUM_HAL_INTERRUPT_TIMERINT0 5 +#define CYGNUM_HAL_INTERRUPT_TIMERINT1 6 +#define CYGNUM_HAL_INTERRUPT_TIMERINT2 7 +#define CYGNUM_HAL_INTERRUPT_RTCINT 8 +#define CYGNUM_HAL_INTERRUPT_EXPINT0 9 +#define CYGNUM_HAL_INTERRUPT_EXPINT1 10 +#define CYGNUM_HAL_INTERRUPT_EXPINT2 11 +#define CYGNUM_HAL_INTERRUPT_EXPINT3 12 +#define CYGNUM_HAL_INTERRUPT_PCIINT0 13 +#define CYGNUM_HAL_INTERRUPT_PCIINT1 14 +#define CYGNUM_HAL_INTERRUPT_PCIINT2 15 +#define CYGNUM_HAL_INTERRUPT_PCIINT3 16 +#define CYGNUM_HAL_INTERRUPT_V3INT 17 +#define CYGNUM_HAL_INTERRUPT_CPINT0 18 +#define CYGNUM_HAL_INTERRUPT_CPINT1 19 +#define CYGNUM_HAL_INTERRUPT_LBUSTIMEOUT 20 +#define CYGNUM_HAL_INTERRUPT_APCINT 21 +#define CYGNUM_HAL_INTERRUPT_CM_SOFTINT 24 +#define CYGNUM_HAL_INTERRUPT_CM_COMMRX 25 +#define CYGNUM_HAL_INTERRUPT_CM_COMMTX 26 + +#define CYGNUM_HAL_ISR_MIN 0 +#define CYGNUM_HAL_ISR_MAX 26 +#define CYGNUM_HAL_ISR_COUNT 27 + +// The vector used by the Real time clock +#define CYGNUM_HAL_INTERRUPT_RTC CYGNUM_HAL_INTERRUPT_TIMERINT2 + +//---------------------------------------------------------------------------- +// Reset. + +#define HAL_PLATFORM_RESET() CYG_EMPTY_STATEMENT + +#define HAL_PLATFORM_RESET_ENTRY 0x4000000 + +#endif // CYGONCE_HAL_PLATFORM_INTS_H
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/include/hal_platform_setup.h @@ -0,0 +1,81 @@ +#ifndef CYGONCE_HAL_PLATFORM_SETUP_H +#define CYGONCE_HAL_PLATFORM_SETUP_H + +/*============================================================================= +// +// hal_platform_setup.h +// +// Platform specific support for HAL (assembly code) +// +//============================================================================= +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): David A Rusling +// Contributors: Philippe Robin +// Date: November 7, 2000 +// Purpose: ARM INTEGRATOR platform specific support routines +// Description: +// Usage: #include <cyg/hal/hal_platform_setup.h> +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +#include <cyg/hal/hal_integrator.h> + +// Define macro used to diddle the LEDs during early initialization. +// Can use r0+r1. Argument in \x. +// Control the LEDs PP0-PP3. This requires the jumpers on pins 9-16 to +// be set on LK11 in order to be visible. Otherwise the parallel port +// data pins are diddled instead. + +#ifdef CYGHWR_HAL_ARM_INTEGRATOR_DIAG_LEDS +#define CYGHWR_LED_MACRO \ + mov r1, #(15 & (\x)) ;\ + ldr r0,=INTEGRATOR_DBG_BASE ;\ + strb r1, [r0, #INTEGRATOR_DBG_LEDS_OFFSET] ; +#endif + +#define PLATFORM_SETUP1 \ + ldr r0,=INTEGRATOR_DBG_BASE ;\ + ldr r1,=0 ;\ + strb r1, [r0, #INTEGRATOR_DBG_LEDS_OFFSET] ;\ + ldr r0, =INTEGRATOR_HDR_BASE ;\ + ldr r1, [r0, #INTEGRATOR_HDR_CTRL_OFFSET] ;\ + orr r1, r1, #INTEGRATOR_HDR_CTRL_REMAP ;\ + str r1, [r0, #INTEGRATOR_HDR_CTRL_OFFSET] ;\ + ldr r1, =INTEGRATOR_IRQCONT_BASE ;\ + ldr r0, =0xFFFFFFFF ;\ + str r0, [r1, #INTEGRATOR_IRQENABLECLEAR] ;\ + str r0, [r1, #INTEGRATOR_FIQENABLECLEAR] ;\ + ldr r0,=INTEGRATOR_DBG_BASE ;\ + ldr r1,=0xF ;\ + strb r1, [r0, #INTEGRATOR_DBG_LEDS_OFFSET] ; + +/*---------------------------------------------------------------------------*/ +/* end of hal_platform_setup.h */ +#endif /* CYGONCE_HAL_PLATFORM_SETUP_H */
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/include/pkgconf/mlt_arm_integrator_ram.h @@ -0,0 +1,13 @@ +// eCos memory layout - Tue Feb 29 14:11:30 2000 + +// This is a generated file - do not edit + +#include <cyg/infra/cyg_type.h> +#include <stddef.h> + +#define CYGMEM_REGION_ram (0) +#define CYGMEM_REGION_ram_SIZE (0x01000000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +extern char CYG_LABEL_NAME (_reserved) []; +#define CYGMEM_SECTION_reserved (CYG_LABEL_NAME (_reserved)) +#define CYGMEM_SECTION_reserved_SIZE (0x8000)
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/include/pkgconf/mlt_arm_integrator_ram.ldi @@ -0,0 +1,24 @@ +// eCos memory layout - Tue Feb 29 14:11:30 2000 + +// This is a generated file - do not edit + +MEMORY +{ + ram : ORIGIN = 0, LENGTH = 0x01000000 +} + +SECTIONS +{ + SECTIONS_BEGIN + __reserved = 0; . = __reserved + 0x8000; + SECTION_rom_vectors (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_text (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fini (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata1 (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixup (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_data (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTIONS_END +}
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/include/pkgconf/mlt_arm_integrator_ram.mlt @@ -0,0 +1,12 @@ +version 0 +region ram 0 01000000 0 ! +section reserved 8000 1 0 0 1 1 1 1 0 0 rom_vectors rom_vectors ! +section rom_vectors 0 4 0 1 0 1 0 1 text text ! +section text 0 4 0 1 0 1 0 1 fini fini ! +section fini 0 4 0 1 0 1 0 1 rodata rodata ! +section rodata 0 4 0 1 0 1 0 1 rodata1 rodata1 ! +section rodata1 0 4 0 1 0 1 0 1 fixup fixup ! +section fixup 0 4 0 1 0 1 0 1 gcc_except_table gcc_except_table ! +section gcc_except_table 0 4 0 1 0 1 0 1 data data ! +section data 0 4 0 1 0 1 0 1 bss bss ! +section bss 0 4 0 1 0 0 0 0 !
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/include/pkgconf/mlt_arm_integrator_rom.h @@ -0,0 +1,16 @@ +// eCos memory layout - Tue Feb 29 14:25:49 2000 + +// This is a generated file - do not edit + +#include <cyg/infra/cyg_type.h> +#include <stddef.h> + +#define CYGMEM_REGION_ram (0) +#define CYGMEM_REGION_ram_SIZE (0x01000000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +#define CYGMEM_REGION_rom (0x24000000) +#define CYGMEM_REGION_rom_SIZE (0x02000000) +#define CYGMEM_REGION_rom_ATTR (CYGMEM_REGION_ATTR_R) +extern char CYG_LABEL_NAME (_reserved) []; +#define CYGMEM_SECTION_reserved (CYG_LABEL_NAME (_reserved)) +#define CYGMEM_SECTION_reserved_SIZE (0x800)
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/include/pkgconf/mlt_arm_integrator_rom.ldi @@ -0,0 +1,25 @@ +// eCos memory layout - Tue Feb 29 14:25:49 2000 + +// This is a generated file - do not edit + +MEMORY +{ + ram : ORIGIN = 0, LENGTH = 0x01000000 + rom : ORIGIN = 0x24000000, LENGTH = 0x02000000 +} + +SECTIONS +{ + SECTIONS_BEGIN + SECTION_rom_vectors (rom, 0x24000000, LMA_EQ_VMA) + SECTION_text (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fini (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) + __reserved = 0; . = __reserved + 0x800; + SECTION_data (ram, ALIGN (0x4), FOLLOWING (.gcc_except_table)) + SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTIONS_END +}
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/include/pkgconf/mlt_arm_integrator_rom.mlt @@ -0,0 +1,13 @@ +version 0 +region ram 0 01000000 0 ! +region rom 24000000 02000000 1 ! +section reserved 800 1 0 0 1 1 1 0 0 0 data ! +section data 0 4 1 1 0 1 0 0 bss ! +section bss 0 4 0 1 0 0 0 0 ! +section rom_vectors 0 1 0 1 1 1 1 1 24000000 02000000 text text ! +section text 0 4 0 1 0 1 0 1 fini fini ! +section fini 0 4 0 1 0 1 0 1 rodata rodata ! +section rodata 0 4 0 1 0 1 0 1 rodata1 rodata1 ! +section rodata1 0 4 0 1 0 1 0 1 fixup fixup ! +section fixup 0 4 0 1 0 1 0 1 gcc_except_table gcc_except_table ! +section gcc_except_table 0 4 0 1 0 0 0 1 data !
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/include/plf_io.h @@ -0,0 +1,362 @@ +#ifndef CYGONCE_PLF_IO_H +#define CYGONCE_PLF_IO_H + +//============================================================================= +// +// plf_io.h +// +// Platform specific IO support +// +//============================================================================= +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Philippe Robin +// Contributors: David A Rusling +// Date: November 7, 2000 +// Purpose: Integrator PCI IO support macros +// Description: +// Usage: #include <cyg/hal/plf_io.h> +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include <pkgconf/hal_arm_integrator.h> + +#include <cyg/hal/hal_integrator.h> + +#include <cyg/hal/hal_io.h> // IO macros +#include <cyg/hal/hal_platform_ints.h> // Interrupt vectors + +// Initialization of the PCI bus. +#define HAL_PCI_INIT() \ + CYG_MACRO_START \ + volatile int i, j; \ + \ + /* setting this register will take the V3 out of reset */ \ + \ + *(cyg_uint32 *)(INTEGRATOR_SC_PCIENABLE) = 1; \ + \ + /* wait a few usecs to settle the device and the PCI bus */ \ + \ + for (i = 0; i < 100 ; i++) \ + j = i + 1; \ + \ + /* Now write the Base I/O Address Word to V3_BASE + 0x6C */ \ + \ + *(cyg_uint16 *)(V3_BASE + V3_LB_IO_BASE) = (cyg_uint16)(V3_BASE >> 16); \ + \ + do { \ + *(cyg_uint8 *)(V3_BASE + V3_MAIL_DATA) = 0xAA; \ + *(cyg_uint8 *)(V3_BASE + V3_MAIL_DATA + 4) = 0x55; \ + } while (*(cyg_uint8 *)(V3_BASE + V3_MAIL_DATA) != 0xAA || \ + *(cyg_uint8 *)(V3_BASE + V3_MAIL_DATA + 4) != 0x55); \ + \ + /* Make sure that V3 register access is not locked, if it is, unlock it */ \ + \ + if ((*(cyg_uint16 *)(V3_BASE + V3_SYSTEM) & V3_SYSTEM_M_LOCK) \ + == V3_SYSTEM_M_LOCK) \ + *(cyg_uint16 *)(V3_BASE + V3_SYSTEM) = 0xA05F; \ + \ + /* Ensure that the slave accesses from PCI are disabled while we */ \ + /* setup windows */ \ + \ + *(cyg_uint16 *)(V3_BASE + V3_PCI_CMD) &= \ + ~(V3_COMMAND_M_MEM_EN | V3_COMMAND_M_IO_EN); \ + \ + /* Clear RST_OUT to 0; keep the PCI bus in reset until we've finished */ \ + \ + *(cyg_uint16 *)(V3_BASE + V3_SYSTEM) &= ~V3_SYSTEM_M_RST_OUT; \ + \ + /* Make all accesses from PCI space retry until we're ready for them */ \ + \ + *(cyg_uint16 *)(V3_BASE + V3_PCI_CFG) |= V3_PCI_CFG_M_RETRY_EN; \ + \ + /* Set up any V3 PCI Configuration Registers that we absolutely have to */ \ + /* LB_CFG controls Local Bus protocol. */ \ + /* Enable LocalBus byte strobes for READ accesses too. */ \ + /* set bit 7 BE_IMODE and bit 6 BE_OMODE */ \ + \ + *(cyg_uint16 *)(V3_BASE + V3_LB_CFG) |= 0x0C0; \ + \ + /* PCI_CMD controls overall PCI operation. */ \ + /* Enable PCI bus master. */ \ + \ + *(cyg_uint16 *)(V3_BASE + V3_PCI_CMD) |= 0x04; \ + \ + /* PCI_MAP0 controls where the PCI to CPU memory window is on Local Bus*/ \ + \ + *(cyg_uint32 *)(V3_BASE + V3_PCI_MAP0) = (INTEGRATOR_BOOT_ROM_BASE) | \ + (V3_PCI_MAP_M_ADR_SIZE_512M | \ + V3_PCI_MAP_M_REG_EN | \ + V3_PCI_MAP_M_ENABLE); \ + \ + /* PCI_BASE0 is the PCI address of the start of the window */ \ + \ + *(cyg_uint32 *)(V3_BASE + V3_PCI_BASE0) = INTEGRATOR_BOOT_ROM_BASE; \ + \ + /* PCI_MAP1 is LOCAL address of the start of the window */ \ + \ + *(cyg_uint32 *)(V3_BASE + V3_PCI_MAP1) = (INTEGRATOR_HDR0_SDRAM_BASE) | \ + (V3_PCI_MAP_M_ADR_SIZE_1024M | V3_PCI_MAP_M_REG_EN | \ + V3_PCI_MAP_M_ENABLE); \ + \ + /* PCI_BASE1 is the PCI address of the start of the window */ \ + \ + *(cyg_uint32 *)(V3_BASE + V3_PCI_BASE1) = INTEGRATOR_HDR0_SDRAM_BASE; \ + \ + /* Set up the windows from local bus memory into PCI configuration, */ \ + /* I/O and Memory. */ \ + /* PCI I/O, LB_BASE2 and LB_MAP2 are used exclusively for this. */ \ + \ + *(cyg_uint16 *)(V3_BASE +V3_LB_BASE2) = \ + ((CPU_PCI_IO_ADRS >> 24) << 8) | V3_LB_BASE_M_ENABLE; \ + *(cyg_uint16 *)(V3_BASE + V3_LB_MAP2) = 0; \ + \ + /* PCI Configuration, use LB_BASE1/LB_MAP1. */ \ + \ + /* PCI Memory use LB_BASE0/LB_MAP0 and LB_BASE1/LB_MAP1 */ \ + /* Map first 256Mbytes as non-prefetchable via BASE0/MAP0 */ \ + /* (INTEGRATOR_PCI_BASE == PCI_MEM_BASE) */ \ + \ + *(cyg_uint32 *)(V3_BASE + V3_LB_BASE0) = \ + INTEGRATOR_PCI_BASE | (0x80 | V3_LB_BASE_M_ENABLE); \ + \ + *(cyg_uint16 *)(V3_BASE + V3_LB_MAP0) = \ + ((INTEGRATOR_PCI_BASE >> 20) << 0x4) | 0x0006; \ + \ + /* Map second 256 Mbytes as prefetchable via BASE1/MAP1 */ \ + \ + *(cyg_uint32 *)(V3_BASE + V3_LB_BASE1) = \ + INTEGRATOR_PCI_BASE | (0x84 | V3_LB_BASE_M_ENABLE); \ + \ + *(cyg_uint16 *)(V3_BASE + V3_LB_MAP1) = \ + (((INTEGRATOR_PCI_BASE + SZ_256M) >> 20) << 4) | 0x0006;\ + \ + /* Allow accesses to PCI Configuration space */ \ + /* and set up A1, A0 for type 1 config cycles */ \ + \ + *(cyg_uint16 *)(V3_BASE + V3_PCI_CFG) = \ + ((*(cyg_uint16 *)(V3_BASE + V3_PCI_CFG)) & \ + ~(V3_PCI_CFG_M_RETRY_EN | V3_PCI_CFG_M_AD_LOW1) ) | \ + V3_PCI_CFG_M_AD_LOW0; \ + \ + /* now we can allow in PCI MEMORY accesses */ \ + \ + *(cyg_uint16 *)(V3_BASE + V3_PCI_CMD) = \ + (*(cyg_uint16 *)(V3_BASE + V3_PCI_CMD)) | V3_COMMAND_M_MEM_EN; \ + \ + /* Set RST_OUT to take the PCI bus is out of reset, PCI devices can */ \ + /* initialise and lock the V3 system register so that no one else */ \ + /* can play with it */ \ + \ + *(cyg_uint16 *)(V3_BASE + V3_SYSTEM) = \ + (*(cyg_uint16 *)(V3_BASE + V3_SYSTEM)) | V3_SYSTEM_M_RST_OUT; \ + \ + *(cyg_uint16 *)(V3_BASE + V3_SYSTEM) = \ + (*(cyg_uint16 *)(V3_BASE + V3_SYSTEM)) | V3_SYSTEM_M_LOCK; \ + \ + CYG_MACRO_END + + +// V3 access routines +#define _V3Write16(o,v) (*(volatile cyg_uint16 *)(PCI_V3_BASE + (cyg_uint32)(o)) \ + = (cyg_uint16)(v)) +#define _V3Read16(o) (*(volatile cyg_uint16 *)(PCI_V3_BASE + (cyg_uint32)(o))) + +#define _V3Write32(o,v) (*(volatile cyg_uint32 *)(PCI_V3_BASE + (cyg_uint32)(o)) \ + = (cyg_uint32)(v)) +#define _V3Read32(o) (*(volatile cyg_uint32 *)(PCI_V3_BASE + (cyg_uint32)(o))) + +// _V3OpenConfigWindow - open V3 configuration window +#define _V3OpenConfigWindow() \ + { \ + /* Set up base0 to see all 512Mbytes of memory space (not */ \ + /* prefetchable), this frees up base1 for re-use by configuration*/ \ + /* memory */ \ + \ + _V3Write32 (V3_LB_BASE0, ((INTEGRATOR_PCI_BASE & 0xFFF00000) | \ + 0x90 | V3_LB_BASE_M_ENABLE)); \ + /* Set up base1 to point into configuration space, note that MAP1 */ \ + /* register is set up by pciMakeConfigAddress(). */ \ + \ + _V3Write32 (V3_LB_BASE1, ((CPU_PCI_CNFG_ADRS & 0xFFF00000) | \ + 0x40 | V3_LB_BASE_M_ENABLE)); \ + } + +// _V3CloseConfigWindow - close V3 configuration window +#define _V3CloseConfigWindow() \ + { \ + /* Reassign base1 for use by prefetchable PCI memory */ \ + _V3Write32 (V3_LB_BASE1, (((INTEGRATOR_PCI_BASE + SZ_256M) & 0xFFF00000) \ + | 0x84 | V3_LB_BASE_M_ENABLE)); \ + _V3Write16 (V3_LB_MAP1, \ + (((INTEGRATOR_PCI_BASE + SZ_256M) & 0xFFF00000) >> 16) | 0x0006); \ + \ + /* And shrink base0 back to a 256M window (NOTE: MAP0 already correct) */ \ + \ + _V3Write32 (V3_LB_BASE0, ((INTEGRATOR_PCI_BASE & 0xFFF00000) | \ + 0x80 | V3_LB_BASE_M_ENABLE)); \ + } + +// Compute address necessary to access PCI config space for the given +// bus and device. +#define HAL_PCI_CONFIG_ADDRESS( __bus, __devfn, __offset ) \ + ({ \ + cyg_uint32 __address, __devicebit; \ + cyg_uint16 __mapaddress; \ + cyg_uint32 __dev = CYG_PCI_DEV_GET_DEV(__devfn); /* FIXME to check!! (slot?) */ \ + \ + if (__bus == 0) { \ + /* local bus segment so need a type 0 config cycle */ \ + /* build the PCI configuration "address" with one-hot in A31-A11 */ \ + __address = PCI_CONFIG_BASE; \ + __address |= ((__devfn & 0x07) << 8); \ + __address |= __offset & 0xFF; \ + __mapaddress = 0x000A; /* 101=>config cycle, 0=>A1=A0=0 */ \ + __devicebit = (1 << (__dev + 11)); \ + \ + if ((__devicebit & 0xFF000000) != 0) { \ + /* high order bits are handled by the MAP register */ \ + __mapaddress |= (__devicebit >> 16); \ + } else { \ + /* low order bits handled directly in the address */ \ + __address |= __devicebit; \ + } \ + } else { /* bus !=0 */ \ + /* not the local bus segment so need a type 1 config cycle */ \ + /* A31-A24 are don't care (so clear to 0) */ \ + __mapaddress = 0x000B; /* 101=>config cycle, 1=>A1&A0 from PCI_CFG */ \ + __address = PCI_CONFIG_BASE; \ + __address |= ((__bus & 0xFF) << 16); /* bits 23..16 = bus number */ \ + __address |= ((__dev & 0x1F) << 11); /* bits 15..11 = device number */ \ + __address |= ((__devfn & 0x07) << 8); /* bits 10..8 = function number*/ \ + __address |= __offset & 0xFF; /* bits 7..0 = register number*/ \ + } \ + _V3Write16(V3_LB_MAP1, __mapaddress); \ + \ + __address; \ + }) + +// Read a value from the PCI configuration space of the appropriate +// size at an address composed from the bus, devfn and offset. +#define HAL_PCI_CFG_READ_UINT8( __bus, __devfn, __offset, __val ) \ + { \ + _V3OpenConfigWindow(); \ + __val = *(cyg_uint8 *)HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset); \ + _V3CloseConfigWindow(); \ + } + +#define HAL_PCI_CFG_READ_UINT16( __bus, __devfn, __offset, __val ) \ + { \ + _V3OpenConfigWindow(); \ + __val = *(cyg_uint16 *)HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset); \ + _V3CloseConfigWindow(); \ + } + +#define HAL_PCI_CFG_READ_UINT32( __bus, __devfn, __offset, __val ) \ + { \ + _V3OpenConfigWindow(); \ + __val = *(cyg_uint32 *)HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset); \ + _V3CloseConfigWindow(); \ + } + +// Write a value to the PCI configuration space of the appropriate +// size at an address composed from the bus, devfn and offset. +#define HAL_PCI_CFG_WRITE_UINT8( __bus, __devfn, __offset, __val ) \ + { \ + _V3OpenConfigWindow(); \ + *(cyg_uint8 *)HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset) = __val; \ + _V3CloseConfigWindow(); \ + } + +#define HAL_PCI_CFG_WRITE_UINT16( __bus, __devfn, __offset, __val ) \ + { \ + _V3OpenConfigWindow(); \ + *(cyg_uint16 *)HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset) = __val; \ + _V3CloseConfigWindow(); \ + } + +#define HAL_PCI_CFG_WRITE_UINT32( __bus, __devfn, __offset, __val ) \ + { \ + _V3OpenConfigWindow(); \ + *(cyg_uint32 *)HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset) = __val; \ + _V3CloseConfigWindow(); \ + } + +//----------------------------------------------------------------------------- +// Resources + +// Map PCI device resources starting from these addresses in PCI space. +#define HAL_PCI_ALLOC_BASE_MEMORY 0 +#define HAL_PCI_ALLOC_BASE_IO 0x4000 + +// This is where the PCI spaces are mapped in the CPU's address space. +#define HAL_PCI_PHYSICAL_MEMORY_BASE (PCI_MEM_BASE) +#define HAL_PCI_PHYSICAL_IO_BASE (PCI_IO_BASE) + +// Translate the PCI interrupt requested by the device (INTA#, INTB#, +// INTC# or INTD#) to the associated CPU interrupt (i.e., HAL vector). +#define INTA CYGNUM_HAL_INTERRUPT_PCIINT0 +#define INTB CYGNUM_HAL_INTERRUPT_PCIINT1 +#define INTC CYGNUM_HAL_INTERRUPT_PCIINT2 +#define INTD CYGNUM_HAL_INTERRUPT_PCIINT3 + +#define HAL_PCI_TRANSLATE_INTERRUPT( __bus, __devfn, __vec, __valid) \ + CYG_MACRO_START \ + cyg_uint8 __req; \ + cyg_uint32 __dev; \ + /* DANGER! For now this is the SDM interrupt table... */ \ + static const cyg_uint8 irq_tab[12][4] = { \ + /* INTA INTB INTC INTD */ \ + {INTA, INTB, INTC, INTD}, /* idsel 20, slot 9 */ \ + {INTB, INTC, INTD, INTA}, /* idsel 21, slot 10 */ \ + {INTC, INTD, INTA, INTB}, /* idsel 22, slot 11 */ \ + {INTD, INTA, INTB, INTC}, /* idsel 23, slot 12 */ \ + {INTA, INTB, INTC, INTD}, /* idsel 24, slot 13 */ \ + {INTB, INTC, INTD, INTA}, /* idsel 25, slot 14 */ \ + {INTC, INTD, INTA, INTB}, /* idsel 26, slot 15 */ \ + {INTD, INTA, INTB, INTC}, /* idsel 27, slot 16 */ \ + {INTA, INTB, INTC, INTD}, /* idsel 28, slot 17 */ \ + {INTB, INTC, INTD, INTA}, /* idsel 29, slot 18 */ \ + {INTC, INTD, INTA, INTB}, /* idsel 30, slot 19 */ \ + {INTD, INTA, INTB, INTC} /* idsel 31, slot 20 */ \ + }; \ + HAL_PCI_CFG_READ_UINT8(__bus, __devfn, CYG_PCI_CFG_INT_PIN, __req); \ + __dev = CYG_PCI_DEV_GET_DEV(__devfn); /* FIXME to check!! (slot?)*/ \ + \ + /* if PIN = 0, default to A */ \ + if (__req == 0) \ + __req = 1; \ + \ + __vec = irq_tab[__dev - 9][__req - 1]; \ + __valid = true; \ + CYG_MACRO_END + +//----------------------------------------------------------------------------- +// end of plf_io.h +#endif // CYGONCE_PLF_IO_H
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/include/plf_stub.h @@ -0,0 +1,77 @@ +#ifndef CYGONCE_HAL_PLF_STUB_H +#define CYGONCE_HAL_PLF_STUB_H + +//============================================================================= +// +// plf_stub.h +// +// Platform header for GDB stub support. +// +//============================================================================= +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): David A Rusling +// Contributors:Philippe Robin +// Date: November 7, 2000 +// Purpose: Platform HAL stub support for ARM INTEGRATOR boards. +// Usage: #include <cyg/hal/plf_stub.h> +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include <pkgconf/hal.h> +#include <pkgconf/hal_arm_integrator.h> + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +#include <cyg/infra/cyg_type.h> // CYG_UNUSED_PARAM + +#include <cyg/hal/arm_stub.h> // architecture stub support + +//---------------------------------------------------------------------------- +// Define some platform specific communication details. This is mostly +// handled by hal_if now, but we need to make sure the comms tables are +// properly initialized. + +externC void cyg_hal_plf_comms_init(void); + +#define HAL_STUB_PLATFORM_INIT_SERIAL() cyg_hal_plf_comms_init() + +#define HAL_STUB_PLATFORM_SET_BAUD_RATE(baud) CYG_UNUSED_PARAM(int, (baud)) +#define HAL_STUB_PLATFORM_INTERRUPTIBLE 0 +#define HAL_STUB_PLATFORM_INIT_BREAK_IRQ() CYG_EMPTY_STATEMENT + +//---------------------------------------------------------------------------- +// Stub initializer. +#define HAL_STUB_PLATFORM_INIT() CYG_EMPTY_STATEMENT + +#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +//----------------------------------------------------------------------------- +#endif // CYGONCE_HAL_PLF_STUB_H +// End of plf_stub.h
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/misc/redboot_RAM.ecm @@ -0,0 +1,72 @@ +cdl_savefile_version 1; +cdl_savefile_command cdl_savefile_version {}; +cdl_savefile_command cdl_savefile_command {}; +cdl_savefile_command cdl_configuration { description hardware template package }; +cdl_savefile_command cdl_package { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_component { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_option { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_interface { value_source user_value wizard_value inferred_value }; + +cdl_configuration eCos { + description "" ; + hardware integrator ; + template redboot ; + package -hardware CYGPKG_HAL_ARM current ; + package -hardware CYGPKG_HAL_ARM_INTEGRATOR current ; + package -hardware CYGPKG_IO_PCI current ; + package -hardware CYGPKG_DEVS_ETH_ARM_INTEGRATOR current ; + package -hardware CYGPKG_IO_SERIAL_ARM_INTEGRATOR current ; + package -hardware CYGPKG_DEVS_FLASH_INTEGRATOR current ; + package -template CYGPKG_HAL current ; + package -template CYGPKG_INFRA current ; + package -template CYGPKG_REDBOOT current ; + package CYGPKG_IO_FLASH current ; + package CYGPKG_IO_ETH_DRIVERS current ; +}; + +cdl_option CYGBLD_BUILD_GDB_STUBS { + user_value 0 +}; + +cdl_option CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT { + user_value 0 +}; + +cdl_option CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM { + inferred_value 0 +}; + +cdl_option CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS { + inferred_value 1 +}; + +cdl_option CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT { + inferred_value 1 +}; + +cdl_option CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT { + inferred_value 0 +}; + +cdl_option CYGSEM_HAL_VIRTUAL_VECTOR_DIAG { + user_value 1 +}; + +cdl_option CYGSEM_HAL_USE_ROM_MONITOR { + inferred_value 0 0 +}; + +cdl_component CYG_HAL_STARTUP { + user_value RAM +}; + +cdl_component CYGBLD_BUILD_REDBOOT { + user_value 1 +}; + +cdl_option CYGSEM_REDBOOT_BSP_SYSCALLS { + inferred_value 1 +}; + + +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/misc/redboot_ROM.ecm @@ -0,0 +1,76 @@ +cdl_savefile_version 1; +cdl_savefile_command cdl_savefile_version {}; +cdl_savefile_command cdl_savefile_command {}; +cdl_savefile_command cdl_configuration { description hardware template package }; +cdl_savefile_command cdl_package { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_component { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_option { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_interface { value_source user_value wizard_value inferred_value }; + +cdl_configuration eCos { + description "" ; + hardware integrator ; + template redboot ; + package -hardware CYGPKG_HAL_ARM current ; + package -hardware CYGPKG_HAL_ARM_INTEGRATOR current ; + package -hardware CYGPKG_IO_PCI current ; + package -hardware CYGPKG_DEVS_ETH_ARM_INTEGRATOR current ; + package -hardware CYGPKG_IO_SERIAL_ARM_INTEGRATOR current ; + package -hardware CYGPKG_DEVS_FLASH_INTEGRATOR current ; + package -template CYGPKG_HAL current ; + package -template CYGPKG_INFRA current ; + package -template CYGPKG_REDBOOT current ; + package CYGPKG_IO_FLASH current ; + package CYGPKG_IO_ETH_DRIVERS current ; +}; + +cdl_option CYGBLD_BUILD_GDB_STUBS { + user_value 0 +}; + +cdl_option CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT { + user_value 0 +}; + +cdl_option CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM { + inferred_value 0 +}; + +cdl_option CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS { + inferred_value 1 +}; + +cdl_option CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT { + inferred_value 1 +}; + +cdl_option CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT { + inferred_value 0 +}; + +#cdl_option CYGSEM_HAL_VIRTUAL_VECTOR_DIAG { +# user_value 1 +#}; + +cdl_option CYGSEM_HAL_ROM_MONITOR { + user_value 1 +}; + +cdl_option CYGSEM_HAL_USE_ROM_MONITOR { + inferred_value 0 0 +}; + +cdl_component CYG_HAL_STARTUP { + user_value ROM +}; + +cdl_component CYGBLD_BUILD_REDBOOT { + user_value 1 +}; + +cdl_option CYGSEM_REDBOOT_BSP_SYSCALLS { + inferred_value 1 +}; + + +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/src/Notes_GDB_stub @@ -0,0 +1,56 @@ +=========================================================================== +####COPYRIGHTBEGIN#### + + ------------------------------------------- + The contents of this file are subject to the Red Hat eCos Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.redhat.com/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations under + the License. + + The Original Code is eCos - Embedded Configurable Operating System, + released September 30, 1998. + + The Initial Developer of the Original Code is Red Hat. + Portions created by Red Hat are + Copyright (C) 1998, 1999, 2000 Red Hat, Inc. + All Rights Reserved. + ------------------------------------------- + +####COPYRIGHTEND#### +=========================================================================== + +How to build and install the GDB module on ARM Integrator + +Make GDB module +~~~~~~~~~~~~~~~ +Configure and build using the 'stubs' template for the PID +target. These are the necessary CLI instructions. It can also be done +from the Configtool by selecting the appropriate templates. + + % cd /tmp + % mkdir stubs + % cd stubs + % ecosconfig new integrator stubs + % ecosconfig tree + % make + +This will install some files in ./install/bin: + + gdb_module.elf: The built stubs image + gdb_module.bin: The image converted to binary (suitable for burning to ROM) + gdb_module.img: The relocated ELF image (suitable for FLASH writing, see below) + + +Prepare board for eCos +~~~~~~~~~~~~~~~~~~~~~~ + +Program FLASH +~~~~~~~~~~~~~ +The GDB module can be programmed into the begining of the user flash using an ARM debugger +connected to the board either via Angel or Multi-ICE. +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/src/flash.c @@ -0,0 +1,669 @@ +//========================================================================== +// +// flash.c +// +// ARM INTEGRATOR A/P FLASH program tool +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: Philippe Robin +// Date: November 7, 2000 +// Description: Tool used to program onboard FLASH image +//####DESCRIPTIONEND#### + +// +// This program will program the FLASH on INTEGRATOR A/P board +// + +#include <pkgconf/libc.h> // Configuration header + +#include <cyg/kernel/kapi.h> +#include <stdlib.h> +#include <ctype.h> +#include <cyg/infra/testcase.h> +#include <sys/cstartup.h> + +#ifndef FALSE +#define FALSE 0 +#define TRUE 1 +#endif + +#define PROGRAM_COMMAND 0x00100010 +#define PROGRAM_VERIFY 0x00D000D0 +#define READ_STATUS 0x70707070 +#define SR_MASK 0x00800080 +#define READ_ARRAY 0x00FF00FF +#define BLOCK_ERASE 0x00200020 +#define BLOCK_WRITE_MODE 0x00E800E8 +#define BLOCK_LOCK_BITS 0x00600060 +#define CFI_QUERY_OFFS 0x00000055 +#define CFI_QUERY_COMMAND 0x00980098 +#define CFI_DATA_OFFS 0x00000020 +#define SYS_INFO_SIZE_OFF 0x00000027 +#define SYS_INFO_WB_OFF 0x0000002A +#define SYS_ERASE_SIZE_OFF 0x0000002F +#define STATUS_READY_MASK 0x00800080 +#define BANK_BOUNDARY 0x0001FFFF +#define STATUS_ERROR 0x00100010 +#define MAX_WRITE_BUFF 0xF + +// Integrator EBI register definitions + +#define INTEGRATOR_EBI_BASE 0x12000000 + +#define INTEGRATOR_EBI_CSR0_OFFSET 0x00 +#define INTEGRATOR_EBI_CSR1_OFFSET 0x04 +#define INTEGRATOR_EBI_CSR2_OFFSET 0x08 +#define INTEGRATOR_EBI_CSR3_OFFSET 0x0C +#define INTEGRATOR_EBI_LOCK_OFFSET 0x20 + +#define INTEGRATOR_EBI_CSR0 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR0_OFFSET) +#define INTEGRATOR_EBI_CSR1 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR1_OFFSET) +#define INTEGRATOR_EBI_CSR2 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR2_OFFSET) +#define INTEGRATOR_EBI_CSR3 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR3_OFFSET) +#define INTEGRATOR_EBI_LOCK (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_LOCK_OFFSET) + +#define INTEGRATOR_EBI_8_BIT 0x00 +#define INTEGRATOR_EBI_16_BIT 0x01 +#define INTEGRATOR_EBI_32_BIT 0x02 +#define INTEGRATOR_EBI_WRITE_ENABLE 0x04 +#define INTEGRATOR_EBI_SYNC 0x08 +#define INTEGRATOR_EBI_WS_2 0x00 +#define INTEGRATOR_EBI_WS_3 0x10 +#define INTEGRATOR_EBI_WS_4 0x20 +#define INTEGRATOR_EBI_WS_5 0x30 +#define INTEGRATOR_EBI_WS_6 0x40 +#define INTEGRATOR_EBI_WS_7 0x50 +#define INTEGRATOR_EBI_WS_8 0x60 +#define INTEGRATOR_EBI_WS_9 0x70 +#define INTEGRATOR_EBI_WS_10 0x80 +#define INTEGRATOR_EBI_WS_11 0x90 +#define INTEGRATOR_EBI_WS_12 0xA0 +#define INTEGRATOR_EBI_WS_13 0xB0 +#define INTEGRATOR_EBI_WS_14 0xC0 +#define INTEGRATOR_EBI_WS_15 0xD0 +#define INTEGRATOR_EBI_WS_16 0xE0 +#define INTEGRATOR_EBI_WS_17 0xF0 + +#define FL_SC_CONTROL 0x06 // Enable Flash Write and Vpp + + +#define INVALID_FTYPE 0x00000000 +#define UNKNOWN_FTYPE 0xFFFFFFFF +#define ATMEL_FTYPE 0x00000001 +#define INTEL_FTYPE 0x00000002 + +#define FLASH_TYPE_MASK (ATMEL_FTYPE | INTEL_FTYPE) + +// On Some platforms Boot and program flash may be part of the same device +#define INTEGRATED_FTYPE 0x80000000 +#define BOOT_FTYPE 0x40000000 +#define APP_FTYPE 0x20000000 + +#define FLASH_USAGE_MASK (BOOT_FTYPE | APP_FTYPE) + +#define DEFAULT_FLASH_MASK 0xFFFFFFF8 +#define FLASH_BLOCK_SIZE 0x00020000 // 128Kb +#define EPROM_BASE 0x20000000 +#define EPROM_SIZE 0x00080000 // 512Kb +#define FLASH_BASE 0x24000000 +#define FLASH_SIZE 0x02000000 // 32Mb + +typedef int flashWrite(char *address, unsignedint data, char *flash); +typedef int flashWriteBlock(char *address, unsigned int *data, unsigned int size, char *flash); +typedef int flashRead(char *address, unsigned int *value); +typedef int flashReadBlock(char *address, unsigned int *data, unsigned int size); +typedef int flashErase(char *address, unsigned size, char *flash); +typedef int flashInit(char *address, char *flash); +typedef int flashClose(char *address, char *flash); + +typedef struct flashType { + char *base; // Base Address of flash + char *physicalBase; // before mem initialisation + unsigned int size; // Size of flash, in bytes + unsigned int type; // Atmel / Intel (CFI) / Unknown + unsigned int writeSize; // Size of physical block + unsigned int eraseSize; // Size of block erase + unsigned int logicalSize; // Size of logical block + flashWrite *write; // Write one word + flashWriteBlock *writeBlock;// Write a block of writeSize bytes + flashRead *read; // Read one word + flashReadBlock *readBlock; // Read a block of writeSize bytes + flashErase *erase; // Erase a block of eraseSize bytes + flashInit *init; // Lock a flash device + flashClose *close; // Unlock a flash device + char *ident; // identification string + struct flashType *next; // Pointer to next flash device +} tFlash; + +tFlash Integrator_Flash[2] = { + { + (char *)EPROM_BASE, // Base Address of flash + (char *)EPROM_BASE, // Physical Address of flash + EPROM_SIZE, // Size of flash, in bytes (512K) + BOOT_FTYPE | ATMEL_FTYPE,// Flash type + FLASH_BLOCK_SIZE, // Size of physical block + FLASH_BLOCK_SIZE, // Size of block erase + FLASH_BLOCK_SIZE, // Size of logical block + ATMEL_Write_Word, // Write one word + ATMEL_Write_Block, // Write a block of WriteSize + ATMEL_Read_Word, + ATMEL_Read_Block, + ATMEL_Erase_Block, + 0, // Lock a flash device + 0, // Unlock a flash device + "Atmel", // Null terminated Info string + (tFlash *)&Integrator_Flash[1] // Pointer to next tFlash struct + }, + { + (char *)FLASH_BASE, // Base Address of flash + (char *)FLASH_BASE, // Physical Address of flash + FLASH_SIZE, // Size of flash, in bytes + APP_FTYPE | INTEL_FTYPE,// Flash type + FLASH_BLOCK_SIZE, // Size of physical block + FLASH_BLOCK_SIZE, // Size of block erase + FLASH_BLOCK_SIZE, // Size of logical block + CFI_Write_Word, // Write one word + CFI_Write_Block, // Write a block of writeSize bytes + CFI_Read_Word, // Read one word + CFI_Read_Block, // Read a block of writeSize bytes + CFI_Erase_Block, // Erase a block of eraseSize bytes + 0, // Lock a flash device + 0, // Unlock a flash device + "Intel 28F320S3", // Null terminated Info string + 0 // Pointer to next tFlash struct + } +}; + +#define SYNC_COUNT 63 + +extern void diag_printf(const char *, ...); +int identify_FLASH(void); +void write_sector(int, char *); +bool load_srecords(char (*readc)(), CYG_ADDRESS *start, int *size); + +char dbuf[256]; +char *raw = (char *)0x10000; +char *flash_buffer = (char *)0x30000; +int pos, len; + +// FUNCTIONS + +externC void +cyg_package_start( void ) +{ +#ifdef CYGPKG_LIBC + cyg_iso_c_start(); +#else + (void)main(0, NULL); +#endif +} // cyg_package_start() + +char nextch(void) +{ + return (raw[pos++]); +} + +int +main( int argc, char *argv[] ) +{ + int i, j, size; + CYG_ADDRESS entry; + char c; + + diag_printf("FLASH here!\n"); + + CFI_Identify_Flash(Integrator_Flash[1]); + + while (identify_FLASH() == 0) { + diag_printf("... Please change FLASH jumper - hit C/R to continue:"); + do { + hal_diag_read_char(&c); + } while ((c != '\r') && (c != '\n')); + diag_printf("\n"); + } + restart: + diag_printf("Ready file - hit C/R to continue:"); + while (TRUE) { + hal_diag_read_char(&c); + if (c == '>') break; + } + i = 0; j = 0; + while (1) { + hal_diag_read_char(&c); + if (c == '!') { + diag_printf("... Reset\n"); + goto restart; + } + raw[i++] = c; + if (++j == SYNC_COUNT) { + hal_diag_write_char(c); + j = 0; + } + if (c == ':') break; + } + diag_printf("\n"); + pos = 0; len = i; + if (load_srecords(nextch, &entry, &size)) { + diag_printf("Read %x bytes, entry: %x\n", size, entry); + dump_buf(flash_buffer, 128); + diag_printf("\nData loaded - hit '!' to continue:"); + while (TRUE) { + hal_diag_read_char(&c); + if (c == '!') break; + } + diag_printf("\n"); + diag_printf("...Programming FLASH\n"); + pos = 0; i = 0; + while (pos < size) { + write_sector(i++, flash_buffer+pos); + pos += 256; + } + } else { + // Display buffer around failure + dump_buf(&raw[pos-32], 64); + } + diag_printf("All done!\n"); + while (1) ; +} + +int +CFI_Identify_Flash(tFlash * flash) +{ + int offset = CFI_DATA_OFFS; + + // CFI query to check for CFI string "QRY" + // Write 0x98 to address flash + 55 + *(unsigned int *)(flash->base + CFI_QUERY_OFFS) = CFI_QUERY_COMMAND; + + if ( *(flash->base + offset) == 'Q') { + int temp = 0; + offset += 2; + + if ( *(flash->base+ offset) == 'R') { + temp = *(flash->base+ SYS_INFO_SIZE_OFF); // read block size + flash->size = 2 ^ temp; + temp = *(flash->base+ SYS_ERASE_SIZE_OFF); // Read Erase Regions + temp += ( *(flash->base+ SYS_ERASE_SIZE_OFF + 1) << 4); + + flash->eraseSize = temp * 256; + // Read Max write Buffer (logical Block size) + } else + return FALSE; + } + + // Reset for Read operation + *(unsigned int *)(flash->base) = READ_ARRAY; + + return TRUE; +} + +// Adapted from ARM sample code +#define SEQ_ADD1 0x5555 +#define SEQ_ADD2 0xAAAA +#define START_CMD1 0xAA +#define START_CMD2 0x55 +#define ID_CMD 0x90 +#define PROG_CMD 0xA0 +#define STOP_CMD 0xF0 + +#define MAN_ATMEL 0x1F +#define ATMEL_AT29C040_ID 0X5B +#define ATMEL_AT29C040A_ID 0XA4 +#define ATMEL_AT29C1024_ID 0X25 +#define ATMEL_SECTOR_SIZE 256 +#define ATMEL_MAX_SECTORS 2048 + +int manuf_code, device_code, sector_size, max_no_of_sectors, word_mode; +volatile char *FLASH = (volatile char *)0x24000000; + +int +identify_FLASH(void ) +{ + // enable write to the Flash + flashWriteEnable(); + + // Enter Software Product Identification Mode + FLASH[SEQ_ADD1] = START_CMD1; + FLASH[SEQ_ADD2] = START_CMD2; + FLASH[SEQ_ADD1] = ID_CMD; + + // Wait at least 10ms + cyg_thread_delay(2); + + // Read Manufacturer and device code from the device + manuf_code = FLASH[0]; + device_code = FLASH[1]; + + diag_printf("manuf: %x, device: %x\n", manuf_code, device_code); + + // Exit Software Product Identification Mode + FLASH[SEQ_ADD1] = START_CMD1; + FLASH[SEQ_ADD2] = START_CMD2; + FLASH[SEQ_ADD1] = STOP_CMD; + + // Wait at least 10ms + cyg_thread_delay(5) + + // disble write to the Flash + flashWriteDisable();; + + if (manuf_code != MAN_ATMEL) { + diag_printf ( "Error: Wrong Manufaturer: %02x\n",manuf_code ); + return (0); + } + + switch (device_code) { + case ATMEL_AT29C040A_ID: + diag_printf ("AT29C040A recognised\n"); + sector_size = ATMEL_SECTOR_SIZE; + max_no_of_sectors = ATMEL_MAX_SECTORS; + word_mode = FALSE; + break; + case ATMEL_AT29C1024_ID: + diag_printf ("AT29C1024 recognised\n"); + sector_size = ATMEL_SECTOR_SIZE; + max_no_of_sectors = ATMEL_MAX_SECTORS; + word_mode = TRUE; + break; + default : + diag_printf ( "Error: Unsupported device: %02x\n", device_code); + return (0); + } + return (1); +} + +void +write_sector(int num, char *buf) +{ + int i, cnt; + volatile char *wrt = (volatile int *)&FLASH[num*sector_size]; + +// diag_printf("Writing to %08x\n", wrt); + // Enter Program Mode + FLASH[SEQ_ADD1] = START_CMD1; + FLASH[SEQ_ADD2] = START_CMD2; + FLASH[SEQ_ADD1] = PROG_CMD; + + // Note: write bytes as longs regardless of bus width + for (i = 0; i < sector_size; i++) { + wrt[i] = buf[i]; + } + + // Wait for sector to program + cnt = 0; + i = sector_size - 1; + while (wrt[i] != buf[i]) { + if (cnt++ > 0x01000000) break; + } +// diag_printf("Out - i: %d, wrt[i] = %08X.%08X, buf[i] = %08X, count = %x\n", i, &wrt[i], wrt[i], buf[i], cnt); + + // Verify + for (i = 0; i < sector_size; i++) { + for (cnt = 0; cnt < 10; cnt++) { + if (*wrt == *buf) break; + cyg_thread_delay(1); + } + if (cnt == 10) { + diag_printf("Can't program at 0x%08X: %02X not %02X\n", wrt, *wrt, *buf); + } + wrt++; buf++; + } +} + +void +flashWriteEnable(void) +{ + volatile unsigned int *ebi_csr1 = (volatile unsigned int *)INTEGRATOR_EBI_CSR1; + + // allow write access to EBI_CSR1 area (Flash) + + *ebi_csr1 |= INTEGRATOR_EBI_WRITE_ENABLE; + + if (!(*ebi_csr1 & INTEGRATOR_EBI_WRITE_ENABLE)) { + *(volatile unsigned int *)INTEGRATOR_EBI_LOCK = 0xA05F; + *ebi_csr1 |= INTEGRATOR_EBI_WRITE_ENABLE; + *(volatile unsigned int *)INTEGRATOR_EBI_LOCK = 0; + } + + /* Enable Vpp and allow write access to Flash in system controller */ + + *(volatile unsigned int *)INTEGRATOR_SC_CTRLS = FL_SC_CONTROL; +} + +// +// flashWriteDisable: disable write access to the Flash memory +// + +void +flashWriteDisable(void) +{ + volatile unsigned int *ebi_csr1 = (volatile unsigned int *)INTEGRATOR_EBI_CSR1; + + // disable write access to EBI_CSR1 area (Flash) + + *ebi_csr1 &= ~INTEGRATOR_EBI_WRITE_ENABLE; + + if (*ebi_csr1 & INTEGRATOR_EBI_WRITE_ENABLE) { + *(volatile unsigned int *)INTEGRATOR_EBI_LOCK = 0xA05F; + *ebi_csr1 &= ~INTEGRATOR_EBI_WRITE_ENABLE; + *(volatile unsigned int *)INTEGRATOR_EBI_LOCK = 1; + } + + // Disable Vpp and disable write access to Flash in system controller + + *(volatile unsigned int *)INTEGRATOR_SC_CTRLS = 0; +} + +// S-record download code - viciously 'adapted' from "kernel/src/sload/sload.c" + +/*---------------------------------------------------------------------------*/ +/* +// +// An srecord looks like this: +// +// byte count-+ address +// start ---+ | | data +- checksum +// | | | | +// S01000006F6B692D746573742E73726563E4 +// S315000448600000000000000000FC00005900000000E9 +// S31A0004000023C1400037DE00F023604000377B009020825000348D +// S30B0004485A0000000000004E +// S70500040000F6 +// +// S<type><length><address><data><checksum> +// +// Where +// - length (2 characters) +// is the number of bytes following upto the checksum. Note that +// this is not the number of chars following, since it takes two +// chars to represent a byte. +// - type (2 characters) +// is one of: +// 0) header record +// 1) two byte address data record +// 2) three byte address data record +// 3) four byte address data record +// 5) record containing the number of S1, S2, or S3 records +// 7) four byte address termination record +// 8) three byte address termination record +// 9) two byte address termination record +// +// - address (4, 6, or 8 characters) +// is the start address of the data following, or in the case of +// a termination record, the start address of the image +// - data (0-2n characters) +// is the data. +// - checksum (2 characters) +// is the sum of all the raw byte data in the record, from the length +// upwards, modulo 256 and subtracted from 255. +// +// Useful S-records for testing purposes: +// Start record: +// S00B0000737461303030447563 +// This sets the default address to be 0x02005000: +// S31A020050002700801481C4E0B0A15000000100000091D02000018F +// S31A0200501500000001000000010000002700801881C4E2E4A150C1 +// S311020080A42407070A090B0A0781050000E1 +// Termination record: +// S70502005000A8 +// +*/ + +#define S0 0 +#define S1 1 +#define S2 2 +#define S3 3 +#define S5 5 +#define S7 7 +#define S8 8 +#define S9 9 + +/*---------------------------------------------------------------------------*/ + +int hex2digit(char c) +{ + if( c & 0x40 ) c += 9;; + return c &0x0f; + +// return ( c <= '9' ? c - '0' : +// c <= 'Z' ? c - 'A' + 10 : +// c - 'a' + 10); +} + +/*---------------------------------------------------------------------------*/ + +bool load_srecords(char (*readc)(), + CYG_ADDRESS *start, + int *size) +{ + CYG_ADDRESS addr, load_addr; + int addrsize; + int length; + int i; + cyg_uint8 chksum, ochksum; + cyg_uint8 val; + cyg_uint8 *tdata; + char s; + char type; + char len0; + char len1; + bool first = true; + + + do { + // Skip whitespace characters until we find something that + // might be an 'S'. + do { + s = readc(); + } while( s == '\r' || s == '\n' || s == ' '); + + // Check that this is an S record + if( s != 'S' ) { + diag_printf("Invalid 'S' record\n"); + return false; + } + + // First 4 bytes are standard S + type + len + type = readc(); + len0 = readc(); + len1 = readc(); + + // decode the type + type = hex2digit(type); + + // determine address size + switch (type) { + case S0: // start records have no address + addrsize = 0; + break; + case S1: // two byte address + case S9: + addrsize = 4; + break; + case S2: // 3 byte address + case S8: + addrsize = 6; + break; + case S3: // 4 byte address + case S7: + addrsize = 8; + break; + } + + length = hex2digit (len0) << 4; + length |= hex2digit (len1); + chksum = length; + + // read the address + addr = 0; + for (i = 0; i < addrsize; i++) { + val = hex2digit(readc()); + addr = (addr << 4) | val; + } + + // calculate the checksum, which is done by the byte, not the digit + for (i = 0; i < addrsize*4; i += 8) { + chksum += ((addr >> i) & 0xff); + } + + // decide where to load this data + if (first && (type != S0)) { + load_addr = addr; + first = false; + } + + // read the data and put it directly into memory where it belongs + tdata = (cyg_uint8 *)((addr - load_addr) + flash_buffer); + if (type < S7) { + *size = (addr - load_addr); + } + val = 0; + for (i = 0; i < ((length - 1) * 2) - addrsize; i += 2 ) { + val = hex2digit (readc()) << 4; + val |= hex2digit (readc()); + chksum += val; + if( type != S0 ) *tdata++ = val; + if (type < S7) *size = *size + 1; + } + + // now get the old checksum + ochksum = hex2digit(readc()) << 4; + ochksum |= hex2digit(readc()); + chksum = ~chksum; + if (chksum != ochksum) { + diag_printf("Bad checksum - addr: %x\n", addr); + return false; + } + + } while( type < S7 ); + + *start = addr; + return true; +}
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/src/hal_diag.c @@ -0,0 +1,669 @@ +/*============================================================================= +// +// hal_diag.c +// +// HAL diagnostic output code +// +//============================================================================= +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): David A Rusling +// Contributors: Philippe Robin +// Date: November 7, 2000 +// Purpose: HAL diagnostic output +// Description: Implementations of HAL diagnostic output support. +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +#include <pkgconf/hal.h> +#include <pkgconf/hal_arm_integrator.h> // board specifics + +#include <cyg/infra/cyg_type.h> // base types +#include <cyg/infra/cyg_trac.h> // tracing macros +#include <cyg/infra/cyg_ass.h> // assertion macros + +#include <cyg/hal/hal_arch.h> // basic machine info +#include <cyg/hal/hal_intr.h> // interrupt macros +#include <cyg/hal/hal_io.h> // IO macros +#include <cyg/hal/hal_if.h> // interface API +#include <cyg/hal/hal_misc.h> // Helper functions +#include <cyg/hal/hal_diag.h> +#include <cyg/hal/drv_api.h> +#include <cyg/hal/hal_integrator.h> // Hardware definitions + + +/*---------------------------------------------------------------------------*/ +void abcd(void); + +/* Codes for ASCI characters 32-127 */ +unsigned int char_codes[] = { + 0x0000, 0x2400, 0x0044, 0x7E12, 0x25DA, 0x4848, 0x2580, 0x0400, + 0x0072, 0x001E, 0x7F80, 0x2580, 0x4000, 0x0180, 0x0000, 0x4800, + 0x007E, 0x080C, 0x01B6, 0x011E, 0x01CC, 0x01DA, 0x01FA, 0x2802, + 0x01FE, 0x01CE, 0x2400, 0x4400, 0x1800, 0x0190, 0x4200, 0x01A6, + 0x217E, 0x01EE, 0x251E, 0x0072, 0x241E, 0x00F2, 0x00E2, 0x017A, + 0x01EC, 0x2412, 0x001C, 0x18E0, 0x0070, 0x0A6C, 0x126C, 0x007E, + 0x01E6, 0x107E, 0x11E6, 0x01DA, 0x2402, 0x007C, 0x4860, 0x506C, + 0x5A00, 0x2A00, 0x4812, 0x0072, 0x1200, 0x001E, 0x0046, 0x0010, + 0x0200, 0x01BE, 0x01F8, 0x01B0, 0x01BC, 0x01F6, 0x2980, 0x01DE, + 0x01E8, 0x2000, 0x001C, 0x3500, 0x2400, 0x21A8, 0x01A8, 0x01B8, + 0x01E6, 0x01CE, 0x01A0, 0x01DA, 0x00F0, 0x0038, 0x4020, 0x5028, + 0x5A00, 0x030C, 0x4190, 0x2480, 0x2400, 0x2500, 0x0640, 0x0000 +}; + +/* Codes for hexadecimal characters */ +unsigned int hex_codes[] = { + 0x007E, 0x080C, 0x01B6, 0x011E, 0x01CC, 0x01DA, 0x01FA, 0x2802, + 0x01FE, 0x01CE, 0x01EE, 0x01F8, 0x0072, 0x01BC, 0x00F2, 0x00E2 +}; + +void hal_diag_alpha_led_char(char c1, char c2); + + +// AMBA uart access macros +#define GET_STATUS(p) (IO_READ((p) + AMBA_UARTFR)) +#define GET_CHAR(p) (IO_READ((p) + AMBA_UARTDR)) +#define PUT_CHAR(p, c) (IO_WRITE(((p) + AMBA_UARTDR), (c))) +#define IO_READ(p) ((*(volatile unsigned int *)(p)) & 0xFF) +#define IO_WRITE(p, c) (*(unsigned int *)(p) = (c)) +#define RX_DATA(s) (((s) & AMBA_UARTFR_RXFE) == 0) +#define TX_READY(s) (((s) & AMBA_UARTFR_TXFF) == 0) +#define TX_EMPTY(p) ((GET_STATUS(p) & AMBA_UARTFR_TMSK) == 0) +#define RX_EMPTY(p) ((GET_STATUS(p) & AMBA_UARTFR_RXFE) == 0) +// Define the serial registers. + +//----------------------------------------------------------------------------- +typedef struct { + cyg_uint8* base; + cyg_int32 msec_timeout; + int isr_vector; +} channel_data_t; + +//----------------------------------------------------------------------------- + +#if (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD == 9600) +#define ARM_INTEGRATOR_BAUD_DIVISOR ARM_BAUD_9600 +#elif (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD == 19200) +#define ARM_INTEGRATOR_BAUD_DIVISOR ARM_BAUD_9600 +#elif (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD == 38400) +#define ARM_INTEGRATOR_BAUD_DIVISOR ARM_BAUD_38400 +#elif (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD == 57600) +#define ARM_INTEGRATOR_BAUD_DIVISOR ARM_BAUD_57600 +#elif (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD == 115200) +#define ARM_INTEGRATOR_BAUD_DIVISOR ARM_BAUD_115200 +#endif + +static void +cyg_hal_plf_serial_init_channel(void* __ch_data) +{ + cyg_uint8* base = ((channel_data_t*)__ch_data)->base; + + // first, disable everything + IO_WRITE(base + AMBA_UARTCR, 0x0); + + // Set baud rate CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD + IO_WRITE(base + AMBA_UARTLCR_M, ((ARM_INTEGRATOR_BAUD_DIVISOR & 0xf00) >> 8)); + IO_WRITE(base + AMBA_UARTLCR_L, (ARM_INTEGRATOR_BAUD_DIVISOR & 0xff)); + + // ----------v----------v----------v----------v---------- + // NOTE: MUST BE WRITTEN LAST (AFTER UARTLCR_M & UARTLCR_L) + // ----------^----------^----------^----------^---------- + // set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled + IO_WRITE(base + AMBA_UARTLCR_H, (AMBA_UARTLCR_H_WLEN_8 | AMBA_UARTLCR_H_FEN)); + + // finally, enable the uart + IO_WRITE(base + AMBA_UARTCR, AMBA_UARTCR_UARTEN); + +} + +void +cyg_hal_plf_serial_putc(void *__ch_data, char c) +{ + channel_data_t* chan = (channel_data_t*)__ch_data; + cyg_uint8* base = chan->base; + cyg_uint32 status; + CYGARC_HAL_SAVE_GP(); + + do { + status = GET_STATUS(base); + } while (!TX_READY(status)); // wait until ready + + PUT_CHAR(base, c); + + if (c == '\n') { + do { + status = GET_STATUS(base); + } while (!TX_READY(status)); // wait until ready + + PUT_CHAR(base, '\r'); + } + + CYGARC_HAL_RESTORE_GP(); +} + +static cyg_bool +cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch) +{ + cyg_uint8* base = ((channel_data_t*)__ch_data)->base; + cyg_uint32 status ; + long timeout = 100; // A long time... + + do { + status = GET_STATUS(base); + if (--timeout == 0) return false ; + } while (!RX_DATA(status)); // wait until ready + + *ch = GET_CHAR(base); + + return true; +} + +cyg_uint8 +cyg_hal_plf_serial_getc(void* __ch_data) +{ + cyg_uint8 ch; + CYGARC_HAL_SAVE_GP(); + + while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch)); + + CYGARC_HAL_RESTORE_GP(); + return ch; +} + +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) \ + || defined(CYGPRI_HAL_IMPLEMENTS_IF_SERVICES) + +static channel_data_t integrator_ser_channels[2] = { + { (cyg_uint8*)0x16000000, 1000, CYGNUM_HAL_INTERRUPT_UARTINT0 }, + { (cyg_uint8*)0x17000000, 1000, CYGNUM_HAL_INTERRUPT_UARTINT1 } +}; + +static void +cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, + cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + cyg_hal_plf_serial_putc(__ch_data, *__buf++); + + CYGARC_HAL_RESTORE_GP(); +} + +static void +cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + *__buf++ = cyg_hal_plf_serial_getc(__ch_data); + + CYGARC_HAL_RESTORE_GP(); +} + +cyg_bool +cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch) +{ + int delay_count; + channel_data_t* chan = (channel_data_t*)__ch_data; + cyg_bool res; + CYGARC_HAL_SAVE_GP(); + + delay_count = chan->msec_timeout * 10; // delay in .1 ms steps + + for(;;) { + res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch); + if (res || 0 == delay_count--) + break; + + CYGACC_CALL_IF_DELAY_US(100); + } + + CYGARC_HAL_RESTORE_GP(); + return res; +} + +static int +cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...) +{ + static int irq_state = 0; + channel_data_t* chan = (channel_data_t*)__ch_data; + int ret = 0; + cyg_uint8 status; + CYGARC_HAL_SAVE_GP(); + + switch (__func) { + case __COMMCTL_IRQ_ENABLE: + irq_state = 1; + // Ensure that only Receive ints are generated. + status = IO_READ(chan->base + AMBA_UARTCR); + + status |= (AMBA_UARTCR_RTIE | AMBA_UARTCR_RIE); + HAL_WRITE_UINT32(chan->base + AMBA_UARTCR, status); + + HAL_INTERRUPT_UNMASK(chan->isr_vector); + break; + case __COMMCTL_IRQ_DISABLE: + ret = irq_state; + irq_state = 0; + + status = IO_READ(chan->base + AMBA_UARTCR); + status &= ~(AMBA_UARTCR_RTIE | AMBA_UARTCR_TIE | AMBA_UARTCR_RIE | AMBA_UARTCR_MSIE); + HAL_WRITE_UINT32(chan->base + AMBA_UARTCR, status); + + HAL_INTERRUPT_MASK(chan->isr_vector); + break; + case __COMMCTL_DBG_ISR_VECTOR: + ret = chan->isr_vector; + break; + case __COMMCTL_SET_TIMEOUT: + { + va_list ap; + + va_start(ap, __func); + + ret = chan->msec_timeout; + chan->msec_timeout = va_arg(ap, cyg_uint32); + + va_end(ap); + } + default: + break; + } + CYGARC_HAL_RESTORE_GP(); + return ret; +} + +static int +cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, + CYG_ADDRWORD __vector, CYG_ADDRWORD __data) +{ + int res = 0; + channel_data_t* chan = (channel_data_t*)__ch_data; + char c; + CYGARC_HAL_SAVE_GP(); + + cyg_drv_interrupt_acknowledge(chan->isr_vector); + + *__ctrlc = 0; + if ( !RX_EMPTY(chan->base) ) { + c = GET_CHAR(chan->base); + + if( cyg_hal_is_break( &c , 1 ) ) + *__ctrlc = 1; + + res = CYG_ISR_HANDLED; + } + + CYGARC_HAL_RESTORE_GP(); + return res; +} + +static void +cyg_hal_plf_serial_init(void) +{ + hal_virtual_comm_table_t* comm; + int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + + // Disable interrupts. + HAL_INTERRUPT_MASK(integrator_ser_channels[0].isr_vector); + HAL_INTERRUPT_MASK(integrator_ser_channels[1].isr_vector); + + // Init channels + cyg_hal_plf_serial_init_channel(&integrator_ser_channels[0]); + cyg_hal_plf_serial_init_channel(&integrator_ser_channels[1]); + + // Setup procs in the vector table + + // Set channel 0 + CYGACC_CALL_IF_SET_CONSOLE_COMM(0); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, &integrator_ser_channels[0]); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout); + + // Set channel 1 + CYGACC_CALL_IF_SET_CONSOLE_COMM(1); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, &integrator_ser_channels[1]); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout); + + // Restore original console + CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); +} + +void +cyg_hal_plf_comms_init(void) +{ + static int initialized = 0; + + if (initialized) + return; + + initialized = 1; + + cyg_hal_plf_serial_init(); + +#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT2 + cyg_hal_gdb_isr_attach(); // FIXME, hack to get CTRLC working +#endif +} + +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG || CYGPRI_HAL_IMPLEMENTS_IF_SERVICES + +/*---------------------------------------------------------------------------*/ + +#ifdef CYGHWR_HAL_ARM_INTEGRATOR_DIAG_LEDS + +void +hal_diag_led(int n) +{ + volatile unsigned int *leds = (unsigned int *)INTEGRATOR_DBG_LEDS ; + + *leds |= (n & 0xF) ; +} +void +hal_diag_alpha_led(unsigned int val) +{ + volatile unsigned int *led = (unsigned int *)INTEGRATOR_DBG_BASE; + + while (*led & 0x01) ; + + *led = val; +} + +void +hal_diag_alpha_led_char(char c1, char c2) +{ + volatile unsigned int *led = (unsigned int *)INTEGRATOR_DBG_BASE; + unsigned int current; + + current = *led; + if (c1) { + if (c1 < 32 || c1 > 127) c1=32; + if (c1 >= 'a' && c1 < 'z') c1 -= 32; + + current &= ~(0x00007FFE << 14); + current |= (char_codes[c1-32] << 14); + } + + if (c2) { + if (c2 < 32 || c2 > 127) c2 = 32; + if (c2 >= 'a' && c2 <= 'z') c2 -= 32; + + current &= ~(0x00007FFE); + current |= char_codes[c2-32]; + } + + hal_diag_alpha_led(current); +} + +#endif // CYGHWR_HAL_ARM_INTEGRATOR_DIAG_LEDS + +//============================================================================= +// Compatibility with older stubs +//============================================================================= +#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +#include <cyg/hal/hal_stub.h> // cyg_hal_gdb_interrupt +#endif + +#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL==0 +// This is the base address of the A-channel +#define CYG_DEVICE_SERIAL_BASE INTEGRATOR_UART0_BASE +#define CYG_DEVICE_SERIAL_INT 1 +#else +// This is the base address of the B-channel +#define CYG_DEVICE_SERIAL_BASE INTEGRATOR_UART1_BASE +#define CYG_DEVICE_SERIAL_INT 2 +#endif + +static channel_data_t integrator_ser_channel = { + (cyg_uint8*)CYG_DEVICE_SERIAL_BASE, 0, CYG_DEVICE_SERIAL_INT +}; + +// Assumption: all diagnostic output must be GDB packetized unless this is a ROM (i.e. +// totally stand-alone) system. + +#if defined(CYG_HAL_STARTUP_ROM) || !defined(CYGDBG_HAL_DIAG_TO_DEBUG_CHAN) +#define HAL_DIAG_USES_HARDWARE +#endif + +#ifndef HAL_DIAG_USES_HARDWARE +#if (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL != CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL) +#define HAL_DIAG_USES_HARDWARE +#endif +#endif + +#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT2 +// Attempt to provide CtrlC support? +static cyg_interrupt gdb_interrupt; +static cyg_handle_t gdb_interrupt_handle; + +// This ISR is called only for serial receive interrupts. +int +cyg_hal_gdb_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs) +{ + cyg_uint8 c; + + hal_diag_read_char(&c); // Fetch the character + cyg_drv_interrupt_acknowledge(CYG_DEVICE_SERIAL_INT); + if( 3 == c ) { // ^C + // Ctrl-C: set a breakpoint at PC so GDB will display the + // correct program context when stopping rather than the + // interrupt handler. + cyg_hal_gdb_interrupt (regs->pc); + } + return 0; // No need to run DSR +} + +int +cyg_hal_gdb_isr_attach(void) +{ + cyg_drv_interrupt_create(CYG_DEVICE_SERIAL_INT, + 99, // Priority - what goes here? + 0, // Data item passed to interrupt handler + cyg_hal_gdb_isr, + 0, + &gdb_interrupt_handle, + &gdb_interrupt); + cyg_drv_interrupt_attach(gdb_interrupt_handle); +} +#endif // CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + +#ifdef HAL_DIAG_USES_HARDWARE + +void hal_diag_init(void) +{ + static int init = 0; + int i; + char *msg = "\n\rARM eCos\n\r"; + + if (init++) return; + + cyg_hal_plf_serial_init_channel(&integrator_ser_channel); + + while (*msg) { + cyg_hal_plf_serial_putc(&integrator_ser_channel, *msg++); + for (i=0; i < 1000; i++) ; + } +} + +#ifdef DEBUG_DIAG +#ifndef CYG_HAL_STARTUP_ROM +#define DIAG_BUFSIZE 2048 +static char diag_buffer[DIAG_BUFSIZE]; +static int diag_bp = 0; +#endif // CYG_HAL_STARTUP_ROM +#endif // DEBUG_DIAG + +void hal_diag_write_char(char c) +{ + hal_diag_init(); + + cyg_hal_plf_serial_putc(&integrator_ser_channel, c); + +#ifdef DEBUG_DIAG + diag_buffer[diag_bp++] = c; + if (diag_bp == DIAG_BUFSIZE) diag_bp = 0; +#endif +} + +void hal_diag_read_char(char *c) +{ + *c = cyg_hal_plf_serial_getc(&integrator_ser_channel); +} + +#else // HAL_DIAG relies on GDB + +// Initialize diag port - assume GDB channel is already set up +void hal_diag_init(void) +{ + if (0) cyg_hal_plf_serial_init_channel(&integrator_ser_channel); // avoid warning +} + +// Actually send character down the wire +static void +hal_diag_write_char_serial(char c) +{ + hal_diag_init(); + + cyg_hal_plf_serial_putc(&integrator_ser_channel, c); +} + +static bool +hal_diag_read_serial(char *c) +{ + return cyg_hal_plf_serial_getc_nonblock(&integrator_ser_channel, c); +} + +void +hal_diag_read_char(char *c) +{ + while (!hal_diag_read_serial(c)) ; +} + +void +hal_diag_write_char(char c) +{ + static char line[100]; + static int pos = 0; + + // No need to send CRs + if( c == '\r' ) return; + + line[pos++] = c; + + if( c == '\n' || pos == sizeof(line) ) + { + CYG_INTERRUPT_STATE old; + + // Disable interrupts. This prevents GDB trying to interrupt us + // while we are in the middle of sending a packet. The serial + // receive interrupt will be seen when we re-enable interrupts + // later. + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION(old); +#else + HAL_DISABLE_INTERRUPTS(old); +#endif + + while(1) + { + static char hex[] = "0123456789ABCDEF"; + cyg_uint8 csum = 0; + int i; + char c1; + + hal_diag_write_char_serial('$'); + hal_diag_write_char_serial('O'); + csum += 'O'; + for( i = 0; i < pos; i++ ) + { + char ch = line[i]; + char h = hex[(ch>>4)&0xF]; + char l = hex[ch&0xF]; + hal_diag_write_char_serial(h); + hal_diag_write_char_serial(l); + csum += h; + csum += l; + } + hal_diag_write_char_serial('#'); + hal_diag_write_char_serial(hex[(csum>>4)&0xF]); + hal_diag_write_char_serial(hex[csum&0xF]); + + // Wait for the ACK character '+' from GDB here and handle + // receiving a ^C instead. This is the reason for this clause + // being a loop. + if (!hal_diag_read_serial(&c1)) + continue; // No response - try sending packet again + + if( c1 == '+' ) + break; // a good acknowledge + +#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + cyg_drv_interrupt_acknowledge(CYG_DEVICE_SERIAL_INT); + if( c1 == 3 ) { + // Ctrl-C: breakpoint. + cyg_hal_gdb_interrupt ((target_register_t)__builtin_return_address(0)); + break; + } +#endif + // otherwise, loop round again + } + + pos = 0; + + // And re-enable interrupts +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION(old); +#else + HAL_RESTORE_INTERRUPTS(old); +#endif + + } +} +#endif + +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG +/*---------------------------------------------------------------------------*/ +/* End of hal_diag.c */
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/src/integrator_misc.c @@ -0,0 +1,178 @@ +//========================================================================== +// +// integrator_misc.c +// +// HAL misc board support code for ARM INTEGRATOR7 +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): David A Rusling +// Contributors: Philippe Robin +// Date: November 7, 2000 +// Purpose: HAL board support +// Description: Implementations of HAL board interfaces +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +#include <pkgconf/hal.h> + +#include <cyg/infra/cyg_type.h> // base types +#include <cyg/infra/cyg_trac.h> // tracing macros +#include <cyg/infra/cyg_ass.h> // assertion macros + +#include <cyg/hal/hal_io.h> // IO macros +#include <cyg/hal/hal_arch.h> // Register state info +#include <cyg/hal/hal_diag.h> +#include <cyg/hal/hal_intr.h> // necessary? +#include <cyg/hal/hal_integrator.h> + +/*------------------------------------------------------------------------*/ +// On-board timer +/*------------------------------------------------------------------------*/ + +// forward declarations +void hal_if_init(void); + +// declarations +static cyg_uint32 _period; + +void hal_clock_initialize(cyg_uint32 period) +{ + //diag_init(); diag_printf("%s(%d)\n", __PRETTY_FUNCTION__, period); + //diag_printf("psr = %x\n", psr()); + HAL_WRITE_UINT32(CYG_DEVICE_TIMER_CONTROL, CTL_DISABLE); // Turn off + HAL_WRITE_UINT32(CYG_DEVICE_TIMER_LOAD, period); + HAL_WRITE_UINT32(CYG_DEVICE_TIMER_CONTROL, + CTL_ENABLE | CTL_PERIODIC | CTL_SCALE_16); + _period = period; +} + +void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period) +{ + //diag_init(); diag_printf("%s\n", __PRETTY_FUNCTION__); + HAL_WRITE_UINT32(CYG_DEVICE_TIMER_CLEAR, 0); + _period = period; +} + +void hal_clock_read(cyg_uint32 *pvalue) +{ + cyg_uint32 value; +// diag_init(); diag_printf("%s\n", __PRETTY_FUNCTION__); + HAL_READ_UINT32(CYG_DEVICE_TIMER_CURRENT, value); + value &= 0xFFFF; + *pvalue = _period - (value & 0xFFFF); // Note: counter is only 16 bits + // and decreases +} + +void hal_hardware_init(void) +{ + // Any hardware/platform initialization that needs to be done. + + // Clear all interrupt sources + HAL_WRITE_UINT32(CYG_DEVICE_IRQ_EnableClear, 0xFFFF); + + // FIXME: The line with the thumb check is a hack, allowing + // the farm to run test. Problem is that virtual vector table + // API needs to be ARM/Thumb consistent. Will fix later. +#ifndef __thumb__ + // Set up eCos/ROM interfaces + hal_if_init(); +#endif +} + +// +// This routine is called to respond to a hardware interrupt (IRQ). It +// should interrogate the hardware and return the IRQ vector number. + +int hal_IRQ_handler(void) +{ + // Do hardware-level IRQ handling + int irq_status, vector; + HAL_READ_UINT32(CYG_DEVICE_IRQ_Status, irq_status); + //diag_init(); diag_printf("IRQ status: 0x%x\n", irq_status); + for (vector = 1; vector <= 16; vector++) { + if (irq_status & (1<<vector)) return vector; + } + return -1 ; // This shouldn't happen! +} + +// +// Interrupt control +// + +void hal_interrupt_mask(int vector) +{ + //diag_init(); diag_printf("hal_interrupt_mask(%d)\n", vector); + HAL_WRITE_UINT32(CYG_DEVICE_IRQ_EnableClear, 1<<vector); +} + +#if 0 +void hal_interrupt_status(void) +{ + int irq_status, irq_enable, timer_status, timer_value, timer_load; + HAL_READ_UINT32(CYG_DEVICE_IRQ_Status, irq_status); + HAL_READ_UINT32(CYG_DEVICE_IRQ_Enable, irq_enable); + HAL_READ_UINT32(CYG_DEVICE_TIMER_LOAD, timer_load); + HAL_READ_UINT32(CYG_DEVICE_TIMER_CURRENT, timer_value); + HAL_READ_UINT32(CYG_DEVICE_TIMER_CONTROL, timer_status); + diag_printf("Interrupt: IRQ: %x.%x, TIMER: %x.%x.%x, psr: %x\n", + irq_status, irq_enable, timer_status, timer_value, + timer_load, psr()); +} +#endif + +void hal_interrupt_unmask(int vector) +{ + //diag_init(); diag_printf("hal_interrupt_unmask(%d)\n", vector); + HAL_WRITE_UINT32(CYG_DEVICE_IRQ_EnableSet, 1<<vector); +} + +void hal_interrupt_acknowledge(int vector) +{ + //diag_init(); diag_printf("%s(%d)\n", __PRETTY_FUNCTION__, vector); +} + +void hal_interrupt_configure(int vector, int level, int up) +{ + //diag_init(); diag_printf("%s(%d,%d,%d)\n", __PRETTY_FUNCTION__, vector, level, up); +} + +void hal_interrupt_set_level(int vector, int level) +{ + //diag_init(); diag_printf("%s(%d,%d)\n", __PRETTY_FUNCTION__, vector, level); +} + +void hal_show_IRQ(int vector, int data, int handler) +{ + // diag_printf("IRQ - vector: %x, data: %x, handler: %x\n", vector, data, handler); +} + +/*---------------------------------------------------------------------------*/ +/* End of hal_misc.c */
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/integrator/current/src/prog_flash.c @@ -0,0 +1,292 @@ +//========================================================================== +// +// prog_flash.c +// +// ARM INTEGRATOR eval board FLASH program tool +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: Philippe Robin +// Date: November 7, 2000 +// Description: Tool used to program onboard FLASH image +//####DESCRIPTIONEND#### + +// +// This program will program the FLASH on the PID board +// It is similar to 'flash' (which also downloads S records) but it always +// programs from a fixed buffer. This is sufficient to load/update the GDB +// stubs on the board. +// + +#include <pkgconf/libc.h> // Configuration header + +#include <cyg/kernel/kapi.h> +#include <stdlib.h> +#include <ctype.h> +#include <cyg/infra/testcase.h> +#include <sys/cstartup.h> +#include <cyg/hal/hal_integrator.h> + +#ifndef FALSE +#define FALSE 0 +#define TRUE 1 +#endif + + +#define INVALID_FTYPE 0x00000000 +#define UNKNOWN_FTYPE 0xFFFFFFFF +#define ATMEL_FTYPE 0x00000001 +#define INTEL_FTYPE 0x00000002 + +#define FLASH_TYPE_MASK (ATMEL_FTYPE | INTEL_FTYPE) + +// On Some platforms Boot and program flash may be part of the same device +#define INTEGRATED_FTYPE 0x80000000 +#define BOOT_FTYPE 0x40000000 +#define APP_FTYPE 0x20000000 + +#define FLASH_USAGE_MASK (BOOT_FTYPE | APP_FTYPE) + +#define DEFAULT_FLASH_MASK 0xFFFFFFF8 +#define FLASH_BLOCK_SIZE 0x00020000 // 128Kb +#define EPROM_BASE 0x20000000 +#define EPROM_SIZE 0x00080000 // 512Kb +#define FLASH_BASE 0x24000000 +#define FLASH_SIZE 0x02000000 // 32Mb + +typedef struct flashType { + char *base; // Base Address of flash + char *physicalBase; // before mem initialisation + unsigned int size; // Size of flash, in bytes + unsigned int type; // Atmel / Intel (CFI) / Unknown + unsigned int writeSize; // Size of physical block + unsigned int eraseSize; // Size of block erase + unsigned int logicalSize; // Size of logical block + char *ident; // identification string +} tFlash; + +tFlash Integrator_Flash[2] = +{ + { + (char *)EPROM_BASE, // Base Address of flash + (char *)EPROM_BASE, // Physical Address of flash + EPROM_SIZE, // Size of flash, in bytes (512K) + BOOT_FTYPE | ATMEL_FTYPE, // Flash type + FLASH_BLOCK_SIZE, // Size of physical block + FLASH_BLOCK_SIZE, // Size of block erase + FLASH_BLOCK_SIZE, // Size of logical block + "Atmel", // Null terminated Info string + }, + { + (char *)FLASH_BASE, // Base Address of flash + (char *)FLASH_BASE, // Physical Address of flash + FLASH_SIZE, // Size of flash, in bytes + APP_FTYPE | INTEL_FTYPE, // Flash type + FLASH_BLOCK_SIZE, // Size of physical block + FLASH_BLOCK_SIZE, // Size of block erase + FLASH_BLOCK_SIZE, // Size of logical block + "Intel 28F320S3", // Null terminated Info string + } +}; + + +extern void diag_printf(const char *, ...); +int identify_FLASH(void); +void write_sector(int, char *); + +char *flash_buffer = (char *)0x60000; +char *flash_buffer_end = (char *)0x80000; + +#ifdef BE_IMAGE +#define BUF(x) buf[x^3] +#else +#define BUF(x) buf[x] +#endif + +// FUNCTIONS + +externC void +cyg_package_start( void ) +{ +#ifdef CYGPKG_LIBC + cyg_iso_c_start(); +#else + (void)main(0, NULL); +#endif +} // cyg_package_start() + +int +main( int argc, char *argv[] ) +{ + int i; + + diag_printf("FLASH here!\n"); + while (identify_FLASH() == 0) { + diag_printf("... Please change FLASH jumper\n"); + cyg_thread_delay(5*100); + } + diag_printf("About to program FLASH using data at %x..%x\n", flash_buffer, flash_buffer_end); + diag_printf("*** Press RESET now to abort!\n"); + cyg_thread_delay(5*100); + diag_printf("\n"); + diag_printf("...Programming FLASH\n"); + + i = 0; + while (flash_buffer < flash_buffer_end) { + write_sector(i++, flash_buffer); + flash_buffer += 256; + } + diag_printf("All done!\n"); + while (1) ; +} + +// Adapted from ARM sample code +#define SEQ_ADD1 0x5555 +#define SEQ_ADD2 0x2aaa +#define START_CMD1 0xaaaaaaaa +#define START_CMD2 0x55555555 +#define ID_CMD 0x90909090 +#define PROG_CMD 0xA0 +#define STOP_CMD 0xf0f0f0f0 + +#define MAN_ATMEL 0x1F +#define ATMEL_AT29C040_ID 0X5B +#define ATMEL_AT29C040A_ID 0XA4 +#define ATMEL_AT29C1024_ID 0X25 +#define ATMEL_SECTOR_SIZE 256 +#define ATMEL_MAX_SECTORS 2048 + +#define MAN_INTEL 0xB0 +#define INTEL_28F320S3_ID 0xD4 + +int manuf_code, device_code; +int sector_size, max_no_of_sectors, word_mode; +volatile unsigned int *FLASH = (volatile unsigned int *)0x24000000; + +int +identify_FLASH(void ) +{ + unsigned int *ptr = (unsigned int *)FLASH; + + HAL_FLASH_WRITE_ENABLE(); + + // Enter Software Product Identification Mode + FLASH[SEQ_ADD1] = START_CMD1; + FLASH[SEQ_ADD2] = START_CMD2; + FLASH[SEQ_ADD1] = ID_CMD; + + // Wait at least 10ms + cyg_thread_delay(4); + + // Read Manufacturer and device code from the device + manuf_code = *ptr++ & 0xff; + device_code = *ptr & 0xff; + + diag_printf("manuf: 0x%x, device: 0x%x\n", manuf_code, device_code); + + // Exit Software Product Identification Mode + FLASH[SEQ_ADD1] = START_CMD1; + FLASH[SEQ_ADD2] = START_CMD2; + FLASH[SEQ_ADD1] = STOP_CMD; + + // Wait at least 10ms + cyg_thread_delay(5); + + HAL_FLASH_WRITE_DISABLE(); + + if (manuf_code != MAN_ATMEL || manuf_code != MAN_INTEL) { + diag_printf ( "Error: Wrong Manufaturer: %02x\n", manuf_code ); + return (0); + } + + switch (device_code) { + case ATMEL_AT29C040A_ID: + diag_printf ("AT29C040A recognised\n"); + sector_size = ATMEL_SECTOR_SIZE; + max_no_of_sectors = ATMEL_MAX_SECTORS; + word_mode = FALSE; + break; + + case ATMEL_AT29C1024_ID: + diag_printf ("AT29C1024 recognised\n"); + sector_size = ATMEL_SECTOR_SIZE; + max_no_of_sectors = ATMEL_MAX_SECTORS; + word_mode = TRUE; + break; + + case INTEL_28F320S3_ID: + diag_printf ("INTEL_28F320S3 recognised\n"); + sector_size = FLASH_BLOCK_SIZE; + // max_no_of_sectors = ATMEL_MAX_SECTORS; + word_mode = TRUE; + break; + + default : + diag_printf ( "Error: Unsupported device: %02x\n", device_code); + return (0); + } + return (1); +} + +void +write_sector(int num, char *buf) +{ + int i, cnt; + volatile char *wrt = (volatile char *)&FLASH[num*sector_size]; + +// diag_printf("Writing to %08x\n", wrt); + // Enter Program Mode + FLASH[SEQ_ADD1] = START_CMD1; + FLASH[SEQ_ADD2] = START_CMD2; + FLASH[SEQ_ADD1] = PROG_CMD; + + // Note: write bytes as longs regardless of bus width + for (i = 0; i < sector_size; i++) { + wrt[i] = BUF(i); + } + + // Wait for sector to program + cnt = 0; + i = sector_size - 1; + while (wrt[i] != BUF(i)) { + if (cnt++ > 0x01000000) break; + } +// diag_printf("Out - i: %d, wrt[i] = %08X.%08X, BUF(i) = %08X, count = %x\n", i, &wrt[i], wrt[i], BUF(i), cnt); + + // Verify + for (i = 0; i < sector_size; i++) { + for (cnt = 0; cnt < 10; cnt++) { + if (wrt[i] == BUF(i)) break; + cyg_thread_delay(1); + } + if (cnt == 10) { + diag_printf("Can't program at 0x%08X: %02X not %02X\n", wrt, *wrt, BUF(0)); + } + } +}
--- a/packages/hal/arm/sa11x0/assabet/current/ChangeLog +++ b/packages/hal/arm/sa11x0/assabet/current/ChangeLog @@ -1,4 +1,4 @@ -2001-10-20 Nicolar Pitre <nico@cam.org> +2001-10-20 Nicolas Pitre <nico@cam.org> * include/hal_platform_setup.h: Wake up from deep sleep mode.
--- a/packages/hal/arm/sa11x0/flexanet/current/ChangeLog +++ b/packages/hal/arm/sa11x0/flexanet/current/ChangeLog @@ -1,3 +1,9 @@ +2001-10-30 Jordi Colomer <jco@ict.es> + + * include/flexanet.h: minor changes to the GPIO usage. + * include/hal_platform_setup.h: solved some problems with the + sleep/wakeup procedure. + 2001-10-04 Jordi Colomer <jco@ict.es> * include/hal_platform_setup.h: Add sleep/resume support.
--- a/packages/hal/arm/sa11x0/flexanet/current/include/flexanet.h +++ b/packages/hal/arm/sa11x0/flexanet/current/include/flexanet.h @@ -68,7 +68,7 @@ extern void flexanet_BCR(unsigned long m // GPIO settings // #define SA1110_GPIO_DIR 0x080037FE -#define SA1110_GPIO_ALT 0x080037FE +#define SA1110_GPIO_ALT 0x080037FC #define SA1110_GPIO_CLR 0x080037FE #define SA1110_GPIO_SET 0x00000000 @@ -123,7 +123,7 @@ extern void flexanet_BCR(unsigned long m #define SA1110_GPIO_GUI_IRQ (1<<23) /* IRQ from GUI board (i.e., UCB1300) */ #define SA1110_GPIO_ETH_IRQ (1<<24) /* IRQ from Ethernet controller */ #define SA1110_GPIO_INTIP_IRQ (1<<25) /* Measurement IRQ (INTIP) */ -#define SA1110_GPIO_LED_RED (1<<26) /* General-purpose red LED */ +#define SA1110_GPIO_XMI_IRQ (1<<26) /* External Module Insertion interrupt */ /* IRQ mappings from GPIOs */ #define SA1110_IRQ_GPIO_CF1_CD CYGNUM_HAL_INTERRUPT_GPIO14
--- a/packages/hal/arm/sa11x0/flexanet/current/include/hal_platform_setup.h +++ b/packages/hal/arm/sa11x0/flexanet/current/include/hal_platform_setup.h @@ -56,6 +56,7 @@ #if defined(CYG_HAL_STARTUP_ROM) #define PLATFORM_SETUP1 _platform_setup1 #define CYGHWR_HAL_ARM_HAS_MMU +#define CYGSEM_HAL_ROM_RESET_USES_JUMP #if (CYGHWR_HAL_ARM_SA11X0_PROCESSOR_CLOCK == 59000) #define SA11X0_PLL_CLOCK 0x0 @@ -127,18 +128,54 @@ #define STATIC_1_CONFIG_VALUE 0x2C290001 +// Macros that handle the red debug LED wired to GPIO-1 + + .macro _red_led_on + + // Turn on the red LED on GPIO-1 + ldr r3,=SA11X0_GPIO_PIN_OUTPUT_SET + ldr r2,=0x02 + str r2,[r3] + .endm + + .macro _red_led_off + + // Turn off the red LED on GPIO-1 + ldr r3,=SA11X0_GPIO_PIN_OUTPUT_CLEAR + ldr r2,=0x02 + str r2,[r3] + .endm + // This macro represents the initial startup code for the platform, // when the startup is ROM. +// Red LED is turned on during redboot execution and turned off +// right before entering the operating system. + +// Green LED is turned off during the redboot execution and +// on right before entering the operating system on a reset +// (not on a wake-up). + .macro _platform_setup1 - // Reset the BCR (LEDs off) + // Disable all interrupts (ICMR not specified on power-up) + ldr r1,=SA11X0_ICMR + mov r0,#0 + str r0,[r1] + + // Disable IRQs and FIQs + mov r0, #(CPSR_IRQ_DISABLE | \ + CPSR_FIQ_DISABLE | \ + CPSR_SUPERVISOR_MODE) + msr cpsr, r0 + + // Reset the BCR (green LED off) ldr r1,=SA1110_BOARD_CONTROL ldr r2,=SA1110_BCR_MIN str r2,[r1] - // Set up GPIOs + // Set up GPIOs (red LED off) ldr r1,=SA11X0_GPIO_PIN_DIRECTION ldr r2,=SA1110_GPIO_DIR str r2,[r1] @@ -154,7 +191,10 @@ ldr r1,=SA11X0_GPIO_PIN_OUTPUT_SET ldr r2,=SA1110_GPIO_SET str r2,[r1] - + + // Turn on the red LED + _red_led_on + // Disable clock switching mcr p15,0,r0,\ SA11X0_TEST_CLOCK_AND_IDLE_REGISTER,\ @@ -174,19 +214,14 @@ nop nop - // Turn on the red LED on GPIO-1 - ldr r1,=SA11X0_GPIO_PIN_OUTPUT_SET - ldr r2,=(1<<1) - str r2,[r1] - - // Let the PLL settle down + // Let the PLL settle down ldr r1,=20000 10: sub r1,r1,#1 cmp r1,#0 bne 10b // Initialize DRAM controller. See table below. - // The DRAM banks are set to disabled. + // The DRAM banks are set to disabled. ldr r1,=dram_table ldr r2,=__exception_handlers @@ -205,46 +240,42 @@ 11: ldr r3,[r1],#4 // Release DRAM hold (PSSR register, bit DH) - // This bit is set upon exit from sleep mode and indicates that the - // nRAS/nSDCS 3:0 and nCAS/DQM 3:0 continue to be held low and that - // the DRAMs are still in self-refresh mode. This bit should be cleared - // by the processor (by writing a one to it) after the DRAM interface - // has been configured but before any DRAM access is attempted. - // The nRAS/nSDCS and nCAS/DQM lines are released when this bit is - // cleared. This bit is cleared on hardware reset. - + // This bit is set upon exit from sleep mode and indicates that the + // nRAS/nSDCS 3:0 and nCAS/DQM 3:0 continue to be held low and that + // the DRAMs are still in self-refresh mode. This bit should be cleared + // by the processor (by writing a one to it) after the DRAM interface + // has been configured but before any DRAM access is attempted. + // The nRAS/nSDCS and nCAS/DQM lines are released when this bit is + // cleared. This bit is cleared on hardware reset. + ldr r1,=SA11X0_PWR_MGR_SLEEP_STATUS ldr r2,=SA11X0_DRAM_CONTROL_HOLD str r2,[r1] - // On hardware reset in systems containing DRAM or SDRAM, - // trigger a number (typically eight) of refresh cycles by attempting - // nonburst read or write accesses to any disabled DRAM bank. - // Each such access causes a simultaneous CBR for all four banks. + // On hardware reset in systems containing DRAM or SDRAM, + // trigger a number (typically eight) of refresh cycles by attempting + // nonburst read or write accesses to any disabled DRAM bank. + // Each such access causes a simultaneous CBR for all four banks. ldr r1,=SA11X0_RAM_BANK0_BASE ldr r2,[r1] - nop - nop + ldr r2,[r1] ldr r2,[r1] - nop - nop + ldr r2,[r1] ldr r2,[r1] - nop - nop + ldr r2,[r1] ldr r2,[r1] - nop - nop + ldr r2,[r1] // Enable DRAM bank 0 ldr r1,=SA11X0_DRAM_CONFIGURATION ldr r2,=DRAM_CONFIG_VALUE - orr r2, r2, #0x01 + orr r2, r2, #0x01 str r2,[r1] b 19f - // Memory controller settings (register, value) + // Memory controller settings (register, value) dram_table: @@ -260,14 +291,9 @@ dram_table: .word SA11X0_DRAM_CONFIGURATION, DRAM_CONFIG_VALUE .word SA11X0_STATIC_CONTROL_0, STATIC_0_CONFIG_VALUE .word SA11X0_STATIC_CONTROL_1, STATIC_1_CONFIG_VALUE - .word 0, 0 + .word 0, 0 19: - // Release peripheral hold (set by RESET) - ldr r1,=SA11X0_PWR_MGR_SLEEP_STATUS - ldr r2,=SA11X0_PERIPHERAL_CONTROL_HOLD - str r2,[r1] - // If waking up from sleep, jump to the resume function // pointed by the scratchpad register. ldr r1,=SA11X0_RESET_STATUS @@ -276,6 +302,9 @@ 19: bne 20f ldr r1,=SA11X0_PWR_MGR_SCRATCHPAD ldr r1,[r1] + + _red_led_off + mov pc,r1 nop 20: nop @@ -307,8 +336,13 @@ 10: ldr r2,=SA1110_BCR_MIN orr r2,r2,#SA1110_BCR_LED_GREEN str r2,[r1] + + // Turn off red LED + _red_led_off + .endm - + + #else // defined(CYG_HAL_STARTUP_ROM) #define PLATFORM_SETUP1 #endif
--- a/packages/hal/arm/sa11x0/var/current/ChangeLog +++ b/packages/hal/arm/sa11x0/var/current/ChangeLog @@ -1,3 +1,7 @@ +2001-10-31 Jonathan Larmour <jlarmour@redhat.com> + + * cdl/hal_arm_sa11x0.cdl: Indicate support of variable baud rates. + 2001-10-09 Hugo Tyson <hmt@redhat.com> * src/hal_diag.c (cyg_hal_plf_serial_isr): As well as the sticky
--- a/packages/hal/arm/sa11x0/var/current/cdl/hal_arm_sa11x0.cdl +++ b/packages/hal/arm/sa11x0/var/current/cdl/hal_arm_sa11x0.cdl @@ -52,6 +52,7 @@ cdl_package CYGPKG_HAL_ARM_SA11X0 { package." implements CYGINT_HAL_ARM_ARCH_STRONGARM + implements CYGINT_HAL_VIRTUAL_VECTOR_COMM_BAUD_SUPPORT # Let the architectural HAL see this variant's interrupts file - # the SA11x0 has no variation between targets here.
--- a/packages/hal/i386/pcmb/current/ChangeLog +++ b/packages/hal/i386/pcmb/current/ChangeLog @@ -1,3 +1,9 @@ +2001-11-01 Jonathan Larmour <jlarmour@redhat.com> + + * src/pcmb_misc.c (hal_pcmb_init): Fix typo: + CYGPKG_HAL_I386_PCMB_HAL_MEMSIZE_BIOS -> + CYGPKG_HAL_I386_PCMB_MEMSIZE_BIOS + 2001-10-19 Ian Campbell <icampbell@arcom.co.uk> * cdl/hal_i386_pcmb.cdl: Add cdl_options for
--- a/packages/hal/i386/pcmb/current/src/pcmb_misc.c +++ b/packages/hal/i386/pcmb/current/src/pcmb_misc.c @@ -75,7 +75,7 @@ void hal_pcmb_init(void) cyg_hal_pcmb_memsize_extended = CYGNUM_HAL_I386_PCMB_MEMSIZE_EXTENDED; #endif -#ifdef CYGPKG_HAL_I386_PCMB_HAL_MEMSIZE_BIOS +#ifdef CYGPKG_HAL_I386_PCMB_MEMSIZE_BIOS cyg_uint8 lo,hi; HAL_READ_CMOS( 0x15, lo );
--- a/packages/hal/mips/atlas/current/ChangeLog +++ b/packages/hal/mips/atlas/current/ChangeLog @@ -1,3 +1,7 @@ +2001-10-31 Jonathan Larmour <jlarmour@redhat.com> + + * cdl/hal_mips_atlas.cdl: Indicate support of variable baud rates. + 2001-07-20 David Woodhouse <dwmw2@redhat.com> * src/redboot_cmds.c: Remove. Obsoleted by generic MIPS version.
--- a/packages/hal/mips/atlas/current/cdl/hal_mips_atlas.cdl +++ b/packages/hal/mips/atlas/current/cdl/hal_mips_atlas.cdl @@ -59,6 +59,7 @@ cdl_package CYGPKG_HAL_MIPS_ATLAS { implements CYGINT_HAL_DEBUG_GDB_STUBS implements CYGINT_HAL_DEBUG_GDB_STUBS_BREAK implements CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT + implements CYGINT_HAL_VIRTUAL_VECTOR_COMM_BAUD_SUPPORT cdl_option CYGBLD_HAL_TARGET_H { display "Variant header"
--- a/packages/hal/mips/vrc437x/current/ChangeLog +++ b/packages/hal/mips/vrc437x/current/ChangeLog @@ -1,3 +1,18 @@ +2001-10-31 Jonathan Larmour <jlarmour@redhat.com> + + * cdl/hal_mips_vr4300_vrc437x.cdl: Indicate support of variable baud + rates. + +2001-10-30 Nick Garnett <nickg@redhat.com> + + * include/platform.inc: + Added local version of hal_intc_decode to make chaining work + correctly. + + * include/plf_intr.h: + Added local version of HAL_TRANSLATE_VECTOR() to make chaining + work correctly. + 2001-10-24 Nick Garnett <nickg@redhat.com> * include/hal_diag.h: Fixed problem with support for virtual
--- a/packages/hal/mips/vrc437x/current/cdl/hal_mips_vr4300_vrc437x.cdl +++ b/packages/hal/mips/vrc437x/current/cdl/hal_mips_vr4300_vrc437x.cdl @@ -54,6 +54,7 @@ cdl_package CYGPKG_HAL_MIPS_VR4300_VRC43 implements CYGINT_HAL_DEBUG_GDB_STUBS implements CYGINT_HAL_DEBUG_GDB_STUBS_BREAK + implements CYGINT_HAL_VIRTUAL_VECTOR_COMM_BAUD_SUPPORT cdl_option CYGSEM_HAL_MIPS_VR4300_VRC437X_DIAG_ACKS_INT_0 { display "Acknowledge spurious interrupt 0 on output"
--- a/packages/hal/mips/vrc437x/current/include/platform.inc +++ b/packages/hal/mips/vrc437x/current/include/platform.inc @@ -239,6 +239,25 @@ 2: #define CYGPKG_HAL_MIPS_INTC_INIT_DEFINED #------------------------------------------------------------------------------ +# Interrupt Translator. +# This translates an interrupt number into an ISR table offset. Vector 0 +# contains a special ISR for dealing with spurious interrupts from the +# Vrc437x, and vectors 1-3 contain springboards, so we chain via vector 4. +# This macro translates interrupt 0 to vector 0 and all others to vector 4. + +#ifndef CYGPKG_HAL_MIPS_INTC_TRANSLATE_DEFINED +#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN + .macro hal_intc_translate inum,vnum + beqz \inum,1f # jump if interrupt is zero + move v0,zero # set v0=0 in delay slot + addi v0,v0,4 # non zero vector, inc v0 +1: move \vnum,v0 # store 0 or 4 in vnum + .endm +#define CYGPKG_HAL_MIPS_INTC_TRANSLATE_DEFINED +#endif +#endif + +#------------------------------------------------------------------------------ # Monitor initialization. #ifndef CYGPKG_HAL_MIPS_MON_DEFINED
--- a/packages/hal/mips/vrc437x/current/include/plf_intr.h +++ b/packages/hal/mips/vrc437x/current/include/plf_intr.h @@ -117,6 +117,24 @@ #define CYGHWR_HAL_INTERRUPT_VECTORS_DEFINED //-------------------------------------------------------------------------- +// Vector translation. +// For chained interrupts we only have a single vector though which all +// are passed. For unchained interrupts we have a vector per interrupt. +// Vector 0 has a special catcher ISR for spurious interrupts from the VRC437X +// and vectors 1-3 are springboards, so we chain through vector 4. + +#if defined(CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN) + +#define HAL_TRANSLATE_VECTOR(_vector_,_index_) \ +{ \ + if ((_vector_)==0) \ + (_index_) = 0; \ + else \ + (_index_) = 4; \ +} +#endif + +//-------------------------------------------------------------------------- // controller access code #define CYGHWR_HAL_MIPS_VRC4372_BASE 0xbc000000
--- a/packages/hal/mn10300/stb/current/ChangeLog +++ b/packages/hal/mn10300/stb/current/ChangeLog @@ -1,3 +1,7 @@ +2001-10-31 Jonathan Larmour <jlarmour@redhat.com> + + * cdl/hal_mn10300_am33_stb.cdl: Indicate support of variable baud rates. + 2001-09-05 David Howells <dhowells@redhat.com> * src/plf_misc.c: made inclusion here of hal_ctrlc_isr()
--- a/packages/hal/mn10300/stb/current/cdl/hal_mn10300_am33_stb.cdl +++ b/packages/hal/mn10300/stb/current/cdl/hal_mn10300_am33_stb.cdl @@ -55,6 +55,7 @@ cdl_package CYGPKG_HAL_MN10300_AM33_STB implements CYGINT_HAL_DEBUG_GDB_STUBS implements CYGINT_HAL_DEBUG_GDB_STUBS_BREAK implements CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT + implements CYGINT_HAL_VIRTUAL_VECTOR_COMM_BAUD_SUPPORT requires CYGSEM_HAL_UNCACHED_FLASH_ACCESS == 1; @@ -112,6 +113,7 @@ cdl_package CYGPKG_HAL_MN10300_AM33_STB flavor data legal_values 9600 19200 38400 115200 default_value 38400 + define CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD description " This option selects the baud rate used for the diagnostic port. Note: this should match the value chosen for the GDB port if the
--- a/packages/io/eth/current/ChangeLog +++ b/packages/io/eth/current/ChangeLog @@ -1,3 +1,21 @@ +2001-10-30 Jonathan Larmour <jlarmour@redhat.com> + + * doc/driver_doc: Add description of poll, deliver and int_vector + driver functions. + +2001-10-29 Hugo Tyson <hmt@redhat.com> + + * src/net/eth_drv.c (eth_drv_tickle_devices): [CASE 106613] Rather + than calling can_send() in the device driver directly, call our + own eth_drv_send() function which will also dequeue a waiting + packet if we find we indeed can_send(). This helps to recover + from queue full situations within the if_ethersubr layer above. + This change is belt & braces with a similar call in the code which + drops a packet if the queue is full, in the main network code in + net/tcpip/.../src/sys/net/if_ethersubr.c (ether_output); this + change will recover the situation shortly even if the application + gives up trying to send because of ENOBUFS. + 2001-10-18 Jonathan Larmour <jlarmour@redhat.com> * cdl/eth_drivers.cdl: Rename CYGSEM_IO_ETH_DRIVERS_DEBUG to
--- a/packages/io/eth/current/doc/driver_doc +++ b/packages/io/eth/current/doc/driver_doc @@ -11,7 +11,7 @@ supported TCP/IP stack, or any other, wi A driver instance is contained within a "struct eth_drv_sc". - struct eth_drv_funs { + struct eth_hwr_funs { // Initialize hardware (including startup) void (*start)(struct eth_drv_sc *sc, unsigned char *enaddr); @@ -34,10 +34,19 @@ A driver instance is contained within a void (*recv)(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len); + // Deliver data to/from device from/to stack memory space + // (moves lots of memcpy()s out of DSRs into thread) + void (*deliver)(struct eth_drv_sc *sc); + // Poll for interrupts/device service + void (*poll)(struct eth_drv_sc *sc); + // Get interrupt information from hardware driver + int (*int_vector)(struct eth_drv_sc *sc); + // Logical driver interface + struct eth_drv_funs *eth_drv, *eth_drv_old; }; struct eth_drv_sc { - struct eth_drv_funs *funs; + struct eth_hwr_funs *funs; void *driver_private; const char *dev_name; struct arpcom sc_arpcom; /* ethernet common */ @@ -216,6 +225,35 @@ interface. The 'eth_drv_recv()' functio and structures for the data and then calls "HRDWR_recv()" to actually move the data from the interface. +static void +HRDWR_deliver(struct eth_drv_sc *sc) +========================================================================= + +This function is actually a call back, and notifies the driver that delivery +is happening. This allows it to actually do the copy of packet data to/from +the hardware from/to the packet buffer. And once that's done, then do things +like unmask its interrupts, and free any relevant resources so it can process +further packets. + +In general it will be called from the user thread responsible for delivering +network packets. + +static void +HRDWR_poll(struct eth_drv_sc *sc) +========================================================================= + +This function is used when in a non-interrupt driven system, e.g. when +interrupts are completely disabled. This allows the driver time to check +whether anything needs doing either for transmission, or to check if +anything has been received, or if any other processing needs doing.. + +static int +HRDWR_int_vector(struct eth_drv_sc *sc) +========================================================================= + +This function returns the interrupt vector number used for RX interrupts. +This is so the common GDB stubs infrastructure can detect when to check +for incoming ctrl-c's when doing debugging over ethernet. Upper layer functions - called by drivers =========================================
--- a/packages/io/eth/current/src/net/eth_drv.c +++ b/packages/io/eth/current/src/net/eth_drv.c @@ -851,8 +851,15 @@ void eth_drv_tickle_devices( void ) cyg_netdevtab_entry_t *t; for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) { struct eth_drv_sc *sc = (struct eth_drv_sc *)t->device_instance; - if ( ETH_DRV_STATE_ACTIVE & sc->state ) - (*sc->funs->can_send)(sc); + if ( ETH_DRV_STATE_ACTIVE & sc->state ) { + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + // Try to dequeue a packet for this interface, if we can. This + // will call can_send() for active interfaces. It is calls to + // this function from tx_done() which normally provide + // continuous transmissions; otherwise we do not get control. + // This call fixes that. + eth_drv_send(ifp); + } } } #endif // CYGPKG_NET_FAST_THREAD_TICKLE_DEVS
--- a/packages/io/flash/current/ChangeLog +++ b/packages/io/flash/current/ChangeLog @@ -1,3 +1,8 @@ +2001-10-28 Gary Thomas <gthomas@redhat.com> + + * src/flash.c (flash_erase): Don't call hardware layer if block + appears to be already erased [faster and less wear & tear]. + 2001-10-25 Jonathan Larmour <jlarmour@redhat.com> * include/flash_dev.h: Fix test of 4x16-bit flash parts.
--- a/packages/io/flash/current/src/flash.c +++ b/packages/io/flash/current/src/flash.c @@ -202,8 +202,21 @@ flash_erase(void *addr, int len, void ** FLASH_Enable(block, end_addr); while (block < end_addr) { // Supply the blocksize for a gross check for erase success - stat = (*_flash_erase_block)(block, flash_info.block_size); - stat = flash_hwr_map_error(stat); + int i; + unsigned char *dp; + bool erased = true; + + dp = (unsigned char *)block; + for (i = 0; i < flash_info.block_size; i++) { + if (*dp++ != (unsigned char)0xFF) { + erased = false; + break; + } + } + if (!erased) { + stat = (*_flash_erase_block)(block, flash_info.block_size); + stat = flash_hwr_map_error(stat); + } if (stat) { *err_addr = (void *)block; break; @@ -275,7 +288,7 @@ flash_program(void *_addr, void *_data, stat = flash_hwr_map_error(stat); #ifdef CYGSEM_IO_FLASH_VERIFY_PROGRAM if (0 == stat) // Claims to be OK - if (memcmp(addr, data, size) != 0) { + if (memcmp(addr, data, size) != 0) { stat = 0x0BAD; (*flash_info.pf)("V"); }
--- a/packages/kernel/current/ChangeLog +++ b/packages/kernel/current/ChangeLog @@ -1,3 +1,12 @@ +2001-10-30 Nick Garnett <nickg@redhat.com> + + * tests/kcache2.c (test_dsync): + Added call to HAL_ICACHE_INVALIDATE_ALL() just before DCACHE + disable. In platforms where both caches are controlled together, + such as the VR4300, not doing this can result in strange behaviour + as the ICACHE gets turned off under the program's feet, when it is + not ready for it. + 2001-10-17 Jesper Skov <jskov@redhat.com> * tests/dhrystone.c: CYGINT_ISO_STRING_STRFUNCS check changed to @@ -6,7 +15,7 @@ 2001-10-17 Jesper Skov <jskov@redhat.c 2001-10-12 Jonathan Larmour <jlarmour@redhat.com> * cdl/synch.cdl (CYGIMP_KERNEL_SYNCH_MQUEUE_NOT_INLINE): New option - to avoid inliningn mqueue implementation. + to avoid inlining mqueue implementation. * src/sync/mqueue.cxx: New file to provide non-inline version of mqueue functions.
--- a/packages/kernel/current/tests/kcache2.c +++ b/packages/kernel/current/tests/kcache2.c @@ -330,6 +330,7 @@ static void test_dsync(void) CYG_TEST_CHECK(43 == aligned_p[HAL_DCACHE_LINE_SIZE], "memory didn't contain flushed data next block after invalidate"); + HAL_ICACHE_INVALIDATE_ALL(); HAL_DCACHE_DISABLE(); CYG_TEST_CHECK(42 == aligned_p[0],
--- a/packages/net/tcpip/current/ChangeLog +++ b/packages/net/tcpip/current/ChangeLog @@ -1,3 +1,24 @@ +2001-11-02 Gary Thomas <gthomas@redhat.com> + + * src/ecos/support.c: + * include/machine/ansi.h: Add C++ support [externC]. + +2001-11-11 Andrew Lunn <andrew.lunn@ascom.ch> + + *src/lib/recv.c: Implement the recv() call. + +2001-10-29 Hugo Tyson <hmt@redhat.com> + + * src/sys/net/if_ethersubr.c (ether_output): [CASE 106613] Even if + the queue is full, and we are dropping the packet, try to start + the interface anyway, to give it a chance to empty the queue if + the device has recovered from whatever made the queue fill up in + the first place - being unplugged from the network for example. + This change is belt & braces with a similar policy in the periodic + tickle function in the logical ether driver in io/eth/... ; this + change will recover the situation immediately if the application + continues trying to send despite ENOBUFS. + 2001-10-25 Hugo Tyson <hmt@redhat.com> * src/sys/net/if_bridge.c (bridge_broadcast): Count if_obytes in
--- a/packages/net/tcpip/current/cdl/net.cdl +++ b/packages/net/tcpip/current/cdl/net.cdl @@ -132,6 +132,7 @@ cdl_package CYGPKG_NET { lib/shutdown.c \ lib/sendto.c \ lib/recvfrom.c \ + lib/recv.c \ lib/getsockname.c \ lib/getpeername.c \ lib/getsockopt.c \
--- a/packages/net/tcpip/current/include/machine/ansi.h +++ b/packages/net/tcpip/current/include/machine/ansi.h @@ -58,8 +58,8 @@ // Mappings of BSD-style functions used in networking code to those provided // by the eCos environment. -void net_memcpy(void *d, void *s, int n); -void net_memset(void *s, int v, int n); +externC void net_memcpy(void *d, void *s, int n); +externC void net_memset(void *s, int v, int n); #define bcopy(s,d,n) net_memcpy(d,s,n) #define bzero(s,n) net_memset(s,0,n)
--- a/packages/net/tcpip/current/src/ecos/support.c +++ b/packages/net/tcpip/current/src/ecos/support.c @@ -364,7 +364,7 @@ cyg_cltom(u_long x) return res; } -void +externC void net_memcpy(void *d, void *s, int n) { START_STATS(); @@ -372,7 +372,7 @@ net_memcpy(void *d, void *s, int n) FINISH_STATS(stats_memcpy); } -void +externC void net_memset(void *s, int v, int n) { START_STATS();
new file mode 100644 --- /dev/null +++ b/packages/net/tcpip/current/src/lib/recv.c @@ -0,0 +1,67 @@ +//========================================================================== +// +// lib/recv.c +// +// recv() system call +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####BSDCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from OpenBSD or other sources, +// and are covered by the appropriate copyright disclaimers included herein. +// +// ------------------------------------------- +// +//####BSDCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas,andrew.lunn@ascom.ch +// Contributors: gthomas +// Date: 2001-11-01 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> + +ssize_t +recv(int s, const void *buf, size_t buflen, + int flags) +{ + + return(recvfrom(s,buf,buflen,NULL,0)); +}
--- a/packages/net/tcpip/current/src/sys/net/if_ethersubr.c +++ b/packages/net/tcpip/current/src/sys/net/if_ethersubr.c @@ -591,6 +591,11 @@ ether_output(ifp, m0, dst, rt0) * not yet active. */ if (IF_QFULL(&ifp->if_snd)) { + // Let the interface try a dequeue anyway, in case the + // interface has "got better" from whatever made the queue + // fill up - being unplugged for example. + if ((ifp->if_flags & IFF_OACTIVE) == 0) + (*ifp->if_start)(ifp); IF_DROP(&ifp->if_snd); splx(s); senderr(ENOBUFS);
--- a/packages/pkgconf/fixhtml.tcl +++ b/packages/pkgconf/fixhtml.tcl @@ -115,6 +115,10 @@ foreach file $files { regsub -all "=" $data "\\=" data regsub -all "#" $data "\\#" data regsub -all "+" $data "\\+" data + regsub -all "%" $data "\\%" data + regsub -all "$" $data "\\$" data + regsub -all "│" $data "\\│" data + regsub -all "\" $data "\\\" data # Now write the data back to the file. Do not bother to # keep an old version lying around, the html files can be
--- a/packages/redboot/current/ChangeLog +++ b/packages/redboot/current/ChangeLog @@ -1,3 +1,66 @@ +2001-11-01 Jesper Skov <jskov@redhat.com> + + * src/flash.c (fis_init): tweaks to the SIB protection code. + +2001-11-01 Gary Thomas <gthomas@redhat.com> + + * src/flash.c (fis_init): Need to init block fully, otherwise old + images can persist after init. + +2001-10-31 Jesper Skov <jskov@redhat.com> + + * include/sib.h: Contains information about ARM Boot Monitor flash + block information. + + * cdl/redboot.cdl: Added CYGOPT_REDBOOT_FIS_DIRECTORY_ARM_SIB_ID + option. + + * src/flash.c (fis_init): Added code to add ARM Boot Monitor + footer on FIS block. + +2001-10-30 Jonathan Larmour <jlarmour@redhat.com> + + * src/flash.c (fis_delete): Prototype arm_fis_delete in correct place. + (fis_list): Fix compilation problem - this isn't C++! + +2001-10-30 Philippe Robin <Philippe.Robin@arm.com> +2001-10-30 Jonathan Larmour <jlarmour@redhat.com> + + * cdl/redboot.cdl: Add CYGINT_REDBOOT_ARM_FLASH_SIB_SUPPORTED and + CYGHWR_REDBOOT_ARM_FLASH_SIB to indicate support for, and a request + to provide ARM flash block structure support. + + * src/flash.c (fis_list): Call out to driver for ARM block FIS listing. + (fis_delete): Call out to driver for ARM block FIS deletion. + +2001-10-29 Gary Thomas <gthomas@redhat.com> + + * src/main.c (cyg_start): New pseudo-commands, useful for scripts. + '# anything' - treated like a comment. + '= anything' - comment, but prints command line on console. + + * src/flash.c (expand_aliases): Don't expand aliases which are + quoted, but only on the command line. This allows aliases to + expand into other aliases which are within quoted strings. + + * include/redboot.h: + * src/io.c (_rb_gets_preloaded): New function which allows for a + buffer to be displayed and edited in place. This is extremely + useful for 'fconfig', now that better line editing functions are + supported. + + * src/flash.c (get_config): Using new function _rb_gets_preloaded(), + which supports edit-in-place for data items. + +2001-10-28 Gary Thomas <gthomas@redhat.com> + + * src/main.c (cyg_start): + * src/io.c (_rb_gets): + * include/redboot.h: Add new global control 'cmd_history' which is + used to enable/disable command history collection. This keeps the + history from being cluttered with things like 'y' (answers to simple + questions). + 2001-10-26 Gary Thomas <gthomas@redhat.com> * src/io.c (_rb_gets): Fix ^A editing - was timing out, thus erasing
--- a/packages/redboot/current/cdl/redboot.cdl +++ b/packages/redboot/current/cdl/redboot.cdl @@ -33,7 +33,7 @@ # # Author(s): gthomas # Original data: gthomas -# Contributors: +# Contributors: Philippe Robin # Date: 2000-05-01 # #####DESCRIPTIONEND#### @@ -406,6 +406,16 @@ cdl_package CYGPKG_REDBOOT { under this name for use in updating the ROM-based RedBoot that boots the board." } + + cdl_option CYGOPT_REDBOOT_FIS_DIRECTORY_ARM_SIB_ID { + display "Include ARM SIB ID in FIS" + default_value 0 + description " + If set, this option will cause the last 5 words of + the FIS to include the special ID needed for the + flash to be recognized as a reserved area for RedBoot + by an ARM BootRom monitor." + } } cdl_component CYGSEM_REDBOOT_FLASH_CONFIG { @@ -485,6 +495,24 @@ cdl_package CYGPKG_REDBOOT { When this option is enabled, RedBoot will use CRC checksums when reading and writing flash images." } + + cdl_interface CYGINT_REDBOOT_ARM_FLASH_SIB_SUPPORTED { + display "ARM FLASH drivers support SIB flash block structure" + active_if CYGPKG_HAL_ARM + description "This interface is implemented by a flash driver + to indicate that it supports the ARM SIB flash + block structure" + } + + cdl_option CYGHWR_REDBOOT_ARM_FLASH_SIB { + display "Use ARM SIB flash block structure" + flavor bool + active_if CYGINT_REDBOOT_ARM_FLASH_SIB_SUPPORTED + default_value 1 + description " + This option is used to interpret ARM Flash System information + blocks." + } } cdl_component CYGPKG_REDBOOT_DISK {
--- a/packages/redboot/current/include/redboot.h +++ b/packages/redboot/current/include/redboot.h @@ -82,6 +82,9 @@ EXTERN bool console_selected; #endif EXTERN bool console_echo; EXTERN bool gdb_active; +#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0 +EXTERN bool cmd_history; +#endif #ifdef CYGPKG_REDBOOT_NETWORKING EXTERN bool have_net, use_bootp; @@ -111,6 +114,9 @@ externC bool verify_action(char *fmt, .. // Read a single line of input from the console, possibly with timeout externC int _rb_gets(char *line, int len, int timeout); +// Just like _rb_gets(), except that the line buffer is assumed to contain +// valid input data. This provides an easy mechanism for edit-in-place. +externC int _rb_gets_preloaded(char *line, int len, int timeout); // Result codes from 'gets()' #define _GETS_TIMEOUT -1 #define _GETS_CTRLC -2
new file mode 100644 --- /dev/null +++ b/packages/redboot/current/include/sib.h @@ -0,0 +1,134 @@ +#ifndef _SIB_H_ +#define _SIB_H_ +//========================================================================== +// +// sib.h +// +// RedBoot - structure of ARM flash file format +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Philippe Robin +// Contributors: Philippe Robin, jskov +// Date: 2001-10-31 +// Purpose: +// Description: +// +// This code is part of RedBoot (tm). +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <cyg/hal/hal_io.h> + +/* type information :- + * 0xffff ffff - deleted (usual flash erased value) + * 0x0000 xxxx - Reserved for ARM usage: + * Bit 0 - ARM Executable Image + * Bit 1 - System Information Block + * Bit 2 - File System Block + * 0xyyyy 0000 - Available for customers (y != 0) + */ +#define TYPE_DELETED 0xFFFFFFFF +#define TYPE_ARM_MASK 0x0000FFFF +#define TYPE_CUSTOM_MASK 0xFFFF0000 +#define TYPE_ARM_EXEC 0x00000001 +#define TYPE_ARM_SIB 0x00000002 +#define TYPE_ARM_SYSBLOCK 0x00000004 + +/* This is the type we use for RedBoot blocks */ +#define TYPE_REDHAT_REDBOOT 0x52420000 + +/* The ARM monitor may be using a different memory mapping than RedBoot */ +#ifndef _ADDR_REDBOOT_TO_ARM +# define _ADDR_REDBOOT_TO_ARM(x) +#endif + +/* Filetypes */ + +#define UNKNOWN_FILE 0x00000000 +#define MOT_S_RECORD 0x00000001 +#define INTEL_HEX 0x00000002 +#define ELF 0x00000004 +#define DWARF 0x00000008 +#define ARM_AOF 0x00000010 +#define ARM_AIF 0x00000020 +#define PLAIN_BINARY 0x00000040 +#define ARM_AIF_BIN 0x00000080 +#define MCS_TYPE 0x00000100 + +#define CONVERT_TYPE (MOT_S_RECORD | INTEL_HEX | MCS_TYPE | ELF) + +#define SIB_OWNER_STRING_SIZE 32 +#define MAX_SIB_SIZE 512 +#define MAX_SIB_INDEX 64 + +#define SIB_HEADER_SIGNATURE 0xA00FFF9F /* This is an invalid instruction - MULGE pc,pc,pc */ +#define FLASH_FOOTER_SIGNATURE 0xA0FFFF9F /* This is an invalid instruction - SMULALGES pc,pc,pc */ + + +typedef struct SIBType { + cyg_uint32 signature; + cyg_uint32 size; + char owner[SIB_OWNER_STRING_SIZE]; + cyg_uint32 index; + cyg_uint32 revision; + cyg_uint32 checksum; +} tSIB; + +typedef struct SIBInfoType { + cyg_uint32 SIB_number; /* Unique number of SIB Block */ + cyg_uint32 SIB_Extension; /* Base of SIB Flash Block */ + char Label[16]; /* String space for ownership string */ + cyg_uint32 checksum; /* SIB Image checksum */ +} tSIBInfo; + +typedef struct FooterType { + void *infoBase; /* Address of first word of ImageFooter */ + char *blockBase; /* Start of area reserved by this footer */ + cyg_uint32 signature; /* 'Magic' number proves it's a footer */ + cyg_uint32 type; /* Area type: ARM Image, SIB, customer */ + cyg_uint32 checksum; /* Just this structure */ +} tFooter ; + +typedef struct ImageInfoType { + cyg_uint32 bootFlags; /* Boot flags, compression etc. */ + cyg_uint32 imageNumber; /* Unique number, selects for boot etc. */ + char *loadAddress; /* Address program should be loaded to */ + cyg_uint32 length; /* Actual size of image */ + char *address; /* Image is executed from here */ + char name[16]; /* Null terminated */ + char *headerBase; /* Flash Address of any stripped header */ + cyg_uint32 header_length; /* Length of header in memory */ + cyg_uint32 headerType; /* AIF, RLF, s-record etc. */ + cyg_uint32 checksum; /* Image checksum (inc. this struct) */ +} tImageInfo; + + +#endif // _SIB_H_
--- a/packages/redboot/current/src/flash.c +++ b/packages/redboot/current/src/flash.c @@ -46,6 +46,7 @@ #include <redboot.h> #include <cyg/io/flash.h> #include <fis.h> +#include <sib.h> // CLI function static cmd_fun do_fis; @@ -216,6 +217,7 @@ fis_init(int argc, char *argv[]) // Create a pseudo image for RedBoot img = (struct fis_image_desc *)fis_work_block; + memset(img, 0xFF, block_size); // Start with erased data #ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE memset(img, 0, sizeof(*img)); strcpy(img->name, "(reserved)"); @@ -274,6 +276,42 @@ fis_init(int argc, char *argv[]) img->size = block_size; img++; +#ifdef CYGOPT_REDBOOT_FIS_DIRECTORY_ARM_SIB_ID + // FIS gets the size of a full block - note, this should be changed + // if support is added for multi-block FIS structures. + img = (struct fis_image_desc *)((CYG_ADDRESS)fis_work_block + block_size); + // Add a footer so the FIS will be recognized by the ARM Boot + // Monitor as a reserved area. + { + tFooter* footer_p = (tFooter*)((CYG_ADDRESS)img - sizeof(tFooter)); + cyg_uint32 check = 0; + cyg_uint32 *check_ptr = (cyg_uint32 *)footer_p; + cyg_int32 count = (sizeof(tFooter) - 4) >> 2; + + // Prepare footer. Try to protect all but the reserved space + // and the first RedBoot image (which is expected to be + // bootable), but fall back to just protecting the FIS if it's + // not at the default position in the flash. +#if defined(CYGOPT_REDBOOT_FIS_RESERVED_BASE) && (-1 == CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK) + footer_p->blockBase = (char*)_ADDR_REDBOOT_TO_ARM(flash_start); + footer_p->blockBase += CYGNUM_REDBOOT_FLASH_RESERVED_BASE + redboot_image_size; +#else + footer_p->blockBase = _ADDR_REDBOOT_TO_ARM(fis_work_block); +#endif + footer_p->infoBase = NULL; + footer_p->signature = FLASH_FOOTER_SIGNATURE; + footer_p->type = TYPE_REDHAT_REDBOOT; + + // and compute its checksum + for ( ; count > 0; count--) { + if (*check_ptr > ~check) + check++; + check += *check_ptr++; + } + footer_p->checksum = ~check; + } +#endif + // Do this after creating the initialized table because that inherently // calculates where the high water mark of default RedBoot images is. @@ -371,6 +409,13 @@ fis_list(int argc, char *argv[]) bool show_datalen = false; struct option_info opts[2]; +#ifdef CYGHWR_REDBOOT_ARM_FLASH_SIB + // FIXME: this is somewhat half-baked + extern void arm_fis_list(void); + arm_fis_list(); + return; +#endif + init_opts(&opts[0], 'd', false, OPTION_ARG_TYPE_FLG, (void **)&show_datalen, (bool *)0, "display data length"); #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK @@ -688,6 +733,7 @@ fis_create(int argc, char *argv[]) } } +extern void arm_fis_delete(char *); static void fis_delete(int argc, char *argv[]) { @@ -702,6 +748,11 @@ fis_delete(int argc, char *argv[]) fis_usage("invalid arguments"); return; } +#ifdef CYGHWR_REDBOOT_ARM_FLASH_SIB + // FIXME: this is somewhat half-baked + arm_fis_delete(name); + return; +#endif slot_found = false; img = (struct fis_image_desc *)fis_work_block; num_reserved = 0; @@ -1238,7 +1289,7 @@ static void config_init(void); static int get_config(unsigned char *dp, char *title, int list_opt, char *newvalue ) { - char line[256], *sp, *lp; + char line[256], hold_line[256], *sp, *lp; int ret; bool hold_bool_val, new_bool_val, enable; unsigned long hold_int_val, new_int_val; @@ -1258,6 +1309,7 @@ get_config(unsigned char *dp, char *titl return CONFIG_OK; // Disabled field } } + lp = line; *lp = '\0'; val_ptr = (void *)CONFIG_OBJECT_VALUE(dp); if (LIST_OPT_NICKNAMES & list_opt) diag_printf("%s: ", CONFIG_OBJECT_KEY(dp)); @@ -1271,26 +1323,25 @@ get_config(unsigned char *dp, char *titl switch (type = CONFIG_OBJECT_TYPE(dp)) { case CONFIG_BOOL: memcpy(&hold_bool_val, val_ptr, sizeof(bool)); - diag_printf("%s ", hold_bool_val ? "true" : "false"); + lp += diag_sprintf(lp, "%s", hold_bool_val ? "true" : "false"); break; case CONFIG_INT: memcpy(&hold_int_val, val_ptr, sizeof(unsigned long)); - diag_printf("%ld ", hold_int_val); + lp += diag_sprintf(lp, "%ld", hold_int_val); break; #ifdef CYGPKG_REDBOOT_NETWORKING case CONFIG_IP: - diag_printf("%s ", inet_ntoa((in_addr_t *)val_ptr)); + lp += diag_sprintf(lp, "%s", inet_ntoa((in_addr_t *)val_ptr)); break; case CONFIG_ESA: for (esa_ptr = 0; esa_ptr < sizeof(enet_addr_t); esa_ptr++) { - diag_printf("0x%02X", ((unsigned char *)val_ptr)[esa_ptr]); - if (esa_ptr < (sizeof(enet_addr_t)-1)) diag_printf(":"); + lp += diag_sprintf(lp, "0x%02X", ((unsigned char *)val_ptr)[esa_ptr]); + if (esa_ptr < (sizeof(enet_addr_t)-1)) lp += diag_sprintf(lp, ":"); } - diag_printf(" "); break; #endif case CONFIG_STRING: - diag_printf("%s ", (unsigned char *)val_ptr); + lp += diag_sprintf(lp, "%s", (unsigned char *)val_ptr); break; case CONFIG_SCRIPT: diag_printf("\n"); @@ -1305,7 +1356,7 @@ get_config(unsigned char *dp, char *titl break; } if (LIST_OPT_LIST_ONLY & list_opt) { - diag_printf("\n"); + diag_printf("%s\n", line); return CONFIG_OK; } if (type != CONFIG_SCRIPT) { @@ -1314,14 +1365,18 @@ get_config(unsigned char *dp, char *titl if (ret > sizeof(line)) return CONFIG_BAD; strcpy(line, newvalue); + strcpy(hold_line, newvalue); diag_printf("Setting to %s\n", newvalue); + } else { + // read from terminal + strcpy(hold_line, line); + ret = _rb_gets_preloaded(line, sizeof(line), 0); } - else // read from terminal - ret = _rb_gets(line, sizeof(line), 0); if (ret < 0) return CONFIG_ABORT; - if (strlen(line) == 0) return CONFIG_OK; // Just a CR - leave value untouched - if (line[0] == '.') return CONFIG_DONE; - if (line[0] == '^') return CONFIG_BACK; + if (strcmp(line, hold_line) == 0) return CONFIG_OK; // Just a CR - leave value untouched + lp = &line[strlen(line)-1]; + if (*lp == '.') return CONFIG_DONE; + if (*lp == '^') return CONFIG_BACK; } switch (type) { case CONFIG_BOOL: @@ -1661,8 +1716,11 @@ lookup_alias(char *alias, char *alias_bu // Expand aliases, this is recursive. ie if one alias contains other // aliases, these will also be expanded from the insertion point // onwards. +// +// If 'iter' is zero, then quoted strings are not expanded +// bool -_expand_aliases(char *line, int len) +_expand_aliases(char *line, int len, int iter) { char *lp = line; char *ms, *me, *ep; @@ -1727,7 +1785,7 @@ bool diag_printf("Alias '%s' not defined\n", ms); *me = '|'; } - } else if (c == '"') { + } else if ((c == '"') && (iter == 0)) { // Skip quoted strings while (*lp && (*lp != '"')) lp++; } @@ -1739,7 +1797,10 @@ bool void expand_aliases(char *line, int len) { - while (_expand_aliases(line, len)) ; + int iter = 0; + + while (_expand_aliases(line, len, iter++)) { + } } #endif // CYGSEM_REDBOOT_FLASH_ALIASES
--- a/packages/redboot/current/src/io.c +++ b/packages/redboot/current/src/io.c @@ -277,13 +277,13 @@ getc_script(char *cp) // // Read a line of input from the user // Return: -// n: 'n' valid characters received -// 0: '$' (GDB lead-in) -// -1: No input before timeout -// -2: ^C typed +// _GETS_OK: 'n' valid characters received +// _GETS_GDB: '$' (GDB lead-in) +// _GETS_TIMEOUT: No input before timeout +// _GETS_CTRLC: ^C typed // int -_rb_gets(char *buf, int buflen, int timeout) +_rb_gets_preloaded(char *buf, int buflen, int timeout) { char *ip = buf; // Insertion point char *eol = buf; // End of line @@ -308,6 +308,12 @@ int char *xp; #endif + // Display current buffer data + while (*eol) { + mon_write_char(*eol++); + } + ip = eol; + while (true) { #ifdef CYGFUN_REDBOOT_BOOT_SCRIPT if (getc_script(&c)) @@ -423,14 +429,27 @@ int eol = ip; } break; + case CTRL('D'): + // Erase the character under the cursor + if (ip != eol) { + xp = ip; + eol--; + while (xp != eol) { + *xp = *(xp+1); + mon_write_char(*xp++); + } + mon_write_char(' '); // Erases last character + mon_write_char('\b'); + while (xp-- != ip) { + mon_write_char('\b'); + } + } + break; #endif // CYGNUM_REDBOOT_CMD_LINE_EDITING case CTRL('C'): // ^C - if (ip == buf) { - diag_printf("^C\n"); - return _GETS_CTRLC; - } - *ip++ = c; - break; + // Abort current input + diag_printf("^C\n"); + return _GETS_CTRLC; case '\n': case '\r': // If previous character was the "other" end-of-line, ignore this one @@ -446,10 +465,12 @@ int } last_ch = c; #if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0 - // Save current line - if (++_cl_index == _CL_NUM_LINES) _cl_index = 0; - if (_cl_index > _cl_max_index) _cl_max_index = _cl_index; - strcpy(_cl_lines[_cl_index], buf); + if (cmd_history) { + // Save current line - only when enabled + if (++_cl_index == _CL_NUM_LINES) _cl_index = 0; + if (_cl_index > _cl_max_index) _cl_max_index = _cl_index; + strcpy(_cl_lines[_cl_index], buf); + } #endif return _GETS_OK; case '\b': @@ -554,6 +575,13 @@ int } } +int +_rb_gets(char *buf, int buflen, int timeout) +{ + *buf = '\0'; // Empty buffer + return _rb_gets_preloaded(buf, buflen, timeout); +} + bool verify_action(char *fmt, ...) {
--- a/packages/redboot/current/src/main.c +++ b/packages/redboot/current/src/main.c @@ -285,7 +285,13 @@ cyg_start(void) diag_printf("RedBoot> "); prompt = false; } +#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0 + cmd_history = true; // Enable history collection +#endif res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT); +#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0 + cmd_history = false; // Enable history collection +#endif if (res == _GETS_TIMEOUT) { // No input arrived } else { @@ -318,11 +324,19 @@ cyg_start(void) expand_aliases(line, sizeof(line)); #endif command = (char *)&line; - while (strlen(command) > 0) { - if ((cmd = parse(&command, &argc, &argv[0])) != (struct cmd *)0) { - (cmd->fun)(argc, argv); - } else { - diag_printf("** Error: Illegal command: \"%s\"\n", argv[0]); + if ((*command == '#') || (*command == '=')) { + // Special cases + if (*command == '=') { + // Print line on console + diag_printf("%s\n", &line[2]); + } + } else { + while (strlen(command) > 0) { + if ((cmd = parse(&command, &argc, &argv[0])) != (struct cmd *)0) { + (cmd->fun)(argc, argv); + } else { + diag_printf("** Error: Illegal command: \"%s\"\n", argv[0]); + } } } prompt = true;
