Mercurial > ecos
changeset 152:f935b880e96c
Merge from eCos master repository on 2001-02-14-01:27:14-GMT
line wrap: on
line diff
--- a/packages/ChangeLog +++ b/packages/ChangeLog @@ -35,11 +35,19 @@ 2000-11-14 Drew Moseley <dmoseley@redh * pkgconf/rules.mak: Get rid of some gnu specific options to cp, find and xargs. +2000-11-04 Mark Salter <msalter@redhat.com> + + * ecos.db: Add CYGPKG_DEVS_ETH_ARM_IQ80310. + 2000-11-01 Jesper Skov <jskov@redhat.com> * ecos.db: Added cq7750 target and SH3/SH4 variant packages. Moved EDK7708 package. +2000-10-26 Mark Salter <msalter@redhat.com> + + * ecos.db: Add support for XScale IQ80310 + 2000-10-25 Drew Moseley <dmoseley@redhat.com> * ecos.db: Add support for SA1100 Multimedia
--- a/packages/NEWS +++ b/packages/NEWS @@ -1,3 +1,6 @@ +* Added Intel XScale support with the IQ80310 Software Development and + Processor Evaluation Kit. Support includes flash and ethernet drivers, + and RedBoot support. * Added support for USB slave devices. This includes generic USB slave support, a device driver for the SA11x0 on-chip USB device, and an additional support package for developing USB-ethernet and similar
--- a/packages/compat/posix/current/ChangeLog +++ b/packages/compat/posix/current/ChangeLog @@ -1,3 +1,17 @@ +2001-02-14 Jonathan Larmour <jlarmour@redhat.com> + + * include/pthread.h: Remove pthread_canceled() and + pthread_testcancel_unlock(). + + * src/pthread.cxx: Ditto. + (pthread_join): Restructure to have function exit only at function end + (pthread_cond_timedwait): Check for timeouts and return ETIMEDOUT + + * src/signal.cxx (sigtimedwait): Restructure cancellation testing + + * src/time.cxx (nanosleep): test for cancellation at the end of the + function to keep Nick happy ;). + 2001-02-11 Jonathan Larmour <jlarmour@redhat.com> * include/pthread.h: Add new pthread_testcancel_unlock and @@ -634,3 +648,26 @@ 2000-03-24 Nick Garnett <nickg@cygnus. ready. Much work is still needed to make them so. Watch this space. +####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) 2000, 2001 Red Hat, Inc. + All Rights Reserved. + ------------------------------------------- + +####COPYRIGHTEND####
--- a/packages/compat/posix/current/include/pthread.h +++ b/packages/compat/posix/current/include/pthread.h @@ -25,7 +25,7 @@ // // The Initial Developer of the Original Code is Red Hat. // Portions created by Red Hat are -// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// Copyright (C) 2000, 2001 Red Hat, Inc. // All Rights Reserved. // ------------------------------------------- // @@ -383,16 +383,6 @@ externC int pthread_cancel (pthread_t th // the thread if there is one. externC void pthread_testcancel (void); -// eCos extension: -// Test for a pending cancellation for the current thread and terminate -// the thread if there is one, unlocking the supplied mutex first. -externC void pthread_testcancel_unlock ( pthread_mutex_t *__mut ); - -// eCos extension: -// Test for a pending cancellation for the current thread and return -// non-zero if this thread has a deferred cancellation pending -externC int pthread_canceled (void); - // Install a cleanup routine. // Note that pthread_cleanup_push() and pthread_cleanup_pop() are macros that // must be used in matching pairs and at the same brace nesting level.
--- a/packages/compat/posix/current/src/pthread.cxx +++ b/packages/compat/posix/current/src/pthread.cxx @@ -23,7 +23,7 @@ // // The Initial Developer of the Original Code is Red Hat. // Portions created by Red Hat are -// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// Copyright (C) 2000, 2001 Red Hat, Inc. // All Rights Reserved. // ------------------------------------------- // @@ -782,6 +782,8 @@ externC void pthread_exit (void *retval) externC int pthread_join (pthread_t thread, void **thread_return) { + int err = 0; + PTHREAD_ENTRY(); // check for cancellation first. @@ -797,24 +799,26 @@ externC int pthread_join (pthread_t thre if( joinee == NULL ) { - pthread_mutex.unlock(); - PTHREAD_RETURN(ESRCH); + err = ESRCH; + } + + if( !err && joinee == self ) + { + err = EDEADLK; } - if( joinee == self ) - { - pthread_mutex.unlock(); - PTHREAD_RETURN(EDEADLK); - } - - switch ( joinee->state ) - { - case PTHREAD_STATE_RUNNING: - // The thread is still running, we must wait for it. + if ( !err ) { + switch ( joinee->state ) + { + case PTHREAD_STATE_RUNNING: + // The thread is still running, we must wait for it. while( joinee->state == PTHREAD_STATE_RUNNING ) { - joinee->joiner->wait(); - // check if we were woken because we were being cancelled - pthread_testcancel_unlock( (pthread_mutex_t *)&pthread_mutex); + if ( !joinee->joiner->wait() ) + // check if we were woken because we were being cancelled + if ( checkforcancel() ) { + err = EAGAIN; // value unimportant, just some error + break; + } } // check that the thread is still joinable @@ -823,37 +827,43 @@ externC int pthread_join (pthread_t thre // The thread has become unjoinable while we waited, so we // fall through to complain. - - case PTHREAD_STATE_FREE: - case PTHREAD_STATE_DETACHED: - case PTHREAD_STATE_EXITED: + + case PTHREAD_STATE_FREE: + case PTHREAD_STATE_DETACHED: + case PTHREAD_STATE_EXITED: // None of these may be joined. - pthread_mutex.unlock(); - PTHREAD_RETURN(EINVAL); - - case PTHREAD_STATE_JOIN: - break; + err = EINVAL; + break; + + case PTHREAD_STATE_JOIN: + break; + } } - // here, we know that joinee is a thread that has exited and is - // ready to be joined. - - // Get the retval - - if( thread_return != NULL ) - *thread_return = joinee->retval; + if ( !err ) { + + // here, we know that joinee is a thread that has exited and is + // ready to be joined. - // set state to exited. - joinee->state = PTHREAD_STATE_EXITED; - pthreads_exited++; - pthreads_tobejoined--; + // Get the retval + if( thread_return != NULL ) + *thread_return = joinee->retval; + + // set state to exited. + joinee->state = PTHREAD_STATE_EXITED; + pthreads_exited++; + pthreads_tobejoined--; - // Dispose of any dead threads - pthread_reap(); + // Dispose of any dead threads + pthread_reap(); + } + + pthread_mutex.unlock(); - pthread_mutex.unlock(); + // check for cancellation before returning + pthread_testcancel(); - PTHREAD_RETURN(0); + PTHREAD_RETURN(err); } //----------------------------------------------------------------------------- @@ -1712,7 +1722,12 @@ externC int pthread_cond_timedwait (pthr // check if we were woken because we were being cancelled pthread_testcancel(); - PTHREAD_RETURN(0); + pthread_info *self = pthread_self_info(); + + if ( self->thread->get_wake_reason() == Cyg_Thread::TIMEOUT ) + PTHREAD_RETURN(ETIMEDOUT); + else + PTHREAD_RETURN(0); } //============================================================================= @@ -1992,42 +2007,6 @@ externC int pthread_cancel (pthread_t th } //----------------------------------------------------------------------------- -// eCos extension: -// Test for a pending cancellation for the current thread and return -// non-zero if this thread has a deferred cancellation pending - -externC int pthread_canceled(void) -{ - PTHREAD_ENTRY(); - PTHREAD_RETURN( checkforcancel() ); -} - -//----------------------------------------------------------------------------- -// eCos extension: -// Test for a pending cancellation for the current thread and terminate -// the thread if there is one, unlocking the supplied mutex first. - -externC void pthread_testcancel_unlock( pthread_mutex_t *__mut ) -{ - PTHREAD_ENTRY_VOID(); - - if( checkforcancel() ) - { - Cyg_Mutex *mut = (Cyg_Mutex *)__mut; - mut->unlock(); - - // If we have cancellation enabled, and there is a cancellation - // pending, then go ahead and do the deed. - - // Exit now with special retval. pthread_exit() calls the - // cancellation handlers implicitly. - pthread_exit(PTHREAD_CANCELED); - } - - PTHREAD_RETURN_VOID; -} - -//----------------------------------------------------------------------------- // Test for a pending cancellation for the current thread and terminate // the thread if there is one.
--- a/packages/compat/posix/current/src/signal.cxx +++ b/packages/compat/posix/current/src/signal.cxx @@ -23,7 +23,7 @@ // // The Initial Developer of the Original Code is Red Hat. // Portions created by Red Hat are -// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// Copyright (C) 2000, 2001 Red Hat, Inc. // All Rights Reserved. // ------------------------------------------- // @@ -798,23 +798,24 @@ externC int sigtimedwait (const sigset_ { if( ticks == 0 || !signal_sigwait.wait(ticks) ) { - // first check we weren't woken up to be cancelled - pthread_testcancel_unlock( (pthread_mutex_t *)&signal_mutex ); - // If the timeout is actually zero, or we have waited and // timed out, then we must quit with an error. err = EAGAIN; break; } } - else signal_sigwait.wait(); + else { + if ( !signal_sigwait.wait() ) { + // check we weren't woken up forcibly (e.g. to be cancelled) + // if so, pretend it's an error + err = EAGAIN; + break; + } + } // Special case check for SIGALRM since the fact SIGALRM is masked // would have prevented it being set pending in the alarm handler. check_sigalarm(); - - // check we weren't woken up to be cancelled - pthread_testcancel_unlock( (pthread_mutex_t *)&signal_mutex ); } if( err == 0 ) @@ -878,7 +879,9 @@ externC int sigtimedwait (const sigset_ } signal_mutex.unlock(); - + + pthread_testcancel(); + if (err) SIGNAL_RETURN(err); else
--- a/packages/compat/posix/current/src/time.cxx +++ b/packages/compat/posix/current/src/time.cxx @@ -23,7 +23,7 @@ // // The Initial Developer of the Original Code is Red Hat. // Portions created by Red Hat are -// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// Copyright (C) 2000, 2001 Red Hat, Inc. // All Rights Reserved. // ------------------------------------------- // @@ -631,8 +631,6 @@ externC int nanosleep( const struct time then = Cyg_Clock::real_time_clock->current_value(); self->thread->delay( ticks ); - // check if we were woken up because we were cancelled. - pthread_testcancel(); now = Cyg_Clock::real_time_clock->current_value(); @@ -649,6 +647,9 @@ externC int nanosleep( const struct time cyg_ticks_to_timespec( ticks, rmtp ); } + // check if we were woken up because we were cancelled. + pthread_testcancel(); + TIME_RETURN(0); }
new file mode 100644 --- /dev/null +++ b/packages/devs/eth/arm/iq80310/current/ChangeLog @@ -0,0 +1,45 @@ +2000-12-21 Mark Salter <msalter@redhat.com> + + * src/if_iq80310.c (i82559_start): Fix syntax error when DEBUG defined. + +2000-11-22 Mark Salter <msalter@redhat.com> + + * src/if_iq80310.c (pci_init_find_82559s): Don't install ISR handler or + unmask interrupt if CYGPKG_REDBOOT defined. + +2000-11-06 Mark Salter <msalter@redhat.com> + + * src/if_iq80310.c: Add initialization of physical layer interface. + Turned off debugging messages. + + * include/iq80310_info.h: Add definitions for ethernet physical + interface. + +//=========================================================================== +//####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/iq80310/current/cdl/iq80310_eth_drivers.cdl @@ -0,0 +1,147 @@ +# ==================================================================== +# +# iq80310_eth_drivers.cdl +# +# Ethernet drivers +# Intel IQ80310 and 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#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): hmt +# Original data: hmt +# Contributors: gthomas +# Date: 2000-02-01 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_ETH_ARM_IQ80310 { + display "Intel IQ80310 with PRO/100+ ethernet driver" + + parent CYGPKG_IO_ETH_DRIVERS + active_if CYGPKG_IO_ETH_DRIVERS + active_if CYGPKG_HAL_ARM_IQ80310 + + 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/iq80310_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_iq80310.h>" + } + + description "Ethernet driver for Intel IQ80310 with PRO/100+ boards." + compile -library=libextras.a if_iq80310.c if_shmem.S + + cdl_option CYGDBG_DEVS_ETH_ARM_IQ80310_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_IQ80310_DEV_COUNT { + display "Number of supported interfaces." + legal_values 1 2 + default_value 2 + flavor data + description " + This option selects the number of PCI ethernet interfaces to + be supported by the driver." + } + + cdl_component CYGDBG_DEVS_ETH_ARM_IQ80310_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_IQ80310_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_IQ80310_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_IQ80310_OPTIONS { + display "Intel IQ80310 with PRO/100+ ethernet driver build options" + flavor none + no_define + + cdl_option CYGPKG_DEVS_ETH_ARM_IQ80310_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 IQ80310 with PRO/100+ ethernet driver + package. These flags are used in addition to the set of + global flags." + } + } + +} + +# EOF iq80310_eth_drivers.cdl
new file mode 100644 --- /dev/null +++ b/packages/devs/eth/arm/iq80310/current/include/iq80310_info.h @@ -0,0 +1,297 @@ +#ifndef CYGONCE_DEVS_ETH_ARM_IQ80310_IQ80310_INFO_H +#define CYGONCE_DEVS_ETH_ARM_IQ80310_IQ80310_INFO_H +/*========================================================================== +// +// iq80310_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): hmt +// Contributors: hmt +// Date: 2000-05-03 +// Description: +// +//####DESCRIPTIONEND#### +*/ + +#include <pkgconf/devs_eth_arm_iq80310.h> + +#ifdef CYGDBG_DEVS_ETH_ARM_IQ80310_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_IQ80310_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 +#ifdef CYGPKG_REDBOOT +#define MAX_RX_DESCRIPTORS 4 // number of Rx descriptors +#else +#define MAX_RX_DESCRIPTORS 128 // number of Rx descriptors +#endif +#endif +#ifndef MAX_TX_DESCRIPTORS +#ifdef CYGPKG_REDBOOT +#define MAX_TX_DESCRIPTORS 4 // number of Tx descriptors +#else +#define MAX_TX_DESCRIPTORS 128 // number of Tx descriptors +#endif +#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_IQ80310_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_IQ80310_IQ80310_INFO_H */ + +// ------------------------------------------------------------------------ + +// MDI definitions +#define MDI_WRITE_OP 0x01 +#define MDI_READ_OP 0x02 +#define MDI_NOT_READY 0 +#define MDI_POLLED 0 +#define MDI_DEFAULT_PHY_ADDR 1 // when only one PHY + +// PHY device register addresses + +// generic register addresses +#define MDI_PHY_CTRL 0 +#define MDI_PHY_STAT 1 +#define MDI_PHY_ID_1 2 +#define MDI_PHY_ID_2 3 +#define MDI_PHY_AUTO_AD 4 +#define MDI_PHY_AUTO_LNK 5 +#define MDI_PHY_AUTO_EXP 6 + +#define I82555_PHY_ID 0x02a80150 +#define ICS1890_PHY_ID 0x0015f420 +#define DP83840_PHY_ID 0x20005c00 +#define I82553_PHY_ID 0x02a80350 +#define I82553_REVAB_PHY_ID 0x03e00000 + +/* I82555/558 Status and Control register */ +#define I82555_STATCTRL_REG 0x10 +#define I82555_100_MBPS (1 << 1) +#define I82555_10_MBPS (0 << 1) + +#define REVISION_MASK 0xf + +/* DP83840 specific register information */ +#define DP83840_PCR_REG 0x17 +#define PCR_TXREADY_SEL (1 << 10) +#define PCR_FCONNECT (1 << 5) + +/* ICS1890 QuickPoll Detailed Status register */ +#define ICS1890_QUICKPOLL_REG 0x11 +#define QUICK_100_MBPS (1 << 15) +#define QUICK_10_MBPS (0 << 15) +#define QUICK_LINK_VALID (1 << 0) +#define QUICK_LINK_INVALID (0 << 0) + +#define DP83840_PHY_ADDR_REG 0x19 +#define PHY_ADDR_CON_STATUS (1 << 5) +#define PHY_ADDR_SPEED_10_MBPS (1 << 6) +#define PHY_ADDR_SPEED_100_MBPS (0 << 6) + +#define DP83840_LOOPBACK_REG 0x18 +#define TWISTER_LOOPBACK (0x1 << 8) +#define REMOTE_LOOPBACK (0x2 << 8) +#define CLEAR_LOOP_BITS ~(TWISTER_LOOPBACK | REMOTE_LOOPBACK) + +/* 82553 specific register information */ +#define I82553_PHY_EXT_REG0 0x10 +#define EXT_REG0_100_MBPS (1 << 1) +#define GET_REV_CNTR(n) ((n & 0x00e0) >> 5) +#define I82553_PHY_EXT_REG1 0x14 + +/* MDI Control Register bits */ +#define MDI_CTRL_COLL_TEST (1 << 7) +#define MDI_CTRL_FULL_DUPLEX (1 << 8) +#define MDI_CTRL_RESTART_AUTO (1 << 9) +#define MDI_CTRL_ISOLATE (1 << 10) +#define MDI_CTRL_POWER_DOWN (1 << 11) +#define MDI_CTRL_AUTO_ENAB (1 << 12) +#define MDI_CTRL_AUTO_DISAB (0 << 12) +#define MDI_CTRL_100_MBPS (1 << 13) +#define MDI_CTRL_10_MBPS (0 << 13) +#define MDI_CTRL_LOOPBACK (1 << 14) +#define MDI_CTRL_RESET (1 << 15) + +/* MDI Status Register bits */ +#define MDI_STAT_EXTENDED (1 << 0) +#define MDI_STAT_JABBER (1 << 1) +#define MDI_STAT_LINK (1 << 2) +#define MDI_STAT_AUTO_CAPABLE (1 << 3) +#define MDI_STAT_REMOTE_FLT (1 << 4) +#define MDI_STAT_AUTO_COMPLETE (1 << 5) +#define MDI_STAT_10BASET_HALF (1 << 11) +#define MDI_STAT_10BASET_FULL (1 << 12) +#define MDI_STAT_TX_HALF (1 << 13) +#define MDI_STAT_TX_FULL (1 << 14) +#define MDI_STAT_T4_CAPABLE (1 << 15) + +/* EOF iq80310_info.h */ +
new file mode 100644 --- /dev/null +++ b/packages/devs/eth/arm/iq80310/current/src/if_iq80310.c @@ -0,0 +1,3033 @@ +//========================================================================== +// +// if_iq80310.c +// +// Ethernet drivers +// Intel IQ80310 and 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, Pacific Softworks; msalter +// Date: 2000-02-01 +// Purpose: +// Description: hardware driver for 82559 Intel PRO/100+ ethernet on +// a Intel XScale IQ80310 development board +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/system.h> +#include <pkgconf/devs_eth_arm_iq80310.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/hal/hal_io.h> +#include <cyg/hal/hal_cache.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> +#define diag_printf printf +#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/iq80310_info.h> +#include <eth_drv_stats.h> + +// ------------------------------------------------------------------------ + +#ifdef CYGDBG_DEVS_ETH_ARM_IQ80310_CHATTER +#define notDEBUG_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); } + +// Bus masters can get to all of SDRAM using direct mapping. +#define VIRT_TO_BUS( _x_ ) ((cyg_uint32)(_x_)) +#define BUS_TO_VIRT( _x_ ) ((cyg_uint32)(_x_)) + +// ------------------------------------------------------------------------ +// +// 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 1 + +I82559 i82559[MAX_82559]; // i82559 device info. structure + +// eth0 + +ETH_DRV_SC(iq80310_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(iq80310_netdev0, + "iq80310-0", + iq80310_i82559_init, + &iq80310_sc0); + +#if (MAX_82559 > 1) + +// eth1 + +ETH_DRV_SC(iq80310_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(iq80310_netdev1, + "iq80310-1", + iq80310_i82559_init, + &iq80310_sc1); + +#else +int iq80310_netdev1 = -1; // for asserts about valid addresses +int iq80310_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 *)&iq80310_netdev0) || \ + ((void *)ndp == (void *)&iq80310_netdev1), "Bad ndp" ); \ + CYG_ASSERT( ((void *)sc == (void *)&iq80310_sc0) || \ + ((void *)sc == (void *)&iq80310_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 + +// ------------------------------------------------------------------------ +// +// 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_IQ80310_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" ); +} + +// Short circuit the drv_interrupt_XXX API once we are started: + +static inline int Mask82559Interrupt(struct i82559* p_i82559) +{ + int cpu_intr; + int old; + int mask = 1 << (CYGNUM_HAL_INTERRUPT_ETHERNET - CYGNUM_HAL_INTERRUPT_TIMER); + + HAL_DISABLE_INTERRUPTS( cpu_intr ); + + old = *X3MASK_REG; + *X3MASK_REG = old | mask; + + HAL_RESTORE_INTERRUPTS( cpu_intr ); + + return old & mask; +} + + +static inline void UnMask82559Interrupt(struct i82559* p_i82559, int old) +{ + int cpu_intr; + int mask = 1 << (CYGNUM_HAL_INTERRUPT_ETHERNET - CYGNUM_HAL_INTERRUPT_TIMER); + + // We must only unmask (enable) if it was unmasked before, + // according to the bit in old. + HAL_DISABLE_INTERRUPTS( cpu_intr ); + *X3MASK_REG = (*X3MASK_REG & ~mask) | old; + HAL_RESTORE_INTERRUPTS( cpu_intr ); +} + +#ifdef CYGDBG_USE_ASSERTS // an indication of a debug build +static int acknowledge82559interrupt_compensating = 0; +#endif + +static void Acknowledge82559Interrupt(struct i82559* p_i82559) +{ + int sources, mask; + cyg_uint32 ioaddr; + cyg_uint16 status; + int loops = 64; + + // XScale does nothing in interrupt_acknowledge, so we can comment + // this all out. So this routine really boils down to + // "wait for the device to stop interrupting before we unmask" + // The acknowledge call is left in place, for documentary purposes. + + 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 << (CYGNUM_HAL_INTERRUPT_ETHERNET - CYGNUM_HAL_INTERRUPT_TIMER)); + sources = *X3ISR_REG; + + 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 = *X3ISR_REG; + 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 600 MHz, to give uS, multiply + // by 600/3 = 200. No volatile is needed on i; gcc recognizes delay + // loops and does NOT elide them. + for ( i = 200 * 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; + int _size = size; + + CYG_ASSERT( + (CYGHWR_HAL_ARM_IQ80310_PCI_MEM_MAP_BASE <= (int)i82559_heap_free) + && + ((CYGHWR_HAL_ARM_IQ80310_PCI_MEM_MAP_BASE + + CYGHWR_HAL_ARM_IQ80310_PCI_MEM_MAP_SIZE) > (int)i82559_heap_free) + && + (0 < i82559_heap_size) + && + (CYGHWR_HAL_ARM_IQ80310_PCI_MEM_MAP_SIZE >= i82559_heap_size) + && + (CYGHWR_HAL_ARM_IQ80310_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; +} + +// ------------------------------------------------------------------------ +// +// MDI +// +// ------------------------------------------------------------------------ + +#define SPEED_NOLINK 0 +#define SPEED_10M 10 +#define SPEED_100M 100 + +// MDI Control Register +typedef union +{ + struct + { + cyg_uint32 data : 16; // data to write or data read + cyg_uint32 regAdd : 5; // PHY register address + cyg_uint32 phyAdd : 5; // PHY address + cyg_uint32 op : 2; // opcode, 1 for MDI write, 2 for MDI read + cyg_uint32 ready : 1; // 1 = operation complete + cyg_uint32 intEnab : 1; // 1 = interrupt at end of cycle + cyg_uint32 rsrv : 2; // reserved + } bits; + cyg_uint32 word; +} MDICTL; + +static cyg_uint16 readMDI (long ioaddr, cyg_uint8 phyAdd, cyg_uint8 regAdd) +{ + int mdi_addr = ioaddr + SCBCtrlMDI; + MDICTL mdiCtrl; + int num_ms = 0; + + // prepare for the MDI operation + mdiCtrl.bits.ready = MDI_NOT_READY; + mdiCtrl.bits.intEnab = MDI_POLLED; // no interrupts + mdiCtrl.bits.op = MDI_READ_OP; + mdiCtrl.bits.phyAdd = phyAdd & 0x1f; + mdiCtrl.bits.regAdd = regAdd & 0x1f; + + // start the operation + OUTW(mdiCtrl.word, mdi_addr); + + // delay a bit + udelay (1000); + + // poll for completion */ + mdiCtrl.word = INW(mdi_addr); + + while ((mdiCtrl.bits.ready == MDI_NOT_READY) && (num_ms != 2000)) { // wait max 2secs + mdiCtrl.word = INW(mdi_addr); + udelay(1000); + num_ms++; + } + + if (num_ms >= 2000) { + CYG_FAIL ("readMDI Timeout!\n"); + return -1; + } + else + return (cyg_uint16)mdiCtrl.bits.data; +} + + +static void writeMDI (long ioaddr, cyg_uint8 phyAdd, cyg_uint8 regAdd, cyg_uint16 data) +{ + int mdi_addr = ioaddr + SCBCtrlMDI; + register MDICTL mdiCtrl; + int num_ms = 0; + + // prepare for the MDI operation + mdiCtrl.bits.ready = MDI_NOT_READY; + mdiCtrl.bits.intEnab = MDI_POLLED; // no interrupts + mdiCtrl.bits.op = MDI_WRITE_OP; + mdiCtrl.bits.phyAdd = phyAdd & 0x1f; + mdiCtrl.bits.regAdd = regAdd & 0x1f; + mdiCtrl.bits.data = data & 0xffff; + + // start the operation + OUTW(mdiCtrl.word, mdi_addr); + + // delay a bit + udelay(1000); + + // poll for completion + mdiCtrl.word = INW(mdi_addr); + + while ((mdiCtrl.bits.ready == MDI_NOT_READY) && (num_ms != 2000)) { + mdiCtrl.word = INW(mdi_addr); + udelay(1000); + num_ms++; + } + if (num_ms >= 2000) + CYG_FAIL ("writeMDI Timeout!\n"); + + return; +} + +static int initPHY (long ioaddr, cyg_uint32 device_type) +{ + cyg_uint16 temp_reg; + cyg_uint8 revision; + + // strip off revision and phy. id information + revision = (cyg_uint8)(device_type & REVISION_MASK); + device_type &= ~REVISION_MASK; + + switch (device_type) { + case ICS1890_PHY_ID: + temp_reg = readMDI(ioaddr, MDI_DEFAULT_PHY_ADDR, MDI_PHY_CTRL); // get ready for loopback setting + writeMDI(ioaddr, MDI_DEFAULT_PHY_ADDR, MDI_PHY_CTRL, temp_reg); + break; + + case DP83840_PHY_ID: // set the Intel-specified "must set" bits + temp_reg = readMDI(ioaddr, MDI_DEFAULT_PHY_ADDR, DP83840_PCR_REG); + temp_reg |= (PCR_TXREADY_SEL | PCR_FCONNECT); + writeMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, DP83840_PCR_REG, temp_reg); + + // get ready for loopback setting + temp_reg = readMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, DP83840_LOOPBACK_REG); + temp_reg &= CLEAR_LOOP_BITS; + writeMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, DP83840_LOOPBACK_REG, temp_reg); + break; + + case I82553_PHY_ID: + case I82553_REVAB_PHY_ID: + case I82555_PHY_ID: + break; + + default: + return 1; + break; + } + + return 0; +} + + + + + +// ------------------------------------------------------------------------ +// +// 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 +iq80310_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, ints; + int addr_length; + cyg_uint8 mac_address[6]; + struct i82559 *p_i82559; + +#ifdef DEBUG + db_printf("iq80310_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 + + ints = 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 = 0x1FFFFF; // Timeout for self-test. + do { + udelay(10); + } while ( (p_selftest[1] == -1) && (--count >= 0) ); + + Acknowledge82559Interrupt(p_i82559); + UnMask82559Interrupt(p_i82559, ints ); + + 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 0 + 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 +#endif + { + p_i82559->mac_addr_ok = 1; +#ifdef DEBUG_EE + os_printf("Valid EEPROM checksum\n"); +#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, phy_id; + cyg_uint16 phy_addr_reg, temp1, temp2; + int broadcom_flag = false; + int link_speed = SPEED_NOLINK; +#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 + + phy_id = readMDI(ioaddr ,MDI_DEFAULT_PHY_ADDR, MDI_PHY_ID_1) << 16; + phy_id |= readMDI(ioaddr ,MDI_DEFAULT_PHY_ADDR, MDI_PHY_ID_2); + + if ((phy_id & 0xfffffff0) == I82555_PHY_ID) { +#ifdef DEBUG + os_printf ("Intel 82555/558 PHY detected...\n"); +#endif + // dummy read for reliable status + (void)readMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT); + + temp1 = readMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT); + + phy_addr_reg = readMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, I82555_STATCTRL_REG); + + if (temp1 & MDI_STAT_LINK) // speed only valid with good LNK + link_speed = (phy_addr_reg & I82555_100_MBPS) ? SPEED_100M : SPEED_10M; +#ifdef DEBUG + else + os_printf ("Connect Speed is NOT VALID\n"); +#endif + } + + if ((phy_id & 0xfffffff0) == ICS1890_PHY_ID) { +#ifdef DEBUG + os_printf ("Integrated Circuit Systems ICS1890 PHY detected...\n"); + os_printf ("Revision = %c\n", 'A' + (phy_id & REVISION_MASK)); +#endif + // dummy read for reliable status + (void)readMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, ICS1890_QUICKPOLL_REG); + temp1 = readMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, ICS1890_QUICKPOLL_REG); + + if (temp1 & QUICK_LINK_VALID) // speed only valid with good LNK + link_speed = (temp1 & QUICK_100_MBPS) ? SPEED_100M : SPEED_10M; +#ifdef DEBUG + else + os_printf ("Connect Speed is NOT VALID\n"); +#endif + } + + if ((phy_id & 0xfffffff0) == DP83840_PHY_ID) { +#ifdef DEBUG + os_printf ("National DP83840 PHY detected...\n"); + os_printf ("Revision = %c\n", 'A' + (phy_id & REVISION_MASK)); +#endif + + // dummy read for reliable status + (void)readMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT); + temp1 = readMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT); + + phy_addr_reg = readMDI (ioaddr ,MDI_DEFAULT_PHY_ADDR, DP83840_PHY_ADDR_REG); + + if (temp1 & MDI_STAT_LINK) // speed only valid with good LNK + link_speed = (phy_addr_reg & PHY_ADDR_SPEED_10_MBPS) ? SPEED_10M : SPEED_100M; +#ifdef DEBUG + else + os_printf ("Connect Speed is NOT VALID\n"); +#endif + } + + if ((phy_id & 0xfffffff0) == I82553_PHY_ID) { +#ifdef DEBUG + os_printf ("Intel 82553 PHY detected...\n"); + os_printf ("Revision = %c\n", 'A' + (phy_id & REVISION_MASK)); +#endif + broadcom_flag = true; + } + + if (phy_id == I82553_REVAB_PHY_ID) { +#ifdef DEBUG + os_printf ("Intel 82553 PHY detected...\n"); + os_printf ("Revision = B\n"); +#endif + broadcom_flag = true; + } + + if (broadcom_flag == true) { + temp2 = readMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, I82553_PHY_EXT_REG0); + + // dummy read for reliable status + (void)readMDI (ioaddr ,MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT); + temp1 = readMDI (ioaddr ,MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT); + + if (temp1 & MDI_STAT_LINK) { // speed only valid with good LNK + link_speed = (temp2 & EXT_REG0_100_MBPS) ? SPEED_100M : SPEED_10M; +#ifdef DEBUG + } else { + os_printf ("Connect Speed is NOT VALID\n"); +#endif + } + } + +#ifdef KEEP_STATISTICS +#ifdef CYGDBG_DEVS_ETH_ARM_IQ80310_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; + + initPHY(ioaddr, phy_id); + +#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; + 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, ints; + 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. + ints = 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, ints); + + 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; + 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, KEY %x\n", + p_i82559->index, (int)p_i82559, key ); +#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; + int ints; + + 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 + ints = Mask82559Interrupt(p_i82559); + TxMachine(p_i82559); + Acknowledge82559Interrupt(p_i82559); // This can eat an Rx interrupt, so + PacketRxReady(p_i82559); + UnMask82559Interrupt(p_i82559,ints); + + 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, ints; + 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\n", + p_i82559->index, (int)p_i82559, sg_len, total_len, 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 + ints = 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); // This can eat an Rx interrupt, so + PacketRxReady(p_i82559); + UnMask82559Interrupt(p_i82559, ints); +} + +// ------------------------------------------------------------------------ +// +// 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", 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; + + p_i82559 = &i82559[0]; + if ( p_i82559->active ) + uni_deliver( p_i82559 ); +} + +// ------------------------------------------------------------------------ +// Device table entry to operate the chip in a polled mode. +// Only diddle the interface we were asked to! + +void i82559_poll(struct eth_drv_sc *sc) +{ + struct i82559 *p_i82559; + int ints; + 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 + ints = Mask82559Interrupt(p_i82559); + + // As it happens, this driver always requests the DSR to be called: + (void)eth_isr( CYGNUM_HAL_INTERRUPT_ETHERNET, (cyg_addrword_t)p_i82559 ); + + // (no harm in calling this ints-off also, when polled) + uni_deliver( p_i82559 ); + + Acknowledge82559Interrupt(p_i82559); + UnMask82559Interrupt(p_i82559, ints); +} + +// ------------------------------------------------------------------------ +// 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); +} + +#if 0 +int +i82559_int_op( struct eth_drv_sc *sc, int mask) +{ + struct i82559 *p_i82559; + p_i82559 = (struct i82559 *)sc->driver_private; + + if ( 1 == mask ) + return Mask82559Interrupt( p_i82559 ); + + if ( 0 == mask ) + UnMask82559Interrupt( p_i82559, 0x0fffffff ); // enable all + + return 0; +} +#endif + + + // form a second level small page entry +#define SL_SMPAGE_ENTRY(base,ap3,ap2,ap1,ap0,c,b) \ + ( ((base) << 12) | ((ap3) << 10) | ((ap2) << 8) | ((ap1) << 6) |\ + ((ap0) << 4) | ((c) << 3) | ((b) << 2) | 2) + +// ------------------------------------------------------------------------ +// +// Function : pci_init_find_82559s +// +// This is called exactly once at the start of time to: +// o setup some uncached memory for bus mastering +// 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; + extern char cyg_io_iq80310_i82559_shmem[]; + +#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 = 16*1024; // match actual size in if_shmem.S + i82559_heap_base = cyg_io_iq80310_i82559_shmem; + + // only first 1MB of board uses 4K page table + if (cyg_io_iq80310_i82559_shmem > (char *)0xa0100000) { +#ifdef DEBUG + db_printf("Can't get shared mem\n"); +#endif + return 0; + } + + { + // page table for 1st 1M of RAM + unsigned *ram_mmutab = (unsigned *)0xA0008400; + unsigned base = ((unsigned)i82559_heap_base) / 4096; + unsigned offset = ((unsigned)i82559_heap_base - 0xa0000000) / 4096; + int i; + + for (i = 0; i < (i82559_heap_size/4096); i++) + ram_mmutab[offset+i] = SL_SMPAGE_ENTRY(base+i, 3, 3, 3, 3, 0, 0); + + HAL_DCACHE_SYNC(); + asm volatile ("mcr p15, 0, %0, c7, c10, 4;\n" // drain WB + "mcr p15, 0, %0, c8, c7, 0;\n" // flush TLBs + : : "r"(i) ); + } + + i82559_heap_free = i82559_heap_base; + + mem_reserved_ioctl = pciwindow_mem_alloc(MAX_MEM_RESERVED_IOCTL); + + cyg_pci_init(); + +#ifdef DEBUG + db_printf("Finished cyg_pci_init();\n"); +#endif + + 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, 0x1209, &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 +#ifndef CYGPKG_REDBOOT + 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); +#endif + + // 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 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); +#ifndef CYGPKG_REDBOOT + cyg_drv_interrupt_unmask(p_i82559->vector); +#endif + } +#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( 2000000 ); + 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 EBSA boards. + +#ifdef CYGPKG_DEVS_ETH_ARM_IQ80310_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_IQ80310_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_IQ80310_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_IQ80310_WRITE_EEPROM + + return p_i82559->mac_addr_ok ? 0 : 1; +} + +#ifdef CYGPKG_DEVS_ETH_ARM_IQ80310_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_IQ80310_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_IQ80310_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, ints; + + ints = 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); // This can eat an Rx interrupt, so + PacketRxReady(p_i82559); + + UnMask82559Interrupt(p_i82559, ints); +} +#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_iq80310.c
new file mode 100644 --- /dev/null +++ b/packages/devs/eth/arm/iq80310/current/src/if_shmem.S @@ -0,0 +1,57 @@ +// #======================================================================== +// # +// # if_shmem.S +// # +// # Declare a chunk of 4Kbyte aligned memory for use by bus-mastering +// # PCI ethernet 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): msalter +// # Contributors: msalter +// # Date: 2000-11-03 +// # Purpose: +// # Description: This file defines a chunk of 4Kbyte aligned memory for use +// # by bus-mastering PCI ethernet device. +// # +// #####DESCRIPTIONEND#### +// # +// #======================================================================== + + + .bss + .p2align(12) + .globl cyg_io_iq80310_i82559_shmem +cyg_io_iq80310_i82559_shmem: + .rept 16*1024 + .byte 0 + .endr + + + + \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/iq80310/current/ChangeLog @@ -0,0 +1,45 @@ +2000-12-05 Jonathan Larmour <jlarmour@redhat.com> + + * src/iq80310_flash.c (flash_code_overlaps): Define stext/etext + as array types so no assumptions can be made by the compiler about + location. + +2000-11-22 Mark Salter <msalter@redhat.com> + + * src/flash_unlock_block.c (flash_unlock_block): Fix broken + read of lock bits. + +2000-11-19 Mark Salter <msalter@redhat.com> + + * src/flash_unlock_block.c (flash_unlock_block): Fix lock state + query to properly use FLASH_P2V macro. Don't issue lock state + query for block we are unlocking. + + * src/flash_program_buf.c (flash_program_buf): Fix code to skip + over Yavapai registers in flash memory space. + +//=========================================================================== +//####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/flash/arm/iq80310/current/cdl/flash_iq80310.cdl @@ -0,0 +1,99 @@ +# ==================================================================== +# +# flash_iq80310.cdl +# +# FLASH memory - Hardware support on Cyclone IQ80310 +# +# ==================================================================== +#####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): msalter +# Original data: msalter +# Contributors: +# Date: 2000-10-10 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_FLASH_IQ80310 { + display "Cyclone IQ80310 FLASH memory support" + + parent CYGPKG_IO_FLASH + active_if CYGPKG_IO_FLASH + requires CYGPKG_HAL_ARM_IQ80310 + + implements CYGHWR_IO_FLASH_DEVICE + implements CYGHWR_IO_FLASH_BLOCK_LOCKING + + include_dir . + include_files ; # none _exported_ whatsoever + description "FLASH memory device support for Cyclone IQ80310" + compile iq80310_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 + } + make -priority 1 { + flash_lock_block.o: $(REPOSITORY)/$(PACKAGE)/src/flash_lock_block.c + $(CC) -S $(INCLUDE_PATH) $(CFLAGS) -g0 -fno-function-sections $(REPOSITORY)/$(PACKAGE)/src/flash_lock_block.c + echo " .globl flash_lock_block_end" >>flash_lock_block.s + echo "flash_lock_block_end:" >>flash_lock_block.s + $(CC) -c -o flash_lock_block.o flash_lock_block.s + $(AR) rcs $(PREFIX)/lib/libtarget.a flash_lock_block.o + } + make -priority 1 { + flash_unlock_block.o: $(REPOSITORY)/$(PACKAGE)/src/flash_unlock_block.c + $(CC) -S $(INCLUDE_PATH) $(CFLAGS) -g0 -fno-function-sections $(REPOSITORY)/$(PACKAGE)/src/flash_unlock_block.c + echo " .globl flash_unlock_block_end" >>flash_unlock_block.s + echo "flash_unlock_block_end:" >>flash_unlock_block.s + $(CC) -c -o flash_unlock_block.o flash_unlock_block.s + $(AR) rcs $(PREFIX)/lib/libtarget.a flash_unlock_block.o + } +} +
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/iq80310/current/src/flash.h @@ -0,0 +1,97 @@ +//========================================================================== +// +// 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: gthomas, msalter +// Date: 2000-07-26 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#ifndef _FLASH_HWR_H_ +#define _FLASH_HWR_H_ + +// First 4K page of flash at physical address zero is +// virtually mapped at address 0xa0000000. +#define FLASH_P2V(x) ((volatile unsigned char *)(((unsigned)(x) < 0x1000) ? \ + ((unsigned)(x) | 0xa0000000) : \ + (unsigned)(x))) + +#define FLASH_BOOT_BLOCK_SIZE 0x4000 + +#define FLASH_Intel_code 0x89 + +#define FLASH_Read_ID 0x90 +#define FLASH_Read_Query 0x98 +#define FLASH_Read_Status 0x70 +#define FLASH_Clear_Status 0x50 +#define FLASH_Status_Ready 0x80 +#define FLASH_Write_Buffer 0xE8 +#define FLASH_Program 0x10 +#define FLASH_Block_Erase 0x20 +#define FLASH_Set_Lock 0x60 +#define FLASH_Set_Lock_Confirm 0x01 +#define FLASH_Clear_Locks 0x60 +#define FLASH_Clear_Locks_Confirm 0xD0 +#define FLASH_Confirm 0xD0 +#define FLASH_Configure 0xB8 +#define FLASH_Configure_ReadyWait 0x00 +#define FLASH_Configure_PulseOnErase 0x01 +#define FLASH_Configure_PulseOnProgram 0x02 +#define FLASH_Configure_PulseOnBoth 0x03 +#define FLASH_Reset 0xFF + +#define FLASH_BLOCK_SIZE 0x10000 +#define FLASH_WBUF_SIZE 32 + +#define FLASH_Intel_code 0x89 + +// Extended query information +struct FLASH_query { + unsigned char manuf_code; + unsigned char device_code; + unsigned char _unused0[14]; + unsigned char id[3]; // Q Q R + unsigned char _unused1[20]; + unsigned char device_size; + unsigned char device_interface[2]; + unsigned char buffer_size[2]; + unsigned char is_block_oriented; + unsigned char num_regions[2]; + unsigned char region_size[2]; +}; + +#endif // _FLASH_HWR_H_
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/iq80310/current/src/flash_erase_block.c @@ -0,0 +1,105 @@ +//========================================================================== +// +// 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: gthomas, msalter +// Date: 2000-07-14 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include "flash.h" + +#include <pkgconf/hal.h> +#include <cyg/hal/hal_arch.h> +#include <cyg/hal/hal_cache.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 unsigned char *block) +{ + volatile unsigned char *ROM; + unsigned short stat; + int timeout = 50000; + int cache_on; + int len; + + HAL_DCACHE_IS_ENABLED(cache_on); + if (cache_on) { + HAL_DCACHE_SYNC(); + HAL_DCACHE_DISABLE(); + } + + + // First 4K page of flash at physcial address zero is + // virtually mapped to address 0xa0000000. + ROM = FLASH_P2V((unsigned)block & 0xFF800000); + + // Clear any error conditions + ROM[0] = FLASH_Clear_Status; + + // Erase block + ROM[0] = FLASH_Block_Erase; + *FLASH_P2V(block) = FLASH_Confirm; + timeout = 5000000; + while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) { + if (--timeout == 0) break; + } + + // Restore ROM to "normal" mode + ROM[0] = FLASH_Reset; + + // If an error was reported, see if the block erased anyway + if (stat & 0x7E) { + len = FLASH_BLOCK_SIZE; + while (len > 0) { + if (*FLASH_P2V(block) != 0xFF) + break; + block++; + len -= sizeof(*block); + } + if (len == 0) stat = 0; + } + + if (cache_on) { + HAL_DCACHE_ENABLE(); + } + + return stat; +}
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/iq80310/current/src/flash_lock_block.c @@ -0,0 +1,87 @@ +//========================================================================== +// +// flash_lock_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: gthomas, msalter +// Date: 2000-09-10 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include "flash.h" + +#include <cyg/hal/hal_cache.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_lock_block(volatile unsigned char *block) +{ + volatile unsigned char *ROM; + unsigned short stat; + int timeout = 5000000; + int cache_on; + + ROM = FLASH_P2V((unsigned long)block & 0xFF800000); + + HAL_DCACHE_IS_ENABLED(cache_on); + if (cache_on) { + HAL_DCACHE_SYNC(); + HAL_DCACHE_DISABLE(); + } + + // Clear any error conditions + ROM[0] = FLASH_Clear_Status; + + // Set lock bit + FLASH_P2V(block)[0] = FLASH_Set_Lock; + FLASH_P2V(block)[0] = FLASH_Set_Lock_Confirm; // Confirmation + while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) { + if (--timeout == 0) break; + } + + // Restore ROM to "normal" mode + ROM[0] = FLASH_Reset; + + if (cache_on) { + HAL_DCACHE_ENABLE(); + } + + return stat; +}
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/iq80310/current/src/flash_program_buf.c @@ -0,0 +1,147 @@ +//========================================================================== +// +// 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: gthomas, msalter +// Date: 2000-07-14 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include "flash.h" + +#include <pkgconf/hal.h> +#include <cyg/hal/hal_arch.h> +#include <cyg/hal/hal_cache.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 char *addr, unsigned char *data, int len) +{ + volatile unsigned char *ROM; + volatile unsigned char *BA; + unsigned short stat; + int timeout = 5000000; + int i, wc, cache_on; + + HAL_DCACHE_IS_ENABLED(cache_on); + if (cache_on) { + HAL_DCACHE_SYNC(); + HAL_DCACHE_DISABLE(); + } + + ROM = FLASH_P2V((unsigned long)addr & 0xFF800000); + BA = FLASH_P2V((unsigned long)addr & 0xFFFE0000); + + // Clear any error conditions + ROM[0] = FLASH_Clear_Status; + + wc = 32; + while (len >= wc) { + len -= wc; + + // The IQ803010 has a hole in flash which must be avoided. + if (((unsigned char *)0x1000) <= addr && addr < ((unsigned char *)0x2000)) { + addr += wc; + data += wc; + continue; + } + + *BA = FLASH_Write_Buffer; + timeout = 5000000; + while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) { + if (--timeout == 0) { + stat |= 0x0100; + goto bad; + } + *BA = FLASH_Write_Buffer; + } + *BA = wc-1; // Count is 0..N-1 + if (FLASH_P2V(addr) != addr) { + volatile unsigned char *tmp; + + tmp = FLASH_P2V(addr); + for (i = 0; i < wc; i++) + *tmp++ = *data++; + addr += wc; + } else { + for (i = 0; i < wc; i++) + *addr++ = *data++; + } + *BA = FLASH_Confirm; + stat = *BA; + } + + ROM[0] = FLASH_Read_Status; + timeout = 5000000; + while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) { + if (--timeout == 0) { + stat |= 0x0200; + goto bad; + } + } + + while (len > 0) { + ROM[0] = FLASH_Program; + + *FLASH_P2V(addr) = *data++; + addr++; + timeout = 5000000; + while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) { + if (--timeout == 0) { + stat |= 0x0300; + goto bad; + } + } + --len; + } + + // Restore ROM to "normal" mode + bad: + ROM[0] = FLASH_Reset; + + if (cache_on) { + HAL_DCACHE_ENABLE(); + } + + return stat; +} + +
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/iq80310/current/src/flash_query.c @@ -0,0 +1,85 @@ +//========================================================================== +// +// 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: gthomas +// Date: 2000-07-26 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include "flash.h" + +#include <pkgconf/hal.h> +#include <cyg/hal/hal_arch.h> +#include <cyg/hal/hal_cache.h> +#include CYGHWR_MEMORY_LAYOUT_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 200*1000*10 // Approx 20ms + +int +flash_query(unsigned char *data) +{ + volatile unsigned short *ROM; + int i, cnt; + int cache_on; + + HAL_DCACHE_IS_ENABLED(cache_on); + if (cache_on) { + HAL_DCACHE_SYNC(); + HAL_DCACHE_DISABLE(); + } + + ROM = FLASH_P2V(0); + ROM[0] = FLASH_Read_Query; + for (cnt = CNT; cnt > 0; cnt--) ; + for (i = 0; i < sizeof(struct FLASH_query); i++) { + *data++ = ROM[i]; + } + + ROM[0] = FLASH_Reset; + + if (cache_on) { + HAL_DCACHE_ENABLE(); + } + + return 0; +}
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/iq80310/current/src/flash_unlock_block.c @@ -0,0 +1,127 @@ +//========================================================================== +// +// flash_unlock_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: gthomas, msalter +// Date: 2000-09-10 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include "flash.h" + +#include <cyg/hal/hal_cache.h> + +// +// CAUTION! This code must be copied to RAM before execution. Therefore, +// it must not contain any code which might be position dependent! +// + +// +// The difficulty with this operation is that the hardware does not support +// unlocking single blocks. However, the logical layer would like this to +// be the case, so this routine emulates it. The hardware can clear all of +// the locks in the device at once. This routine will use that approach and +// then reset the regions which are known to be locked. +// + +#define MAX_FLASH_BLOCKS 128 + +int +flash_unlock_block(volatile unsigned char *block, int block_size, int blocks) +{ + volatile unsigned short *ROM, *bp; + unsigned short stat; + int timeout = 5000000; + unsigned short is_locked[MAX_FLASH_BLOCKS]; + int i, cache_on; + + HAL_DCACHE_IS_ENABLED(cache_on); + if (cache_on) { + HAL_DCACHE_SYNC(); + HAL_DCACHE_DISABLE(); + } + + ROM = FLASH_P2V((unsigned long)block & 0xFF800000); + + // Clear any error conditions + ROM[0] = FLASH_Clear_Status; + + // Get current block lock state. This needs to access each block on + // the device so currently locked blocks can be re-locked. + bp = (unsigned short *)((unsigned long)block & 0xFF800000); + for (i = 0; i < blocks; i++) { + if (bp == block) { + is_locked[i] = 0; + } else { + *(volatile unsigned short *)FLASH_P2V(bp) = FLASH_Read_Query; + is_locked[i] = ((volatile unsigned short *)FLASH_P2V(bp))[2]; + } + bp += block_size / sizeof(*bp); + } + + // Clears all lock bits + FLASH_P2V(block)[0] = FLASH_Clear_Locks; + FLASH_P2V(block)[0] = FLASH_Clear_Locks_Confirm; // Confirmation + timeout = 5000000; + while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) { + if (--timeout == 0) goto done; + } + + // Restore the lock state + bp = (unsigned char *)((unsigned long)block & 0xFF800000); + for (i = 0; i < blocks; i++) { + if (is_locked[i]) { + *FLASH_P2V(bp) = FLASH_Set_Lock; + *FLASH_P2V(bp) = FLASH_Set_Lock_Confirm; // Confirmation + timeout = 5000000; + while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) { + if (--timeout == 0) goto done; + } + } + bp += block_size / sizeof(*bp); + } + + done: + // Restore ROM to "normal" mode + ROM[0] = FLASH_Reset; + + if (cache_on) { + HAL_DCACHE_ENABLE(); + } + + return stat; +}
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/arm/iq80310/current/src/iq80310_flash.c @@ -0,0 +1,121 @@ +//========================================================================== +// +// iq80310_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: gthomas, msalter +// Date: 2000-07-26 +// 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 _si(p) ((p[1]<<8)|p[0]) + +int +flash_hwr_init(void) +{ + struct FLASH_query data, *qp; + 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 + + memset(&data,0,sizeof(data)); + stat = (*_flash_query)((void*)&data); + HAL_ICACHE_ENABLE(); + + qp = &data; + if (/*(qp->manuf_code == FLASH_Intel_code) && */ + (strncmp(qp->id, "QRY", 3) == 0)) { + num_regions = _si(qp->num_regions)+1; + region_size = _si(qp->region_size)*256; + + flash_info.block_size = region_size; + flash_info.blocks = num_regions; + flash_info.start = (void *)0x00000000; + flash_info.end = (void *)(0x00000000+(num_regions*region_size)); + return FLASH_ERR_OK; + } else { + 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) { + printf("Err = %x\n", err); + 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))); +}
--- a/packages/ecos.db +++ b/packages/ecos.db @@ -161,6 +161,16 @@ package CYGPKG_DEVS_FLASH_ASSABET { This package contains hardware support for FLASH memory on the Intel StrongARM SA-1110 Assabet platform." } +package CYGPKG_DEVS_FLASH_IQ80310 { + alias { "FLASH memory support for Cyclone IQ80310" flash_iq80310 } + directory devs/flash/arm/iq80310 + script flash_iq80310.cdl + hardware + description " + This package contains hardware support for FLASH memory + on the Cyclone IQ80310 platform." +} + package CYGPKG_DEVS_FLASH_MBX { alias { "FLASH memory support for Motorola PowerPC/860 MBX" flash_mbx } directory devs/flash/powerpc/mbx @@ -180,6 +190,15 @@ package CYGPKG_IO_SERIAL_ARM_EBSA285 { description "Intel StrongARM/EBSA285 serial device drivers" } +package CYGPKG_IO_SERIAL_ARM_IQ80310 { + alias { "Intel XScale IQ80310 serial driver" + devs_serial_arm_iq80310 iq80310_serial_driver } + hardware + directory devs/serial/arm/iq80310 + script ser_arm_iq80310.cdl + description "Intel XScale/IQ80310 serial device drivers" +} + package CYGPKG_IO_SERIAL_ARM_SA11X0 { alias { "Intel StrongARM SA11x0 serial driver" devs_serial_arm_sa11x0 sa11x0_serial_driver } @@ -476,6 +495,15 @@ package CYGPKG_DEVS_ETH_INTEL_I82559 { description "Ethernet driver for Intel 82559 NIC." } +package CYGPKG_DEVS_ETH_ARM_IQ80310 { + alias { "Intel IQ80310 with onboard 82559 ethernet driver" + devs_eth_arm_iq80310 iq80310_eth_driver } + hardware + directory devs/eth/arm/iq80310 + script iq80310_eth_drivers.cdl + description "Ethernet driver for Intel IQ80310 with onboard 82559 NIC." +} + # Not sure whether this should be "hardware"; if so, it should be mentioned # in all targets that can use it. package CYGPKG_DEVS_ETH_CF { @@ -869,6 +897,16 @@ The cma230 HAL package provides the supp CMA230 (ARM7TDMI) or CMA222 (ARM710T) eval board." } +package CYGPKG_HAL_ARM_IQ80310 { + alias { "Intel IQ80310 XScale board" hal_arm_iq80310 arm_iq80310_hal } + directory hal/arm/iq80310 + script hal_arm_iq80310.cdl + hardware + description " + The IQ80310 HAL package provides the support needed to run + eCos on an Intel XScale IQ80310 evaluation board." +} + # -------------------------------------------------------------------------- # SH packages package CYGPKG_HAL_SH { @@ -1390,6 +1428,20 @@ target sa1100mm { eCos on an Intel StrongARM SA1100 Multimedia evaluation board." } +target iq80310 { + alias { "Intel IQ80310 XScale board" iq80310 } + packages { CYGPKG_HAL_ARM + CYGPKG_HAL_ARM_IQ80310 + CYGPKG_IO_PCI + CYGPKG_DEVS_ETH_ARM_IQ80310 + CYGPKG_IO_SERIAL_ARM_IQ80310 + CYGPKG_DEVS_FLASH_IQ80310 + } + description " + The iq80310 target provides the packages needed to run + eCos on a Cyclone IQ80310 board." +} + target edb7xxx { alias { "Cirrus Logic development board" edb7211 eb7xxx eb7211 } packages { CYGPKG_HAL_ARM @@ -1669,7 +1721,7 @@ target ceb_v850 { } description " The ceb_v850 target provides the packages needed to run eCos on a -Cosmo CEB-V850 evaluation board fitted with a V850/SA1." +Cosmo CEB-V850 evaluation board fitted with a V850/SA1 or V850/SB1." } # --------------------------------------------------------------------------
--- a/packages/hal/arm/aeb/current/ChangeLog +++ b/packages/hal/arm/aeb/current/ChangeLog @@ -1,3 +1,8 @@ +2001-02-13 Gary Thomas <gthomas@redhat.com> + + * src/aeb_misc.c (hal_IRQ_handler): Use CYGNUM_HAL_INTERRUPT_NONE + for spurious interrupt. + 2001-02-08 Jesper Skov <jskov@redhat.com> * cdl/hal_arm_aeb.cdl: Respect channel configuration constraints.
--- a/packages/hal/arm/aeb/current/src/aeb_misc.c +++ b/packages/hal/arm/aeb/current/src/aeb_misc.c @@ -23,7 +23,7 @@ // // The Initial Developer of the Original Code is Red Hat. // Portions created by Red Hat are -// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc. // All Rights Reserved. // ------------------------------------------- // @@ -302,7 +302,7 @@ int hal_IRQ_handler(void) for (vector = 0; vector < 16; vector++) { if (irq_status & (1<<vector)) return vector; } - return CYGNUM_HAL_INTERRUPT_unused; // This shouldn't happen! + return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen! } //
--- a/packages/hal/arm/arch/current/ChangeLog +++ b/packages/hal/arm/arch/current/ChangeLog @@ -1,3 +1,15 @@ +2001-02-13 Gary Thomas <gthomas@redhat.com> + + * src/vectors.S (handle_IRQ_or_FIQ): Change behaviour for + handling spurious interrupts. + + * src/hal_misc.c (hal_spurious_IRQ): New function - called + when a spurious interrupt is detected. Defined as "weak" + so platforms can provide localized support. + + * src/hal_mk_defs.c: + * include/hal_intr.h (CYGNUM_HAL_INTERRUPT_NONE): Define. + 2001-02-09 Hugo Tyson <hmt@redhat.com> * src/vectors.S (UNMAPPED()): Handle CYGHWR_HAL_ROM_VADDR if so @@ -100,6 +112,8 @@ 2000-11-06 Mark Salter <msalter@redhat 2000-11-04 Mark Salter <msalter@redhat.com> + * include/hal_io.h: Include cyg/hal/plf_io.h for IQ80310. + * src/arm_stub.c (__computeSignal): New interface for HAL_STUB_IS_STOPPED_BY_HARDWARE
--- a/packages/hal/arm/arch/current/include/hal_intr.h +++ b/packages/hal/arm/arch/current/include/hal_intr.h @@ -67,6 +67,9 @@ # endif #endif +// Spurious interrupt (no interrupt source could be found) +#define CYGNUM_HAL_INTERRUPT_NONE -1 + //-------------------------------------------------------------------------- // ARM exception vectors.
--- a/packages/hal/arm/arch/current/src/hal_misc.c +++ b/packages/hal/arm/arch/current/src/hal_misc.c @@ -140,6 +140,17 @@ exception_handler(HAL_SavedRegisters *re return; } +void hal_spurious_IRQ(HAL_SavedRegisters *regs) CYGBLD_ATTRIB_WEAK; +void +hal_spurious_IRQ(HAL_SavedRegisters *regs) +{ +#if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) + exception_handler(regs); +#else + CYG_FAIL("Spurious interrupt!!"); +#endif +} + /*------------------------------------------------------------------------*/ /* C++ support - run initial constructors */
--- a/packages/hal/arm/arch/current/src/hal_mk_defs.c +++ b/packages/hal/arm/arch/current/src/hal_mk_defs.c @@ -23,7 +23,7 @@ // // The Initial Developer of the Original Code is Red Hat. // Portions created by Red Hat are -// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc. // All Rights Reserved. // ------------------------------------------- // @@ -106,6 +106,7 @@ main(void) #if defined(CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT) DEFINE(CYGNUM_CALL_IF_TABLE_SIZE, CYGNUM_CALL_IF_TABLE_SIZE); #endif + DEFINE(CYGNUM_HAL_INTERRUPT_NONE, CYGNUM_HAL_INTERRUPT_NONE); return 0; }
--- a/packages/hal/arm/arch/current/src/vectors.S +++ b/packages/hal/arm/arch/current/src/vectors.S @@ -747,11 +747,14 @@ 10: str v6,[r2] #endif -#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS - cmp r0,#0 // ignore spurious interrupts - beq spurious_IRQ -#endif // CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS - ldr r1,.hal_interrupt_data + cmp r0,#CYGNUM_HAL_INTERRUPT_NONE // spurious interrupt + bne 10f +#ifndef CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS + bl hal_spurious_IRQ +#endif // CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS + b spurious_IRQ + +10: ldr r1,.hal_interrupt_data ldr r1,[r1,v1,lsl #2] // handler data ldr r2,.hal_interrupt_handlers ldr v3,[r2,v1,lsl #2] // handler (indexed by vector #) @@ -776,9 +779,7 @@ IRQ_15A: mov pc,v3 // thru v3) #endif -#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS spurious_IRQ: -#endif // CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK // If we are returning from the last nested interrupt, move back
--- a/packages/hal/arm/cma230/current/ChangeLog +++ b/packages/hal/arm/cma230/current/ChangeLog @@ -1,3 +1,8 @@ +2001-02-13 Gary Thomas <gthomas@redhat.com> + + * src/cma230_misc.c (hal_IRQ_handler): + Return CYGNUM_HAL_INTERRUPT_NONE for spurious interrupts. + 2001-02-08 Jesper Skov <jskov@redhat.com> * cdl/hal_arm_cma230.cdl: Respect channel configuration
--- a/packages/hal/arm/cma230/current/src/cma230_misc.c +++ b/packages/hal/arm/cma230/current/src/cma230_misc.c @@ -23,7 +23,7 @@ // // The Initial Developer of the Original Code is Red Hat. // Portions created by Red Hat are -// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc. // All Rights Reserved. // ------------------------------------------- // @@ -120,22 +120,21 @@ void hal_hardware_init(void) // This routine is called to respond to a hardware interrupt (IRQ). It // should interrogate the hardware and return the IRQ vector number. +#if 0 // TEMP int tot_ints; cyg_uint32 int_PC[2048]; // TEMP +#endif -#if 0 -int hal_IRQ_handler(void) -#else int hal_IRQ_handler(HAL_SavedRegisters *regs) -#endif { volatile cyg_uint8 isr = *(volatile cyg_uint8 *)CMA230_ISR; volatile cyg_uint8 *imrr = (volatile cyg_uint8 *)CMA230_IMRr; int vector; isr &= *imrr; // The Interrupt Source Register shows _all_ current // interrupt sources, not just the enabled ones +#if 0 // TEMP int_PC[tot_ints++] = 0xFFFFFFFF; int_PC[tot_ints++] = isr; @@ -143,12 +142,14 @@ int hal_IRQ_handler(HAL_SavedRegisters * int_PC[tot_ints++] = regs->pc; if (tot_ints == 2048) tot_ints = 0; // TEMP +#endif + for (vector = 0; vector < 8; vector++) { if (isr & (1<<vector)) { return (vector+1); } } - return CYGNUM_HAL_INTERRUPT_unused; // This shouldn't happen! + return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen! } //
--- a/packages/hal/arm/ebsa285/current/ChangeLog +++ b/packages/hal/arm/ebsa285/current/ChangeLog @@ -1,3 +1,8 @@ +2001-02-13 Gary Thomas <gthomas@redhat.com> + + * src/ebsa285_misc.c (hal_IRQ_handler): + Return CYGNUM_HAL_INTERRUPT_NONE for spurious interrupts. + 2001-02-08 Jesper Skov <jskov@redhat.com> * src/hal_diag.c: Replace CYGSEM_HAL_DIAG_MANGLER_None with
--- a/packages/hal/arm/ebsa285/current/src/ebsa285_misc.c +++ b/packages/hal/arm/ebsa285/current/src/ebsa285_misc.c @@ -23,7 +23,7 @@ // // The Initial Developer of the Original Code is Red Hat. // Portions created by Red Hat are -// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc. // All Rights Reserved. // ------------------------------------------- // @@ -436,7 +436,7 @@ int hal_IRQ_handler(void) index++; } while ( index & 7 ); - return CYGNUM_HAL_INTERRUPT_reserved0; // This shouldn't happen! + return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen! } //
--- a/packages/hal/arm/edb7xxx/current/ChangeLog +++ b/packages/hal/arm/edb7xxx/current/ChangeLog @@ -1,3 +1,8 @@ +2001-02-13 Gary Thomas <gthomas@redhat.com> + + * src/edb7xxx_misc.c (hal_IRQ_handler): + Return CYGNUM_HAL_INTERRUPT_NONE for spurious interrupts. + 2001-02-08 Jesper Skov <jskov@redhat.com> * src/hal_diag.c: Replace CYGSEM_HAL_DIAG_MANGLER_None with
--- a/packages/hal/arm/edb7xxx/current/src/edb7xxx_misc.c +++ b/packages/hal/arm/edb7xxx/current/src/edb7xxx_misc.c @@ -23,7 +23,7 @@ // // The Initial Developer of the Original Code is Red Hat. // Portions created by Red Hat are -// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc. // All Rights Reserved. // ------------------------------------------- // @@ -444,7 +444,7 @@ int hal_IRQ_handler(void) map++; // Next interrupt status register } hal_spurious_ints++; - return CYGNUM_HAL_INTERRUPT_unused; // This shouldn't happen! + return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen! } //
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/ChangeLog @@ -0,0 +1,196 @@ +2001-02-13 Gary Thomas <gthomas@redhat.com> + + * src/iq80310_misc.c (hal_IRQ_handler): + Return CYGNUM_HAL_INTERRUPT_NONE for spurious interrupts. + +2001-02-08 Jesper Skov <jskov@redhat.com> + + * src/hal_diag.c: Replace CYGSEM_HAL_DIAG_MANGLER_None with + CYGDBG_HAL_DIAG_TO_DEBUG_CHAN. + +2001-02-07 Mark Salter <msalter@redhat.com> + + * src/diag/external_timer.c (counter_test): Fix printf format + string to work with stripped down RedBoot printf.(counter_test): + +2001-02-06 Mark Salter <msalter@redhat.com> + + * src/diag/external_timer.c: Merged in Cyclone changes. + * src/diag/interrupts.c: Ditto. + * src/diag/memtest.c: Ditto. + * src/diag/xscale_test.c: Ditto. + +2001-02-02 Mark Salter <msalter@redhat.com> + + * src/diag/xscale_test.c (seven_segment_display): Use volatile for + delay loop variable to avoid optimizing it away. + + * src/diag/flash.c (flash_buffer): Change huge array (.bss) to a + pointer to scratchpad RAM above RedBoot. + + * src/iq80310_misc.c (hal_hardware_init): Don't enable FIQ (for now). + (cyg_hal_plf_is_stopped_by_hardware): Check for stopped by BKPT insn. + + * misc/redboot_ROM.cfg (CYGNUM_IO_ETH_DRIVERS_NUM_PKT): Set value to 2. + * misc/redboot_ROMA.cfg: Ditto. + * misc/redboot_RAM.cfg: Ditto. + * misc/redboot_RAMA.cfg: Ditto. + +2001-01-31 Mark Salter <msalter@redhat.com> + + * src/iq80310_pci.c (__pci_abort_handler): Use naked attribute for + use as abort handler. + + * src/iq80310_misc.c (_scrub_ecc): New function. + (hal_IRQ_handler): Fix switched sensing of FIQ/IRQ. + (hal_hardware_init): Install handlers for NMI FIQs. Fix switched + installation of FIQ/IRQ ISRs. + + * include/hal_iq80310.h (RFR_INIT_VAL): Double refresh interval. + Add more register definitions. + + * include/hal_platform_setup.h: Add support for baterry test. + Enable Yavapai single-bit error correction. + + * src/diag/*: Integrate latest Cyclone code. Add RHEPL to contributed + files. + +2001-01-31 Jesper Skov <jskov@redhat.com> + + * src/hal_diag.c: Replaced CYGDBG_HAL_DIAG_DISABLE_GDB_PROTOCOL + with CYGSEM_HAL_DIAG_MANGLER_None + + * include/hal_diag.h: Fix hal_delay_us declaration. + +2001-01-26 Jesper Skov <jskov@redhat.com> + + * src/hal_diag.c: Removed CYGSEM_HAL_VIRTUAL_VECTOR_DIAG check. + * include/plf_stub.h: Moved reset macro to + * include/hal_platform_ints.h: this file. + +2001-01-11 Mark Salter <msalter@redhat.com> + + * include/hal_platform_setup.h: Remove hardcoded position dependencies + in page table setup. + + * cdl/hal_arm_iq80310.cdl (CYGSEM_HAL_ARM_IQ80310_ARMBOOT): New + bool option. If true, modifies ROM startup so that we coexist with + ARM bootloader. + + * include/pkgconf/mlt_arm_iq80310_roma.mlt: New file. ROM statrup + with modified start address to coexist with ARM bootloader. + * include/pkgconf/mlt_arm_iq80310_roma.h: Regenerated. + * include/pkgconf/mlt_arm_iq80310_roma.ldi: Regenerated. + + * misc/redboot_ROMA.cfg: RedBoot configuration for ROM startup by + ARM booloader in FLASH boot sector. + * misc/redboot_RAMA.cfg: RedBoot configuration for RAM startup with + ARM booloader in FLASH boot sector. + +2001-01-08 Mark Salter <msalter@redhat.com> + + * src/diag/diag.c (do_hdwr_diag): Turn off debug channel interrupt + and reset PCI bus before calling Cyclone diag code. + + * src/diag/xscale_test.c (hdwr_diag): Uncomment call to + sys_pci_device_init. + +2001-01-05 Mark Salter <msalter@redhat.com> + + * src/iq80310_misc.c (iq80310_program_new_stack): New function to + setup stack for programs called by RedBoot. + * cdl/hal_arm_iq80310.cdl: Add define for HAL_ARCH_PROGRAM_NEW_STACK. + (Merged from XScale branch). + + * cdl/hal_arm_iq80310.cdl: Add compile of Cyclone diag code. + * src/diag: New directory with IQ80310 hw diag code from Cyclone. + +2000-12-21 Mark Salter <msalter@redhat.com> + + * src/iq80310_pci.c (cyg_hal_plf_pci_init): Play nice with PC BIOS. + (pci_config_cleanup): Don't use fixed bus numbers. + + * include/plf_io.h (HAL_PCI_TRANSLATE_INTERRUPT): Don't use fixed + secondary bus number. + + * include/hal_platform_setup.h: Increase reset delay to 60ms. + Remove dead code. + +2000-11-22 Mark Salter <msalter@redhat.com> + + * src/hal_diag.c: Support 57600 baud. + * cdl/hal_arm_iq80310.cdl: Accept 57600 as legal baudrate. + + * misc/redboot_RAM.cfg: Set CYGBLD_REDBOOT_MIN_IMAGE_SIZE to 0x40000. + * misc/redboot_ROM.cfg: Ditto. + +2000-11-19 Mark Salter <msalter@redhat.com> + + * src/iq80310_misc.c (hal_clock_read): Fix timer bit juggling. + +2000-11-19 Gary Thomas <gthomas@redhat.com> + + * cdl/hal_arm_iq80310.cdl: Define CYGBLD_HAL_PLATFORM_IO_H. + +2000-11-16 Mark Salter <msalter@redhat.com> + + * src/iq80310_misc.c: Add support for external timer as RTC. + (nirq_ISR): Correct dispatch for X3 interrupts. + + * include/hal_platform_ints.h (CYGNUM_HAL_INTERRUPT_RTC): Use ext timer. + (HAL_DELAY_US): Define. + + * cdl/hal_arm_iq80310.cdl: Correct CYGNUM_HAL_RTC_PERIOD. + +2000-11-06 Mark Salter <msalter@redhat.com> + + * misc/redboot_RAM.cfg: Turn on CYGSEM_REDBOOT_BSP_SYSCALLS. + * misc/redboot_ROM.cfg: Ditto. + +2000-11-04 Mark Salter <msalter@redhat.com> + + * misc/redboot_RAM.cfg: Add in PCI and ethernet. + * misc/redboot_ROM.cfg: Ditto. + + * include/plf_io.h: Fleshed out PCI support. + + * cdl/hal_arm_iq80310.cdl: Add iq80310_pci.C for compile. + Change default baud to 115200. + + * src/iq80310_pci.c: New file. HAL pci support. + + * include/plf_stub.h: Reworked HW watchpoint/breakpoint support. + + * src/iq80310_misc.c (hal_hardware_init): Remove DSU setup. + (cyg_hal_plf_hw_watchpoint): Support one range instead of two + single byte locations. + (cyg_hal_plf_is_stopped_by_hardware): Rework interface to return + reason for hardware stop and data address. + + * include/hal_platform_setup.h (PLATFORM_SETUP1): Clear DSU state. + +//=========================================================================== +//####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/hal/arm/iq80310/current/cdl/hal_arm_iq80310.cdl @@ -0,0 +1,385 @@ +# ==================================================================== +# +# hal_arm_iq80310.cdl +# +# IQ80310 evaluation 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): msalter +# Original data: +# Contributors: +# Date: 2000-10-09 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== +cdl_package CYGPKG_HAL_ARM_IQ80310 { + display "Intel IQ80310 XScale evaluation boards" + parent CYGPKG_HAL_ARM + define_header hal_arm_iq80310.h + include_dir cyg/hal + hardware + description " + The IQ80310 HAL package provides the support needed to run + eCos on an Intel IQ80310 XScale eval board." + + compile hal_diag.c iq80310_misc.c iq80310_pci.c + + implements CYGINT_HAL_DEBUG_GDB_STUBS + implements CYGINT_HAL_DEBUG_GDB_STUBS_BREAK + implements CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT + + 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_iq80310.h>" + puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_IO_H <cyg/hal/plf_io.h>" + puts $::cdl_header "#define HAL_PLATFORM_CPU \"XScale\"" + puts $::cdl_header "#define HAL_PLATFORM_BOARD \"IQ80310\"" + puts $::cdl_header "#define HAL_PLATFORM_EXTRA \"\"" + puts $::cdl_header "#define HAL_ARCH_PROGRAM_NEW_STACK iq80310_program_new_stack" + } + + cdl_component CYG_HAL_STARTUP { + display "Startup type" + flavor data + default_value {"RAM"} + legal_values {"RAM" "ROM"} + no_define + define -file system.h CYG_HAL_STARTUP + description " + When targetting the IQ80310 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. Selection of 'stubs' is for the special case of + building the eCos GDB stubs themselves." + } + + cdl_option CYGSEM_HAL_ARM_IQ80310_ARMBOOT { + display "Coexist with ARM bootloader" + flavor bool + default_value 0 + description " + Enable this option if the ARM bootloader is programmed into + the FLASH boot sector on the board." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_DEFAULT { + display "Default console channel." + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + calculated 0 + } + + 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 0 + description " + 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 EBSA285 board has only one serial port. This option + chooses which port will be used for diagnostic output." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD { + display "Diagnostic serial port baud rate" + flavor data + legal_values 9600 19200 38400 57600 115200 + default_value 115200 + 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 CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD { + display "GDB serial port baud rate" + flavor data + legal_values 9600 19200 38400 57600 115200 + default_value 115200 + description " + This option selects the baud rate used for the GDB port." + } + + # 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 330000 ;# External timer is 33MHz + } + } + + cdl_component CYGBLD_GLOBAL_OPTIONS { + display "Global build options" + flavor none + description " + Global build options including control over + compiler flags, linker flags and choice of toolchain." + + + parent CYGPKG_NONE + + cdl_option CYGBLD_GLOBAL_COMMAND_PREFIX { + display "Global command prefix" + flavor data + no_define + default_value { "xscale-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 { "-Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority -mapcs-frame" } + default_value { "-Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -fno-rtti -fno-exceptions -fvtable-gc -finit-priority -mapcs-frame" } + 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 { "-Wl,--gc-sections -Wl,-static -g -O2 -nostdlib" } + 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 { CYG_HAL_STARTUP == "ROM" } + requires CYGSEM_HAL_ROM_MONITOR + requires CYGBLD_BUILD_COMMON_GDB_STUBS + 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 common HAL controls takes care of most of the + build process, but the final conversion from ELF image to + binary data is handled by the platform CDL, allowing + relocation of the data if necessary." + + make -priority 320 { + <PREFIX>/bin/gdb_module.bin : <PREFIX>/bin/gdb_module.img + $(OBJCOPY) -O binary $< $@ + } + } + } + + cdl_option CYGNUM_HAL_BREAKPOINT_LIST_SIZE { + display "Number of breakpoints supported by the HAL." + flavor data + default_value 32 + description " + This option determines the number of breakpoints supported by the HAL." + } + + cdl_component CYGPKG_HAL_ARM_IQ80310_OPTIONS { + display "XScale IQ80310 build options" + flavor none + description " + Package specific build options including control over + compiler flags used only in building this package, + and details of which tests are built." + + + cdl_option CYGPKG_HAL_ARM_IQ80310_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the XScale IQ80310 HAL. These flags are used + in addition to the set of global flags." + } + + cdl_option CYGPKG_HAL_ARM_IQ80310_CFLAGS_REMOVE { + display "Suppressed compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the XScale IQ80310 HAL. These flags are + removed from the set of global flags if present." + } + + cdl_option CYGPKG_HAL_ARM_IQ80310_TESTS { + display "XScale IQ80310 tests" + flavor data + no_define + calculated { "" } + description " + This option specifies the set of tests for the XScale IQ80310 HAL." + } + } + + cdl_component CYGHWR_MEMORY_LAYOUT { + display "Memory layout" + flavor data + no_define + calculated { CYG_HAL_STARTUP == "RAM" ? "arm_iq80310_ram" : \ + CYGSEM_HAL_ARM_IQ80310_ARMBOOT ? "arm_iq80310_roma" : \ + "arm_iq80310_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_iq80310_ram.ldi>" : \ + CYGSEM_HAL_ARM_IQ80310_ARMBOOT ? "<pkgconf/mlt_arm_iq80310_roma.ldi>" : \ + "<pkgconf/mlt_arm_iq80310_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_iq80310_ram.h>" : \ + CYGSEM_HAL_ARM_IQ80310_ARMBOOT ? "<pkgconf/mlt_arm_iq80310_roma.h>" : \ + "<pkgconf/mlt_arm_iq80310_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_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." + + compile -library=libextras.a diag/diag.c diag/io_utils.c diag/external_timer.c \ + diag/i557_eep.c diag/pci_serv.c diag/interrupts.c \ + diag/xscale_test.c diag/flash.c diag/cycduart.c \ + diag/ether_test.c diag/memtest.c diag/test_menu.c \ + diag/irq.S + + 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/iq80310/current/include/hal_cache.h @@ -0,0 +1,355 @@ +#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): hmt +// Contributors:hmt +// Date: 1999-07-05 +// 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> +//#include <cyg/hal/hal_mmu.h> + +//----------------------------------------------------------------------------- +// Cache dimensions + +#define HAL_DCACHE_SIZE 0x8000 // Size of data cache in bytes +#define HAL_DCACHE_LINE_SIZE 32 // Size of a data cache line +#define HAL_DCACHE_WAYS 32 // Associativity of the cache +#define HAL_DCACHE_SETS (HAL_DCACHE_SIZE/(HAL_DCACHE_LINE_SIZE*HAL_DCACHE_WAYS)) + +#define HAL_ICACHE_SIZE 0x8000 // Size of icache in bytes +#define HAL_ICACHE_LINE_SIZE 32 // Size of ins cache line +#define HAL_ICACHE_WAYS 32 // Associativity of the cache +#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() \ +CYG_MACRO_START \ + asm volatile ( \ + "mrc p15,0,r1,c7,c10,4;" /* drain write buffer */ \ + "mrc p15,0,r1,c1,c0,0;" \ + "orr r1,r1,#0x0007;" /* enable DCache (also ensures the */ \ + /* MMU and alignment faults are */ \ + /* enabled) */ \ + "mcr p15,0,r1,c1,c0,0;" \ + : \ + : \ + : "r1" /* Clobber list */ \ + ); \ +CYG_MACRO_END + +// Disable the data cache (and invalidate it, required semanitcs) +#define HAL_DCACHE_DISABLE() \ +CYG_MACRO_START \ + asm volatile ( \ + "mrc p15,0,r1,c1,c0,0;" \ + "bic r1,r1,#4;" \ + "mcr p15,0,r1,c1,c0,0;" \ + /* cpuwait */ \ + "mrc p15,0,r1,c2,c0,0;" /* arbitrary read */ \ + "mov r1,r1;" \ + "sub pc,pc,#4;" \ + "mcr p15,0,r1,c7,c6,0;" /* invalidate data cache */ \ + /* cpuwait */ \ + "mrc p15,0,r1,c2,c0,0;" /* arbitrary read */ \ + "mov r1,r1;" \ + "sub pc,pc,#4;" \ + : \ + : \ + : "r1" /* Clobber list */ \ + ); \ +CYG_MACRO_END + +// Invalidate the entire cache (and both TLBs, just in case) +#define HAL_DCACHE_INVALIDATE_ALL() \ +CYG_MACRO_START \ + /* this macro can discard dirty cache lines. */ \ + asm volatile ( \ + "mcr p15,0,r1,c7,c6,0;" /* invalidate data cache */ \ + "mcr p15,0,r1,c8,c7,0;" /* flush I+D TLBs */ \ + : \ + : \ + : "r1" /* Clobber list */ \ + ); \ +CYG_MACRO_END + + +// Synchronize the contents of the cache with memory. +#define HAL_DCACHE_SYNC() \ +CYG_MACRO_START \ + /* The best way to evict a dirty line is by using the */ \ + /* line allocate operation on non-existent memory. */ \ + asm volatile ( \ + "mov r0, #0xC0000000;" /* cache flush region */ \ + "add r1, r0, #0x8000;" /* 32KB cache */ \ + "667: " \ + "mcr p15,0,r0,c7,c2,5;" /* allocate a line */ \ + "add r0, r0, #32;" /* 32 bytes/line */ \ + "teq r1, r0;" \ + "bne 667b;" \ + "mcr p15,0,r0,c7,c6,0;" /* invalidate data cache */ \ + /* cpuwait */ \ + "mrc p15,0,r1,c2,c0,0;" /* arbitrary read */ \ + "mov r1,r1;" \ + "sub pc,pc,#4;" \ + "mcr p15,0,r0,c7,c10,4;" /* and drain the write buffer */ \ + /* cpuwait */ \ + "mrc p15,0,r1,c2,c0,0;" /* arbitrary read */ \ + "mov r1,r1;" \ + "sub pc,pc,#4;" \ + "nop" \ + : \ + : \ + : "r0","r1" /* Clobber list */ \ + ); \ +CYG_MACRO_END + +// Query the state of the data cache +#define HAL_DCACHE_IS_ENABLED(_state_) \ +CYG_MACRO_START \ + register int reg; \ + asm volatile ("mrc p15,0,%0,c1,c0,0" \ + : "=r"(reg) \ + : \ + /*:*/ \ + ); \ + (_state_) = (0 != (4 & reg)); /* Bit 2 is DCache enable */ \ +CYG_MACRO_END + +// 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 + +// Get the current writeback mode - or only writeback mode if fixed +#define HAL_DCACHE_QUERY_WRITE_MODE( _mode_ ) CYG_MACRO_START \ + _mode_ = HAL_DCACHE_WRITEBACK_MODE; \ +CYG_MACRO_END + +// 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. +// ---- this seems not to work despite the documentation --- +//#define HAL_DCACHE_FLUSH( _base_ , _size_ ) +//CYG_MACRO_START +// HAL_DCACHE_STORE( _base_ , _size_ ); +// HAL_DCACHE_INVALIDATE( _base_ , _size_ ); +//CYG_MACRO_END + +// Invalidate cache lines in the given range without writing to memory. +// ---- this seems not to work despite the documentation --- +//#define HAL_DCACHE_INVALIDATE( _base_ , _size_ ) +//CYG_MACRO_START +// register int addr, enda; +// for ( addr = (~(HAL_DCACHE_LINE_SIZE - 1)) & (int)(_base_), +// enda = (int)(_base_) + (_size_); +// addr < enda ; +// addr += HAL_DCACHE_LINE_SIZE ) +// { +// asm volatile ( +// "mcr p15,0,%0,c7,c6,1;" /* flush entry away */ +// : +// : "r"(addr) +// : "memory" +// ); +// } +//CYG_MACRO_END + +// Write dirty cache lines to memory for the given address range. +// ---- this seems not to work despite the documentation --- +//#define HAL_DCACHE_STORE( _base_ , _size_ ) +//CYG_MACRO_START +// register int addr, enda; +// for ( addr = (~(HAL_DCACHE_LINE_SIZE - 1)) & (int)(_base_), +// enda = (int)(_base_) + (_size_); +// addr < enda ; +// addr += HAL_DCACHE_LINE_SIZE ) +// { +// asm volatile ("mcr p15,0,%0,c7,c10,1" /* push entry to RAM */ +// : +// : "r"(addr) +// : "memory" +// ); +// } +//CYG_MACRO_END + + +// 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() \ +CYG_MACRO_START \ + asm volatile ( \ + "mrc p15,0,r1,c1,c0,0;" \ + "orr r1,r1,#0x1000;" /* enable ICache */ \ + "mcr p15,0,r1,c1,c0,0;" \ + : \ + : \ + : "r1" /* Clobber list */ \ + ); \ +CYG_MACRO_END + +// Disable the instruction cache (and invalidate it, required semanitcs) +#define HAL_ICACHE_DISABLE() \ +CYG_MACRO_START \ + asm volatile ( \ + "mrc p15,0,r1,c1,c0,0;" \ + "bic r1,r1,#0x1000;" /* disable Icache */ \ + "mcr p15,0,r1,c1,c0,0;" \ + "mcr p15,0,r1,c7,c5,0;" /* invalidate instruction cache */ \ + "nop;" /* next few instructions may be via cache */ \ + "nop;" \ + "nop;" \ + "nop;" \ + "nop;" \ + "nop" \ + : \ + : \ + : "r1" /* Clobber list */ \ + ); \ +CYG_MACRO_END + +// Invalidate the entire cache +#define HAL_ICACHE_INVALIDATE_ALL() \ +CYG_MACRO_START \ + asm volatile ( \ + "mcr p15,0,r1,c7,c5,0;" /* clear instruction cache */ \ + "mcr p15,0,r1,c8,c5,0;" /* flush I TLB only */ \ + /* cpuwait */ \ + "mrc p15,0,r1,c2,c0,0;" /* arbitrary read */ \ + "mov r1,r1;" \ + "sub pc,pc,#4;" \ + "nop;" /* next few instructions may be via cache */ \ + "nop;" \ + "nop;" \ + "nop;" \ + "nop;" \ + "nop" \ + : \ + : \ + : "r1" /* Clobber list */ \ + ); \ +CYG_MACRO_END + + +// Synchronize the contents of the cache with memory. +// (which includes flushing out pending writes) +#define HAL_ICACHE_SYNC() \ +CYG_MACRO_START \ + HAL_DCACHE_SYNC(); /* ensure data gets to RAM */ \ + HAL_ICACHE_INVALIDATE_ALL(); /* forget all we know */ \ +CYG_MACRO_END + +// Query the state of the instruction cache +#define HAL_ICACHE_IS_ENABLED(_state_) \ +CYG_MACRO_START \ + /* SA-110 manual states clearly that the control reg is readable */ \ + register cyg_uint32 reg; \ + asm volatile ("mrc p15,0,%0,c1,c0,0" \ + : "=r"(reg) \ + : \ + /*:*/ \ + ); \ + (_state_) = (0 != (0x1000 & reg)); /* Bit 12 is ICache enable */ \ +CYG_MACRO_END + +// 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/iq80310/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): nickg, gthomas +// Contributors: nickg, gthomas +// Date: 1998-09-11 +// 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_) + +// Not the best place for this, but ... +extern void hal_delay_us(cyg_uint32 usecs); + +#define HAL_DELAY_US(n) hal_delay_us(n); + +#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 + +/*---------------------------------------------------------------------------*/ +/* end of hal_diag.h */ +#endif /* CYGONCE_HAL_DIAG_H */
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/include/hal_iq80310.h @@ -0,0 +1,577 @@ +#ifndef CYGONCE_HAL_IQ80310_H +#define CYGONCE_HAL_IQ80310_H + +/*============================================================================= +// +// hal_iq80310.h +// +// HAL Description of SA-110 and 21285 control registers +// and ARM memory control in general. +// +//============================================================================= +//####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): msalter +// Contributors: msalter +// Date: 2000-10-10 +// Purpose: Intel IQ80310 hardware description +// Description: +// Usage: #include <cyg/hal/hal_iq80310.h> +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +// Addresses of the left and right 7-segment display +#define DISPLAY_LEFT 0xFE840000 +#define DISPLAY_RIGHT 0xFE850000 + +// 7-segment encodings for the hex display +#define DISPLAY_0 0xc0 +#define DISPLAY_1 0xf9 +#define DISPLAY_2 0xa4 +#define DISPLAY_3 0xb0 +#define DISPLAY_4 0x99 +#define DISPLAY_5 0x92 +#define DISPLAY_6 0x82 +#define DISPLAY_7 0xF8 +#define DISPLAY_8 0x80 +#define DISPLAY_9 0x90 +#define DISPLAY_A 0x88 +#define DISPLAY_B 0x83 +#define DISPLAY_C 0xa7 +#define DISPLAY_D 0xa1 +#define DISPLAY_E 0x86 +#define DISPLAY_F 0x8e + +/* Backplane Detect Register */ +#define BACKPLANE_DET_REG ((volatile unsigned char *)0xfe870000) +# define BP_HOST_BIT 0x1 +#define iq80310_is_host() (*BACKPLANE_DET_REG & BP_HOST_BIT) + +// XINT3 mask register +#define X3ISR_REG ((volatile unsigned char *)0xfe820000) +#define X3MASK_REG ((volatile unsigned char *)0xfe860000) +# define XINT3_TIMER 0x01 +# define XINT3_ETHERNET 0x02 +# define XINT3_UART_1 0x04 +# define XINT3_UART_2 0x08 +# define XINT3_PCI_INTD 0x10 + +/* PAL-based external timer definitions */ +#define TIMER_LA0_REG_ADDR ((volatile unsigned char *)0xfe880000) +#define TIMER_LA1_REG_ADDR ((volatile unsigned char *)0xfe890000) +#define TIMER_LA2_REG_ADDR ((volatile unsigned char *)0xfe8a0000) +#define TIMER_LA3_REG_ADDR ((volatile unsigned char *)0xfe8b0000) +#define TIMER_ENABLE_REG_ADDR ((volatile unsigned char *)0xfe8c0000) + +#define TIMER_COUNT_MASK 0x5f /* 6 bits of timer data with the MSB in bit 6 not bit 5 */ +#define TIMER_CNT_ENAB 0x1 +#define TIMER_INT_ENAB 0x2 +#define EXT_TIMER_CLK_FREQ 33000000 /* external timer runs at 33 MHz */ +#define TICKS_10MSEC 100 /* 10msec = 100 ticks/sec */ +#define EXT_TIMER_10MSEC_COUNT (EXT_TIMER_CLK_FREQ / TICKS_10MSEC) +#define TICKS_5MSEC 200 /* 5msec = 200 ticks/sec */ +#define EXT_TIMER_5MSEC_COUNT (EXT_TIMER_CLK_FREQ / TICKS_5MSEC) + +#define EXT_TIMER_CNT_ENAB() (*TIMER_ENABLE_REG_ADDR |= TIMER_CNT_ENAB) +#define EXT_TIMER_CNT_DISAB() (*TIMER_ENABLE_REG_ADDR &= ~TIMER_CNT_ENAB) +#define EXT_TIMER_INT_ENAB() (*TIMER_ENABLE_REG_ADDR |= TIMER_INT_ENAB) +#define EXT_TIMER_INT_DISAB() (*TIMER_ENABLE_REG_ADDR &= ~TIMER_INT_ENAB) + +// Companion chip MCU registers +#define MMR_BASE 0x00001500 +#define SDIR_OFF 0x00000000 +#define SDCR_OFF 0x00000004 +#define SDBR_OFF 0x00000008 +#define SBR0_OFF 0x0000000C +#define SBR1_OFF 0x00000010 +#define ECCR_OFF 0x00000034 +#define FEBR1_OFF 0x00000050 +#define FBSR1_OFF 0x00000058 +#define FWSR0_OFF 0x0000005C +#define FWSR1_OFF 0x00000060 +#define RFR_OFF 0x00000068 + +// MCU Register Values +#define MRS_CAS_LAT_2 0x00000000 +#define MRS_CAS_LAT_3 0x00000001 +#define MRS_PRECHRG 0x00000002 +#define MRS_NO_OP 0x00000003 +#define MRS_AUTO_RFRSH 0x00000004 +#define MRS_NORM_OP 0x00000006 +#define MRS_NOP_DELAY 0x00004000 +#define SDCR_INIT_VAL 0x00000aa0 // was 0x14 +#define SBR0_INIT_VAL 0x00000008 // 32 Meg Boundary (64 mbit device) +#define SBR1_INIT_VAL 0x00000008 // 32 Meg Boundary (64 mbit device) +#define ECCR_INIT_VAL 0x0000000C // ECC enabled, correction on and no reporting +#define RFR_INIT_VAL 0x00000600 // Initial Refresh Rate +#define FBSR1_INIT_VAL 0x00000040 // 8MB Bank Size +#define FWSR0_INIT_VAL 0x00000001 // 1ws add-data (needed for PP state machine), 0ws recovery +#define FWSR1_INIT_VAL 0x00000000 // 0ws add-data, 0ws recovery + + +/************************** + * I2C Bus Interface Unit * + **************************/ + +/* Processor I2C Device ID */ +#define I2C_DEVID 0x02 /* I2C slave address to which the unit responds when in slave-receive mode */ + +/* Timeout limit for SDRAM EEPROM to respond */ +#define I2C_TIMOUT 0x1000000 /* bumped this way up...used to be 0x100000*/ + +/* Control Register */ +#define ICR_ADDR 0x00001680 /* Address */ +#define ICR_START 0x0001 /* 1:send a Start condition to the I2C when in master mode */ +#define ICR_STOP 0x0002 /* 1:send a Stop condition after next data byte transferred on I2C bus in master mode */ +#define ICR_ACK 0x0004 /* Ack/Nack control: 1:Nack, 0:Ack (negative or positive pulse) */ +#define ICR_TRANSFER 0x0008 /* 1:send/receive byte, 0:cleared by I2C unit when done */ +#define ICR_ABORT 0x0010 /* 1:I2C sends STOP w/out data permission, 0:ICR bit used only */ +#define ICR_SCLENB 0x0020 /* I2C clock output: 1:Enabled, 0:Disabled. ICCR configured before ! */ +#define ICR_ENB 0x0040 /* I2C unit: 1:Enabled, 0:Disabled */ +#define ICR_GCALL 0x0080 /* General Call: 1:Disabled, 0:Enabled */ +#define ICR_IEMPTY 0x0100 /* 1: IDBR Transmit Empty Interrupt Enable */ +#define ICR_IFULL 0x0200 /* 1: IDBR Receive Full Interrupt Enable */ +#define ICR_IERR 0x0400 /* 1: Bus Error Interrupt Enable */ +#define ICR_ISTOP 0x0800 /* 1: Slave Stop Detected Interrupt Enable */ +#define ICR_IARB 0x1000 /* 1: Arbitration Loss Detected Interrupt Enable */ +#define ICR_ISADDR 0x2000 /* 1: Slave Address Detected Interrupt Enable */ +#define ICR_RESET 0x4000 /* 1: I2C unit reset */ + +/* Status Register */ +#define ISR_ADDR 0x00001684 /* Address */ +#define ISR_RWMODE 0x0001 /* 1: I2C in master receive = slave transmit mode */ +#define ISR_ACK 0x0002 /* 1: I2C received/sent a Nack, 0: Ack */ +#define ISR_BUSY 0x0004 /* 1: Processor's I2C unit busy */ +#define ISR_BUSBUSY 0x0008 /* 1: I2C bus busy. Processor's I2C unit not involved */ +#define ISR_STOP 0x0010 /* 1: Slave Stop detected (when in slave mode: receive or transmit) */ +#define ISR_ARB 0x0020 /* 1: Arbitration Loss Detected */ +#define ISR_EMPTY 0x0040 /* 1: Transfer finished on I2C bus. If enabled in ICR, interrupt signaled */ +#define ISR_FULL 0x0080 /* 1: IDBR received new byte from I2C bus. If ICR, interrupt signaled */ +#define ISR_GCALL 0x0100 /* 1: I2C unit received a General Call address */ +#define ISR_SADDR 0x0200 /* 1: I2C unit detected a 7-bit address matching the general call or ISAR */ +#define ISR_ERROR 0x0400 /* Bit set by unit when a Bus Error detected */ + +#define ISAR_ADDR 0x00001688 /* Address of the I2C Slave Address Register */ +#define IDBR_ADDR 0x0000168C /* Address of the I2C Data Buffer Register */ +#define IDBR_MASK 0x000000ff +#define IDBR_MODE 0x01 +#define ICCR_ADDR 0x00001690 /* Address of the I2C Clock Control Register */ +#define IBMR_ADDR 0x00001694 /* Address of the I2C Bus Monitor Register */ + +/* SDRAM configuration */ + +/* SDRAM bank size values (SPD << 2) */ +#define RAM_0MEG +#define RAM_4MEG 4 +#define RAM_8MEG 8 +#define RAM_16MEG 16 +#define RAM_32MEG 32 +#define RAM_64MEG 64 +#define RAM_128MEG 128 +#define RAM_256MEG 256 + +/* SBR register definitions (valid bits are [7:3])*/ +#define SBR_32MEG 0x08 +#define SBR_64MEG 0x10 +#define SBR_128MEG 0x20 +#define SBR_256MEG 0x40 + +/* Drive Strengths - assume single DIMM configuration */ +#define SDCR_1BANK_X16 0x0aa0 +#define SDCR_2BANK_X16 0x12c8 +#define SDCR_1BANK_X8 0x1520 +#define SDCR_2BANK_X8 0x1548 + +/* SDRAM PD bytes */ +#define BANKCNT_BYTE 0x06 /* Byte #5 of SPD: number of module banks */ +#define SDRAM_WIDTH_BYTE 0x0e /* Byte #13 of SPD: DRAM width */ +#define BANKSZ_BYTE 0x20 /* Byte #31 of SPD: module bank density */ +#define CHECKSUM_BYTE 0x40 /* Byte #63 of SPD: checksum for bytes 0-62 */ +#define CONFIG_BYTE 0x0C /* Byte #11 of SPD: DIMM configuration type (Parity or not, EEC) */ + +#define SDRAM_DEVID 0xA2 /* SDRAM Device ID */ + +// Yavapai PCI and Peripheral Interrupt Unit +/*** Yavapai Registers ***/ + +/* PCI-to-PCI Bridge Unit 0000 1000H through 0000 10FFH */ +#define VIDR_ADDR 0x00001000 +#define DIDR_ADDR 0x00001002 +#define PCR_ADDR 0x00001004 +#define PSR_ADDR 0x00001006 +#define RIDR_ADDR 0x00001008 +#define CCR_ADDR 0x00001009 +#define CLSR_ADDR 0x0000100C +#define PLTR_ADDR 0x0000100D +#define HTR_ADDR 0x0000100E +/* Reserved 0x0000100F through 0x00001017 */ +#define PBNR_ADDR 0x00001018 +#define SBNR_ADDR 0x00001019 +#define SUBBNR_ADDR 0x0000101A +#define SLTR_ADDR 0x0000101B +#define IOBR_ADDR 0x0000101C +#define IOLR_ADDR 0x0000101D +#define SSR_ADDR 0x0000101E +#define MBR_ADDR 0x00001020 +#define MLR_ADDR 0x00001022 +#define PMBR_ADDR 0x00001024 +#define PMLR_ADDR 0x00001026 +/* Reserved 0x00001028 through 0x00001033 */ +#define BSVIR_ADDR 0x00001034 +#define BSIR_ADDR 0x00001036 +/* Reserved 0x00001038 through 0x0000103D */ +#define BCR_ADDR 0x0000103E +#define EBCR_ADDR 0x00001040 +#define SISR_ADDR 0x00001042 +#define PBISR_ADDR 0x00001044 +#define SBISR_ADDR 0x00001048 +#define SACR_ADDR 0x0000104C +#define PIRSR_ADDR 0x00001050 +#define SIOBR_ADDR 0x00001054 +#define SIOLR_ADDR 0x00001055 +#define SCCR_ADDR 0x00001056 /* EAS inconsistent */ +#define SMBR_ADDR 0x00001058 +#define SMLR_ADDR 0x0000105A +#define SDER_ADDR 0x0000105C +#define QCR_ADDR 0x0000105E +#define CDTR_ADDR 0x00001060 /* EAS inconsistent */ +/* Reserved 0x00001064 through 0x000010FFH */ + +/* Performance Monitoring Unit 0000 1100H through 0000 11FFH */ +#define GTMR_ADDR 0x00001100 +#define ESR_ADDR 0x00001104 +#define EMISR_ADDR 0x00001108 +/* Reserved 0x0000110C */ /* EAS inconsistent */ +#define GTSR_ADDR 0x00001110 /* EAS inconsistent */ +#define PECR1_ADDR 0x00001114 /* EAS inconsistent */ +#define PECR2_ADDR 0x00001118 /* EAS inconsistent */ +#define PECR3_ADDR 0x0000111C /* EAS inconsistent */ +#define PECR4_ADDR 0x00001120 /* EAS inconsistent */ +#define PECR5_ADDR 0x00001124 /* EAS inconsistent */ +#define PECR6_ADDR 0x00001128 /* EAS inconsistent */ +#define PECR7_ADDR 0x0000112C /* EAS inconsistent */ +#define PECR8_ADDR 0x00001130 /* EAS inconsistent */ +#define PECR9_ADDR 0x00001134 /* EAS inconsistent */ +#define PECR10_ADDR 0x00001138 /* EAS inconsistent */ +#define PECR11_ADDR 0x0000113C /* EAS inconsistent */ +#define PECR12_ADDR 0x00001140 /* EAS inconsistent */ +#define PECR13_ADDR 0x00001144 /* EAS inconsistent */ +#define PECR14_ADDR 0x00001148 /* EAS inconsistent */ +/* Reserved 0x0000104C through 0x000011FFH */ /* EAS inconsistent */ + +/* Address Translation Unit 0000 1200H through 0000 12FFH */ +#define ATUVID_ADDR 0x00001200 +#define ATUDID_ADDR 0x00001202 +#define PATUCMD_ADDR 0x00001204 +#define PATUSR_ADDR 0x00001206 +#define ATURID_ADDR 0x00001208 +#define ATUCCR_ADDR 0x00001209 +#define ATUCLSR_ADDR 0x0000120C +#define ATULT_ADDR 0x0000120D +#define ATUHTR_ADDR 0x0000120E +#define ATUBISTR_ADDR 0x0000120F +#define PIABAR_ADDR 0x00001210 +/* Reserved 0x00001214 through 0x0000122B */ +#define ASVIR_ADDR 0x0000122C +#define ASIR_ADDR 0x0000122E +#define ERBAR_ADDR 0x00001230 +/* Reserved 0x00001234 */ +/* Reserved 0x00001238 */ +#define ATUILR_ADDR 0x0000123C +#define ATUIPR_ADDR 0x0000123D +#define ATUMGNT_ADDR 0x0000123E +#define ATUMLAT_ADDR 0x0000123F +#define PIALR_ADDR 0x00001240 +#define PIATVR_ADDR 0x00001244 +#define SIABAR_ADDR 0x00001248 +#define SIALR_ADDR 0x0000124C +#define SIATVR_ADDR 0x00001250 +#define POMWVR_ADDR 0x00001254 +/* Reserved 0x00001258 */ +#define POIOWVR_ADDR 0x0000125C +#define PODWVR_ADDR 0x00001260 +#define POUDR_ADDR 0x00001264 +#define SOMWVR_ADDR 0x00001268 +#define SOIOWVR_ADDR 0x0000126C +/* Reserved 0x00001270 */ +#define ERLR_ADDR 0x00001274 +#define ERTVR_ADDR 0x00001278 +/* Reserved 0x0000127C */ +/* Reserved 0x00001280 */ +/* Reserved 0x00001284 */ +#define ATUCR_ADDR 0x00001288 +/* Reserved 0x0000128C */ +#define PATUISR_ADDR 0x00001290 +#define SATUISR_ADDR 0x00001294 +#define SATUCMD_ADDR 0x00001298 +#define SATUSR_ADDR 0x0000129A +#define SODWVR_ADDR 0x0000129C +#define SOUDR_ADDR 0x000012A0 +#define POCCAR_ADDR 0x000012A4 +#define SOCCAR_ADDR 0x000012A8 +#define POCCDR_ADDR 0x000012AC +#define SOCCDR_ADDR 0x000012B0 +#define PAQCR_ADDR 0x000012B4 +#define SAQCR_ADDR 0x000012B8 +#define PAIMR_ADDR 0x000012BC +#define SAIMR_ADDR 0x000012C0 +/* Reserved 0x000012C4 through 0x000012FF */ + +/* Messaging Unit 0000 1300H through 0000 130FH */ +#define IMR0_ADDR 0x00001310 +#define IMR1_ADDR 0x00001314 +#define OMR0_ADDR 0x00001318 +#define OMR1_ADDR 0x0000131C +#define IDR_ADDR 0x00001320 +#define IISR_ADDR 0x00001324 +#define IIMR_ADDR 0x00001328 +#define ODR_ADDR 0x0000132C +#define OISR_ADDR 0x00001330 +#define OIMR_ADDR 0x00001334 +/* Reserved 0x00001338 through 0x0000134F */ +#define MUCR_ADDR 0x00001350 +#define QBAR_ADDR 0x00001354 +/* Reserved 0x00001358 */ +/* Reserved 0x0000135C */ +#define IFHPR_ADDR 0x00001360 +#define IFTPR_ADDR 0x00001364 +#define IPHPR_ADDR 0x00001368 +#define IPTPR_ADDR 0x0000136C +#define OFHPR_ADDR 0x00001370 +#define OFTPR_ADDR 0x00001374 +#define OPHPR_ADDR 0x00001378 +#define OPTPR_ADDR 0x0000137C +#define IAR_ADDR 0x00001380 +/* Reserved 0x00001384 through 0x000013FF */ + +/* DMA Controller 0000 1400H through 0000 14FFH */ +#define CCR0_ADDR 0x00001400 +#define CSR0_ADDR 0x00001404 +/* Reserved 0x00001408 */ +#define DAR0_ADDR 0x0000140C +#define NDAR0_ADDR 0x00001410 +#define PADR0_ADDR 0x00001414 +#define PUADR0_ADDR 0x00001418 +#define LADR0_ADDR 0x0000141C +#define BCR0_ADDR 0x00001420 +#define DCR0_ADDR 0x00001424 +/* Reserved 0x00001428 through 0x0000143F */ +#define CCR1_ADDR 0x00001440 +#define CSR1_ADDR 0x00001444 +/* Reserved 0x00001448 */ +#define DAR1_ADDR 0x0000144C +#define NDAR1_ADDR 0x00001450 +#define PADR1_ADDR 0x00001454 +#define PUADR1_ADDR 0x00001458 +#define LADR1_ADDR 0x0000145C +#define BCR1_ADDR 0x00001460 +#define DCR1_ADDR 0x00001464 +/* Reserved 0x00001468 through 0x0000147F */ +#define CCR2_ADDR 0x00001480 +#define CSR2_ADDR 0x00001484 +/* Reserved 0x00001488 */ +#define DAR2_ADDR 0x0000148C +#define NDAR2_ADDR 0x00001490 +#define PADR2_ADDR 0x00001494 +#define PUADR2_ADDR 0x00001498 +#define LADR2_ADDR 0x0000149C +#define BCR2_ADDR 0x000014A0 +#define DCR2_ADDR 0x000014A4 +/* Reserved 0x000014A8 through 0x000014FF */ + +/* Memory Controller 0000 1500H through 0000 15FFH */ +#define SDIR_ADDR 0x00001500 +#define SDCR_ADDR 0x00001504 +#define SDBR_ADDR 0x00001508 +#define SBR0_ADDR 0x0000150C +#define SBR1_ADDR 0x00001510 +#define SDPR0_ADDR 0x00001514 +#define SDPR1_ADDR 0x00001518 +#define SDPR2_ADDR 0x0000151C +#define SDPR3_ADDR 0x00001520 +#define SDPR4_ADDR 0x00001524 +#define SDPR5_ADDR 0x00001528 +#define SDPR6_ADDR 0x0000152C +#define SDPR7_ADDR 0x00001530 +#define ECCR_ADDR 0x00001534 +#define ELOG0_ADDR 0x00001538 +#define ELOG1_ADDR 0x0000153C +#define ECAR0_ADDR 0x00001540 +#define ECAR1_ADDR 0x00001544 +#define ECTST_ADDR 0x00001548 +#define FEBR0_ADDR 0x0000154C +#define FEBR1_ADDR 0x00001550 +#define FBSR0_ADDR 0x00001554 +#define FBSR1_ADDR 0x00001558 +#define FWSR0_ADDR 0x0000155C +#define FWSR1_ADDR 0x00001560 +#define MCISR_ADDR 0x00001564 +#define RFR_ADDR 0x00001568 +/* Reserved 0x0000156C through 0x000015FF */ + +/* Arbitration Control Unit 0000 1600H through 0000 167FH */ +#define IACR_ADDR 0x00001600 +#define MLTR_ADDR 0x00001604 +#define MTTR_ADDR 0x00001608 +/* Reserved 0x0000160C through 0x0000163F */ + +/* Bus Interface Control Unit 0000 1640H through 0000 167FH */ +#define BIUCR_ADDR 0x00001640 +#define BIUISR_ADDR 0x00001644 +/* Reserved 0x00001648 through 0x0000167F */ + +/* I2C Bus Interface Unit 0000 1680H through 0000 16FFH */ +#define ICR_ADDR 0x00001680 +#define ISR_ADDR 0x00001684 +#define ISAR_ADDR 0x00001688 +#define IDBR_ADDR 0x0000168C +#define ICCR_ADDR 0x00001690 +#define IBMR_ADDR 0x00001694 +/* Reserved 0x00001698 through 0x000016FF */ + +/* PCI And Peripheral Interrupt Controller 0000 1700H through 0000 17FFH */ +#define NISR_ADDR 0x00001700 +#define X7ISR_ADDR 0x00001704 +#define X6ISR_ADDR 0x00001708 +#define PDIDR_ADDR 0x00001710 /* EAS inconsistent */ +/* Reserved 0x00001714 through 0x0000177F */ + +/* Application Accelerator Unit 0000 1800H through 0000 18FFH */ +#define ACR_ADDR 0x00001800 +#define ASR_ADDR 0x00001804 +#define ADAR_ADDR 0x00001808 +#define ANDAR_ADDR 0x0000180C +#define SAR1_ADDR 0x00001810 +#define SAR2_ADDR 0x00001814 +#define SAR3_ADDR 0x00001818 +#define SAR4_ADDR 0x0000181C +#define DAR_ADDR 0x00001820 +#define ABCR_ADDR 0x00001824 +#define ADCR_ADDR 0x00001828 +#define SAR5_ADDR 0x0000182C +#define SAR6_ADDR 0x00001830 +#define SAR7_ADDR 0x00001834 +#define SAR8_ADDR 0x00001838 + +/* Reserved 0x0000183C through 0x000018FF */ + +#define X6ISR_REG ((cyg_uint32 *)X6ISR_ADDR) +# define X6ISR_DIP0 0x01 +# define X6ISR_DIP1 0x02 +# define X6ISR_DIP2 0x04 +# define X6ISR_EMIP 0x10 +# define X6ISR_AAIP 0x20 + +#define X7ISR_REG ((cyg_uint32 *)X7ISR_ADDR) +# define X7ISR_ISQC 0x02 +# define X7ISR_INDB 0x04 +# define X7ISR_BIST 0x08 + +#define NISR_REG ((cyg_uint32 *)NISR_ADDR) +# define NISR_MCU 0x01 +# define NISR_PATU 0x02 +# define NISR_SATU 0x04 +# define NISR_PBDG 0x08 +# define NISR_SBDG 0x10 +# define NISR_DMA0 0x20 +# define NISR_DMA1 0x40 +# define NISR_DMA2 0x80 +# define NISR_MU 0x100 +# define NISR_AAU 0x400 +# define NISR_BIU 0x800 + +#define PIRSR_REG ((cyg_uint32 *)PIRSR_ADDR) +#define IISR_REG ((cyg_uint32 *)IISR_ADDR) +#define IIMR_REG ((cyg_uint32 *)IIMR_ADDR) +#define OISR_REG ((cyg_uint32 *)OISR_ADDR) +#define OIMR_REG ((cyg_uint32 *)OIMR_ADDR) +#define EMISR_REG ((cyg_uint32 *)EMISR_ADDR) +#define ISR_REG ((cyg_uint32 *)ISR_ADDR) +#define GTMR_REG ((cyg_uint32 *)GTMR_ADDR) +#define ESR_REG ((cyg_uint32 *)ESR_ADDR) +#define ADCR_REG ((cyg_uint32 *)ADCR_ADDR) +#define ICR_REG ((cyg_uint32 *)ICR_ADDR) +#define ATUCR_REG ((cyg_uint32 *)ATUCR_ADDR) + +#define DCR0_REG ((cyg_uint32 *)DCR0_ADDR) +#define DCR1_REG ((cyg_uint32 *)DCR1_ADDR) +#define DCR2_REG ((cyg_uint32 *)DCR2_ADDR) + +#define ECCR_REG ((cyg_uint32 *)ECCR_ADDR) +#define MCISR_REG ((cyg_uint32 *)MCISR_ADDR) +#define ELOG0_REG ((cyg_uint32 *)ELOG0_ADDR) +#define ELOG1_REG ((cyg_uint32 *)ELOG1_ADDR) +#define ECAR0_REG ((cyg_uint32 *)ECAR0_ADDR) +#define ECAR1_REG ((cyg_uint32 *)ECAR1_ADDR) + +#define PATUISR_REG ((cyg_uint32 *)PATUISR_ADDR) +#define SATUISR_REG ((cyg_uint32 *)SATUISR_ADDR) +#define PBISR_REG ((cyg_uint32 *)PBISR_ADDR) +#define SBISR_REG ((cyg_uint32 *)SBISR_ADDR) +#define CSR0_REG ((cyg_uint32 *)CSR0_ADDR) +#define CSR1_REG ((cyg_uint32 *)CSR1_ADDR) +#define CSR2_REG ((cyg_uint32 *)CSR2_ADDR) +#define IISR_REG ((cyg_uint32 *)IISR_ADDR) +#define ASR_REG ((cyg_uint32 *)ASR_ADDR) +#define BIUISR_REG ((cyg_uint32 *)BIUISR_ADDR) + +#define PATUSR_REG ((cyg_uint32 *)PATUSR_ADDR) +#define SATUSR_REG ((cyg_uint32 *)SATUSR_ADDR) +#define PSR_REG ((cyg_uint32 *)PSR_ADDR) +#define SSR_REG ((cyg_uint32 *)SSR_ADDR) + + +#define MEMBASE_DRAM 0xa0000000 + +/* primary PCI bus definitions */ +#define PRIMARY_BUS_NUM 0 +#define PRIMARY_MEM_BASE 0x80000000 +#define PRIMARY_DAC_BASE 0x84000000 +#define PRIMARY_IO_BASE 0x90000000 +#define PRIMARY_MEM_LIMIT 0x83ffffff +#define PRIMARY_DAC_LIMIT 0x87ffffff +#define PRIMARY_IO_LIMIT 0x9000ffff + +/* secondary PCI bus definitions */ +#define SECONDARY_BUS_NUM 1 +#define SECONDARY_MEM_BASE 0x88000000 +#define SECONDARY_DAC_BASE 0x8c000000 +#define SECONDARY_IO_BASE 0x90010000 +#define SECONDARY_MEM_LIMIT 0x8bffffff +#define SECONDARY_DAC_LIMIT 0x8fffffff +#define SECONDARY_IO_LIMIT 0x9001ffff + +#ifndef __ASSEMBLER__ +extern unsigned int _80312_EMISR; // Only valid for PEC ISR +#endif + + +/*---------------------------------------------------------------------------*/ +/* end of hal_iq80310.h */ +#endif /* CYGONCE_HAL_IQ80310_H */
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/include/hal_platform_ints.h @@ -0,0 +1,140 @@ +#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): msalter +// Contributors: +// Date: 2000-10-10 +// Purpose: Define Interrupt support +// Description: The interrupt details for the IQ80310 are defined here. +// Usage: +// #include <cyg/hal/hal_platform_ints.h> +// ... +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +// *** 80200 CPU *** +#define CYGNUM_HAL_INTERRUPT_reserved0 0 +#define CYGNUM_HAL_INTERRUPT_PMU_PMN0_OVFL 1 // See Ch.12 - Performance Mon. +#define CYGNUM_HAL_INTERRUPT_PMU_PMN1_OVFL 2 // PMU counter 0/1 overflow +#define CYGNUM_HAL_INTERRUPT_PMU_CCNT_OVFL 3 // PMU clock overflow +#define CYGNUM_HAL_INTERRUPT_BCU_INTERRUPT 4 // See Ch.11 - Bus Control Unit +#define CYGNUM_HAL_INTERRUPT_NIRQ 5 // external IRQ +#define CYGNUM_HAL_INTERRUPT_NFIQ 6 // external FIQ + +// *** XINT6 interrupts *** +#define CYGNUM_HAL_INTERRUPT_DMA_0 7 +#define CYGNUM_HAL_INTERRUPT_DMA_1 8 +#define CYGNUM_HAL_INTERRUPT_DMA_2 9 +#define CYGNUM_HAL_INTERRUPT_GTSC 10 // Global Time Stamp Counter +#define CYGNUM_HAL_INTERRUPT_PEC 11 // Performance Event Counter +#define CYGNUM_HAL_INTERRUPT_AAIP 12 // application accelerator unit + +// *** XINT7 interrupts *** +// I2C interrupts +#define CYGNUM_HAL_INTERRUPT_I2C_TX_EMPTY 13 +#define CYGNUM_HAL_INTERRUPT_I2C_RX_FULL 14 +#define CYGNUM_HAL_INTERRUPT_I2C_BUS_ERR 15 +#define CYGNUM_HAL_INTERRUPT_I2C_STOP 16 +#define CYGNUM_HAL_INTERRUPT_I2C_LOSS 17 +#define CYGNUM_HAL_INTERRUPT_I2C_ADDRESS 18 +// Messaging Unit interrupts +#define CYGNUM_HAL_INTERRUPT_MESSAGE_0 19 +#define CYGNUM_HAL_INTERRUPT_MESSAGE_1 20 +#define CYGNUM_HAL_INTERRUPT_DOORBELL 21 +#define CYGNUM_HAL_INTERRUPT_NMI_DOORBELL 22 // FIQ +#define CYGNUM_HAL_INTERRUPT_QUEUE_POST 23 +#define CYGNUM_HAL_INTERRUPT_OUTBOUND_QUEUE_FULL 24 // FIQ +#define CYGNUM_HAL_INTERRUPT_INDEX_REGISTER 25 +// PCI Address Translation Unit +#define CYGNUM_HAL_INTERRUPT_BIST 26 + +// *** External board interrupts (XINT3) *** +#define CYGNUM_HAL_INTERRUPT_TIMER 27 // external timer +#define CYGNUM_HAL_INTERRUPT_ETHERNET 28 // onboard enet +#define CYGNUM_HAL_INTERRUPT_SERIAL_A 29 // 16x50 uart A +#define CYGNUM_HAL_INTERRUPT_SERIAL_B 30 // 16x50 uart B +#define CYGNUM_HAL_INTERRUPT_PCI_S_INTD 31 // secondary PCI INTD +// The hardware doesn't (yet?) provide masking or status for these +// even though they can trigger cpu interrupts. ISRs will need to +// poll the device to see if the device actually triggered the +// interrupt. +#define CYGNUM_HAL_INTERRUPT_PCI_S_INTC 32 // secondary PCI INTC +#define CYGNUM_HAL_INTERRUPT_PCI_S_INTB 33 // secondary PCI INTB +#define CYGNUM_HAL_INTERRUPT_PCI_S_INTA 34 // secondary PCI INTA + +// *** NMI Interrupts go to FIQ *** +#define CYGNUM_HAL_INTERRUPT_MCU_ERR 35 +#define CYGNUM_HAL_INTERRUPT_PATU_ERR 36 +#define CYGNUM_HAL_INTERRUPT_SATU_ERR 37 +#define CYGNUM_HAL_INTERRUPT_PBDG_ERR 38 +#define CYGNUM_HAL_INTERRUPT_SBDG_ERR 39 +#define CYGNUM_HAL_INTERRUPT_DMA0_ERR 40 +#define CYGNUM_HAL_INTERRUPT_DMA1_ERR 41 +#define CYGNUM_HAL_INTERRUPT_DMA2_ERR 42 +#define CYGNUM_HAL_INTERRUPT_MU_ERR 43 +#define CYGNUM_HAL_INTERRUPT_reserved52 44 +#define CYGNUM_HAL_INTERRUPT_AAU_ERR 45 +#define CYGNUM_HAL_INTERRUPT_BIU_ERR 46 + +// *** ATU FIQ sources *** +#define CYGNUM_HAL_INTERRUPT_P_SERR 47 +#define CYGNUM_HAL_INTERRUPT_S_SERR 48 + +#define CYGNUM_HAL_ISR_MIN 0 +#define CYGNUM_HAL_ISR_MAX 48 + +#define CYGNUM_HAL_ISR_COUNT (CYGNUM_HAL_ISR_MAX+1) + +// The vector used by the Real time clock +#define CYGNUM_HAL_INTERRUPT_RTC CYGNUM_HAL_INTERRUPT_TIMER +//#define CYGNUM_HAL_INTERRUPT_RTC CYGNUM_HAL_INTERRUPT_PMU_CCNT_OVFL + +extern void hal_delay_us(cyg_uint32 usecs); +#define HAL_DELAY_US(n) hal_delay_us(n); + +//---------------------------------------------------------------------------- +// Reset. +#include <cyg/hal/hal_iq80310.h> // registers +#include <cyg/hal/hal_io.h> // IO macros + +// FIXME - Can we reset the board? +#define HAL_PLATFORM_RESET() CYG_EMPTY_STATEMENT + +#define HAL_PLATFORM_RESET_ENTRY 0x00000000 + +#endif // CYGONCE_HAL_PLATFORM_INTS_H
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/include/hal_platform_setup.h @@ -0,0 +1,894 @@ +#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, 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): msalter +// Contributors: +// Date: 2000-10-10 +// Purpose: Intel IQ80310 platform specific support routines +// Description: +// Usage: #include <cyg/hal/hal_platform_setup.h> +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +#include <pkgconf/system.h> // System-wide configuration info +#include CYGBLD_HAL_PLATFORM_H // Platform specific configuration +#include <cyg/hal/hal_iq80310.h> // Platform specific hardware definitions +#include <cyg/hal/hal_mmu.h> // MMU definitions + +// Define macro used to diddle the LEDs during early initialization. +// Can use r0+r1. Argument in \x. +#define CYGHWR_LED_MACRO \ + b 667f ;\ + 666: ;\ + .byte 0xc0, 0xf9, 0xa4, 0xb0 ;\ + .byte 0x99, 0x92, 0x82, 0xf8 ;\ + .byte 0x80, 0x90, 0x88, 0x83 ;\ + .byte 0xa7, 0xa1, 0x86, 0x8e ;\ + 667: ;\ + ldr r0, =666b ;\ + add r0, r0, #\x ;\ + ldrb r1, [r0] ;\ + ldr r0, =DISPLAY_RIGHT ;\ + str r1, [r0] + + +// The main useful output of this file is PLATFORM_SETUP1: it invokes lots +// of other stuff (may depend on RAM or ROM start). The other stuff is +// divided into further macros to make it easier to manage what's enabled +// when. + +#if defined(CYG_HAL_STARTUP_ROM) +#define PLATFORM_SETUP1 _platform_setup1 +//#define CYGHWR_HAL_ARM_HAS_MMU +#else +#define PLATFORM_SETUP1 +#endif + + +#define RAM_BASE 0xa0000000 +#define DRAM_SIZE (512*1024*1024) // max size of available SDRAM +#define DCACHE_SIZE (32*1024) // size of the Dcache +#define DCACHE_FLUSH_AREA (RAM_BASE+DRAM_SIZE) // NB: needs page table support + +#define MMU_Control_BTB 0x800 + +// Reserved area for battery backup SDRAM memory test +// This area is not zeroed out by initialization code +#define SDRAM_BATTERY_TEST_BASE 0xA1FFFFF0 // base address of last 16 memory locations in a 32MB SDRAM + + + + // Display 'lvalue:rvalue' on the hex display + // lvalue and rvalue must be of the form 'DISPLAY_x' + // where 'x' is a hex digit from 0-F. + .macro HEX_DISPLAY reg0, reg1, lvalue, rvalue + ldr \reg0, =DISPLAY_LEFT // display left digit + ldr \reg1, =\lvalue + str \reg1, [\reg0] + ldr \reg0, =DISPLAY_RIGHT + ldr \reg1, =\rvalue // display right digit + str \reg1, [\reg0] + .endm + + // Trigger the logic analyzer by writing a particular + // address, and triggering on that address. + .macro TRIGGER_LA_ON_ADDRESS address, reg0, reg1 + mrc p15, 0, \reg0, c1, c0, 0 // read ARM control register + // CPWAIT \reg0 + ldr \reg1, =\address + str \reg0, [\reg1] + .endm + + // Delay a bit + .macro DELAY_FOR cycles, reg0 + ldr \reg0, =\cycles + subs \reg0, \reg0, #1 + subne pc, pc, #0xc + .endm + + // wait for coprocessor write complete + .macro CPWAIT reg + mrc p15,0,\reg,c2,c0,0 + mov \reg,\reg + sub pc,pc,#4 + .endm + + // form a first-level section entry + .macro FL_SECTION_ENTRY base,x,ap,p,d,c,b + .word (\base << 20) | (\x << 12) | (\ap << 10) | (\p << 9) |\ + (\d << 5) | (\c << 3) | (\b << 2) | 2 + .endm + + // form a first-level page table entry + .macro FL_PT_ENTRY base,d + // I wanted to use logical operations here, but since I am using symbols later + // to fill in the parameters, I had to use addition to force the assembler to + // do it right + .word \base + (\d << 5) + 1 + .endm + + // form a second level small page entry + .macro SL_SMPAGE_ENTRY base,ap3,ap2,ap1,ap0,c,b + .word (\base << 12) | (\ap3 << 10) | (\ap2 << 8) | (\ap1 << 6) |\ + (\ap0 << 4) | (\c << 3) | (\b << 2) | 2 + .endm + + // form a second level extended small page entry + .macro SL_XSMPAGE_ENTRY base,x,ap,c,b + .word (\base << 12) | (\x << 6) | (\ap << 4) | (\c << 3) | (\b << 2) | 3 + .endm + + + // start of platform setup + .macro _platform_setup1 + + // This is where we wind up immediately after reset. On the IQ80310, we have + // to jump around a hole in flash which runs from 0x00001000 - 0x0001fff. + // The start of _platform_setup1 will be below 0x1000 and since we need to + // align the mmu table on a 16k boundary, we just branch around the page + // table which we will locate at FLASH_BASE+0x4000. + b _real_platform_setup + + .p2align 13 + // the following alignment creates the mmu table at address 0x4000. + mmu_table: + + // 1MB of FLASH with i80312 MMRs mapped in using 4K small pages so we can + // set the access permission on flash and memory-mapped registers properly. + FL_PT_ENTRY mmu_table_flashbase,0 + + // Remaining 7MB of FLASH + // rw, cacheable, non-bufferable + .set __base,1 + .rept 7 + FL_SECTION_ENTRY __base,0,3,0,0,1,0 + .set __base,__base+1 + .endr + + // nothing interesting here (Address Translation) + .rept 0xA00 - 0x8 + FL_SECTION_ENTRY __base,0,3,0,0,0,0 + .set __base,__base+1 + .endr + + // up to 512MB ECC SDRAM + // x=c=b=1 + // first 1MB mapped by second level table + FL_PT_ENTRY mmu_table_rambase,0 + .set __base,__base+1 + + // remainder of SDRAM mapped 1-to-1 + .rept 0xC00 - 0xA01 + FL_SECTION_ENTRY __base,1,3,1,0,1,1 + .set __base,__base+1 + .endr + + // Cache flush region. + // Don't need physical memory, just a cached area. + .rept 0xD00 - 0xC00 + FL_SECTION_ENTRY __base,0,3,0,0,1,1 + .set __base,__base+1 + .endr + + // Invalid + .rept 0xF00 - 0xD00 + .word 0 + .set __base,__base+1 + .endr + + // only I/O at 0xFE8xxxxx + .rept 0x1000 - 0xF00 + FL_SECTION_ENTRY __base,0,3,0,0,0,0 + .set __base,__base+1 + .endr + + // Immediately after the above table (at 0x8000) is the + // second level page table which breaks up the lowest 1MB + // of physical memory into 4KB sized virtual pages. These + // pages work around a hole in flash (0x1000-0x1fff) used + // by the Yavapai companion chip internal registers. + mmu_table_flashbase: + // Virtual address 0 (Flash boot code). + // Map 4k page at 0x00000000 virt --> 0xA0000000 physical + // This allows us to have a writable vector table. + // Read-Write, cacheable, bufferable + SL_XSMPAGE_ENTRY 0xa0000,1,3,1,1 + + // Virtual address 0x1000 (Memory mapped registers) + // Map 1-to-1, but don't cache or buffer + // Read-Write, non-cacheable, non-bufferable + .set __base,1 + SL_SMPAGE_ENTRY __base,3,3,3,3,0,0 + .set __base,__base+1 + + // Virtual address 0x2000-0x100000 (remainder of flash1) + // Read-Write, cacheable, non-bufferable + .rept 0x100 - 0x2 + SL_SMPAGE_ENTRY __base,3,3,3,3,1,0 + .set __base,__base+1 + .endr + + // Now is the second level table for the first megabyte + // of DRAM. + mmu_table_rambase: + // Map 4k page at 0xa0000000 virt --> 0x00000000 physical + // Read-Write, cacheable, non-bufferable + SL_SMPAGE_ENTRY 0x00000,3,3,3,3,1,0 + .set __base,__base+1 + + // Map remainder of first meg of SDRAM + // Read-Write, cacheable, non-bufferable + .set __base,0xA0001 + .rept 0x100 - 0x1 + SL_XSMPAGE_ENTRY __base,1,3,1,1 + .set __base,__base+1 + .endr + +_real_platform_setup: + // Drain write and fill buffer + mcr p15,0,r0,c7,c10,4 + CPWAIT r0 + + // Disable write buffer coalescing + mrc p15,0,r0,c1,c0,1 + orr r0,r0,#1 // set the disable bit + mcr p15,0,r0,c1,c0,1 + CPWAIT r0 + + // Delay appx 60 ms to let battery-backup reset complete + DELAY_FOR 0x400000, r0 + // Eventually we will be able to check a register bit + // to determine when this is complete + + HEX_DISPLAY r0, r1, DISPLAY_0, DISPLAY_1 + + // + // *** I2C interface initialization *** + // + + // Setup I2C Slave Address Register + ldr r1, =I2C_DEVID // Load slave address r1. + ldr r2, =ISAR_ADDR // Load address of the I2C Slave Address Register in r2. + ldr r3, =0x0000007f // Load mask in r3. + and r1, r3, r3 // The mask zeroes the 25 MSBs of r1 just to make sure. + str r3, [r2] // Save the value 0x02 (I2C_DEVID) in the register. + + // Setup I2C Clock Count Register + ldr r2, =ICCR_ADDR // Load the address of the I2C Clock Control Register in r2. + ldr r3, =0x0000014d // Set for 5.05 us transition time at 66MHz (0x14D = 333). + str r3, [r2] // Save the value in the register. + + // Enable I2C Interface Unit - status will be polled + ldr r2, =ICR_ADDR // Load the address of the Control Register in r2. + ldr r1, =ICR_GCALL // Disable General Call (will be master) + ldr r3, =ICR_ENB // Enable I2C unit ). + orr r1, r3, r1 // OR the two and store in R1 + ldr r3, =ICR_SCLENB // Enable I2C Clock Generator disabled + orr r1, r3, r1 // OR the two and store in R1 + str r1, [r2] // Save the value to the Control Register. + + // + // *** Now read the SPD Data *** + // + + // Pointers to I2C Registers + ldr r11, =ICR_ADDR // Load the address of the I2C Control Register in r11. + ldr r12, =ISR_ADDR // Load the address of the I2C Status Register in r12. + ldr r13, =IDBR_ADDR // Load the address of the I2C Data Buffer Register in r13. + + // Initialize byte counters + ldr r6, =0x00000000 // Counter incremented before byte is read + ldr r7, =0x00000040 // Number of bytes to read in the Presence Detect EEPROM of SDRAM: 64 bytes + ldr r5, =0x00000000 // R5 has running checksum calculation + ldr r9, =I2C_TIMOUT // Timeout limit in case EEPROM does not respond + + // At the end of all this, R4 has DRAM size, R8 has bank count, and R10 has Bank size + ldr r10,=0x00000000 // Bank size + ldr r8, =0x00000000 // Bank count + ldr r4, =0x00000000 // SDRAM size + + /* FREE REGISTERS ARE R0 - R3 */ + + // *** Put out address, with WRITE mode *** + + // Set SDRAM module address and write mode + ldr r1, =SDRAM_DEVID // Load slave address for SDRAM module: 0xA2 (Presence Detect Data) + bic r1, r1, #IDBR_MODE // Clear read bit (bit #0) + str r1, [r13] // Store to data register + + // Initiate dummy write to set EEPROM pointer to 0 + ldr r1, [r11] // read the current Control Register value + orr r1, r1, #ICR_START // Set start bit + orr r1, r1, #ICR_TRANSFER // Set transfer bit - bit is self_clearing + str r1, [r11] // Store to control register + + // Wait for transmit empty status + ldr r1, =0x00000000 // Initialize I2C timeout counter + 0: + add r1, r1, #1 // Increment I2C timeout counter (r1 = r1 + 1) + cmp r1, r9 + beq i2c_error // Kick out of SDRAM initialization if timeout occurs + ldr r0, [r12] // Load I2C Status Reg into R0 + str r2, =ISR_EMPTY // Poll status register + and r3, r2, r0 // Bit #6 is checked: IDBR Transmit Empty + cmp r3, r2 // If bit = 0 then branch to 0 and check again + bne 0b + str r0, [r12] // Write back status to clear + + // *** Write pointer register on EEPROM to 0x00000000 *** + + // Set SDRAM module EEPROM address to 0 + ldr r1, =0x00000000 // Load base address of SDRAM module EEPROM + str r1, [r13] // Store to data register + + // Send address to EEPROM + ldr r1, [r11] // read the current Control Register value + bic r1, r1, #ICR_START // No start bit (already started) + orr r1, r1, #ICR_TRANSFER // Set transfer bit - bit is self_clearing + str r1, [r11] // Store to control register + + // Wait for transmit empty status + ldr r1, =0x00000000 // Initialize I2C timeout counter + 0: + add r1, r1, #1 // Increment I2C timeout counter (r1 = r1 + 1) + cmp r1, r9 + beq i2c_error // Kick out of SDRAM initialization if timeout occurs + ldr r0, [r12] // Load I2C Status Reg into R0 - ld (r12), r10 + str r2, =ISR_EMPTY // Poll status register + and r3, r2, r0 // Bit #6 is checked: IDBR Transmit Empty + cmp r3, r2 // If bit = 0 then branch to 0 and check again (r3 = 0x00) + bne 0b + str r0, [r12] // Write back status to clear + + // *** Read SDRAM PD data *** + + // *** Put out address, with READ mode *** + + // Set SDRAM module address and read mode + ldr r0, =SDRAM_DEVID // Load slave address for SDRAM module (0xA2) + orr r1, r0, #IDBR_MODE // Set read bit (bit #0) + str r1, [r13] // Store to data register + + // Send next read request + ldr r1, [r11] // read the current Control Register value + orr r1, r1, #ICR_START // Set start bit + orr r1, r1, #ICR_TRANSFER // Set transfer bit - bit is self_clearing + str r1, [r11] // Store to control register + + // Wait for transmit empty status + ldr r1, =0x00000000 // Initialize I2C timeout counter + 0: + add r1, r1, #1 // Increment I2C timeout counter (r1 = r1 + 1) + cmp r1, r9 + beq i2c_error // Kick out of SDRAM initialization if timeout occurs + ldr r0, [r12] // Load I2C Status Reg into R0 - ld (r12), r10 + str r2, =ISR_EMPTY // Poll status register + and r3, r2, r0 // Bit #6 is checked: IDBR Transmit Empty + cmp r3, r2 // If bit = 0 then branch to 0 and check again (r3 = 0x00) + bne 0b + str r0, [r12] // Write back status to clear + + sdram_loop: + add r6, r6, #1 // Increment byte counter + + // *** READ the next Byte!!! *** + + ldr r1, [r11] // read the current Control Register value + bic r1, r1, #ICR_START // No start bit (already started) + orr r1, r1, #ICR_TRANSFER // Set transfer bit - bit is self_clearing + + // we have to set NACK before reading the last bit + cmp r6, r7 // r7 = 64 (decimal) so if r6 = 64, this is the last byte to be read + bne 1f // If bytes left, skip ahead + orr r1, r1, #ICR_ACK // Set NACK if this is the last byte + orr r1, r1, #ICR_STOP // Set STOP if this is the last byte + 1: + str r1, [r11] // Store to control register + + // Wait for read full status + ldr r1, =0x00000000 // Initialize I2C timeout counter + 0: + add r1, r1, #1 // Increment I2C timeout counter (r1 = r1 + 1) + cmp r1, r9 + beq i2c_error // Kick out of SDRAM initialization if timeout occurs + ldr r0, [r12] // Load I2C Status Reg into R0 + str r2, =ISR_FULL // Poll status register + and r3, r2, r0 // Bit #6 is checked: IDBR Transmit Empty + cmp r3, r2 // If bit = 0 then branch to 0 and check again + bne 0b + str r0, [r12] // Write back status to clear + + // Read the data byte + ldr r1, [r13] // Read the byte + + ldr r2, =CHECKSUM_BYTE + cmp r6, r2 // is it the CHECKSUM byte??? + beq 1f + add r5, r5, r1 // Add it to the checksum if not the checksum byte + bal 2f // skip checksum comparison + 1: + ldr r0, =0xff // If this is the checksum byte, compare it + and r5, r5, r0 // against the calculated checksum + cmp r1, r5 + bne bad_checksum // If no match, skip SDRAM controller initialization + 2: + ldr r2, =BANKCNT_BYTE // Check for bank count byte + cmp r6, r2 + bne 1f + mov r8, r1 // Store bank count + 1: + ldr r2, =BANKSZ_BYTE // Check for bank size byte + cmp r6, r2 + bne 1f + + ldr r2, =0x04 // Store bank size in Mbytes (shift left 2 bits) + mul r10, r1, r2 + mul r2, r8, r10 // Multiply by bank count to get DRAM size in MB + ldr r0, =0x100000 + mul r4, r2, r0 // Convert size to bytes - r4 contains DRAM size in bytes + +1: + // Handle the SDRAM drive strength setup here since we are out of + // temporary registers to hold the SDRAM width value until after + // all of the SPD data has been read. Using the value of r8 for + // the Bank Count is allright here since the SPD specification states that + // the Bank Count SPD byte is #5 and the SDRAM Width SPD byte is #13. + + ldr r2, =SDRAM_WIDTH_BYTE // Check for SDRAM width byte + cmp r6, r2 + bne 1f + mov r2, #0x10 // Check for data width of 16 + cmp r1, r2 + bne SDRAM_DRIVE_X8 + + // Module is composed of x16 devices + mov r2, #0x02 + cmp r2, r8 // do we have 2 banks??? + beq SDRAM_DRIVE_2_BANK_X16 + + // Module is composed of 1 Bank of x16 devices + ldr r1, =SDCR_ADDR // point at SDRAM Control Register + ldr r2, =SDCR_1BANK_X16 // drive strength value + str r2, [r1] // set value in SDCR + b 1f + +SDRAM_DRIVE_2_BANK_X16: + // Module is composed of 2 Banks of x16 devices + ldr r1, =SDCR_ADDR // point at SDRAM Control Register + ldr r2, =SDCR_2BANK_X16 // drive strength value + str r2, [r1] // set value in SDCR + b 1f + +SDRAM_DRIVE_X8: + // Module is composed of x8 devices + mov r2, #0x02 + cmp r2, r8 // do we have 2 banks??? + beq SDRAM_DRIVE_2_BANK_X8 + + // Module is composed of 1 Bank of x8 devices + ldr r1, =SDCR_ADDR // point at SDRAM Control Register + ldr r2, =SDCR_1BANK_X8 // drive strength value + str r2, [r1] // set value in SDCR + b 1f + +SDRAM_DRIVE_2_BANK_X8: + // Module is composed of 2 Banks of x16 devices + ldr r1, =SDCR_ADDR // point at SDRAM Control Register + ldr r2, =SDCR_2BANK_X8 // drive strength value + str r2, [r1] // set value in SDCR + 1: + + + // Continue reading bytes if not done + cmp r6, r7 + bne sdram_loop + + b i2c_disable + + bad_checksum: + HEX_DISPLAY r2, r3, DISPLAY_7, DISPLAY_7 + + i2c_error: + // hit the leds if an error occurred + HEX_DISPLAY r2, r3, DISPLAY_5, DISPLAY_5 + + + i2c_disable: + // Disable I2C Interface Unit + ldr r1, [r11] + bic r1, r1, #ICR_ENB // Disable I2C unit + bic r1, r1, #ICR_SCLENB // Disable I2C clock generator + str r1, [r11] // Store to control register + + // ADD THIS???: + // cmpobne 1, g9, test_init + // Skip SDRAM controller initialization if checksum test failed + + // *** SDRAM setup *** + + ldr r9, =MMR_BASE // get base of MMRs + ldr r0, =RAM_BASE // Program SDRAM Base Address register + str r0, [r9, #SDBR_OFF] + + // Set up bank 0 register + CHECK_32MB: + ldr r1, =RAM_32MEG // do we have 32 MB banks? + cmp r10, r1 + bne CHECK_64MB + + ldr r0, =SBR_32MEG // Program SDRAM Bank0 Boundary register to 32 MB + b SET_BANK1 + + CHECK_64MB: + ldr r1, =RAM_64MEG // do we have 64 MB banks? + cmp r10, r1 + bne CHECK_128MB + + ldr r0, =SBR_64MEG // Program SDRAM Bank0 Boundary register to 64 MB + b SET_BANK1 + + CHECK_128MB: + ldr r1, =RAM_128MEG // do we have 128 MB banks? + cmp r10, r1 + bne CHECK_256MB + + ldr r0, =SBR_128MEG // Program SDRAM Bank0 Boundary register to 128 MB + b SET_BANK1 + + CHECK_256MB: + ldr r1, =RAM_256MEG // do we have 256 MB banks? + cmp r10, r1 + bne dram_error + + ldr r0, =SBR_256MEG // Program SDRAM Bank0 Boundary register to 64 MB + b SET_BANK1 + + SET_BANK1: + str r0, [r9, #SBR0_OFF] // store SBR0 + + ldr r2, =0x02 + cmp r2, r8 // do we have 2 banks??? + bne SDRAM_1_BANK + + add r0, r0, r0 // SDRAM Bank1 Boundary register is double SBR0 + str r0, [r9, #SBR1_OFF] + b END_DRAM_SIZE + + SDRAM_1_BANK: + // SDRAM Bank1 Boundary register is same as SBR0 for 1 bank configuration + str r0, [r9, #SBR1_OFF] + b END_DRAM_SIZE + + END_DRAM_SIZE: + b init_dram + + dram_error: + + HEX_DISPLAY r2, r3, DISPLAY_F, DISPLAY_F + + init_dram: + ldr r0, =0 // turn off refresh + str r0, [r9, #RFR_OFF] + + ldr r0, =MRS_NO_OP // Issue NOP cmd to SDRAM + str r0, [r9, #SDIR_OFF] + DELAY_FOR 0x4000, r0 + + ldr r0, =MRS_PRECHRG // Issue 1 Precharge all + str r0, [r9, #SDIR_OFF] + DELAY_FOR 0x4000, r0 + + + ldr r0, =MRS_AUTO_RFRSH // Issue 1 Auto Refresh command + str r0, [r9, #SDIR_OFF] + DELAY_FOR 0x4000, r0 + + + ldr r0, =MRS_AUTO_RFRSH + str r0, [r9, #SDIR_OFF] // Auto Refresh #1 + str r0, [r9, #SDIR_OFF] // Auto Refresh #2 + str r0, [r9, #SDIR_OFF] // Auto Refresh #3 + str r0, [r9, #SDIR_OFF] // Auto Refresh #4 + str r0, [r9, #SDIR_OFF] // Auto Refresh #5 + str r0, [r9, #SDIR_OFF] // Auto Refresh #6 + str r0, [r9, #SDIR_OFF] // Auto Refresh #7 + str r0, [r9, #SDIR_OFF] // Auto Refresh #8 + + ldr r0, =MRS_CAS_LAT_2 // set the CAS latency + str r0, [r9, #SDIR_OFF] + DELAY_FOR 0x4000, r0 + + ldr r0, =MRS_NORM_OP // Issue a Normal Operation command + str r0, [r9, #SDIR_OFF] + + ldr r0, =RFR_INIT_VAL // Program Refresh Rate register + str r0, [r9, #RFR_OFF] + + // ldr r0, =(FLASH_BASE :AND: &FFFF0000) + // str r0, [r10, #FEBR1_OFF] ; Program Flash Bank1 Base Address register + + // ldr r0, =(FLASH_SIZE :AND: &FFFF0000) + // str r0, [r10, #FBSR1_OFF] ; Program Flash Bank1 Size register + + // ldr r0, =FWSR0_INIT_VAL + // str r0, [r10, #FWSR0_OFF] ; Program Flash Bank0 Wait State register + + // ldr r0, =FWSR1_INIT_VAL + // str r0, [r10, #FWSR1_OFF] ; Program Flash Bank1 Wait State register + + HEX_DISPLAY r0, r1, DISPLAY_0, DISPLAY_2 + + // begin initializing the i80310 + + // Enable access to all coprocessor registers + ldr r0, =0x2001 // enable access to all coprocessors + mcr p15, 0, r0, c15, c1, 0 + + mcr p15, 0, r0, c7, c10, 4 // drain the write & fill buffers + CPWAIT r0 + + mcr p15, 0, r0, c7, c7, 0 // flush Icache, Dcache and BTB + CPWAIT r0 + + mcr p15, 0, r0, c8, c7, 0 // flush instuction and data TLBs + CPWAIT r0 + + // Enable the Icache + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #MMU_Control_I + mcr p15, 0, r0, c1, c0, 0 + CPWAIT r0 + + // Set the TTB register + ldr r0, =mmu_table + mcr p15, 0, r0, c2, c0, 0 + + // Enable permission checks in all domains + ldr r0, =0x55555555 + mcr p15, 0, r0, c3, c0, 0 + + // Enable the MMU + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #MMU_Control_M + orr r0, r0, #MMU_Control_R + mcr p15, 0, r0, c1, c0, 0 + CPWAIT r0 + + mcr p15, 0, r0, c7, c10, 4 // drain the write & fill buffers + CPWAIT r0 + + // Enable the Dcache + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #MMU_Control_C + mcr p15, 0, r0, c1, c0, 0 + CPWAIT r0 + + // Enable the BTB + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #MMU_Control_BTB + mcr p15, 0, r0, c1, c0, 0 + CPWAIT r0 + + // Battery Backup SDRAM Memory Test + // Move 4 byte Test Pattern into register prior to zeroing out + // contents of SDRAM locations + ldr r9, =SDRAM_BATTERY_TEST_BASE + ldr r10, [r9] + + // scrub/init SDRAM if enabled/present + ldr r11, =RAM_BASE // base address of SDRAM + mov r12, r4 // size of memory to scrub + mov r8,r4 // save DRAM size + mov r0, #0 // scrub with 0x0000:0000 + mov r1, #0 + mov r2, #0 + mov r3, #0 + mov r4, #0 + mov r5, #0 + mov r6, #0 + mov r7, #0 + 10: // fastScrubLoop + subs r12, r12, #32 // 32 bytes/line + stmia r11!, {r0-r7} + beq 15f + b 10b + 15: + + // Battery Backup SDRAM Memory Test + // Store 4 byte Test Pattern back into memory + str r10, [r9, #0x0] + + HEX_DISPLAY r0, r1, DISPLAY_1, DISPLAY_0 + + // clean/drain/flush the main Dcache + mov r1, #DCACHE_FLUSH_AREA // use a CACHEABLE area of + // the memory map above SDRAM + mov r0, #1024 // number of lines in the Dcache + 20: + mcr p15, 0, r1, c7, c2, 5 // allocate a Dcache line + add r1, r1, #32 // increment the address to + // the next cache line + subs r0, r0, #1 // decrement the loop count + bne 20b + + HEX_DISPLAY r0, r1, DISPLAY_9, DISPLAY_9 + + // clean/drain/flush the mini Dcache + ldr r2, =(DCACHE_FLUSH_AREA+DCACHE_SIZE) // use a CACHEABLE area of + // the memory map above SDRAM + mov r0, #64 // number of lines in the mini Dcache + 21: + mcr p15, 0, r2, c7, c2, 5 // allocate a Dcache line + add r2, r2, #32 // increment the address to + // the next cache line + subs r0, r0, #1 // decrement the loop count + bne 21b + + mcr p15, 0, r0, c7, c6, 0 // flush Dcache + CPWAIT r0 + + HEX_DISPLAY r0, r1, DISPLAY_7, DISPLAY_7 + + mcr p15, 0, r0, c7, c10, 4 // drain the write & fill buffers + CPWAIT r0 + + // enable ECC stuff here + mcr p15, 0, r0, c7, c10, 4 // + CPWAIT r0 + + mrc p13, 0, r0, c0, c1, 0 // BCU_WAIT --> wait until the BCU isn't busy + submi pc, pc, #0xc + + checkme: // add in multi-bit error reporting */ + mrc p13, 0, r0, c0, c1, 0 // disable ECC + and r0, r0, #(-1-8) + mcr p13, 0, r0, c0, c1, 0 + orr r0, r0, #6 // enable single-bit correction, + mcr p13, 0, r0, c0, c1, 0 // multi-bit detection + orr r0, r0, #8 // enable ECC + mcr p13, 0, r0, c0, c1, 0 + + mrc p13, 0, r0, c0, c1, 0 // BCU_WAIT --> wait until the BCU isn't busy + submi pc, pc, #0xc + + // Enable ECC circuitry in Yavapai + ldr r1, =ECCR_ADDR + mov r0, #0x4 // Enable single bit ECC Correction (Reporting Disabled) + str r0, [r1, #0] + + HEX_DISPLAY r0, r1, DISPLAY_6, DISPLAY_6 + +#if 1 + mov r0, #0x1000000 + 1: subs r0,r0,#1 + bne 1b +#endif + // Save SDRAM size + ldr r1, =hal_dram_size /* [see hal_intr.h] */ + str r8, [r1] + + // Move mmu tables into RAM so page table walks by the cpu + // don't interfere with FLASH programming. + ldr r0, =mmu_table + mov r4, r0 + add r2, r0, #0x4800 // End of tables + mov r1, #RAM_BASE + orr r1, r1, #0x4000 // RAM tables + mov r5, r1 + + // first, fixup physical address to second level + // table used to map first 1MB of flash. + ldr r3, [r0], #4 + sub r3, r3, r4 + add r3, r3, r5 + str r3, [r1], #4 + // everything else can go as-is + 1: + ldr r3, [r0], #4 + str r3, [r1], #4 + cmp r0, r2 + bne 1b + + // go back and fixup physical address to second level + // table used to map first 1MB of SDRAM. + add r1, r5, #(0xA00 * 4) + ldr r0, [r1] // entry for first 1MB of DRAM + sub r0, r0, r4 + add r0, r0, r5 + str r0, [r1] // store it back + + // Flush the cache + mov r0, #DCACHE_FLUSH_AREA /* cache flush region */ + add r1, r0, #0x8000 /* 32KB cache */ + 667: + mcr p15,0,r0,c7,c2,5 /* allocate a line */ + add r0, r0, #32 /* 32 bytes/line */ + teq r1, r0 + bne 667b + mcr p15,0,r0,c7,c6,0 /* invalidate data cache */ + /* cpuwait */ + mrc p15,0,r1,c2,c0,0 /* arbitrary read */ + mov r1,r1 + sub pc,pc,#4 + mcr p15,0,r0,c7,c10,4 + /* cpuwait */ + mrc p15,0,r1,c2,c0,0 /* arbitrary read */ + mov r1,r1 + sub pc,pc,#4 + nop + + HEX_DISPLAY r0, r1, DISPLAY_5, DISPLAY_2 + + // Set the TTB register to DRAM mmu_table + mov r0, r5 + mov r1, #0 + mcr p15, 0, r1, c7, c5, 0 // flush I cache + mcr p15, 0, r1, c7, c10, 4 // drain WB + mcr p15, 0, r0, c2, c0, 0 // load page table pointer + mcr p15, 0, r1, c8, c7, 0 // flush TLBs + CPWAIT r0 + + // Interrupt init + mov r0, #0 // enable no sources + mcr p13,0,r0,c0,c0,0 // write to INTCTL + // Steer both BCU and PMU to IRQ + mcr p13,0,r0,c8,c0,0 // write to INTSTR + + mov r0,#0 + mcr p15,0,r0,c14,c8,0 // ibcr0 + mcr p15,0,r0,c14,c9,0 // ibcr1 + mcr p15,0,r0,c14,c4,0 // dbcon + mov r0,#0x80000000 + mcr p14,0,r0,c10,c0,0 // dcsr + + HEX_DISPLAY r0, r1, DISPLAY_0, DISPLAY_0 + + .endm // _platform_setup1 + + +#define PLATFORM_VECTORS _platform_vectors + .macro _platform_vectors + .globl _80312_EMISR +_80312_EMISR: .long 0 // Companion chip "clear-on-read" interrupt status + // register for the performance monitor unit. + .endm + +/*---------------------------------------------------------------------------*/ +/* end of hal_platform_setup.h */ +#endif /* CYGONCE_HAL_PLATFORM_SETUP_H */ +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/include/pkgconf/mlt_arm_iq80310_ram.h @@ -0,0 +1,22 @@ +// eCos memory layout - Tue Sep 05 16:58:21 2000 + +// This is a generated file - do not edit + +#ifndef __ASSEMBLER__ +#include <cyg/infra/cyg_type.h> +#include <stddef.h> + +#endif +#define CYGMEM_REGION_ram (0xA0000000) +#define CYGMEM_REGION_ram_SIZE (0x2000000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0xf00000 - (size_t) CYG_LABEL_NAME (__heap1)) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__pci_window) []; +#endif +//#define CYGMEM_SECTION_pci_window (CYG_LABEL_NAME (__pci_window)) +//#define CYGMEM_SECTION_pci_window_SIZE (0x100000)
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/include/pkgconf/mlt_arm_iq80310_ram.ldi @@ -0,0 +1,29 @@ +// eCos memory layout - Tue Sep 05 16:58:21 2000 + +// This is a generated file - do not edit + +#include <cyg/infra/cyg_type.inc> + +MEMORY +{ + vrom : ORIGIN = 0x00000000, LENGTH = 0x1000 + ram : ORIGIN = 0xA0000000, LENGTH = 0x2000000 +} + +SECTIONS +{ + SECTIONS_BEGIN + SECTION_fixed_vectors (vrom, 0x20, LMA_EQ_VMA) // virtual ROM addr, but really in physical ram + SECTION_rom_vectors (ram, 0xa0020000, 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) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); +// CYG_LABEL_DEFN(__pci_window) = 0xf00000; . = CYG_LABEL_DEFN(__pci_window) + 0x100000; + SECTIONS_END +}
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/include/pkgconf/mlt_arm_iq80310_ram.mlt @@ -0,0 +1,14 @@ +version 0 +region ram 0 1000000 0 ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section rom_vectors 0 1 0 1 1 1 1 1 20000 20000 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 1 0 1 heap1 heap1 ! +section heap1 0 8 0 0 0 0 0 0 ! +section pci_window 100000 1 0 0 1 0 1 0 f00000 f00000 !This is the memory area that is dual-ported to devices onthe PCI bus. Such devices can read and write this memory areaas their own. Examples include the EBSA-285 Ethernet driver,which receives and transmits packets via this memory area.It must be 1Mb aligned, so that the MMU initialization can arrange for it to be uncacheable.
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/include/pkgconf/mlt_arm_iq80310_rom.h @@ -0,0 +1,25 @@ +// eCos memory layout - Tue Sep 05 18:46:49 2000 + +// This is a generated file - do not edit + +#ifndef __ASSEMBLER__ +#include <cyg/infra/cyg_type.h> +#include <stddef.h> + +#endif +#define CYGMEM_REGION_ram (0xA0000000) +#define CYGMEM_REGION_ram_SIZE (0x2000000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +#define CYGMEM_REGION_rom (0x00000000) +#define CYGMEM_REGION_rom_SIZE (0x800000) +#define CYGMEM_REGION_rom_ATTR (CYGMEM_REGION_ATTR_R) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0x1f00000 - (size_t) CYG_LABEL_NAME (__heap1)) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__pci_window) []; +#endif +// #define CYGMEM_SECTION_pci_window (CYG_LABEL_NAME (__pci_window)) +// #define CYGMEM_SECTION_pci_window_SIZE (0x100000)
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/include/pkgconf/mlt_arm_iq80310_rom.ldi @@ -0,0 +1,29 @@ +// eCos memory layout - Tue Sep 05 18:46:49 2000 + +// This is a generated file - do not edit + +#include <cyg/infra/cyg_type.inc> + +MEMORY +{ + ram : ORIGIN = 0xA0000000, LENGTH = 0x2000000 + rom : ORIGIN = 0x00000000, LENGTH = 0x800000 +} + +SECTIONS +{ + SECTIONS_BEGIN + SECTION_rom_vectors (ram, 0xA0000000, AT(0x00000000)) // vector page gets remapped from ROM to RAM + SECTION_text (rom, 0x00002000, 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) + SECTION_fixed_vectors (rom, 0x20, LMA_EQ_VMA) + SECTION_data (ram, 0xA000A000, FOLLOWING (.gcc_except_table)) + SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); +// CYG_LABEL_DEFN(__pci_window) = 0xf00000; . = CYG_LABEL_DEFN(__pci_window) + 0x100000; + SECTIONS_END +}
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/include/pkgconf/mlt_arm_iq80310_rom.mlt @@ -0,0 +1,14 @@ +version 0 +region ram a0000000 2000000 0 ! +region rom 00000000 800000 1 ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section data 0 1 1 1 1 1 0 0 8000 bss ! +section bss 0 4 0 1 0 1 0 1 heap1 heap1 ! +section heap1 0 8 0 0 0 0 0 0 ! +section rom_vectors 0 1 0 1 1 1 1 1 00000000 00000000 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/iq80310/current/include/pkgconf/mlt_arm_iq80310_roma.h @@ -0,0 +1,23 @@ +// eCos memory layout - Sun Jan 14 22:42:04 2001 + +// This is a generated file - do not edit + +#ifndef __ASSEMBLER__ +#include <cyg/infra/cyg_type.h> +#include <stddef.h> + +#endif +#define CYGMEM_REGION_vecs (0) +#define CYGMEM_REGION_vecs_SIZE (0x1000) +#define CYGMEM_REGION_vecs_ATTR (CYGMEM_REGION_ATTR_R) +#define CYGMEM_REGION_rom (0x40000) +#define CYGMEM_REGION_rom_SIZE (0x7c0000) +#define CYGMEM_REGION_rom_ATTR (CYGMEM_REGION_ATTR_R) +#define CYGMEM_REGION_ram (0xa0000000) +#define CYGMEM_REGION_ram_SIZE (0x2000000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0xa2000000 - (size_t) CYG_LABEL_NAME (__heap1))
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/include/pkgconf/mlt_arm_iq80310_roma.ldi @@ -0,0 +1,29 @@ +// eCos memory layout - Sun Jan 14 22:42:04 2001 + +// This is a generated file - do not edit + +#include <cyg/infra/cyg_type.inc> + +MEMORY +{ + vecs : ORIGIN = 0, LENGTH = 0x1000 + rom : ORIGIN = 0x40000, LENGTH = 0x7c0000 + ram : ORIGIN = 0xa0000000, LENGTH = 0x2000000 +} + +SECTIONS +{ + SECTIONS_BEGIN + SECTION_fixed_vectors (vecs, 0x20, LMA_EQ_VMA) + SECTION_rom_vectors (rom, 0x40000, 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) + SECTION_data (ram, 0xa000a000, FOLLOWING (.gcc_except_table)) + SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); + SECTIONS_END +}
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/include/pkgconf/mlt_arm_iq80310_roma.mlt @@ -0,0 +1,15 @@ +version 0 +region vecs 0 1000 1 ! +region rom 40000 7c0000 1 ! +region ram a0000000 2000000 0 ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section rom_vectors 0 1 0 1 1 1 1 1 40000 40000 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 ! +section data 0 1 1 1 1 1 0 0 a000a000 bss ! +section bss 0 4 0 1 0 1 0 1 heap1 heap1 ! +section heap1 0 8 0 0 0 0 0 0 !
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/include/plf_io.h @@ -0,0 +1,201 @@ +#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): msalter +// Contributors: hmt, jskov, msalter +// Date: 2000-10-10 +// Purpose: Intel IQ80310 PCI IO support macros +// Description: +// Usage: #include <cyg/hal/plf_io.h> +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include <pkgconf/hal_arm_iq80310.h> + +#include <cyg/hal/hal_iq80310.h> + +#include <cyg/hal/hal_io.h> // IO macros +#include <cyg/hal/hal_platform_ints.h> // Interrupt vectors + +extern cyg_uint32 cyg_hal_plf_pci_cfg_read_dword (cyg_uint32 bus, + cyg_uint32 devfn, + cyg_uint32 offset); +extern cyg_uint16 cyg_hal_plf_pci_cfg_read_word (cyg_uint32 bus, + cyg_uint32 devfn, + cyg_uint32 offset); +extern cyg_uint8 cyg_hal_plf_pci_cfg_read_byte (cyg_uint32 bus, + cyg_uint32 devfn, + cyg_uint32 offset); +extern void cyg_hal_plf_pci_cfg_write_dword (cyg_uint32 bus, + cyg_uint32 devfn, + cyg_uint32 offset, + cyg_uint32 val); +extern void cyg_hal_plf_pci_cfg_write_word (cyg_uint32 bus, + cyg_uint32 devfn, + cyg_uint32 offset, + cyg_uint16 val); +extern void cyg_hal_plf_pci_cfg_write_byte (cyg_uint32 bus, + cyg_uint32 devfn, + cyg_uint32 offset, + cyg_uint8 val); + +/* primary PCI bus definitions */ +#define PRIMARY_BUS_NUM 0 +#define PRIMARY_MEM_BASE 0x80000000 +#define PRIMARY_DAC_BASE 0x84000000 +#define PRIMARY_IO_BASE 0x90000000 +#define PRIMARY_MEM_LIMIT 0x83ffffff +#define PRIMARY_DAC_LIMIT 0x87ffffff +#define PRIMARY_IO_LIMIT 0x9000ffff + + +/* secondary PCI bus definitions */ +#define SECONDARY_BUS_NUM 1 +#define SECONDARY_MEM_BASE 0x88000000 +#define SECONDARY_DAC_BASE 0x8c000000 +#define SECONDARY_IO_BASE 0x90010000 +#define SECONDARY_MEM_LIMIT 0x8bffffff +#define SECONDARY_DAC_LIMIT 0x8fffffff +#define SECONDARY_IO_LIMIT 0x9001ffff + +// Initialize the PCI bus. +externC void cyg_hal_plf_pci_init(void); +#define HAL_PCI_INIT() cyg_hal_plf_pci_init() + +// 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 ) \ + __val = cyg_hal_plf_pci_cfg_read_byte((__bus), (__devfn), (__offset)) + +#define HAL_PCI_CFG_READ_UINT16( __bus, __devfn, __offset, __val ) \ + __val = cyg_hal_plf_pci_cfg_read_word((__bus), (__devfn), (__offset)) + +#define HAL_PCI_CFG_READ_UINT32( __bus, __devfn, __offset, __val ) \ + __val = cyg_hal_plf_pci_cfg_read_dword((__bus), (__devfn), (__offset)) + +// 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 ) \ + cyg_hal_plf_pci_cfg_write_byte((__bus), (__devfn), (__offset), (__val)) + +#define HAL_PCI_CFG_WRITE_UINT16( __bus, __devfn, __offset, __val ) \ + cyg_hal_plf_pci_cfg_write_word((__bus), (__devfn), (__offset), (__val)) + +#define HAL_PCI_CFG_WRITE_UINT32( __bus, __devfn, __offset, __val ) \ + cyg_hal_plf_pci_cfg_write_dword((__bus), (__devfn), (__offset), (__val)) + +//----------------------------------------------------------------------------- +// Resources + +// Map PCI device resources starting from these addresses in PCI space. +#define HAL_PCI_ALLOC_BASE_MEMORY (SECONDARY_MEM_BASE) +#define HAL_PCI_ALLOC_BASE_IO (SECONDARY_IO_BASE) + +// This is where the PCI spaces are mapped in the CPU's address space. +#define HAL_PCI_PHYSICAL_MEMORY_BASE 0x00000000 +#define HAL_PCI_PHYSICAL_IO_BASE 0x00000000 + +// Translate the PCI interrupt requested by the device (INTA#, INTB#, +// INTC# or INTD#) to the associated CPU interrupt (i.e., HAL vector). +#define HAL_PCI_TRANSLATE_INTERRUPT( __bus, __devfn, __vec, __valid) \ + CYG_MACRO_START \ + cyg_uint32 __dev = CYG_PCI_DEV_GET_DEV(__devfn); \ + cyg_uint32 __fn = CYG_PCI_DEV_GET_FN(__devfn); \ + __valid = false; \ + if (__bus == (*((cyg_uint8 *)SBNR_ADDR) + 1) && __dev == 0 && __fn == 0) {\ + __vec = CYGNUM_HAL_INTERRUPT_ETHERNET; \ + __valid = true; \ + } else { \ + cyg_uint8 __req; \ + HAL_PCI_CFG_READ_UINT8(__bus, __devfn, CYG_PCI_CFG_INT_PIN, __req); \ + switch (__dev % 4) { \ + case 0: \ + switch(__req) { \ + case 1: /* INTA */ \ + __vec=CYGNUM_HAL_INTERRUPT_PCI_S_INTA; __valid=true; break; \ + case 2: /* INTB */ \ + __vec=CYGNUM_HAL_INTERRUPT_PCI_S_INTB; __valid=true; break; \ + case 3: /* INTC */ \ + __vec=CYGNUM_HAL_INTERRUPT_PCI_S_INTC; __valid=true; break; \ + case 4: /* INTD */ \ + __vec=CYGNUM_HAL_INTERRUPT_PCI_S_INTD; __valid=true; break; \ + } \ + break; \ + case 1: \ + switch(__req) { \ + case 1: /* INTA */ \ + __vec=CYGNUM_HAL_INTERRUPT_PCI_S_INTB; __valid=true; break; \ + case 2: /* INTB */ \ + __vec=CYGNUM_HAL_INTERRUPT_PCI_S_INTC; __valid=true; break; \ + case 3: /* INTC */ \ + __vec=CYGNUM_HAL_INTERRUPT_PCI_S_INTD; __valid=true; break; \ + case 4: /* INTD */ \ + __vec=CYGNUM_HAL_INTERRUPT_PCI_S_INTA; __valid=true; break; \ + } \ + break; \ + case 2: \ + switch(__req) { \ + case 1: /* INTA */ \ + __vec=CYGNUM_HAL_INTERRUPT_PCI_S_INTC; __valid=true; break; \ + case 2: /* INTB */ \ + __vec=CYGNUM_HAL_INTERRUPT_PCI_S_INTD; __valid=true; break; \ + case 3: /* INTC */ \ + __vec=CYGNUM_HAL_INTERRUPT_PCI_S_INTA; __valid=true; break; \ + case 4: /* INTD */ \ + __vec=CYGNUM_HAL_INTERRUPT_PCI_S_INTB; __valid=true; break; \ + } \ + break; \ + case 3: \ + switch(__req) { \ + case 1: /* INTA */ \ + __vec=CYGNUM_HAL_INTERRUPT_PCI_S_INTD; __valid=true; break; \ + case 2: /* INTB */ \ + __vec=CYGNUM_HAL_INTERRUPT_PCI_S_INTA; __valid=true; break; \ + case 3: /* INTC */ \ + __vec=CYGNUM_HAL_INTERRUPT_PCI_S_INTB; __valid=true; break; \ + case 4: /* INTD */ \ + __vec=CYGNUM_HAL_INTERRUPT_PCI_S_INTC; __valid=true; break; \ + } \ + break; \ + } \ + } \ + CYG_MACRO_END + +//----------------------------------------------------------------------------- +// end of plf_io.h +#endif // CYGONCE_PLF_IO_H
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/include/plf_stub.h @@ -0,0 +1,86 @@ +#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): msalter +// Contributors:jskov, gthomas, msalter +// Date: 2000-10-10 +// Purpose: Platform HAL stub support for Intel IQ80310 boards. +// Usage: #include <cyg/hal/plf_stub.h> +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include <pkgconf/hal.h> +#include <pkgconf/hal_arm_iq80310.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 + + +extern int cyg_hal_plf_hw_breakpoint(int setflag, void *addr, int len); +extern int cyg_hal_plf_hw_watchpoint(int setflag, void *addr, int len, int type); +extern int cyg_hal_plf_is_stopped_by_hardware(void **paddr); + +#define HAL_STUB_HW_BREAKPOINT(f,a,l) cyg_hal_plf_hw_breakpoint((f),(a),(l)) +#define HAL_STUB_HW_WATCHPOINT(f,a,l,t) cyg_hal_plf_hw_watchpoint((f),(a),(l),(t)) +#define HAL_STUB_IS_STOPPED_BY_HARDWARE(p) cyg_hal_plf_is_stopped_by_hardware(&(p)) + +//----------------------------------------------------------------------------- +#endif // CYGONCE_HAL_PLF_STUB_H +// End of plf_stub.h
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/misc/redboot_RAM.cfg @@ -0,0 +1,85 @@ +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 iq80310 ; + template redboot ; + package -hardware CYGPKG_HAL_ARM current ; + package -hardware CYGPKG_HAL_ARM_IQ80310 current ; + package -hardware CYGPKG_IO_PCI current ; + package -hardware CYGPKG_DEVS_ETH_ARM_IQ80310 current ; + package -hardware CYGPKG_IO_SERIAL_ARM_IQ80310 current ; + package -hardware CYGPKG_DEVS_FLASH_IQ80310 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_DEVS_ETH_ARM_IQ80310_CHATTER { + user_value 0 +}; + +cdl_option CYGNUM_DEVS_ETH_ARM_IQ80310_DEV_COUNT { + user_value 1 +}; + +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_USE_ROM_MONITOR { + inferred_value 0 0 +}; + +cdl_component CYG_HAL_STARTUP { + user_value RAM +}; + +cdl_option CYGBLD_BUILD_REDBOOT { + user_value 1 +}; + +cdl_option CYGSEM_REDBOOT_FLASH_CONFIG { + user_value 1 +}; + +cdl_option CYGSEM_REDBOOT_BSP_SYSCALLS { + inferred_value 1 +}; + +cdl_option CYGBLD_REDBOOT_MIN_IMAGE_SIZE { + inferred_value 0x40000 +}; + +cdl_option CYGNUM_IO_ETH_DRIVERS_NUM_PKT { + user_value 2 +};
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/misc/redboot_RAMA.cfg @@ -0,0 +1,89 @@ +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 iq80310 ; + template redboot ; + package -hardware CYGPKG_HAL_ARM current ; + package -hardware CYGPKG_HAL_ARM_IQ80310 current ; + package -hardware CYGPKG_IO_PCI current ; + package -hardware CYGPKG_DEVS_ETH_ARM_IQ80310 current ; + package -hardware CYGPKG_IO_SERIAL_ARM_IQ80310 current ; + package -hardware CYGPKG_DEVS_FLASH_IQ80310 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_DEVS_ETH_ARM_IQ80310_CHATTER { + user_value 0 +}; + +cdl_option CYGNUM_DEVS_ETH_ARM_IQ80310_DEV_COUNT { + user_value 1 +}; + +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_USE_ROM_MONITOR { + inferred_value 0 0 +}; + +cdl_component CYG_HAL_STARTUP { + user_value RAM +}; + +cdl_option CYGBLD_BUILD_REDBOOT { + user_value 1 +}; + +cdl_option CYGSEM_REDBOOT_FLASH_CONFIG { + user_value 1 +}; + +cdl_option CYGSEM_REDBOOT_BSP_SYSCALLS { + inferred_value 1 +}; + +cdl_option CYGBLD_REDBOOT_MIN_IMAGE_SIZE { + inferred_value 0x40000 +}; + +cdl_option CYGBLD_REDBOOT_FLASH_BOOT_OFFSET { + inferred_value 0x40000 +}; + +cdl_option CYGNUM_IO_ETH_DRIVERS_NUM_PKT { + user_value 2 +};
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/misc/redboot_ROM.cfg @@ -0,0 +1,89 @@ +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 iq80310 ; + template redboot ; + package -hardware CYGPKG_HAL_ARM current ; + package -hardware CYGPKG_HAL_ARM_IQ80310 current ; + package -hardware CYGPKG_IO_PCI current ; + package -hardware CYGPKG_DEVS_ETH_ARM_IQ80310 current ; + package -hardware CYGPKG_IO_SERIAL_ARM_IQ80310 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 ; + package CYGPKG_DEVS_FLASH_IQ80310 current ; +}; + +cdl_option CYGBLD_BUILD_GDB_STUBS { + user_value 0 +}; + +cdl_option CYGDBG_DEVS_ETH_ARM_IQ80310_CHATTER { + user_value 0 +}; + +cdl_option CYGNUM_DEVS_ETH_ARM_IQ80310_DEV_COUNT { + user_value 1 +}; + +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_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_option CYGBLD_BUILD_REDBOOT { + user_value 1 +}; + +cdl_option CYGSEM_REDBOOT_FLASH_CONFIG { + user_value 1 +}; + +cdl_option CYGSEM_REDBOOT_BSP_SYSCALLS { + inferred_value 1 +}; + +cdl_option CYGBLD_REDBOOT_MIN_IMAGE_SIZE { + inferred_value 0x40000 +}; + +cdl_option CYGNUM_IO_ETH_DRIVERS_NUM_PKT { + user_value 2 +};
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/misc/redboot_ROMA.cfg @@ -0,0 +1,97 @@ +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 iq80310 ; + template redboot ; + package -hardware CYGPKG_HAL_ARM current ; + package -hardware CYGPKG_HAL_ARM_IQ80310 current ; + package -hardware CYGPKG_IO_PCI current ; + package -hardware CYGPKG_DEVS_ETH_ARM_IQ80310 current ; + package -hardware CYGPKG_IO_SERIAL_ARM_IQ80310 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 ; + package CYGPKG_DEVS_FLASH_IQ80310 current ; +}; + +cdl_option CYGBLD_BUILD_GDB_STUBS { + user_value 0 +}; + +cdl_option CYGDBG_DEVS_ETH_ARM_IQ80310_CHATTER { + user_value 0 +}; + +cdl_option CYGNUM_DEVS_ETH_ARM_IQ80310_DEV_COUNT { + user_value 1 +}; + +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_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_option CYGBLD_BUILD_REDBOOT { + user_value 1 +}; + +cdl_option CYGSEM_REDBOOT_FLASH_CONFIG { + user_value 1 +}; + +cdl_option CYGSEM_REDBOOT_BSP_SYSCALLS { + inferred_value 1 +}; + +cdl_option CYGBLD_REDBOOT_MIN_IMAGE_SIZE { + inferred_value 0x40000 +}; + +cdl_option CYGSEM_HAL_ARM_IQ80310_ARMBOOT { + user_value 1 +}; + +cdl_option CYGBLD_REDBOOT_FLASH_BOOT_OFFSET { + inferred_value 0x40000 +}; + +cdl_option CYGNUM_IO_ETH_DRIVERS_NUM_PKT { + user_value 2 +};
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/7_segment_displays.h @@ -0,0 +1,93 @@ +//============================================================================= +// +// 7_segment_displays.h +// +// Definitions for IQ80310 7-segment display. +// +//============================================================================= +//####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): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-02 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + + +/* Addresses of the 7-segment displays registers */ + +/* 08/25/00 jwf */ +/* iq80303 address decode */ +/* +#define MSB_DISPLAY_REG (volatile unsigned char *)0xe0040000 +#define LSB_DISPLAY_REG (volatile unsigned char *)0xe0050000 +*/ + +/* 08/25/00 jwf */ +/* iq80310 address decode */ +#define MSB_DISPLAY_REG (volatile unsigned char *)0xfe840000 /* 7 segment 0 */ +#define LSB_DISPLAY_REG (volatile unsigned char *)0xfe850000 /* 7 segment 1 */ + + +/* Values for the 7-segment displays */ +#define DISPLAY_OFF 0xFF +#define ZERO 0xC0 +#define ONE 0xF9 +#define TWO 0xA4 +#define THREE 0xB0 +#define FOUR 0x99 +#define FIVE 0x92 +#define SIX 0x82 +#define SEVEN 0xF8 +#define EIGHT 0x80 +#define NINE 0x90 +#define LETTER_A 0x88 +#define LETTER_B 0x83 +#define LETTER_C 0xC6 +#define LETTER_D 0xA1 +#define LETTER_E 0x86 +#define LETTER_F 0x8E +#define LETTER_I 0xCF +#define LETTER_L 0xC7 +#define LETTER_P 0x8C +#define LETTER_S 0x92 +#define DECIMAL_POINT 0x7F +#define DISPLAY_ERROR 0x06 /* Displays "E." */ + + +/* Parameters for functions */ +#define MSB 0 +#define LSB 1 +#define BOTH 2 + + + +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/cycduart.c @@ -0,0 +1,489 @@ +//============================================================================= +// +// cycduart.c - Cyclone UART Diagnostics +// +//============================================================================= +//####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): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-25 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +#include "cycduart.h" +#include "iq80310.h" + +#define DFLTLOOPERMS 500 + +extern int printf(char*,...); +extern long hexIn(); + +int break_flag = 0; +unsigned long baud_rate = 0; + +static int duart_already_init = FALSE; +static unsigned int uart_unit = DFLTPORT; +static int looperms; + +static int calc_looperms(void); +void serial_init(void); +int inreg(int); +void outreg(int, unsigned char); +void serial_set(unsigned long); +void serial_loopback(int); +int serial_getc(); +void serial_putc(int); +int serial_write(int, const unsigned char *, int); +int serial_read(int, unsigned char *, int, int); + +extern int enable_external_interrupt (int int_id); +extern int disable_external_interrupt (int int_id); + +extern int isr_connect(int int_num, void (*handler)(int), int arg); +extern int isr_disconnect(int int_num); + + +void duart_initialize() +{ + + if (duart_already_init == FALSE) + { + /* Calculate the time constant for timeouts on serial_read. */ + if ((looperms = calc_looperms()) <= 0) + looperms = DFLTLOOPERMS; + + } + + /* Initialize the serial port and set the baud rate. + * The baud rate is set here for sanity only; the autobaud + * mechanism will change it as required when the host connects. + */ + + serial_init(); + serial_set(baud_rate?baud_rate:9600L); + + duart_already_init = TRUE; + +} + + +/* Establish the loop/time constant to be used in the timing loop in + * serial_read. This is done by putting the UART into loopback mode. + * After transmitting a character at 300 baud, we wait for the character + * to be received. Then divide the number of loops waited by the number + * of milliseconds it takes to transmit 10 bits at 300 baud. + * If your transmitter doesn't have a loopback mode, this value can be + * calculated using a timer or some other facility, or an approximate + * constant can be used. + */ + +#define TESTBAUD 300L +#define NBYTES 10 +#define BITS_PER_BYTE 10 /* 1 start bit, 8 data bits, 1 stop bit */ +#define TOTAL_MS (NBYTES*BITS_PER_BYTE*1000/TESTBAUD) + +static int +calc_looperms(void) +{ + int i, count, c; + int totalloops = 0; + + serial_init(); + serial_set(TESTBAUD); /* set 300 baud */ + serial_loopback(1); /* enable loop back mode */ + + for (i=0; i < NBYTES; i++) + { + count = 1; + serial_putc(0xaa); /* xmit character */ + + /* + * The timing loop is the same as the loops in serial_read. + * Any changes to the loops in serial_read should be reflected + * here. + */ + do + { + c = serial_getc(); + } while (c < 0 && count++ > 0); + + totalloops += count; + } + + serial_loopback(0); + + return(totalloops/TOTAL_MS); +} + +/* + * Initialize the device driver. + */ +void serial_init(void) +{ + /* If the serial port has been init'd before, there may be data in it */ + /* Wait for the transmit FIFO to empty out before resetting anything */ + if (duart_already_init == TRUE) + { + while (!(inreg(LSR) & LSR_TSRE)); + } + + /* + * Configure active port, (uart_unit already set.) + * + * Set 8 bits, 1 stop bit, no parity. + * + * LCR<7> 0 divisor latch access bit + * LCR<6> 0 break control (1=send break) + * LCR<5> 0 stick parity (0=space, 1=mark) + * LCR<4> 0 parity even (0=odd, 1=even) + * LCR<3> 0 parity enable (1=enabled) + * LCR<2> 0 # stop bits (0=1, 1=1.5) + * LCR<1:0> 11 bits per character(00=5, 01=6, 10=7, 11=8) + */ + + outreg(LCR, 0x3); + + /* Assert DTR and RTS to prevent hardware handshake problems with + serial terminals, etc. which can be connected to the serial port */ + outreg(MCR, MCR_DTR | MCR_RTS); + + outreg(FCR, FIFO_ENABLE); /* Enable the FIFO */ + outreg(IER, INT_ENABLE); /* Enable appropriate interrupts */ + +} + +/* Read a received character if one is available. Return -1 otherwise. */ +int serial_getc() +{ + if (inreg(LSR) & LSR_DR) + { + return inreg(DataIn); + } + return -1; +} + +/* Transmit a character. */ +void serial_putc(int c) +{ + while ((inreg(LSR) & LSR_THRE) == 0) + ; + outreg(DataOut, c); +} + +/* + * Set the baud rate. + */ +void serial_set(unsigned long baud) +{ + unsigned char sav_lcr; + + if(baud == 0) + baud = 9600L; + + /* + * Enable access to the divisor latches by setting DLAB in LCR. + * + */ + sav_lcr = inreg(LCR); + outreg(LCR, LCR_DLAB | sav_lcr); + + /* + * Set divisor latches. + */ + outreg(BaudLsb, XTAL/(16*baud)); + outreg(BaudMsb, (XTAL/(16*baud)) >> 8); + + /* + * Restore line control register + */ + outreg(LCR, sav_lcr); +} + +/* + * This routine is used by calc_looperms to put the UART in loopback mode. + */ + +void serial_loopback(int flag) +{ + if (flag) + outreg(MCR, inreg(MCR) | MCR_LOOP); /* enable loop back mode */ + else + outreg(MCR, inreg(MCR) & ~MCR_LOOP); /* disable loop back mode */ +} + +/* + * These routines are used to read and write to the registers of the + * 16552. The delay routine guarantees the required recovery time between + * cycles to the 16552. + * DUART is the base address of the 16552. + * DUART_DELTA gives the spacing between adjacent registers of the 16552. + * For example, if A0,A1,A2 of the 16552 are connected to A2,A3,A4 of + * the processor, DUART_DELTA must be 4. + */ + +int inreg(int reg) +{ + int val; + val = *((volatile unsigned char *)TERMINAL + (uart_unit * SCALE + reg)); + + return val; +} + +void outreg(int reg, unsigned char val) +{ + *((volatile unsigned char *)TERMINAL + (uart_unit * SCALE + reg)) = val; +} + + + +/****************************************************************/ +/* The following functions are all part of the Breeze UART test */ +/****************************************************************/ + + +static volatile int uart_int; + + +/************************************************/ +/* BUS_TEST */ +/* This routine performs a walking ones test */ +/* on the given uart chip to test it's bus */ +/* interface. It writes to the scratchpad reg. */ +/* then reads it back. During */ +/* this test all 8 data lines from the chip */ +/* get written with both 1 and 0. */ +/************************************************/ +static int bus_test () +{ + unsigned char out, in; + int bitpos; + volatile int junk; + + junk = (int) &junk; /* Don't let compiler optimize or "registerize" */ + + outreg(SCR,0); /* Clear scratchpad register */ + + for (bitpos = 0; bitpos < 8; bitpos++) + { + out = 1 << bitpos; + + outreg(SCR,out); /* Write data to scratchpad reg. */ + + junk = ~0; /* Force data lines high */ + + in = inreg(SCR); /* Read data */ + + printf ("%02X ", in); + + /* make sure it's what we wrote */ + if (in != out) + return (0); + } + outreg(SCR,0); /* Clear scratchpad register */ + printf ("\n"); + + return (1); +} + +/************************************************/ +/* DISABLE_UART_INTS */ +/* This routine disables uart interrupts */ +/************************************************/ +static void disable_uart_ints () +{ + outreg(IER,0); /* Make the uart shut up */ +} + +/************************************************/ +/* UART_ISR */ +/* This routine responds to uart interrupts */ +/* must return 1 to indicate that an interrupt */ +/* was serviced. */ +/************************************************/ +static void uart_isr (int unused) +{ + unsigned char iir; + + disable_uart_ints (); + uart_int = 1; + + /* read the IIR to clear the interrupt */ + iir = inreg(IIR); + + return ; +} + +/************************************************/ +/* INIT_UART */ +/* This routine initializes the 16550 interrupt */ +/* and uart registers and initializes the uart */ +/* count. */ +/************************************************/ +static void init_uart () +{ + outreg(IER,0x02); /* Enable Tx Empty interrupt - + should generate an interrupt since Tx is + empty to begin with */ +} + + +/****************************************/ +/* UART DIAGNOSTIC TEST */ +/****************************************/ +void uart_test () +{ +volatile int loop; +int looplim; +int int_id; +unsigned long* reg_ptr; +int i, baud; + +/*11/01/00 */ +char info[] = {"Move Console Cable back to Connector J9 and hit <CR> to exit test"}; +int index; + + looplim = 400000; + + /* perform tests on both UARTs */ + for (uart_unit = 0; uart_unit < 2; uart_unit++) + { + + if (uart_unit == 0) + int_id = UART1_INT_ID; + else + int_id = UART2_INT_ID; + + if (!bus_test ()) + printf ("\nERROR: bus_test for UART Unit %d failed\n", uart_unit); + else + { + printf ("\nbus_test for UART Unit %d passed\n", uart_unit); + + uart_int = 0; + + isr_connect (int_id, uart_isr, 0); + + if (enable_external_interrupt(int_id) != OK) + printf("ERROR enabling UART UINT %d interrupt!\n", uart_unit); + + init_uart (); + + loop = 0; + + while (!uart_int && (loop < looplim)) + loop++; + if (!uart_int) + printf ("UART Unit %d INTERRUPT test failed %X\n", uart_unit, loop) ; + else + printf ("UART Unit %d INTERRUPT test passed\n", uart_unit); + + serial_putc(' '); + } + + /* disable UART interrupt */ + if (disable_external_interrupt(int_id)!= OK) + printf("ERROR disabling UART UNIT %d interrupt!\n", uart_unit); + + /* disconnect test handler */ + isr_disconnect (int_id); + + } + +/* 11/01/00 */ +/* #if 0 */ /* writing to port 2 doesnt work yet... */ +#if 1 /* writing to port 2 doesnt work yet... */ + +/* + printf ("\nMove the Console Cable to the 2nd Serial Port,\n"); + printf ("Connector J10,\n"); + printf ("and Hit <CR> when the cable is connected.\n\n"); + printf ("After alphabet prints, move Console Cable back to 1st Serial Port,\n"); + printf ("Connector J9,\n"); + printf ("and hit <CR> to exit test\n"); +*/ + +/* 10/30/00 */ + uart_unit = DFLTPORT; /* test J10, the PCI-700 GDB port */ + + printf ("\nMove the Console Cable to the 2nd Serial Port, Connector J10,\n"); + printf ("and Hit <CR> when the cable is connected.\n"); + printf ("The alphabet should print on the screen.\n\n"); + +/* 11/01/00 */ +/* + printf ("After alphabet prints, move Console Cable back to 1st Serial Port,\n"); + printf ("Connector J9,\n"); + printf ("and hit <CR> to exit test\n"); +*/ + baud = 115200; + serial_init(); + serial_set(baud?baud:115200L); + +/* while (serial_getc() == -1); */ + while (serial_getc() != 0x0d); /* wait for a carriage return character to start test */ + +/* + while (1) + { + for ( i = 65; i <= 90; i++ ) + serial_putc(i); + } +*/ + for ( i = 65; i <= 90; i++ ) /* transmit the alphabet */ + serial_putc(i); + + serial_putc(10); /* transmit a New Line */ + serial_putc(13); /* transmit a Carriage Return */ + serial_putc(10); /* transmit a New Line */ + + for (index=0; info[index] != '\0'; index++) /* transmit some instructions to the user */ + { + serial_putc(info[index]); + } + + + /* point at default port before returning */ +/* uart_unit = DFLTPORT; */ + + (void)hexIn(); + +#endif + + printf ("\n\nUART tests done.\n"); + + printf ("Press return to continue.\n"); + (void) hexIn(); +} + + + +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/cycduart.h @@ -0,0 +1,153 @@ +//============================================================================= +// +// cycduart.h - Cyclone Diagnostics +// +//============================================================================= +//####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) 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-25 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + + +/* Control/status register offsets from base address */ + +#define RBR 0x00 +#define THR 0x00 +#define DLL 0x00 +#define IER 0x01 +#define DLM 0x01 +#define IIR 0x02 +#define FCR 0x02 +#define LCR 0x03 +#define MCR 0x04 +#define LSR 0x05 +#define MSR 0x06 +#define SCR 0x07 + +/* 16550A Line Control Register */ + +#define LCR_5BITS 0x00 +#define LCR_6BITS 0x01 +#define LCR_7BITS 0x02 +#define LCR_8BITS 0x03 +#define LCR_NSB 0x04 +#define LCR_PEN 0x08 +#define LCR_EPS 0x10 +#define LCR_SP 0x20 +#define LCR_SB 0x40 +#define LCR_DLAB 0x80 + +/* 16550A Line Status Register */ + +#define LSR_DR 0x01 +#define LSR_OE 0x02 +#define LSR_PE 0x04 +#define LSR_FE 0x08 +#define LSR_BI 0x10 +#define LSR_THRE 0x20 +#define LSR_TSRE 0x40 +#define LSR_FERR 0x80 + +/* 16550A Interrupt Identification Register */ + +#define IIR_IP 0x01 +#define IIR_ID 0x0e +#define IIR_RLS 0x06 +#define IIR_RDA 0x04 +#define IIR_THRE 0x02 +#define IIR_MSTAT 0x00 +#define IIR_TIMEOUT 0x0c + +/* 16550A interrupt enable register bits */ + +#define IER_DAV 0x01 +#define IER_TXE 0x02 +#define IER_RLS 0x04 +#define IER_MS 0x08 + +/* 16550A Modem control register */ + +#define MCR_DTR 0x01 +#define MCR_RTS 0x02 +#define MCR_OUT1 0x04 +#define MCR_OUT2 0x08 +#define MCR_LOOP 0x10 + +/* 16550A Modem Status Register */ + +#define MSR_DCTS 0x01 +#define MSR_DDSR 0x02 +#define MSR_TERI 0x04 +#define MSR_DRLSD 0x08 +#define MSR_CTS 0x10 +#define MSR_DSR 0x20 +#define MSR_RI 0x40 +#define MSR_RLSD 0x80 + +/* (*) 16550A FIFO Control Register */ + +#define FCR_EN 0x01 +#define FCR_RXCLR 0x02 +#define FCR_TXCLR 0x04 +#define FCR_DMA 0x08 +#define FCR_RES1 0x10 +#define FCR_RES2 0x20 +#define FCR_RXTRIG_L 0x40 +#define FCR_RXTRIG_H 0x80 + + +#define CHAN1 0x8 +#define CHAN2 0x0 + +#define DataIn 0x00 /* data input port */ +#define DataOut 0x00 /* data output port */ +#define BaudLsb 0x00 /* baud rate divisor least significant byte */ +#define BaudMsb 0x01 /* baud rate divisor most significant byte */ + + +/* + * Enable receive and transmit FIFOs. + * + * FCR<7:6> 00 trigger level = 1 byte + * FCR<5:4> 00 reserved + * FCR<3> 0 mode 1 - interrupt on fifo threshold + * FCR<2> 1 clear xmit fifo + * FCR<1> 1 clear recv fifo + * FCR<0> 1 turn on fifo mode + */ +#define FIFO_ENABLE 0x07 +#define INT_ENABLE (IER_RLS) /* default interrupt mask */ + + +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/diag.c @@ -0,0 +1,203 @@ +//========================================================================== +// +// diag.c +// +// Additional RedBoot commands to run board diags. +// +//========================================================================== +//####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): msalter +// Contributors: msalter +// Date: 2000-10-10 +// Purpose: +// Description: +// +// This code is part of RedBoot (tm). +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#define DEFINE_VARS +#include <redboot.h> +#include <cyg/hal/hal_arch.h> +#include <cyg/hal/hal_intr.h> +#include <cyg/hal/hal_cache.h> +#include CYGHWR_MEMORY_LAYOUT_H + +#include <cyg/hal/hal_tables.h> + +#include "iq80310.h" + +int pci_config_cycle = 0; /* skip exception handling when performing pci config cycle */ + +static void do_hdwr_diag(int argc, char *argv[]); + +RedBoot_cmd("diag", + "Run board diagnostics", + "", + do_hdwr_diag + ); + + +void hdwr_diag (void); + +void do_hdwr_diag(int arg, char *argv[]) +{ + hal_virtual_comm_table_t* __chan; + + // Turn off interrupts on debug channel. + // All others should already be disabled. + __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + if (__chan) + CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE); + + // Reset secondary PCI bus + *(volatile cyg_uint16 *)BCR_ADDR |= 0x40; // reset secondary bus + *(volatile cyg_uint16 *)BCR_ADDR &= ~0x40; // release reset + + hdwr_diag(); +} + +void __disableDCache(void) +{ + HAL_DCACHE_SYNC(); + HAL_DCACHE_DISABLE(); +} + +void __enableDCache() +{ + HAL_DCACHE_ENABLE(); +} + + +void _flushICache() +{ + HAL_ICACHE_INVALIDATE_ALL(); +} + +void __enableICache() +{ + HAL_ICACHE_ENABLE(); +} + +void __disableICache() +{ + HAL_ICACHE_DISABLE(); +} + +void _enableFiqIrq() +{ + asm ("mrc p15, 0, r0, c13, c0, 1;" + "orr r0, r0, #0x2000;" + "mrc p15, 0, r0, c13, c0, 1;" + "mrc p13, 0, r0, c0, c0, 0;" + "orr r0, r0, #3;" + "mcr p13, 0, r0, c0, c0, 0;" + : : ); +} + + +void _enable_timer() +{ + asm("ldr r1, =0x00000005;" + "mcr p14, 0, r1, c0, c0, 0 ;" + : : : "r1" ); +} + +void _disable_timer() +{ + asm("ldr r1, =0x00000000;" + "mcr p14, 0, r1, c0, c0, 0 ;" + : : : "r1" ); +} + +void _usec_delay() +{ + asm ("ldr r2, =0x258;" /* 1 microsec = 600 clocks (600 MHz CPU core) */ + "0: mrc p14, 0, r0, c1, c0, 0;" /*read CCNT into r0 */ + "cmp r2, r0;" /* compare the current count */ + "bpl 0b;" /* stay in loop until count is greater */ + "mrc p14, 0, r1, c0, c0, 0;" + "orr r1, r1, #4;" /* clear the timer */ + "mcr p14, 0, r1, c0, c0, 0 ;" + : : : "r0","r1","r2"); +} + +void _msec_delay() +{ + asm ("ldr r2, =0x927c0;" /* 1 millisec = 600,000 clocks (600 MHz CPU core) */ + "0: mrc p14, 0, r0, c1, c0, 0;" /*read CCNT into r0 */ + "cmp r2, r0;" /* compare the current count */ + "bpl 0b;" /* stay in loop until count is greater */ + "mrc p14, 0, r1, c0, c0, 0;" + "orr r1, r1, #4;" /* clear the timer */ + "mcr p14, 0, r1, c0, c0, 0 ;" + : : : "r0","r1","r2"); +} + +unsigned int _read_timer() +{ + unsigned x; + asm("mrc p14, 0, %0, c1, c0, 0;" : "=r"(x) : ); + return x; +} + +#if 0 +FUNC_START _read_intstr + mrc p13, 0, r0, c4, c0, 0 + + mov pc, lr +FUNC_END _read_intstr + + +FUNC_START _read_cpsr + mrs r0, cpsr + + mov pc, lr +FUNC_END _read_cpsr + + +FUNC_START _cspr_enable_fiq_int + mrs r0, cpsr + bic r0, r0, #0x40 + msr cpsr, r0 + + mov pc, lr +FUNC_END _cspr_enable_fiq_int + + +FUNC_START _cspr_enable_irq_int + mrs r0, cpsr + bic r0, r0, #0x80 + msr cpsr, r0 + + mov pc, lr +FUNC_END _cspr_enable_irq_int + +#endif
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/ether_test.c @@ -0,0 +1,1302 @@ +//============================================================================= +// +// ether_test.c - Cyclone Diagnostics +// +//============================================================================= +//####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) 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-25 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +#include "pci_bios.h" +#include "iq80310.h" +#include "ether_test.h" + +/* Forward declarations */ +static int i557SelfTest (); +static int i557Init (); +static int i557Config (UINT8 loopBackMode); +static int i557AddrSet (); +static int i557RUStart (); +static void setUpPacket (); +static int txPacket (); +static char *malloc (); +static void bzero (); +static void Wait(); +static int waitForRxInt(); +static int get_ether_addr(); + +/* Externals */ +void printf(); +void bcopy(); +extern void sgets(); +extern int atod(); +extern int enable_external_interrupt (int int_id); +extern int isr_connect(int int_num, void (*handler)(int), int arg); +extern STATUS pci_isr_connect (int intline, int bus, int device, int (*handler)(int), int arg); +extern ULONG sys_read_config_dword (UINT32 busno,UINT32 devno,UINT32 funcno,UINT32 offset,UINT32 *data); +extern void delay_ms(int msecs); + +extern int eeprom_read (UINT32 pci_base,/* PCI Base address */ + int eeprom_addr, /* word offset from start of eeprom */ + UINT16 *p_data,/* where to put data in memory */ + int nwords /* number of 16bit words to read */ + ); +extern int eeprom_write (UINT32 pci_base,/* PCI Base address */ + int eeprom_addr, /* word offset from start of eeprom */ + UINT16 *p_data,/* data location in memory */ + int nwords /* number of 16bit words to write */ + ); + +/* Globals needed by both main program and irq handler */ +static volatile struct SCBtype *pSCB; /* Pointer to SCB in use */ +static volatile UINT32 waitSem; /* Used to block test until interrupt */ +static volatile UINT32 rxSem; /* Used to block test until rx sinterrupt */ +static UINT16 i557Status; /* Status code from SCB */ +static volatile char *mem_pool; /* Ptr to malloc's free memory pool */ +static UINT32 adapter[2]; /* Ptr to PCI Ethernet adapter */ +static UINT8 node_address[6]; +/*static long timer0_ticks = 0;*/ +static char buf[4]; +static int count = 0; +static int forever_flag = FALSE; +static UINT32 phy_id = 0; + +/* 82557 required data structures which must be allocated */ +static struct rfd *pRfd; +static union cmdBlock *pCmdBlock; +static char *pPacketBuf; + +#define SPEED_NOLINK 0 +#define SPEED_10M 10 +#define SPEED_100M 100 +static int link_speed = SPEED_NOLINK; + +UINT8 unit_intpin; +int unit_devno, unit_busno, unit_funcno; + +#define BUSY_WAIT_LIMIT 0xf000 /* the upper limit on a busy wait + for command completion, etc. */ + +#if 0 +/* names for MDI registers */ +static char *mdi_reg_name [] = + { + "MDI Control Register ", + "MDI Status Register ", + "MDI PHY Identification Register (Word 1) ", + "MDI PHY Identification Register (Word 2) ", + "MDI Auto-Negotiation Advertisement Register ", + "MDI Auto-Negotiation Link Partner Ability Register ", + "MDI Auto-Negotiation Expansion Register ", + }; +#endif + +static void mask_557_ints (void) +{ + pSCB->cmdStat.bits.m = 1; +} + +static void unmask_557_ints (void) +{ + pSCB->cmdStat.bits.m = 0; +} + +/***************************************************************************** +* pci_ether_test - i8255x PCI Ethernet test +* +* Main diagnostic routine for the Intel 8255x 10/100BaseT Ethernet Controller +* family. Arguments include the PCI bus, device and function numbers of the +* controller that is to be tested. +* +*/ +void pci_ether_test (UINT32 busno, UINT32 devno, UINT32 funcno) +{ + volatile int i; + int ntimes; + int broadcom_flag = FALSE; + UINT16 phy_addr_reg, temp1, temp2; + char inputLine[80]; + + count = 0; + + /* read the PCI BAR for the Ethernet controller */ + if (sys_read_config_dword(busno, devno, funcno, 0x10, &adapter[0]) == ERROR) + { + printf ("Error Reading Adapter PCI Address\n"); + return; + } + + /* strip off BAR indicator bits */ + adapter[0] &= 0xfffffff0; + + unit_devno = devno; + unit_busno = busno; + unit_funcno = funcno; + + /* pointer to on-chip SCB */ + pSCB = (struct SCBtype *)(adapter[0] + SCB_OFFSET); + + unit_intpin = INTA; + + printf ("PCI Base Address = 0x%X\n", adapter[0]); + printf ("PCI Interrupt Pin = 0x%02X\n", unit_intpin); + + /* Initialize malloc's memory pool pointer */ + mem_pool = (char *) ETHER_MEM_POOL; + + + /* Start the timer for delay implementation + printf("Starting timer... "); + StartTimer(); */ + printf("Done.\n Resetting chip... "); + + /* reset the 82557 to start with a clean slate */ + resetChip(); + printf("Done.\n"); + + /* Get the UUT's ethernet address */ + if (get_ether_addr (0, node_address, TRUE) == ERROR) + { + printf("Error Reading Adapter Ethernet Address\n"); + return; + } + + temp1 = readMDI (0 ,MDI_DEFAULT_PHY_ADDR, MDI_PHY_ID_1); + temp2 = readMDI (0 ,MDI_DEFAULT_PHY_ADDR, MDI_PHY_ID_2); + phy_id = ((temp1 << 16) | temp2); + + if ((phy_id & 0xfffffff0) == I82555_PHY_ID) + { + printf ("Intel 82555/558 PHY detected...\n"); + + /* dummy read for reliable status */ + (void)readMDI (0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT); + + temp1 = readMDI (0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT); + printf ("Status Register Link Status is %s\n", (temp1 & MDI_STAT_LINK) ? "UP" : "DOWN"); + + phy_addr_reg = readMDI (0, MDI_DEFAULT_PHY_ADDR, I82555_STATCTRL_REG); + + if (temp1 & MDI_STAT_LINK) /* speed only valid with good LNK */ + { + printf ("Connect Speed is %s\n", (phy_addr_reg & I82555_100_MBPS) ? "100Mbps" : "10Mbps"); + link_speed = (phy_addr_reg & I82555_100_MBPS) ? SPEED_100M : SPEED_10M; + } + else + printf ("Connect Speed is NOT VALID\n"); + } + + if ((phy_id & 0xfffffff0) == ICS1890_PHY_ID) + { + printf ("Integrated Circuit Systems ICS1890 PHY detected...\n"); + printf ("Revision = %c\n", 'A' + (phy_id & REVISION_MASK)); + + /* dummy read for reliable status */ + (void)readMDI (0, MDI_DEFAULT_PHY_ADDR, ICS1890_QUICKPOLL_REG); + temp1 = readMDI (0, MDI_DEFAULT_PHY_ADDR, ICS1890_QUICKPOLL_REG); + printf ("Status Register Link Status is %s\n", (temp1 & QUICK_LINK_VALID) ? "UP" : "DOWN"); + + if (temp1 & QUICK_LINK_VALID) /* speed only valid with good LNK */ + { + printf ("Connect Speed is %s\n", (temp1 & QUICK_100_MBPS) ? "100Mbps" : "10Mbps"); + link_speed = (temp1 & QUICK_100_MBPS) ? + SPEED_100M : SPEED_10M; + } + else printf ("Connect Speed is NOT VALID\n"); + } + + if ((phy_id & 0xfffffff0) == DP83840_PHY_ID) + { + printf ("National DP83840 PHY detected...\n"); + printf ("Revision = %c\n", 'A' + (phy_id & REVISION_MASK)); + + /* dummy read for reliable status */ + (void)readMDI (0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT); + temp1 = readMDI (0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT); + printf ("Status Register Link Status is %s\n", (temp1 & MDI_STAT_LINK) ? "UP" : "DOWN"); + + phy_addr_reg = readMDI (0 ,MDI_DEFAULT_PHY_ADDR, DP83840_PHY_ADDR_REG); + + if (temp1 & MDI_STAT_LINK) /* speed only valid with good LNK */ + { + printf ("Connect Speed is %s\n", (phy_addr_reg & PHY_ADDR_SPEED_10_MBPS) ? "10Mbps" : "100Mbps"); + link_speed = (phy_addr_reg & PHY_ADDR_SPEED_10_MBPS) ? SPEED_10M : SPEED_100M; + } + else printf ("Connect Speed is NOT VALID\n"); + } + + if ((phy_id & 0xfffffff0) == I82553_PHY_ID) + { + printf ("Intel 82553 PHY detected...\n"); + printf ("Revision = %c\n", 'A' + (phy_id & REVISION_MASK)); + broadcom_flag = TRUE; + } + + if (phy_id == I82553_REVAB_PHY_ID) + { + printf ("Intel 82553 PHY detected...\n"); + printf ("Revision = B\n"); + broadcom_flag = TRUE; + } + + if (broadcom_flag == TRUE) + { + temp2 = readMDI (0,MDI_DEFAULT_PHY_ADDR, I82553_PHY_EXT_REG0); + printf ("Stepping = %02X\n", GET_REV_CNTR(temp2)); + + /* dummy read for reliable status */ + (void)readMDI (0 ,MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT); + temp1 = readMDI (0 ,MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT); + printf ("Status Register Link Status is %s\n", (temp1 & MDI_STAT_LINK) ? "UP" : "DOWN"); + + if (temp1 & MDI_STAT_LINK) /* speed only valid with good LNK */ + { + printf ("Connect Speed is %s\n", (temp2 & EXT_REG0_100_MBPS) ? "100Mbps" : "10Mbps"); + link_speed = (temp2 & EXT_REG0_100_MBPS) ? SPEED_100M : SPEED_10M; + } + else printf ("Connect Speed is NOT VALID\n"); + } + + printf ("\n"); + + /* Run the built-in self test through the port register */ + if (i557SelfTest () == ERROR) + { + mask_557_ints (); /* Disable 557 interrupt */ + return; + } + + /* Reset clears the interrupt mask */ + mask_557_ints(); + + printf ("Press return to initialize ethernet controller.\n"); + sgets (buf); + + /* Initialize data structures */ + if (i557Init () == ERROR) + { + mask_557_ints (); /* Disable 557 interrupt */ + return; + } + + /* Set hardware address */ + if (i557AddrSet () == ERROR) + { + mask_557_ints (); /* Disable 557 interrupt */ + return; + } + + printf ("Press return to perform internal loopback test.\n"); + sgets (buf); + + /* Configure for internal loopback */ + if (i557Config (INT_LOOP_BACK) == ERROR) + { + mask_557_ints (); /* Disable 557 interrupt */ + return; + } + + Wait(100); + + /* Initialize receive buffer and enable receiver */ + if (i557RUStart () == ERROR) + { + mask_557_ints (); /* Disable 557 interrupt */ + return; + } + + /* Send a packet */ + setUpPacket (pPacketBuf); + if (txPacket (pPacketBuf) == ERROR) + { + mask_557_ints (); /* Disable 557 interrupt */ + return; + } + + printf ("Press return to perform loopback through PHY.\n"); + sgets (buf); + + /* Configure for external loopback */ + if (i557Config (EXT_LOOP_BACK) == ERROR) + { + mask_557_ints (); /* Disable 557 interrupt */ + return; + } + + Wait(100); + + /* Initialize receive buffer and enable receiver */ + if (i557RUStart () == ERROR) + { + mask_557_ints (); /* Disable 557 interrupt */ + return; + } + + /* Send a packet */ + setUpPacket (pPacketBuf); + if (txPacket (pPacketBuf) == ERROR) + { + mask_557_ints (); /* Disable 557 interrupt */ + return; + } + + printf ("Press return to perform external loopback through\n"); + printf ("10/100 Base T Hub. NOTE: If test duration is not forever,\n"); + printf ("this test will work only if a properly functioning Hub\n"); + printf ("and Twisted Pair cable are attached to the network connector\n"); + printf ("on the front panel.\n"); + sgets (buf); + + printf ("Enter the number of times to run test (0 = forever): "); + ntimes = decIn(); + printf ("\n\n"); + +/* if (atod (inputLine, &ntimes) == FALSE) + ntimes = 0; +*/ + if (i557RUStart () == ERROR) + { + mask_557_ints (); /* Disable 557 interrupt */ + return; + } + + setUpPacket (pPacketBuf); + + if (ntimes == 0) + { + forever_flag = TRUE; + + while (1) + { + if ((i557RUStart() == ERROR)||(txPacket (pPacketBuf) == ERROR)) + { + printf ("Double-check TP cable and 10/100 Base T Hub\n"); + printf ("Try testing them with another system\n"); + printf ("(such as a workstation) that is working correctly.\n"); + mask_557_ints (); /* Disable 557 interrupt */ + return; + } + + count++; + if (((count) % 1000) == 0) + printf("Loopback Cycle Count = %d\n", count); + } + } + else + { + forever_flag = FALSE; + + for (i=0; i<ntimes; i++) + { + if ((i557RUStart() == ERROR)||(txPacket (pPacketBuf) == ERROR)) + { + printf ("Double-check TP cable and 10/100 Base T Hub\n"); + printf ("Try testing them with another system\n"); + printf ("(such as a workstation) that is working correctly.\n"); + mask_557_ints (); /* Disable 557 interrupt */ + return; + } + + count++; + printf("Loopback Cycle Count = %d\n", count); + } + + /* It worked! */ + + mask_557_ints (); /* Disable 557 interrupt */ + + printf ("\nEthernet controller passed. Press return to continue.\n"); + + sgets (buf); + } +} + + +/* Perform internal self test - returns OK if sucessful, ERROR if not. */ +static int i557SelfTest () +{ +volatile struct selfTest *pSelfTestMem; +UINT32 oldWord2; +long delay; +UINT32 temp; +int rtnVal; + + /* reset the 82557 to start with a clean slate */ + resetChip(); + + /* Allocate some memory for the self test */ + pSelfTestMem = (struct selfTest *) malloc (sizeof(struct selfTest)); + + if (pSelfTestMem == NULL) + { + printf ("Couldn't get memory for self test.\n"); + return (ERROR); + } + + printf ("Sending PORT* self-test command...\n"); + printf ("Local Dump address = 0x%X\n", pSelfTestMem); + + /* Set all bits in second word, wait until it changes or a timeout */ + pSelfTestMem->u.word2 = ~0; + oldWord2 = pSelfTestMem->u.word2; + + temp = ((UINT32) pSelfTestMem) + PORT_SELF_TEST; + + portWrite (temp); + + /* Wait for test completion or for timeout */ + for (delay = 0; (delay < MAX_DELAY) && (pSelfTestMem->u.word2 == oldWord2); delay++); /* Wait... */ + + /* Print results */ + printf ("Self test result: %s\n", (pSelfTestMem->u.bits.selfTest) ? "Fail" : "Pass"); + printf ("ROM content test: %s\n", (pSelfTestMem->u.bits.romTest) ? "Fail" : "Pass"); + printf ("Register test: %s\n", (pSelfTestMem->u.bits.regTest) ? "Fail" : "Pass"); + printf ("Diagnose test: %s\n", (pSelfTestMem->u.bits.diagnTest) ? "Fail" : "Pass"); + printf ("ROM signature: 0x%X\n", pSelfTestMem->romSig); + + rtnVal = pSelfTestMem->u.bits.selfTest ? ERROR : OK; + + return (rtnVal); +} + + +/* Initialize the 82557. */ +static int i557Init (void) +{ + /* Get memory for system data structures */ + if ( ((pRfd = (struct rfd *) malloc (sizeof(struct rfd))) == NULL) || + ((pPacketBuf = malloc(ETHERMTU + sizeof(UINT16) + 6)) == NULL) || + ((pCmdBlock = (union cmdBlock *) malloc (sizeof(union cmdBlock))) == NULL) ) + { + printf ("Memory allocation failed.\n"); + return (ERROR); + } + + /* Set EL bits in command block and rfd so we don't fall of the end */ + pCmdBlock->nop.el = END_OF_LIST; + pRfd->el = END_OF_LIST; + + /* Reset chip and initialize */ + printf ("Initializing... "); + + /* Reset 82557 */ + resetChip (); + + /* set up the CU and RU base values to 0x0 */ + sendCommand (LOAD_CU_BASE, RU_NOP, 0); + sendCommand (CU_NOP, LOAD_RU_BASE, 0); + + /* Initialize interrupts */ + + /* if it is the onboard i82559, it does not use the conventional PCI + interrupt routines because the interrupt is not multiplexed onto + the PCI bus */ + if ((unit_busno == 2) && (unit_devno == 0) && (unit_funcno == 0)) + { + if (isr_connect (ENET_INT_ID, (VOIDFUNCPTR)i557IntHandler, 0xdeadbeef) != OK) + { + printf ("Error connecting Ethernet interrupt!\n"); + return (ERROR); + } + if (enable_external_interrupt (ENET_INT_ID) != OK) + { + printf ("Error enabling Ethernet interrupt!\n"); + return (ERROR); + } + } + + else /* use regular PCI int connect scheme */ + { + if (pci_isr_connect (unit_intpin, unit_busno, unit_devno, i557IntHandler, 0xdeadbeef) != OK) + { + printf ("Error connecting Ethernet interrupt!\n"); + return (ERROR); + } + + } + unmask_557_ints(); + + printf ("Done\n"); + + return (OK); +} + + +static int initPHY (UINT32 device_type, int loop_mode) +{ +UINT16 temp_reg; +UINT8 revision; + + /* strip off revision and phy. id information */ + revision = (UINT8)(device_type & REVISION_MASK); + device_type &= ~REVISION_MASK; + + switch (device_type) + { + case ICS1890_PHY_ID: + temp_reg = readMDI (0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_CTRL); /* get ready for loopback setting */ + + switch (loop_mode) + { + case EXT_LOOP_BACK: /* loopback on the MII interface */ + temp_reg |= MDI_CTRL_LOOPBACK; /* MII loopback */ + break; + + case INT_LOOP_BACK: + default: + break; + } + + writeMDI(0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_CTRL, temp_reg); + break; + + case DP83840_PHY_ID: /* set the Intel-specified "must set" bits */ + temp_reg = readMDI (0,MDI_DEFAULT_PHY_ADDR, DP83840_PCR_REG); + temp_reg |= (PCR_TXREADY_SEL | PCR_FCONNECT); + writeMDI (0,MDI_DEFAULT_PHY_ADDR, DP83840_PCR_REG, temp_reg); + + /* get ready for loopback setting */ + temp_reg = readMDI (0,MDI_DEFAULT_PHY_ADDR, DP83840_LOOPBACK_REG); + temp_reg &= CLEAR_LOOP_BITS; + + switch (loop_mode) + { + case EXT_LOOP_BACK: + temp_reg |= TWISTER_LOOPBACK; + break; + + case INT_LOOP_BACK: + default: + break; + } + + writeMDI (0,MDI_DEFAULT_PHY_ADDR, DP83840_LOOPBACK_REG, temp_reg); + break; + + case I82553_PHY_ID: + case I82553_REVAB_PHY_ID: + case I82555_PHY_ID: + break; + + default: + return (ERROR); + break; + } + + return (OK); +} + + +/* Set hardware address of the 82557. */ +static int i557AddrSet () +{ + printf ("Setting hardware ethernet address to "); + printf ("%02X:%02X:%02X:", node_address[0], node_address[1], node_address[2]); + printf ("%02X:%02X:%02X... ", node_address[3], node_address[4], node_address[5]); + + /* Set up iaSetup command block and execute */ + bzero ((char *) pCmdBlock, sizeof(union cmdBlock)); + pCmdBlock->iaSetup.code = IA_SETUP; + pCmdBlock->iaSetup.el = END_OF_LIST; + bcopy (node_address, pCmdBlock->iaSetup.enetAddr, sizeof(node_address)); + + sendCommand (CU_START, RU_NOP, ((UINT32)pCmdBlock)); + + if ((waitForInt() == ERROR) || (pCmdBlock->iaSetup.ok != 1)) + { + printf ("failed. Status: 0x%04X.\n", pSCB->cmdStat.words.status); + printf ("C bit = %d\n",pCmdBlock->iaSetup.c); + printf ("OK bit = %d\n",pCmdBlock->iaSetup.ok); + return (ERROR); + } + + printf ("done.\n"); + + return (OK); +} + + +/* Configure the 82557. */ +static int i557Config (UINT8 loopBackMode) /* None, int, or ext 1, 2 (see etherTest.h) */ +{ + printf ("\nConfiguring for "); + + switch (loopBackMode) + { + case INT_LOOP_BACK: + printf ("internal loopback... "); + break; + case EXT_LOOP_BACK: + printf ("external loopback, LPBK* active... "); + break; + default: + printf ("Unknown loopback mode, exiting...\n"); + return (ERROR); + } + + /* Set up configure command block and execute */ + bzero ((char *) pCmdBlock, sizeof(union cmdBlock)); + pCmdBlock->configure.code = CONFIGURE; + pCmdBlock->configure.el = END_OF_LIST; + pCmdBlock->configure.configData[ 0] = CONFIG_BYTE_00; + pCmdBlock->configure.configData[ 1] = CONFIG_BYTE_01; + pCmdBlock->configure.configData[ 2] = CONFIG_BYTE_02; + pCmdBlock->configure.configData[ 3] = CONFIG_BYTE_03; + pCmdBlock->configure.configData[ 4] = CONFIG_BYTE_04; + pCmdBlock->configure.configData[ 5] = CONFIG_BYTE_05; + pCmdBlock->configure.configData[ 6] = CONFIG_BYTE_06; + pCmdBlock->configure.configData[ 7] = CONFIG_BYTE_07; + pCmdBlock->configure.configData[ 8] = CONFIG_BYTE_08; + pCmdBlock->configure.configData[ 9] = CONFIG_BYTE_09; + pCmdBlock->configure.configData[10] = CONFIG_BYTE_10 | loopBackMode; + pCmdBlock->configure.configData[11] = CONFIG_BYTE_11; + pCmdBlock->configure.configData[12] = CONFIG_BYTE_12; + pCmdBlock->configure.configData[13] = CONFIG_BYTE_13; + pCmdBlock->configure.configData[14] = CONFIG_BYTE_14; + pCmdBlock->configure.configData[15] = CONFIG_BYTE_15; + pCmdBlock->configure.configData[16] = CONFIG_BYTE_16; + pCmdBlock->configure.configData[17] = CONFIG_BYTE_17; + pCmdBlock->configure.configData[18] = CONFIG_BYTE_18; + + if (link_speed == SPEED_100M) + pCmdBlock->configure.configData[19] = CONFIG_BYTE_19_100T; + else + { + pCmdBlock->configure.configData[19] = CONFIG_BYTE_19_10T; + pCmdBlock->configure.configData[20] = CONFIG_BYTE_20; + pCmdBlock->configure.configData[21] = CONFIG_BYTE_21; + } + + sendCommand (CU_START, RU_NOP, ((UINT32)pCmdBlock)); + + if ((waitForInt() == ERROR) || (pCmdBlock->configure.ok != 1)) + { + printf ("failed. Status: 0x%04X.\n", + pSCB->cmdStat.words.status); + + return (ERROR); + } + + initPHY (phy_id, loopBackMode); /* set up the PHY interface appropriately */ + + printf ("done.\n"); + + return (OK); +} + + +static int i557RUStart () +{ + volatile long delay; + +#if 0 + printf ("Enabling receiver... "); +#endif + + bzero ((char *) pRfd, sizeof(struct rfd)); + + /* Set end-of-list bit in the rfd so we don't fall off the end */ + pRfd->el = END_OF_LIST; + pRfd->s = 1; + pRfd->sf = 0; /* Simplified mode */ + pRfd->rbdAddr = (UINT8 *) 0xffffffff; /* No RBD */ + /* buffer size: */ + pRfd->size = sizeof (pRfd->rxData) + sizeof (pRfd->destAddr) + sizeof (pRfd->sourceAddr) + sizeof (pRfd->length); + + sendCommand (CU_NOP, RU_START, ((UINT32)pRfd)); + + /* + * Poll, can't use waitForInt (), as this step doesn't generate interrupts. + */ + + i557Status = 0; + + /* Wait for timeout (i557Status changes) or RU_STAT is RU_READY */ + for (delay = 0; (delay < MAX_DELAY) && (pSCB->cmdStat.bits.rus != RU_READY); delay++) + ; /* Wait... */ + + if (pSCB->cmdStat.bits.rus != RU_READY) + { + printf ("failed. Status: 0x%04X.\n", + pSCB->cmdStat.words.status); + return (ERROR); + } + +#if 0 + printf ("done. Status: 0x%04X.\n", pSCB->cmdStat.words.status); +#endif + + return (OK); +} + + +/* + * Get packet ready to send out over the network. Buffer should be + * ETHERMTU + sizeof(enet_addr) + sizeof(UINT16) + */ +static void setUpPacket (char *pBuf)/* Where to put it */ +{ + bcopy (node_address, pBuf, sizeof(node_address)); + pBuf += sizeof(node_address); /* skip dest. address */ + + *((UINT16 *) pBuf) = 0; + pBuf += sizeof(UINT16); /* skip length field */ + + makePacket (pBuf, ETHERMTU); +} + + +/* Send and verify a packet using the current loopback mode. */ +static int txPacket (char *pBuf) /* Dest addr, ethertype, buffer */ +{ + int status = OK; + + /* Set up transmit command block and execute */ + bzero ((char *) pCmdBlock, sizeof(union cmdBlock)); + pCmdBlock->transmit.code = TRANSMIT; + pCmdBlock->transmit.el = END_OF_LIST; + pCmdBlock->transmit.sf = 0; /* Simplified mode */ + pCmdBlock->transmit.tbdAddr = (UINT8 *) 0xffffffff; /* No TBD */ + pCmdBlock->transmit.eof = 1; /* Entire frame here */ + /* # bytes to tx: */ + pCmdBlock->transmit.tcbCount = sizeof (pCmdBlock->transmit.destAddr) + sizeof (pCmdBlock->transmit.length) + + sizeof (pCmdBlock->transmit.txData); + +#if 0 + printf ("destAddr size = %d\n", sizeof (pCmdBlock->transmit.destAddr)); + printf ("length size = %d\n", sizeof (pCmdBlock->transmit.length)); + printf ("Transmitting %d bytes\n", pCmdBlock->transmit.tcbCount); +#endif + + bcopy (pBuf, pCmdBlock->transmit.destAddr, sizeof(node_address) + sizeof(UINT16) + ETHERMTU); + + rxSem = 0; /* no Receive interrupt */ + + sendCommand (CU_START, RU_NOP, ((UINT32)pCmdBlock)); + + if (waitForInt() == ERROR) + { + printf ("No Transmit Interrupt\n"); + status = ERROR; + } + + if (pCmdBlock->transmit.ok != 1) + { + printf ("tx failed. Status: 0x%04X.\n", + pSCB->cmdStat.words.status); + status = ERROR; + } + + if (status == ERROR) + { + printf ("Transmit OK = %d\n", pCmdBlock->transmit.ok); + return (ERROR); + } + +#if 1 + if (waitForRxInt() == ERROR) + { + printf ("No Receive Interrupt\n"); + status = ERROR; + } + + if (pRfd->ok != 1) + { + printf ("rx failed. Status: 0x%04X.\n", pSCB->cmdStat.words.status); + status = ERROR; + } + +#if 1 + /* If RU still ready, hang for receive interrupt */ + if (pSCB->cmdStat.bits.rus == RU_READY) + { + if (waitForRxInt() == ERROR) + { + printf ("No Receive Interrupt\n"); + status = ERROR; + } + + if (pRfd->ok != 1) + { + printf ("rx failed. Status: 0x%04X.\n", pSCB->cmdStat.words.status); + status = ERROR; + } + } +#endif + + if (status == ERROR) + { + printf ("\nTransmit Stats:\n"); + printf ("---------------\n"); + printf ("Transmit OK = %d\n", pCmdBlock->transmit.ok); + + printf ("\nReceive Stats:\n"); + printf ("---------------\n\n"); + printf ("Receive OK = %d\n", pRfd->ok); + printf ("CRC Error = %d\n", pRfd->crcErr); + printf ("Alignment Error = %d\n", pRfd->alignErr); + printf ("Resource Error = %d\n", pRfd->noRsrc); + printf ("DMA Overrun Error = %d\n", pRfd->dmaOverrun); + printf ("Frame Too Short Error = %d\n", pRfd->frameTooshort); + printf ("Receive Collision Error = %d\n", pRfd->rxColl); + return (ERROR); + } + +#if 0 + printf ("Packet Actual Size = %d\n", pRfd->actCount); +#endif + + if (checkPacket (pCmdBlock->transmit.txData, pRfd->rxData, ETHERMTU) == ERROR) + { + printf ("data verify error.\n"); + return (ERROR); + } + + if (forever_flag == FALSE) printf ("data OK.\n"); +#endif + + return (OK); +} + + +/* + * "Poor Man's Malloc" - return a pointer to a block of memory at least + * The block returned will have been zeroed. + */ +static char *malloc (int numBytes) /* number of bytes needed */ +{ + volatile char *rtnPtr; /* ptr to return to caller */ + long new_mem_pool; /* For figuring new pool base address */ + + rtnPtr = mem_pool; /* Return pointer to start of free pool */ + + /* Now calculate new base of free memory pool (round to >= 16 bytes) */ + new_mem_pool = (UINT32) mem_pool; + new_mem_pool = ((new_mem_pool + numBytes + 0x10) & (~((UINT32) 0x0f))); + mem_pool = (volatile char *) new_mem_pool; + + bzero (rtnPtr, numBytes); + + return ((char *) rtnPtr); +} + + +/* "Poor Man's bzero" - zero's a block of memory. */ +static void bzero (volatile char *ptr, long num_bytes) +{ +volatile long i; /* loop counter */ + + /* zero out space */ + for (i = 0; i < num_bytes; *ptr++ = 0, i++) + ; +} + + +/* + * Write "value" to PORT register of PRO/100. + */ +static void portWrite (UINT32 value) +{ + *PORT_REG(adapter[0]) = value; +} + + +/****************************************************************************** +* +* sendCommand - send a command to the 82557 via the on-chip SCB +* +* Send a command to the 82557. On the 82557, the Channel Attention signal +* has been replaced by an on-chip SCB. Accesses to the Command Word portion +* of the SCB automatically forces the '557 to look at the various data +* structures which make up its interface. +*/ +static void sendCommand (UINT8 cuc, UINT8 ruc, UINT32 scb_general_ptr) +{ + register CMD_STAT_U temp_cmdStat; + volatile union cmdBlock *pBlock = (union cmdBlock *)scb_general_ptr; + volatile int loop_ctr; + + /* Mask adapter interrupts to prevent the interrupt handler from + playing with the SCB */ + mask_557_ints(); + + /* must wait for the Command Unit to become idle to prevent + us from issueing a CU_START to an active Command Unit */ + for (loop_ctr = BUSY_WAIT_LIMIT; loop_ctr > 0; loop_ctr--) + { + if ((pSCB->cmdStat.words.status & SCB_S_CUMASK) == SCB_S_CUIDLE) + break; + } + if (loop_ctr == 0) + { + printf("sendCommand: CU won't go idle, command ignored\n"); + unmask_557_ints(); + return; + } + + /* when setting the command word, read the current word from + the SCB and preserve the upper byte which contains the interrupt + mask bit */ + temp_cmdStat.words.command = (pSCB->cmdStat.words.command & 0xff00); + temp_cmdStat.words.status = 0; + + /* set up the Command and Receive unit commands */ + temp_cmdStat.bits.cuc = cuc & 0x07; + temp_cmdStat.bits.ruc = ruc & 0x07; + + /* Clear flag */ + waitSem = 0; + + /* write the General Pointer portion of the SCB first */ + pSCB->scb_general_ptr = scb_general_ptr; + + /* write the Command Word of the SCB */ + pSCB->cmdStat.words.command = temp_cmdStat.words.command; + + /* only wait for command which will complete immediately */ + if ((scb_general_ptr != 0/* NULL*/) && (ruc != RU_START)) + { + /* wait for command acceptance and completion */ + for (loop_ctr = BUSY_WAIT_LIMIT; loop_ctr > 0; loop_ctr--) + { + if ((pSCB->cmdStat.bits.cuc == 0) && (pBlock->nop.c == 1)) + break; + } + if (loop_ctr == 0) + { + printf("sendCommand: Timeout on command complete\n"); + printf("Cmd Complete bit = %02X\n", pBlock->nop.c); + printf("CU command = 0x%02X\n", cuc); + printf("RU command = 0x%02X\n", ruc); + printf("SCB Gen Ptr = 0x%X\n", scb_general_ptr); + printf("scb status = 0x%04X\n", pSCB->cmdStat.words.status); + printf("scb command = 0x%04X\n", pSCB->cmdStat.words.command); + } + } + +#if 0 + /* DEBUG */ + printf("scb command = 0x%04X\n", pSCB->cmdStat.words.command); + printf("scb status = 0x%04X\n", pSCB->cmdStat.words.status); +#endif + + unmask_557_ints(); + return; +} + + +/* + * Do a port reset on 82557. + */ +static void resetChip () +{ + portWrite (PORT_RESET); /* bits 4-31 not used for reset */ + + /* wait 5 msec for device to stabilize */ + Wait(5); +} + + +/* + * Setup contents of a packet. + */ +static void makePacket (UINT8 *pPacket, int length) +{ +int byteNum; /* Current byte number */ + + for (byteNum = 0; byteNum < length; byteNum++) + *pPacket++ = byteNum + ' '; +} + + +/* + * Verify contents of a received packet to what was transmitted. + * Returns OK if they match, ERROR if not. + */ +static int checkPacket (pTxBuffer, pRxBuffer, length) +UINT8 *pTxBuffer; /* Pointer data that was transmitted */ +UINT8 *pRxBuffer; /* Pointer data that was received */ +int length; /* How many bytes to check */ +{ +int byteNum; /* Current byte number */ + +#if 0 + printf ("\n"); + printf ("Transmit Buffer at 0x%08X\n", pTxBuffer); + printf ("Receive Buffer at 0x%08X\n", pRxBuffer); +#endif + for (byteNum = 0; byteNum < length; byteNum++) + { + if (*pTxBuffer++ != *pRxBuffer++) + { + printf("Error at byte 0x%x\n", byteNum); + printf("Expected 0x%02X, got 0x%02X\n", *(pTxBuffer - 1), *(pRxBuffer - 1)); + return (ERROR); + } + } + return (OK); +} + + +/* + * Interrupt handler for i82557. It acknowledges the interrupt + * by setting the ACK bits in the command word and issuing a + * channel attention. It then updates the global status variable + * and gives the semaphore to wake up the main routine. + */ +int i557IntHandler (int arg) /* should return int */ +{ +register CMD_STAT_U temp_cmdStat; +register int rxFlag = FALSE; + + temp_cmdStat.words.status = pSCB->cmdStat.words.status; + + /* check to see if it was the PRO/100 */ + if (temp_cmdStat.words.status & I557_INT) + { + /* Wait for command word to clear - indicates no pending commands */ + while (pSCB->cmdStat.words.command) + ; + + /* Update global status variable */ + i557Status = temp_cmdStat.words.status; + +#if 0 + printf ("i557IntHandler: i557Status = 0x%04x\n", i557Status); +#endif + + /* If the interrupt was due to a received frame... */ + if (temp_cmdStat.bits.statack_fr) + rxFlag = TRUE; + + temp_cmdStat.words.status = temp_cmdStat.words.status & I557_INT; + + /* Acknowledge interrupt by setting ack bits */ + pSCB->cmdStat.words.status = temp_cmdStat.words.status; + + /* Wait for command word to clear - indicates IACK accepted */ + while (pSCB->cmdStat.words.command) + ; + +#if 0 + /* DEBUG */ + printf ("give waitSem\n"); +#endif + + /* Update global status variable and unblock task */ + waitSem = 1; + + if (rxFlag == TRUE) + rxSem = 1; + + return(1); /* serviced - return 1 */ + } + + return(0); /* nothing serviced - return 0 */ +} + + + +/* + * Take the semaphore and block until i557 interrupt or timeout. + * Returns OK if an interrupt occured, ERROR if a timeout. + */ +static int waitForInt() +{ +int num_ms = 0; + + while ((waitSem == 0) && (num_ms != 2000)) /* wait max 2secs for the interrupt */ + { + delay_ms(1); + num_ms++; + } + + if (!waitSem) + { + printf("Wait error!\n"); + return (ERROR); + } + else + return (OK); + +} + + +static int waitForRxInt() +{ +int num_ms = 0; + + while ((rxSem == 0) && (num_ms != 2000)) /* wait max 2secs for the interrupt */ + { + delay_ms(1); + num_ms++; + } + + if (!rxSem) + { + printf("Rx Wait error!\n"); + return (ERROR); + } + else + return (OK); +} + + +static UINT16 readMDI (int unit, UINT8 phyAdd, UINT8 regAdd) +{ + +register MDI_CONTROL_U mdiCtrl; +int num_ms = 0; + + + /* prepare for the MDI operation */ + mdiCtrl.bits.ready = MDI_NOT_READY; + mdiCtrl.bits.intEnab = MDI_POLLED; /* no interrupts */ + mdiCtrl.bits.op = MDI_READ_OP; + mdiCtrl.bits.phyAdd = phyAdd & 0x1f; + mdiCtrl.bits.regAdd = regAdd & 0x1f; + + /* start the operation */ + *MDI_CTL_REG(adapter[unit]) = mdiCtrl.word; + + /* delay a bit */ + Wait (1); + + /* poll for completion */ + mdiCtrl.word = *MDI_CTL_REG(adapter[unit]); + + while ((mdiCtrl.bits.ready == MDI_NOT_READY) && (num_ms != 2000)) /* wait max 2secs */ + { + mdiCtrl.word = *MDI_CTL_REG(adapter[unit]); + delay_ms(1); + num_ms++; + } + + if (num_ms >= 2000) + { + printf ("readMDI Timeout!\n"); + return (-1); + } + else + return ((UINT16)mdiCtrl.bits.data); +} + + +static void writeMDI (int unit, UINT8 phyAdd, UINT8 regAdd, UINT16 data) +{ + +register MDI_CONTROL_U mdiCtrl; +int num_ms = 0; + + + /* prepare for the MDI operation */ + mdiCtrl.bits.ready = MDI_NOT_READY; + mdiCtrl.bits.intEnab = MDI_POLLED; /* no interrupts */ + mdiCtrl.bits.op = MDI_WRITE_OP; + mdiCtrl.bits.phyAdd = phyAdd & 0x1f; + mdiCtrl.bits.regAdd = regAdd & 0x1f; + mdiCtrl.bits.data = data & 0xffff; + + /* start the operation */ + *MDI_CTL_REG(adapter[unit]) = mdiCtrl.word; + + /* delay a bit */ + Wait (1); + + /* poll for completion */ + mdiCtrl.word = *MDI_CTL_REG(adapter[unit]); + + while ((mdiCtrl.bits.ready == MDI_NOT_READY) && (num_ms != 2000)) + { + mdiCtrl.word = *MDI_CTL_REG(adapter[unit]); + delay_ms(1); + num_ms++; + } + if (num_ms >= 2000) + printf ("writeMDI Timeout!\n"); + + return; +} + + +static void Wait (int msecs) +{ + delay_ms(msecs); +} + + +static int get_ether_addr ( + int unit, + UINT8 *buffer, + int print_flag /* TRUE to print the information */ + ) +{ + UINT16 temp_node_addr[3] = {0,0,0}; + register int i; + + /* Get the adapter's node address */ + if (eeprom_read (adapter[unit],IA_OFFSET,temp_node_addr,3) != OK) + { + printf ("Error reading the IA address from Serial EEPROM.\n"); + return (ERROR); + } + + buffer[0] = (UINT8)(temp_node_addr[0] & 0x00ff); + buffer[1] = (UINT8)((temp_node_addr[0] & 0xff00)>>8); + buffer[2] = (UINT8)(temp_node_addr[1] & 0x00ff); + buffer[3] = (UINT8)((temp_node_addr[1] & 0xff00)>>8); + buffer[4] = (UINT8)(temp_node_addr[2] & 0x00ff); + buffer[5] = (UINT8)((temp_node_addr[2] & 0xff00)>>8); + + if (print_flag == TRUE) + { + printf("Ethernet Address = [ "); + for (i=0; i<6; i++) + { + printf("0x%02X ", buffer[i]); + } + printf("]\n\n"); + } + return (OK); +} + + +void bcopy(UINT32* src, UINT32* dst, int num_bytes) +{ +int i; + for (i = 0; i < num_bytes; i++) + *dst++ = *src++; +} +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/ether_test.h @@ -0,0 +1,604 @@ +//============================================================================= +// +// ether_test.h - Cyclone Diagnostics +// +//============================================================================= +//####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) 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-25 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + + +#define ETHERMTU 1500 +#define OK 0 +#define ERROR -1 + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL 0 +#endif + +/* Starting location for ether_test private malloc pool */ +#define ETHER_MEM_POOL 0xa0400000 /* above top of diags. BE CAREFUL */ + +/* Length of interrupt time-out loops. */ +#define MAX_DELAY 6000000 + +/* PCI Runtime Register offsets */ +#define SCB_OFFSET 0 +#define SCB_STAT_REG(n) ((UINT16 *)(n + 0x00)) +#define SCB_CMD_REG(n) ((UINT16 *)(n + 0x02)) +#define SCB_GENPTR_REG(n) ((UINT32 *)(n + 0x04)) +#define PORT_REG(n) ((UINT32 *)(n + 0x08)) +#define FLASH_CTL_REG(n) ((UINT16 *)(n + 0x0c)) +#define EEPROM_CTL_REG(n) ((UINT16 *)(n + 0x0e)) +#define MDI_CTL_REG(n) ((UINT32 *)(n + 0x10)) +#define RXBC_REG(n) ((UINT32 *)(n + 0x14)) + +/* PORT* commands (lower 4 bits) */ +#define PORT_RESET ((UINT32) 0x0) +#define PORT_SELF_TEST ((UINT32) 0x1) +#define PORT_DUMP ((UINT32) 0x3) + +/* Individual Address offset into '557's serial eeprom */ +#define IA_OFFSET 0 + +/* Command codes for the command fields of command descriptor blocks */ + +#define NOP 0 +#define IA_SETUP 1 +#define CONFIGURE 2 +#define MC_SETUP 3 +#define TRANSMIT 4 +#define TDR 5 +#define DUMP 6 +#define DIAGNOSE 7 + +/* Commands for CUC in command word of SCB */ +#define CU_NOP 0 +#define CU_START 1 +#define CU_RESUME 2 +#define LOAD_DUMPCTR_ADDR 4 /* Load Dump Counters Address */ +#define DUMP_STAT_COUNTERS 5 /* Dump Statistical Counters */ +#define LOAD_CU_BASE 6 /* Load CU Base Register */ +#define DUMP_RESET_COUNTERS 7 /* Dump and Reset Statistical + Counters */ +/* Commands for RUC in command word of SCB */ +#define RU_NOP 0 +#define RU_START 1 +#define RU_RESUME 2 +#define RU_ABORT 4 +#define LOAD_HDS 5 /* Load Header Data Size */ +#define LOAD_RU_BASE 6 /* Load RU Base Register */ +#define RBD_RESUME 7 /* Resume frame reception */ + +/* Misc. defines */ +#define END_OF_LIST 1 +#define BUSY 1 + +/* RU Status field */ +#define RU_IDLE 0x0 +#define RU_SUSPENDED 0x1 +#define RU_NORESOURCE 0x2 +#define RU_READY 0x4 +#define RU_SUSP_NORBD 0x5 +#define RU_NORSRC_NORBD 0x6 +#define RU_READY_NORBD 0xc + +/* Mask for interrupt status bits in SCB - six possible sources */ +#define I557_INT 0xfc00 + +/* MDI definitions */ +#define MDI_WRITE_OP 0x01 +#define MDI_READ_OP 0x02 +#define MDI_NOT_READY 0 +#define MDI_POLLED 0 +#define MDI_DEFAULT_PHY_ADDR 1 /* when only one PHY */ + +/* PHY device register addresses */ + +/* generic register addresses */ +#define MDI_PHY_CTRL 0 +#define MDI_PHY_STAT 1 +#define MDI_PHY_ID_1 2 +#define MDI_PHY_ID_2 3 +#define MDI_PHY_AUTO_AD 4 +#define MDI_PHY_AUTO_LNK 5 +#define MDI_PHY_AUTO_EXP 6 + +#define I82555_PHY_ID 0x02a80150 +#define ICS1890_PHY_ID 0x0015f420 +#define DP83840_PHY_ID 0x20005c00 +#define I82553_PHY_ID 0x02a80350 +#define I82553_REVAB_PHY_ID 0x03e00000 + +/* I82555/558 Status and Control register */ +#define I82555_STATCTRL_REG 0x10 +#define I82555_100_MBPS (1 << 1) +#define I82555_10_MBPS (0 << 1) + +#define REVISION_MASK 0xf + +/* DP83840 specific register information */ +#define DP83840_PCR_REG 0x17 +#define PCR_TXREADY_SEL (1 << 10) +#define PCR_FCONNECT (1 << 5) + +/* ICS1890 QuickPoll Detailed Status register */ +#define ICS1890_QUICKPOLL_REG 0x11 +#define QUICK_100_MBPS (1 << 15) +#define QUICK_10_MBPS (0 << 15) +#define QUICK_LINK_VALID (1 << 0) +#define QUICK_LINK_INVALID (0 << 0) + +#define DP83840_PHY_ADDR_REG 0x19 +#define PHY_ADDR_CON_STATUS (1 << 5) +#define PHY_ADDR_SPEED_10_MBPS (1 << 6) +#define PHY_ADDR_SPEED_100_MBPS (0 << 6) + +#define DP83840_LOOPBACK_REG 0x18 +#define TWISTER_LOOPBACK (0x1 << 8) +#define REMOTE_LOOPBACK (0x2 << 8) +#define CLEAR_LOOP_BITS ~(TWISTER_LOOPBACK | REMOTE_LOOPBACK) + +/* 82553 specific register information */ +#define I82553_PHY_EXT_REG0 0x10 +#define EXT_REG0_100_MBPS (1 << 1) +#define GET_REV_CNTR(n) ((n & 0x00e0) >> 5) +#define I82553_PHY_EXT_REG1 0x14 + +/* MDI Control Register bits */ +#define MDI_CTRL_COLL_TEST (1 << 7) +#define MDI_CTRL_FULL_DUPLEX (1 << 8) +#define MDI_CTRL_RESTART_AUTO (1 << 9) +#define MDI_CTRL_ISOLATE (1 << 10) +#define MDI_CTRL_POWER_DOWN (1 << 11) +#define MDI_CTRL_AUTO_ENAB (1 << 12) +#define MDI_CTRL_AUTO_DISAB (0 << 12) +#define MDI_CTRL_100_MBPS (1 << 13) +#define MDI_CTRL_10_MBPS (0 << 13) +#define MDI_CTRL_LOOPBACK (1 << 14) +#define MDI_CTRL_RESET (1 << 15) + +/* MDI Status Register bits */ +#define MDI_STAT_EXTENDED (1 << 0) +#define MDI_STAT_JABBER (1 << 1) +#define MDI_STAT_LINK (1 << 2) +#define MDI_STAT_AUTO_CAPABLE (1 << 3) +#define MDI_STAT_REMOTE_FLT (1 << 4) +#define MDI_STAT_AUTO_COMPLETE (1 << 5) +#define MDI_STAT_10BASET_HALF (1 << 11) +#define MDI_STAT_10BASET_FULL (1 << 12) +#define MDI_STAT_TX_HALF (1 << 13) +#define MDI_STAT_TX_FULL (1 << 14) +#define MDI_STAT_T4_CAPABLE (1 << 15) + +/* + * Structure allignments. All addresses passed to the 557 must be + * even (bit 0 = 0), EXCEPT for addresses passed by the PORT* + * function (self-test address & dump address, which must be 16-byte aligned. + */ + +#define SELF_TEST_ALIGN 16 +#define DUMP_ALIGN 16 +#define DEF_ALIGN 4 + +/* + * Bit definitions for the configure command. NOTE: Byte offsets are + * offsets from the start of the structure (8 and up) to correspond + * with the offsets in the PRO/100 PCI Adapter manual. + */ + +/* Byte 0 */ +#define BYTE_COUNT 0x16 /* use all 22 configure bytes */ +#define CONFIG_BYTE_00 (BYTE_COUNT) + +/* Byte 1 */ +#define RX_FIFO_LIMIT 0x08 +#define CONFIG_BYTE_01 (RX_FIFO_LIMIT) + +/* Byte 2 */ +#define ADAPT_IFS 0x00 +#define CONFIG_BYTE_02 (ADAPT_IFS) + +/* Byte 3 - must be 0x00 */ +#define CONFIG_BYTE_03 (0x00) + +/* Byte 4 */ +#define RX_DMA_BCOUNT 0x00 +#define CONFIG_BYTE_04 (RX_DMA_BCOUNT) + +/* Byte 5 */ +#define TX_DMA_BCOUNT 0x00 +#define DMA_BCOUNT_ENAB 0x80 +#define CONFIG_BYTE_05 (DMA_BCOUNT_ENAB | TX_DMA_BCOUNT) + +/* Byte 6 */ +#define NO_LATE_SCB 0x00 +#define NO_TNO_INT 0x00 /* no interrupt on xmit failure */ +#define INT_CU_IDLE 0x08 /* interrupt when CU goes idle */ +#define NO_SV_BAD_FRAME 0x00 /* don't save bad frames */ +#define DISCARD_RX_OVER 0x00 /* discard overrun frames */ +#define BYTE6_REQUD 0x32 /* required "1" bits */ + +#define CONFIG_BYTE_06 (NO_LATE_SCB | NO_TNO_INT | INT_CU_IDLE |\ + NO_SV_BAD_FRAME | DISCARD_RX_OVER | BYTE6_REQUD) + +/* Byte 7 */ +#define DISCARD_SHORT_RX 0x00 /* discard short rx frames */ +#define ONE_URUN_RETRY 0x02 /* one underrun retry */ +#define CONFIG_BYTE_07 (DISCARD_SHORT_RX | ONE_URUN_RETRY) + +/* Byte 8 */ +#define USE_503_MODE 0x00 +#define USE_MII_MODE 0x01 +#define CONFIG_BYTE_08 (USE_MII_MODE) + +/* Byte 9 */ +#define CONFIG_BYTE_09 (0x00) + +/* Byte 10 */ +#define INSERT_SRC_ADDR 0 /* Source address comes from IA of '557 */ +#define PREAMBLE_LEN 0x20 /* 7 bytes */ +#define NO_LOOP_BACK 0x00 +#define INT_LOOP_BACK 0x40 +#define EXT_LOOP_BACK 0xc0 +#define BYTE10_REQUD 0x06 /* required "1" bits */ +#define CONFIG_BYTE_10 (NO_LOOP_BACK | PREAMBLE_LEN | INSERT_SRC_ADDR | BYTE10_REQUD) + +/* Byte 11 */ +#define LIN_PRIORITY 0 /* normal CSMA/CD */ +#define CONFIG_BYTE_11 (LIN_PRIORITY) + +/* Byte 12 */ +#define LIN_PRIORITY_MODE 0 +#define IF_SPACING 96 /* inter-frame spacing */ +#define CONFIG_BYTE_12 (IF_SPACING | LIN_PRIORITY_MODE) + +/* Byte 13 */ +#define CONFIG_BYTE_13 (0x00) + +/* Byte 14 */ +#define CONFIG_BYTE_14 (0xf2) + +/* Byte 15 */ +#define PROM_MODE 0 /* not promiscuous */ +#define BROADCAST 0 /* disabled */ +#define CRS 0x80 /* CDT = carrier */ +#define BYTE15_REQUD 0x48 /* required "1" bits */ +#define CONFIG_BYTE_15 (PROM_MODE | BROADCAST | CRS | BYTE15_REQUD) + +/* Byte 16 */ +#define CONFIG_BYTE_16 (0x00) + +/* Byte 17 */ +#define CONFIG_BYTE_17 (0x40) + +/* Byte 18 */ +#define STRIPPING_DISABLE 0x00 +#define STRIPPING_ENABLE 0x01 +#define PADDING_ENABLE 0x02 +#define XFER_CRC 0x04 /* store CRC */ +#define NO_XFER_CRC 0x00 +#define BYTE18_REQUD 0xf0 /* required "1" bits */ +#define CONFIG_BYTE_18 (NO_XFER_CRC | PADDING_ENABLE | STRIPPING_ENABLE | BYTE18_REQUD) + +/* Byte 19 */ +#define NO_FORCE_FDX 0x00 +#define FORCE_FDX 0x40 +#define FDX_PIN_ENAB 0x80 +#define CONFIG_BYTE_19_10T FORCE_FDX +#define CONFIG_BYTE_19_100T NO_FORCE_FDX + +/* Byte 20 */ +#define NO_MULTI_IA 0x00 +#define CONFIG_BYTE_20 (NO_MULTI_IA) + +/* Byte 21 */ +#define NO_MULTI_ALL 0x00 +#define CONFIG_BYTE_21 (NO_MULTI_ALL) + +#define SCB_S_CUMASK 0x00c0 /* state mask */ +#define SCB_S_CUIDLE (0x00 << 6) /* CU is idle */ +#define SCB_S_CUSUSP (0x01 << 6) /* CU is suspended */ +#define SCB_S_CUACTIVE (0x02 << 6) /* CU is active */ +#define SCB_S_CURSV1 (0x03 << 6) /* reserved */ + +/* + * 82557 structures. NOTE: the 557 is used in 32-bit linear addressing + * mode. See alignment restrictions above. + */ + +/* Result of PORT* self-test command - MUST be 16 byte aligned! */ +struct selfTest { + UINT32 romSig; /* signature of rom */ + union { /* Flag bits - as UINT32 or field */ + struct { + UINT32 rsrv1 : 2; + UINT32 romTest : 1; + UINT32 regTest : 1; + UINT32 rsrv2 : 1; + UINT32 diagnTest : 1; + UINT32 rsrv3 : 6; + UINT32 selfTest : 1; + UINT32 rsrv4 : 19; + } bits; + UINT32 word2; + } u; +}; + +/* MDI Control Register */ +typedef union +{ + struct + { + UINT32 data : 16; /* data to write or data read */ + UINT32 regAdd : 5; /* PHY register address */ + UINT32 phyAdd : 5; /* PHY address */ + UINT32 op : 2; /* opcode, 1 for MDI write, 2 for MDI read */ + UINT32 ready : 1; /* 1 = operation complete */ + UINT32 intEnab : 1; /* 1 = interrupt at end of cycle */ + UINT32 rsrv : 2; /* reserved */ + } bits; + UINT32 word; +} MDI_CONTROL_U; + +/* Command/Status Word of SCB */ +typedef union +{ + struct + { + UINT32 rsrv1 : 2; /* Reserved */ + UINT32 rus : 4; /* Receive unit status */ + UINT32 cus : 2; /* Command unit status */ + UINT32 rsrv2 : 2; /* Reserved */ + UINT32 statack_swi : 1; /* Software generated int. */ + UINT32 statack_mdi : 1; /* MDI read/write complete */ + UINT32 statack_rnr : 1; /* RU not ready */ + UINT32 statack_cna : 1; /* CU not active */ + UINT32 statack_fr : 1; /* Frame reception done */ + UINT32 statack_cx_tno : 1; /* Cmd exec completed */ + UINT32 ruc : 3; /* Receive unit command */ + UINT32 rsrv3 : 1; /* Reserved */ + UINT32 cuc : 3; /* Command unit command */ + UINT32 rsrv4 : 1; /* Reserved */ + UINT32 m : 1; /* Interrupt mask bit */ + UINT32 si : 1; /* Software generated int. */ + UINT32 rsrv5 : 6; /* Reserved */ + } bits; + struct + { + UINT16 status; + UINT16 command; + } words; +} CMD_STAT_U; + +/* System command block - on chip for the 82557 */ +struct SCBtype +{ + CMD_STAT_U cmdStat; + UINT32 scb_general_ptr; /* SCB General Pointer */ +}; + +/* Command blocks - declared as a union; some commands have different fields */ +union cmdBlock { + /* No operation */ + struct { + UINT32 rsrv1 : 13; /* reserved bits (set to 0) */ + UINT32 ok : 1; /* 1 = command completed, no error */ + UINT32 rsrv2 : 1; /* reserved bits (set to 0) */ + UINT32 c : 1; /* 1 = command completed */ + UINT32 code : 3; /* command code (0 = NOP) */ + UINT32 rsrv3 : 10; /* reserved bits (set to 0) */ + UINT32 i : 1; /* 1 = interrupt upon completion */ + UINT32 s : 1; /* 1 = suspend CU upon completion */ + UINT32 el : 1; /* 1 = last cmdBlock in list */ + union cmdBlock *link; /* next block in list */ + } nop; + /* Individual address setup */ + struct { + UINT32 rsrv1 : 13; /* reserved bits (set to 0) */ + UINT32 ok : 1; /* 1 = command completed, no error */ + UINT32 rsrv2 : 1; /* reserved bits (set to 0) */ + UINT32 c : 1; /* 1 = command completed */ + UINT32 code : 3; /* command code (1 = ia setup) */ + UINT32 rsrv3 : 10; /* reserved bits (set to 0) */ + UINT32 i : 1; /* 1 = interrupt upon completion */ + UINT32 s : 1; /* 1 = suspend CU upon completion */ + UINT32 el : 1; /* 1 = last cmdBlock in list */ + union cmdBlock *link; /* next block in list */ + UINT8 enetAddr[6]; /* hardware ethernet address */ + UINT16 rsrv4; /* padding */ + } iaSetup; + /* Configure */ + struct { + UINT32 rsrv1 : 13; /* reserved bits (set to 0) */ + UINT32 ok : 1; /* 1 = command completed, no error */ + UINT32 rsrv2 : 1; /* reserved bits (set to 0) */ + UINT32 c : 1; /* 1 = command completed */ + UINT32 code : 3; /* command code (2 = configure) */ + UINT32 rsrv3 : 10; /* reserved bits (set to 0) */ + UINT32 i : 1; /* 1 = interrupt upon completion */ + UINT32 s : 1; /* 1 = suspend CU upon completion */ + UINT32 el : 1; /* 1 = last cmdBlock in list */ + union cmdBlock *link; /* next block in list */ + UINT8 configData[20]; /* configuration data */ + } configure; + /* Multicast address setup */ + struct { + UINT32 rsrv1 : 13; /* reserved bits (set to 0) */ + UINT32 ok : 1; /* 1 = command completed, no error */ + UINT32 rsrv2 : 1; /* reserved bits (set to 0) */ + UINT32 c : 1; /* 1 = command completed */ + UINT32 code : 3; /* command code (3 = mc setup) */ + UINT32 rsrv3 : 10; /* reserved bits (set to 0) */ + UINT32 i : 1; /* 1 = interrupt upon completion */ + UINT32 s : 1; /* 1 = suspend CU upon completion */ + UINT32 el : 1; /* 1 = last cmdBlock in list */ + union cmdBlock *link; /* next block in list */ + UINT16 mcCount; /* # of bytes in mcAddrList[] */ + UINT8 mcAddrList[6]; /* list of multicast addresses */ + } mcSetup; + /* Transmit */ + struct { + UINT32 rsrv1 : 12; /* reserved bits (set to 0) */ + UINT32 u : 1; /* 1 = underrun was encountered */ + UINT32 ok : 1; /* 1 = command completed, no error */ + UINT32 rsrv2 : 1; /* reserved bits (set to 0) */ + UINT32 c : 1; /* 1 = command completed */ + UINT32 code : 3; /* command code (4 = transmit) */ + UINT32 sf : 1; /* 1 = flexible mode */ + UINT32 rsrv3 : 9; /* reserved bits (set to 0) */ + UINT32 i : 1; /* 1 = interrupt upon completion */ + UINT32 s : 1; /* 1 = suspend CU upon completion */ + UINT32 el : 1; /* 1 = last cmdBlock in list */ + union cmdBlock *link; /* next block in list */ + UINT8 *tbdAddr; /* tx buf addr; all 1s for simp mode */ + UINT32 tcbCount : 14; /* # bytes to be tx from cmd block */ + UINT32 rsrv4 : 1; /* reserved (set to 0) */ + UINT32 eof : 1; /* 1 = entire frame in cmd block */ + UINT8 tx_threshold; /* # of bytes in FIFO before xmission */ + UINT8 tbd_number; /* # of tx. buffers in TBD array */ + UINT8 destAddr[6]; /* destination hardware address */ + UINT16 length; /* 802.3 packet length (from packet) */ + UINT8 txData[ETHERMTU]; /* optional data to tx */ + } transmit; + /* Dump 82557 registers */ + struct { + UINT32 rsrv1 : 13; /* reserved bits (set to 0) */ + UINT32 ok : 1; /* 1 = command completed, no error */ + UINT32 rsrv2 : 1; /* reserved bits (set to 0) */ + UINT32 c : 1; /* 1 = command completed */ + UINT32 code : 3; /* command code (6 = dump) */ + UINT32 rsrv3 : 10; /* reserved bits (set to 0) */ + UINT32 i : 1; /* 1 = interrupt upon completion */ + UINT32 s : 1; /* 1 = suspend CU upon completion */ + UINT32 el : 1; /* 1 = last cmdBlock in list */ + union cmdBlock *link; /* next block in list */ + UINT8 *bufAddr; /* where to dump registers */ + } dump; + /* Diagnose - perform self test */ + struct { + UINT32 rsrv1 : 11; /* reserved bits (set to 0) */ + UINT32 f : 1; /* 1 = self test failed */ + UINT32 rsrv2 : 1; /* reserved bits (set to 0) */ + UINT32 ok : 1; /* 1 = command completed, no error */ + UINT32 rsrv3 : 1; /* reserved bits (set to 0) */ + UINT32 c : 1; /* 1 = command completed */ + UINT32 code : 3; /* command code (7 = diagnose) */ + UINT32 rsrv4 : 10; /* reserved bits (set to 0) */ + UINT32 i : 1; /* 1 = interrupt upon completion */ + UINT32 s : 1; /* 1 = suspend CU upon completion */ + UINT32 el : 1; /* 1 = last cmdBlock in list */ + union cmdBlock *link; /* next block in list */ + } diagnose; +}; + +/* Receive frame descriptors (uses simplified memory structure) */ +struct rfd { + UINT32 rxColl : 1; /* 1 = collision on reception */ + UINT32 iaMatch : 1; /* Dest addr matched chip's hardware addr */ + UINT32 rsrv1 : 2; /* reserved bits (set to 0) */ + UINT32 rxErr : 1; /* RX_ER pin asserted during frame reception */ + UINT32 typeFrame : 1; /* Type field of pkt. indicates a TYPE frame */ + UINT32 rsrv2 : 1; /* reserved bits (set to 0) */ + UINT32 frameTooshort : 1; + UINT32 dmaOverrun : 1; /* DMA overrun (couldn't get local bus) */ + UINT32 noRsrc : 1; /* No resources (out of buffer space) */ + UINT32 alignErr : 1; /* CRC error on misaligned frame */ + UINT32 crcErr : 1; /* CRC error on aligned frame */ + UINT32 rsrv3 : 1; /* reserved bits (set to 0) */ + UINT32 ok : 1; /* 1 = command completed, no error */ + UINT32 rsrv4 : 1; /* reserved bits (set to 0) */ + UINT32 c : 1; /* 1 = command completed */ + UINT32 rsrv5 : 3; /* reserved bits (set to 0) */ + UINT32 sf : 1; /* 1 = Flexible mode */ + UINT32 h : 1; /* 1 = Header RFD */ + UINT32 rsrv6 : 9; /* reserved bits (set to 0) */ + UINT32 s : 1; /* 1 = suspend CU upon completion */ + UINT32 el : 1; /* 1 = last cmdBlock in list */ + union cmdBlock *link; /* next block in list */ + UINT8 *rbdAddr; /* rx buf desc addr; all 1s for simple mode */ + UINT32 actCount : 14; /* # bytes in this buffer (set by 82557) */ + UINT32 f : 1; /* 1 = buffer used */ + UINT32 eof : 1; /* 1 = last buffer for this frame */ + UINT32 size : 14; /* # bytes avail in this buffer (set by CPU) */ + UINT32 rsrv7 : 2; /* reserved bits (set to 0) */ + UINT8 destAddr[6]; /* destination address */ + UINT8 sourceAddr[6]; /* source address */ + UINT16 length; /* 802.3 packet length (from packet) */ + UINT8 rxData[ETHERMTU]; /* optional data (simplified mode) */ +}; + +/* Forward declarations */ +static void portWrite (); +static void resetChip (); +static void makePacket (); +static int checkPacket (); +static int i557IntHandler (int); +static int waitForInt(); + +static void sendCommand (UINT8 cuc, + UINT8 ruc, + UINT32 scb_general_ptr); + +static UINT16 readMDI ( + int unit, + UINT8 phyAdd, + UINT8 regAdd + ); + +static void writeMDI ( + int unit, + UINT8 phyAdd, + UINT8 regAdd, + UINT16 data + ); + +static int initPHY (UINT32 device_type, int loop_mode); + +static int get_ether_addr ( + int unit, + UINT8 *buffer, + int print_flag /* TRUE to print the information */ + ); + +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/external_timer.c @@ -0,0 +1,458 @@ +//============================================================================= +// +// external_timer.c - Cyclone Diagnostics +// +//============================================================================= +//####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) 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-25 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +#include "iq80310.h" + + +extern int enable_external_interrupt (int int_id); +extern int disable_external_interrupt (int int_id); + +extern int isr_connect(int int_num, void (*handler)(int), int arg); +extern int isr_disconnect(int int_num); + + +/* 01/05/01 jwf */ +/* extern void _restart_tmr(); */ + + +volatile int timer_ticks; + + +/* interrupt handler for the PAL-based external timer */ +void ext_timer_handler (int arg) +{ + /* increment tick counter */ + timer_ticks++; + + /* to clear the timer interrupt, clear the timer interrupt + enable, then re-set the int. enable bit */ +/* 01/05/01 jwf */ +/* _restart_tmr(); */ + + EXT_TIMER_INT_DISAB(); + EXT_TIMER_INT_ENAB(); + + return; +} + + +/* timer count must be written 8 bits at a time */ +void write_timer_count (UINT32 count) +{ + UINT8 cnt_word; + + /* first ensure that there are only 22 bits of count data */ + count &= 0x003fffff; + + /* grab least significant 8 bits of timer value */ + cnt_word = (UINT8)(count & 0xff); + *TIMER_LA0_REG_ADDR = cnt_word; + + /* grab next 8 bits of timer value */ + count = (count >> 8); + cnt_word = (UINT8)(count & 0xff); + *TIMER_LA1_REG_ADDR = cnt_word; + + /* grab last 6 bits of timer value */ + count = (count >> 8); + cnt_word = (UINT8)(count & 0x3f); + *TIMER_LA2_REG_ADDR = cnt_word; + + return; +} + +/* timer must be read 6 bits at a time */ +UINT32 read_timer_count (void) +{ + UINT8 timer_cnt0, timer_cnt1, timer_cnt2, timer_cnt3; + UINT8 timer_byte0, timer_byte1, timer_byte2; + UINT32 count; + + /* first read latches the count */ + timer_cnt0 = (*TIMER_LA0_REG_ADDR & TIMER_COUNT_MASK); + timer_cnt1 = (*TIMER_LA1_REG_ADDR & TIMER_COUNT_MASK); + timer_cnt2 = (*TIMER_LA2_REG_ADDR & TIMER_COUNT_MASK); + timer_cnt3 = (*TIMER_LA3_REG_ADDR & 0xf); /* only 4 bits in most sig. */ + + /* now build up the count value */ + timer_byte0 = (((timer_cnt0 & 0x20) >> 1) | (timer_cnt0 & 0x1f)); + timer_byte1 = (((timer_cnt1 & 0x20) >> 1) | (timer_cnt1 & 0x1f)); + timer_byte2 = (((timer_cnt2 & 0x20) >> 1) | (timer_cnt2 & 0x1f)); + + count = ((timer_cnt3 << 18) | (timer_byte2 << 12) | (timer_byte1 << 6) | + timer_byte0); + + return (count); +} + + +/* 12/18/00 jwf */ +/* This test reads the timer la0-la3 registers on the fly while an up count is in progress. */ +void counter_test (void) +{ + + unsigned char TmrLa0Write=0xff; /* ff max, b0-b7, b0-b7 contain timer load data */ + unsigned char TmrLa1Write=0xff; /* ff max, b8-b15, b0-b7 contain timer load data */ + unsigned char TmrLa2Write=0x3f; /* 3f max, b16-b21, b0-b5 contain timer load data */ + unsigned char TmrLa3Write=0x00; /* x - don't care */ + + unsigned long int TmrLa0Read=0; + unsigned long int TmrLa1Read=0; + unsigned long int TmrLa2Read=0; + unsigned long int TmrLa3Read=0; + + unsigned long int temp3=0; + unsigned long int temp4=0; + + unsigned long int CntInit=0; + + unsigned long int CurrentCount; + unsigned long int LastCount; + unsigned long int LastLastCount; + + char Error = FALSE; /* This flag indicates a test pass(FALSE) or fail(TRUE) condition */ + + unsigned long int sample; + unsigned long int index; + + const int MAX_N_PASSES = 10; /* N times the counter shall wrap around */ + const unsigned long int MAX_N_SAMPLES = 65536; /* N samples to cover the full range of count, 0x3fffff/0x40 = 0xffff <--> 65535d, use 65536 to guarantee a counter wrap around occurs */ + unsigned long int MAX_N_SIZE = MAX_N_PASSES * MAX_N_SAMPLES * 4; /* allocate 4 bytes per sample for a 0x0 - 0x3fffff count range to hold contents of registers LA0-LA3 */ + unsigned char *data; + + // Arbitrarily pick a spot in memory. + // RedBoot won't ever use more than 1MB. + data = (unsigned char *) MEMBASE_DRAM + (1*1024*1024); /* sample storage area */ + + if( data != NULL ) + { + printf( "Allocated %d bytes\n", MAX_N_SIZE ); + + /* load control data to disable timer enable b0=0 and timer disable interrupt b1=0, write to timer enable port */ + EXT_TIMER_INT_DISAB(); + EXT_TIMER_CNT_DISAB(); + + /* write timer la0 port count data */ + *TIMER_LA0_REG_ADDR = TmrLa0Write; + + /* write timer la1 port count data */ + *TIMER_LA1_REG_ADDR = TmrLa1Write; + + /* write timer la2 port count data */ + *TIMER_LA2_REG_ADDR = TmrLa2Write; + + /* write timer la3 port count data */ + *TIMER_LA3_REG_ADDR = TmrLa3Write; + + CntInit = TmrLa0Write + (TmrLa1Write << 8 ) + (TmrLa2Write << 16 ); + + printf("Timer load data = 0x%x\n", CntInit ); + + printf("Reading Timer registers LA0-LA3 on the fly...\n"); + + /* load control data to enable timer counter and write control data to start the counter */ + EXT_TIMER_CNT_ENAB(); + + /* sample the timer counter on the fly and store LA0-3 register contents in an array */ + for ( sample=0, index=0 ; sample < ( MAX_N_PASSES * MAX_N_SAMPLES ) ; sample++, index += 4) + + { + + /* read LSB register first to latch 22 bits data into four la registers */ + data[index] = *TIMER_LA0_REG_ADDR; /* bits 0 1 2 3 4 6 contain count data b0-b5 */ + + data[index+1] = *TIMER_LA1_REG_ADDR; /* bits 0 1 2 3 4 6 contain count data b6-b11 */ + + data[index+2] = *TIMER_LA2_REG_ADDR; /* bits 0 1 2 3 4 6 contain count data b12-b17 */ + + data[index+3] = *TIMER_LA3_REG_ADDR; /* bits 0 1 2 3 contain count data b18-b21 */ + + } + + printf("Checking for errors...\n" ); + + /* Assemble and check recorded register data for errors */ + for ( sample=0, index=0 ; sample < ( MAX_N_PASSES * MAX_N_SAMPLES ) ; sample++, index += 4) + + { + + /* Assembles counter data that was read on the fly */ + /* xbxbbbbb */ + /* 01000000 = 0x40 */ + /* 00011111 = 0x1F */ + data[index] &= 0x7f; /* mask all unused bits */ + temp3=data[index]; + temp4=data[index]; + temp3 &= 0x40; /* isolate bit 6 */ + temp3 = temp3 >> 1; /* shift bit 6 to bit 5 */ + temp4 &= 0x1f; /* isolate bits 0-4 */ + TmrLa0Read = temp3 + temp4; + + data[index+1] &= 0x7f; /* mask all unused bits */ + temp3=data[index+1]; + temp4=data[index+1]; + temp3 &= 0x40; /* isolate bit 6 */ + temp3 = temp3 >> 1; /* shift bit 6 to bit 5 */ + temp4 &= 0x1f; /* isolate bits 0-4 */ + TmrLa1Read = temp3 + temp4; + + data[index+2] &= 0x7f; /* mask all unused bits */ + temp3=data[index+2]; + temp4=data[index+2]; + temp3 &= 0x40; /* isolate bit 6 */ + temp3 = temp3 >> 1; /* shift bit 6 to bit 5 */ + temp4 &= 0x1f; /* isolate bits 0-4 */ + TmrLa2Read = temp3 + temp4; + + data[index+3] &= 0x0f; /* mask all unused bits */ + TmrLa3Read = data[index+3]; + + /* sum timer count data */ + CurrentCount = TmrLa0Read + (TmrLa1Read << 6 ) + (TmrLa2Read << 12 ) + (TmrLa3Read << 18 ); + + if ( sample == 0 ) + { + LastLastCount = 0; + LastCount = CurrentCount; + } + + if (sample == 1 ) + + { + LastLastCount = LastCount; + LastCount = CurrentCount; + } + + if ( sample > 1 ) /* check for data anomaly, is count value read 2 samples ago greater than the count value read 1 sample ago */ + { + /* print error value (LastCount) positioned in between the previous and current values */ + if ( ( LastLastCount > LastCount ) && ( CurrentCount > LastLastCount ) ) /* show error only, do not show a counter wrap around reading, print error value (LastCount) positioned in between the previous and current values */ + { + printf("0x%x 0x%x 0x%x \n", LastLastCount, LastCount, CurrentCount ); + Error = TRUE; /* set flag to error condition */ + } + LastLastCount = LastCount; + LastCount = CurrentCount; + } + + } + + /* load control data to stop timer b0=0 and reset timer interrupt b1=0 */ + EXT_TIMER_CNT_DISAB(); + + } /* end if( data != NULL ) */ + + else /* data = NULL */ + { + printf( "Cannot allocate memory.\n" ); + } + + if ( Error == TRUE ) + { + printf("Timer LA0-3 register read test FAILED.\n"); + } + else + { + printf("Timer LA0-3 register read test PASSED.\n"); + } + +} /* end counter_test() */ + + +/* initialize timer for diagnostic use */ +void init_external_timer() +{ + + /* disable timer in case it was running */ + EXT_TIMER_INT_DISAB(); + EXT_TIMER_CNT_DISAB(); + + timer_ticks = 0; + + /* connect the timer ISR */ + isr_connect (TIMER_INT_ID, ext_timer_handler, 0); + + /* enable the external interrupt */ + if (enable_external_interrupt(TIMER_INT_ID) != OK) + printf("ERROR enabling EXT TIMER interrupt!\n"); +} + + +/* uninitialize timer after diagnostics */ +void uninit_external_timer() +{ + + /* disable timer */ + EXT_TIMER_INT_DISAB(); + EXT_TIMER_CNT_DISAB(); + + /* disable and disconnect timer interrupts */ + disable_external_interrupt(TIMER_INT_ID); + isr_disconnect (TIMER_INT_ID); +} + + +/* 02/02/01 jwf */ +/* delay_ms - delay specified number of milliseconds */ +void delay_ms(int num_ms) +{ +UINT32 count; +int num_ticks; + + timer_ticks = 0; + + if (num_ms < 10) + num_ticks = 1; + else + { + /* num_ms must be multiple of 10 - round up */ + num_ticks = num_ms / 10; + if (num_ms % 10) + num_ticks++; /* round up */ + } + + /* for the test we will setup the timer to generate a 10msec tick */ + count = EXT_TIMER_10MSEC_COUNT; + + /* write the initial count to the timer */ + write_timer_count (count); + + /* enable the interrupt at the timer */ + EXT_TIMER_INT_ENAB(); + + /* enable the timer to count */ + EXT_TIMER_CNT_ENAB(); + + while (timer_ticks < num_ticks) + ; + + /* disable timer */ + EXT_TIMER_INT_DISAB(); + EXT_TIMER_CNT_DISAB(); + +} + + +/* test the 32 bit timer inside the CPLD, U17 */ +void timer_test (void) +{ + volatile int i; + UINT32 count; + + + /***** Perform 10 second count at 100 ticks/sec ****/ + + /* for the test we will setup the timer to generate a 10msec tick */ + count = EXT_TIMER_10MSEC_COUNT; + + /* write the initial count to the timer */ + write_timer_count (count); + + /* enable the interrupt at the timer */ + EXT_TIMER_INT_ENAB(); + + /* enable the timer to count */ + EXT_TIMER_CNT_ENAB(); + + printf ("Counting at %d Ticks Per Second.\n", TICKS_10MSEC); + printf ("Numbers should appear on 1 second increments...\n"); + + for (i = 0; i < 10; i++) + { + while (timer_ticks < TICKS_10MSEC) + ; + printf ("%d ", i); + timer_ticks = 0; + } + + printf ("\nDone\n\n"); + + /* disable timer */ + EXT_TIMER_INT_DISAB(); + EXT_TIMER_CNT_DISAB(); + + + /***** Perform 10 second count at 200 ticks/sec ****/ + + count = EXT_TIMER_5MSEC_COUNT; + write_timer_count (count); + + timer_ticks = 0; + + /* enable the interrupt at the timer */ + EXT_TIMER_INT_ENAB(); + + /* enable the timer to count */ + EXT_TIMER_CNT_ENAB(); + + printf ("Counting at %d Ticks Per Second.\n", TICKS_5MSEC); + printf ("Numbers should appear on 1 second increments...\n"); + + for (i = 0; i < 10; i++) + { + while (timer_ticks < TICKS_5MSEC) + ; + printf ("%d ", i); + timer_ticks = 0; + } + + printf ("\nDone\n\n"); + + /* disable timer */ + EXT_TIMER_INT_DISAB(); + EXT_TIMER_CNT_DISAB(); + +/* 12/18/00 jwf */ + uninit_external_timer(); /* disable interrupt */ + counter_test(); + init_external_timer(); /* enable interrupt */ + + printf("\nExternal Timer Test Done\n"); + +/* 12/18/00 jwf */ + printf("\n\nStrike <CR> to exit this test." ); + while (xgetchar() != 0x0d); + + return; + +} /* end timer_test() */ + +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/flash.c @@ -0,0 +1,1217 @@ +//============================================================================= +// +// flash.c - Cyclone Diagnostics +// +//============================================================================= +//####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) 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-25 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +#include <redboot.h> +#include <cyg/io/flash.h> + +#include "iq80310.h" /* 80310 chip set specific */ +#include "7_segment_displays.h" + +typedef unsigned char FLASH_TYPE; +#define MASK 0xff /* for 1 bank */ + +/* 28F016S5/28F640J3A Command Definitions - First Bus Cycle */ +#define RESET_CMD (0xffffffff & MASK) +#define WRITE_TO_BUF_CMD (0xe8e8e8e8 & MASK) +#define WRITE_CONFIRM_CMD (0xd0d0d0d0 & MASK) +#define READ_ID_CMD (0x90909090 & MASK) +#define READ_STAT_REG (0x70707070 & MASK) +#define CLEAR_STAT_REG (0x50505050 & MASK) +#define ERASE_CMD (0x20202020 & MASK) +#define PROGRAM_CMD (0x40404040 & MASK) +#define BEP_SUSPEND (0xb0b0b0b0 & MASK) +#define BEP_RESUME (0xd0d0d0d0 & MASK) +#define LOCK_CMD (0x60606060 & MASK) +#define CLEAR_LOCK_BIT_SETUP (0x60606060 & MASK) /* 10/06/00 */ + +/* 28F016S5/28F640J3A Command Definitions - Second Bus Cycle */ +#define ERASE_CONFIRM (0xd0d0d0d0 & MASK) +#define LOCK_BLOCK_CONFIRM (0x01010101 & MASK) +#define MASTER_LOCK_CONFIRM (0xf1f1f1f1 & MASK) /* DO NOT EVER set master enable bit!!! */ +#define UNLOCK_BLOCK_CONFIRM (0xd0d0d0d0 & MASK) +#define CLEAR_LOCK_BIT_CONFIRM (0xd0d0d0d0 & MASK) /* 10/06/00 */ + +/* Flash category definitions */ +#define SECTOR_PROG 0 +#define BLOCK_PROG 1 + +/* status register bits */ +#define WSM_READY (FLASH_TYPE) (1 << 7) +#define WSM_BUSY (FLASH_TYPE) (0 << 7) +#define BE_SUSPENDED (FLASH_TYPE) (1 << 6) +#define BE_COMPLETED (FLASH_TYPE) (0 << 6) +#define ERASE_UNLOCK_ERROR (FLASH_TYPE) (1 << 5) +#define ERASE_UNLOCK_SUCCESS (FLASH_TYPE) (0 << 5) +#define CLEAR_LOCK_BIT_ERROR (FLASH_TYPE) (1 << 5) /* 10/06/00 */ +#define CLEAR_LOCK_BIT_SUCCESS (FLASH_TYPE) (0 << 5) /* 10/06/00 */ +#define PROGRAM_LOCK_ERROR (FLASH_TYPE) (1 << 4) +#define PROGRAM_LOCK_SUCCESS (FLASH_TYPE) (0 << 4) +#define SET_LOCK_BIT_ERROR (FLASH_TYPE) (1 << 4) /* 10/17/00 */ +#define SET_LOCK_BIT_SUCCESS (FLASH_TYPE) (0 << 4) /* 10/17/00 */ +#define VPP_LOW_DETECT (FLASH_TYPE) (1 << 3) +#define VPP_OK (FLASH_TYPE) (0 << 3) +#define PROGRAM_SUSPENDED (FLASH_TYPE) (1 << 2) +#define PROGRAM_COMPLETED (FLASH_TYPE) (0 << 2) +#define DEVICE_PROTECTED (FLASH_TYPE) (1 << 1) +#define DEVICE_UNLOCKED (FLASH_TYPE) (0 << 1) + + +/* Other Intel 28F016S5/28F640J3A definitions */ +#define CMD_SEQ_ERR (FLASH_TYPE) (ERASE_UNLOCK_ERROR | PROGRAM_LOCK_ERROR) +#define ALL_FLASH_STATUS (FLASH_TYPE) (0xfe) +#define UNKNOWN_ERR (FLASH_TYPE) (0xff) + +#define TEST_BUF_LONGS 16384 +#define TEST_BUF_CHARS 65536 + +#define MADE_BY_INTEL (0x89898989 & MASK) /* Manufacturer Code, read at address 0, note that address bit A0 is not used in x8 or x16 mode when obtaining identifier code */ + +/*#define I28F016S5 (0xAAAAAAAA & MASK)*/ /* 28F016S5 */ +#define I28F640J3A (0x17171717 & MASK) /* Device Code, read at address 1, note that bit address A0 is not used in x8 or x16 mode when obtaining identifier code */ + +/*#define FLASH_BLOCK_SIZE 0x10000*/ /* 28F016S5 */ +#define FLASH_BLOCK_SIZE 0x20000 /* 28F640J3A */ + +#define BLOCK_LOCKED 1 +#define BLOCK_UNLOCKED 0 + +// First 4K page of flash at physical address zero is +// virtually mapped at address 0xa0000000. +#define FLASH_P2V(x) ((volatile FLASH_TYPE *)(((unsigned)(x) < 0x1000) ? \ + ((unsigned)(x) | 0xa0000000) : \ + (unsigned)(x))) + + +unsigned long *flash_buffer = (unsigned long *)0xa1000000; + + +extern void _flushICache(); +extern void _enableICache(); +extern void _disableICache(); +extern void _switchMMUpageTables(); + + +extern void _usec_delay(); +extern void _msec_delay(); + +unsigned long eeprom_size; +unsigned long flash_base; + +ADDR flash_addr=FLASH_ADDR, eeprom_prog_first, eeprom_prog_last; + +extern long hexIn(); +extern char * sgets(); + +/* forward declarations */ +void init_eeprom() RAM_FUNC_SECT; +int reserved_check(ADDR addr, unsigned long length) RAM_FUNC_SECT; +int is_eeprom(ADDR addr, unsigned long length) RAM_FUNC_SECT; +int check_eeprom(ADDR addr, unsigned long length) RAM_FUNC_SECT; +int lock_breeze() RAM_FUNC_SECT; +int check_bstat(int block_num) RAM_FUNC_SECT; +int set_all_lock_bits(void) RAM_FUNC_SECT; /* 10/11/00 added */ +int clear_all_lock_bits(ADDR addr) RAM_FUNC_SECT; /* 10/06/00 added */ +int check_erase_unlock(volatile FLASH_TYPE *flash) RAM_FUNC_SECT; +int check_op_status(int cmd, volatile FLASH_TYPE *flash) RAM_FUNC_SECT; +int erase_eeprom(ADDR addr, unsigned long length) RAM_FUNC_SECT; +int check_program_lock(volatile FLASH_TYPE *flash) RAM_FUNC_SECT; +int write_eeprom(ADDR start_addr, const void *data_arg, int data_size) RAM_FUNC_SECT; +void flash_test(void) RAM_FUNC_SECT; +void delay_and_flush(void) RAM_FUNC_SECT; +void do_nothing(void) RAM_FUNC_SECT; +void display_val(int num) RAM_FUNC_SECT; +void display_out (int msb_flag, unsigned char val) RAM_FUNC_SECT; +void check_lock_bit_status(void) RAM_FUNC_SECT; + +#define MSB_DISPLAY_REG (volatile unsigned char *)0xfe840000 +#define LSB_DISPLAY_REG (volatile unsigned char *)0xfe850000 + +void display_out (int msb_flag, unsigned char val) +{ +/* unsigned char *ledPtr; */ + volatile unsigned char *ledPtr; + unsigned char SevSegDecode; + + if (msb_flag) ledPtr = MSB_DISPLAY_REG; + else ledPtr = LSB_DISPLAY_REG; + + switch (val) + { + case 0: + SevSegDecode = ZERO; + break; + + case 1: + SevSegDecode = ONE; + break; + + case 2: + SevSegDecode = TWO; + break; + + case 3: + SevSegDecode = THREE; + break; + + case 4: + SevSegDecode = FOUR; + break; + + case 5: + SevSegDecode = FIVE; + break; + + case 6: + SevSegDecode = SIX; + break; + + case 7: + SevSegDecode = SEVEN; + break; + + case 8: + SevSegDecode = EIGHT; + break; + + case 9: + SevSegDecode = NINE; + break; + + case 10: + SevSegDecode = LETTER_A; + break; + + case 11: + SevSegDecode = LETTER_B; + break; + + case 12: + SevSegDecode = LETTER_C; + break; + + case 13: + SevSegDecode = LETTER_D; + break; + + case 14: + SevSegDecode = LETTER_E; + break; + + case 15: + SevSegDecode = LETTER_F; + break; + + default: + SevSegDecode = DECIMAL_POINT; + + } + *ledPtr = SevSegDecode; +} + +void display_val (int number) +{ + unsigned char disp_val = number % 256; + unsigned char msb, lsb; + + lsb = disp_val & 0x0f; + msb = (disp_val & 0xf0) >> 4; + + display_out (0, lsb); + display_out (1, msb); +} + +/* Used in write to buffer routine */ +void do_nothing (void) +{ + + volatile int i; + for (i = 0; i < 50; i++); /* Rev 2.0B and Rev 2.0C */ +/* for (i = 0; i < 100; i++); */ /* Rev 2.0A */ +} + + +void delay_and_flush (void) +{ + + do_nothing(); + + _flushICache(); + +} + + +/********************************************************/ +/* INIT FLASH */ +/* */ +/* This routine initializes the variables for timing */ +/* with any board configuration. This is used to get */ +/* exact timing every time. */ +/********************************************************/ + +void init_eeprom() +{ +#if 1 + unsigned char MfgCode=MADE_BY_INTEL; + unsigned char DevCode=I28F640J3A; + + eeprom_size = 0x800000; +#else + unsigned char MfgCode=0; + unsigned char DevCode=0; + + flash_addr = FLASH_ADDR; + + flash_base = FLASH_BASE_ADDR; + + /* Set defaults */ + eeprom_size = 0; + + /* Note: the PCI-700 platform has only 1 memory bank */ + +/* + *( volatile unsigned char * ) FLASH_BASE_ADDR = RESET_CMD; + printf( "Wrote 1rst Read Array Command\n"); +*/ + + *FLASH_P2V(FLASH_BASE_ADDR) = RESET_CMD; /* issue read array command */ + delay_and_flush(); /* wait for Flash to re-enter Read Array mode */ + + + *FLASH_P2V(FLASH_BASE_ADDR) = READ_ID_CMD; /* issue read id command */ + + MfgCode = *FLASH_P2V(FLASH_BASE_ADDR); /* read a manufacturer code at addr 0, address bit A0 is not used */ + + DevCode = *FLASH_P2V(DEV_CODE_ADDR); /* read a device code at addr 1 */ + + if (MfgCode == (MADE_BY_INTEL)) + { + switch ( DevCode ) /* device code stored in addr 1, address bit A0 is not used, must shift 0x00000001<<1=0x00000002 */ + { + case I28F640J3A: + eeprom_size += 0x800000 * FLASH_WIDTH; /* I28F640J3A */ + break; + default: + break; + } + } + + *FLASH_P2V(FLASH_BASE_ADDR) = READ_ID_CMD; /* issue 2nd read id command */ + + *FLASH_P2V(FLASH_BASE_ADDR) = RESET_CMD; /* issue read array command */ + + delay_and_flush(); /* wait for Flash to re-enter Read Array mode */ +#endif + + printf( "\nManufacturer Code = 0x%x\n", MfgCode); + printf( "Device Code = %x\n", DevCode); + printf( "Flash Memory size = 0x%x\n", eeprom_size); + + return; +} + +/********************************************************/ +/* RESERVED AREA CHECK */ +/* */ +/* returns TRUE if the address falls into the */ +/* reserved system area */ +/* returns FALSE if the address is outside */ +/* the reserved system area */ +/********************************************************/ +int reserved_check(ADDR addr, unsigned long length) +{ + + /* check start address */ + if ( ( addr >= RESERVED_AREA1 ) && ( addr <= ( FLASH_BLK4_BASE_ADDR - 1 ) ) ) + return TRUE; + + + /* must be outside the area */ + else + return FALSE; +} + +/********************************************************/ +/* IS EEPROM */ +/* Check if memory is Flash */ +/* */ +/* returns TRUE if it is; FALSE if not eeprom ; */ +/* returns ERROR bad addr or partial eeprom */ +/* */ +/********************************************************/ +int is_eeprom(ADDR addr, unsigned long length) +{ + ADDR eeprom_end = flash_addr + eeprom_size - 1; + ADDR block_end = addr + length - 1; + + /* Check for wrap: if the address and length given wrap past + * the end of memory, it is an error. */ + if (block_end < addr) + return ERR; + if (addr >= flash_addr && block_end <= eeprom_end) + return TRUE; + if (addr > eeprom_end || block_end < flash_addr) + return FALSE; + /* If the block was partly within the Flash, it is an error. */ + return ERR; +} + + +/********************************************************/ +/* CHECK EEPROM */ +/* Check if Flash is Blank */ +/* */ +/* returns OK if it is; returns ERROR and sets cmd_stat */ +/* to an error code if memory region is not Flash or if */ +/* it is not blank. */ +/* */ +/********************************************************/ +int check_eeprom(ADDR addr, unsigned long length) +{ + + FLASH_TYPE *p, *end; + + if (eeprom_size == 0) + { + cmd_stat = E_NO_FLASH; + return ERR; + } + + if (addr == NO_ADDR) + { + addr = FLASH_BLK4_BASE_ADDR; /* start at base address of block */ + + length = eeprom_size - RESERVED_AREA_SIZE; + + } + else if (length == 0) + length = 1; + +/* Original */ +/* if (is_eeprom(addr, length) != 1) */ +/* + if (is_eeprom(addr, length) != TRUE) + { + cmd_stat = E_EEPROM_ADDR; + return ERR; + } +*/ + + p = (FLASH_TYPE *)addr; + +/* Original */ +/* end = p + length; */ + /* find first non_blank address */ +/* while (p != end) */ +/* { */ +/* if (*p != 0xff) */ +/* { */ +/* cmd_stat = E_EEPROM_PROG; */ +/* eeprom_prog_first = (ADDR)p; */ + + /* find last non_blank address */ +/* for (p = end; *--p == 0xff; ); */ +/* eeprom_prog_last = (ADDR)p; */ +/* return ERR; */ +/* } */ +/* p++; */ +/* } */ +/* return OK; */ + + end = (FLASH_TYPE *)FLASH_TOP_ADDR; + /* search for first non blank address starting at base address of Flash Block 2 */ + while (p != end) + { + if (*FLASH_P2V(p) != 0xff) + { + + eeprom_prog_first = (ADDR)p; /* found first non blank memory cell */ + + /* now find last non blank memory cell starting from top of Flash memory */ + for (p = end - 1; *FLASH_P2V(p) == 0xff; --p); + + eeprom_prog_last = (ADDR)p; /* found last non blank memory cell */ + + cmd_stat = E_EEPROM_PROG; + + return ERR; + } + p++; + } + return OK; +} + +/********************************************************/ +/* LOCK BREEZE FLASH AREA */ +/* */ +/* Lock the Flash ROM blocks which contain the Breeze */ +/* Development environment to prevent inadvertent */ +/* erasure/reprogramming. */ +/* */ +/* RETURNS: 1 = success, 0 = failure */ +/********************************************************/ +int lock_breeze() +{ + void *err_addr; + + if (flash_lock((void *)BREEZE_BLOCK_0, NUM_BREEZE_BLOCKS*FLASH_BLOCK_SIZE, (void **)&err_addr) != 0) { + cmd_stat = E_EEPROM_FAIL; + return (BLOCK_UNLOCKED); + } + return(BLOCK_LOCKED); +} + + +/********************************************************/ +/* CHECK BLOCK STATUS */ +/* */ +/* Check the lock status of a flash block */ +/* */ +/* Input: block number to check */ +/* -1 = master lock */ +/* */ +/* Returns: 1 = locked, 0 = unlocked */ +/* 2 = invalid block number */ +/********************************************************/ +#if 0 +int check_bstat(int block_num) +{ + volatile FLASH_TYPE *lock_data_addr; + FLASH_TYPE lock_data; + + /* shut the compiler up */ + lock_data_addr = 0x00000000; + + /* derive the address for block lock configuration data */ + if ((block_num >= 0) && (block_num <= NUM_FLASH_BLOCKS)) + lock_data_addr = (FLASH_TYPE*)(FLASH_ADDR + (FLASH_BLOCK_SIZE * block_num) + 2); + else if (block_num == -1) + lock_data_addr = (FLASH_TYPE*)(FLASH_ADDR + 3); + else + return (2); + + lock_data_addr = FLASH_P2V(lock_data_addr); + + /* read block lock configuration data from address */ + *lock_data_addr = READ_ID_CMD; + + lock_data = *lock_data_addr; + + /* reset flash to read mode */ + *lock_data_addr = RESET_CMD; + delay_and_flush(); /* wait for Flash to re-enter Read Array mode */ + + /* now check data to see if block is indeed locked */ + if (lock_data & BLOCK_LOCKED) + return (BLOCK_LOCKED); + else + return (BLOCK_UNLOCKED); +} +#endif + +/********************************************************/ +/* CHECK ERASE OR UNLOCK STATUS */ +/* */ +/* Check the status of erase or unlock operation */ +/* using the Status Register of the Flash */ +/* */ +/* Returns: OK - Erase successful */ +/* VPP_LOW_DETECT - Vpp low detected */ +/* ERASE_UNLOCK_ERROR - Erase / Unlock error */ +/* CMD_SEQ_ERR - Command sequencing error */ +/* UNKNOWN_ERR - Unknown error condition */ +/* */ +/********************************************************/ +#if 0 +int check_erase_unlock(volatile FLASH_TYPE *flash) +{ + FLASH_TYPE stat; + flash = FLASH_P2V(flash); + *flash = READ_STAT_REG ; + stat = *flash; + + /* poll and wait for Write State Machine Ready */ + while ((stat & WSM_READY) == WSM_BUSY) + { + stat = *flash; + } + + /* now check completion status */ + if (stat & VPP_LOW_DETECT) + { + *flash = CLEAR_STAT_REG; + return VPP_LOW_DETECT; + } + if ((stat & CMD_SEQ_ERR) == CMD_SEQ_ERR) + { + *flash = CLEAR_STAT_REG; + return CMD_SEQ_ERR; + } + if (stat & ERASE_UNLOCK_ERROR) + { + *flash = CLEAR_STAT_REG; + return ERASE_UNLOCK_ERROR; + } + if ((stat & ALL_FLASH_STATUS) == WSM_READY) + { + *flash = CLEAR_STAT_REG; + return OK; + } + else + { + *flash = CLEAR_STAT_REG; + return UNKNOWN_ERR; + } +} +#endif + +/********************************************************/ +/* CHECK OPERATION STATUS */ +/* */ +/* Check the status of an operation */ +/* using the Status Register of the Flash */ +/* */ +/* if the "cmd" argument flag is TRUE, then a */ +/* READ_STAT_REG command should be issued first */ +/* */ +/* Returns: */ +/* OK - Operation successful */ +/* value of Status register - Otherwise */ +/* */ +/********************************************************/ +#if 0 +int check_op_status(int cmd, volatile FLASH_TYPE *flash) +{ + FLASH_TYPE stat; + + flash = FLASH_P2V(flash); + + if (cmd == TRUE) + { + *flash = READ_STAT_REG; + } + + stat = *flash; + + /* poll and wait for Write State Machine Ready */ + while ((stat & WSM_READY) == WSM_BUSY) + { + stat = *flash; + } + + /* now check completion status */ + if ((stat & ALL_FLASH_STATUS) == WSM_READY) + { + *flash = CLEAR_STAT_REG; + return OK; + } + else + { + *flash = CLEAR_STAT_REG; + return stat; + } +} +#endif + +#if 0 +/* used for debugging only */ +/* check block lock configuration and display status of 64 blocks, 1=locked, 0=unlocked */ +void check_lock_bit_status (void) +{ + + int block; + + volatile FLASH_TYPE *block_addr; + + /* address bit A0 is not used when obtaining identifier codes */ + +/* 11/01/00 */ +/* unsigned long addr = 0x2<<1; */ + unsigned long addr = 0x4; + + unsigned char block_lock_status[64]; + + block_addr = (volatile FLASH_TYPE *) addr; + +/* printf("Checking lock status of %d blocks, 1=locked, 0=unlocked...\n", block ); */ + + /* address bit A0 is not used when obtaining identifier codes */ + for (block=0; block<=63; block++) + { + + *FLASH_P2V(block_addr) = READ_ID_CMD; + + block_lock_status[block] = *FLASH_P2V(block_addr); + + *FLASH_P2V(block_addr) = RESET_CMD; + + do_nothing(); + +/* 11/01/00 */ + do_nothing(); + + block_lock_status[block] &= 0x01; /* Checking lock status of block, 1=locked, 0=unlocked */ + + block_addr = (volatile FLASH_TYPE *)((unsigned long)block_addr + (unsigned long)FLASH_BLOCK_SIZE); /* block address offset for byte wide data storage */ + } + + + for (block=0; block<=63; block++) + { + if (block == 32) + { + printf("\n\r"); + } + printf("%d ", block_lock_status[block] ); + } + printf("\nDone!\n\n" ); + +/** return; **/ +} +#endif + +/********************************************************/ +/* SET ALL LOCK BITS */ +/* */ +/* returns OK if successful; otherwise returns ERROR */ +/* and sets cmd_stat to an error code */ +/* The 28F640J3A is divided into 64, 128Kbyte blocks */ +/* This routine sets a lock bit in the block specified */ +/* by a given address */ +/********************************************************/ +int set_all_lock_bits() +{ + unsigned long addr = 0x0; + void *err_addr; + int stat; + + if ((stat = flash_lock((void *)addr, 4 * FLASH_BLOCK_SIZE, (void **)&err_addr)) != 0) { + return stat; + } + return( OK ); +} + + +/********************************************************/ +/* CLEAR ALL LOCK BITS */ +/* */ +/* returns OK if successful; otherwise returns ERROR */ +/* and sets cmd_stat to an error code */ +/* The 28F640J3A is divided into 64, 128Kbyte blocks */ +/* This routine clears all block lock bits */ +/********************************************************/ +int clear_all_lock_bits(ADDR addr) +{ + void *err_addr; + int stat; + + if ((stat = flash_unlock((void *)0, eeprom_size, (void **)&err_addr)) != 0) + return stat; + return OK; +} + + +/********************************************************/ +/* ERASE EEPROM */ +/* */ +/* returns OK if erase was successful, */ +/* otherwise returns ERROR */ +/* and sets cmd_stat to an error code */ +/* */ +/********************************************************/ +int erase_eeprom(ADDR addr, unsigned long length) +{ + void *err_addr; + int num_blocks; + + /********************************************************/ + /* The 28F640J3A is divided into 64, 128Kbyte blocks */ + /* each of which must be individually erased. */ + /* This routine and erases a whole number of blocks */ + /********************************************************/ + + /* don't erase boot area even if entire eeprom is specified */ + if (addr == NO_ADDR) + { + /* 10/06/00 *//* Original */ + /*addr = flash_addr;*/ + addr = FLASH_BLK4_BASE_ADDR; + + length = eeprom_size - RESERVED_AREA_SIZE; + } + + /* Original */ + /* check for reserved area if one is used */ + /* check to see if the address is within the reserved area */ +/* + if (reserved_check(addr, length) == TRUE) + { + cmd_stat = E_EEPROM_ADDR; + + return ERR; + } +*/ + + + if (length == 0) + { + + /* 10/06/00 */ + printf( "erase_eeprom, return OK, length=0\n"); + + return OK; + } + + /* start address must be block-aligned */ + if ((addr % FLASH_BLOCK_SIZE) != 0) + { + cmd_stat = E_EEPROM_ADDR; + + printf( "erase_eeprom, addr = 0x%x\n", addr); + printf( "erase_eeprom, FLASH_BLOCK_SIZE = 0x%x\n", FLASH_BLOCK_SIZE); + printf( "erase_eeprom, return ERR, (addr %% FLASH_BLOCK_SIZE) = %d\n", addr % FLASH_BLOCK_SIZE); + + return ERR; + } + + /* figure out how many blocks require erasure - round up using integer division */ + if (length % FLASH_BLOCK_SIZE) /* non-multiple, round up */ + num_blocks = (length + FLASH_BLOCK_SIZE) / FLASH_BLOCK_SIZE; + else /* multiple number of blocks */ + num_blocks = length / FLASH_BLOCK_SIZE; + + if (eeprom_size == 0) + { + cmd_stat = E_NO_FLASH; + return ERR; + } + + /* Original */ + /* If it's already erased, don't bother */ + /*if (check_eeprom(addr, length) == OK)*/ + /* return OK;*/ + /* check_bstat(int block_num); */ + + if (flash_erase((void *)addr, num_blocks * FLASH_BLOCK_SIZE, (void **)&err_addr) != 0) { + cmd_stat = E_EEPROM_FAIL; + return ERR; + } + + return OK; +} + + +/********************************************************/ +/* CHECK PROGRAM OR LOCK STATUS */ +/* */ +/* Check the status of program or lock operations */ +/* using the Status Register of the Flash */ +/* */ +/* Returns: OK - Write successful */ +/* VPP_LOW_DETECT - Vpp low detected */ +/* PROGRAM_LOCK_ERROR - Write error */ +/* UNKNOWN_ERR - Unknown error condition */ +/* */ +/********************************************************/ +#if 0 +int check_program_lock(volatile FLASH_TYPE *flash) +{ + FLASH_TYPE stat; + flash = FLASH_P2V(flash); + *flash = READ_STAT_REG; + stat = *flash; + + /* poll and wait for Write State Machine Ready */ + while (!(stat & WSM_READY)) + stat = *flash; + + /* now check completion status */ + if (stat & VPP_LOW_DETECT) + { + *flash = CLEAR_STAT_REG; + return VPP_LOW_DETECT; + } + + if (stat & PROGRAM_LOCK_ERROR) + { + *flash = CLEAR_STAT_REG; + return PROGRAM_LOCK_ERROR; + } + + if ((stat & ALL_FLASH_STATUS) == (WSM_READY | PROGRAM_LOCK_SUCCESS)) + { + *flash = CLEAR_STAT_REG; + return OK; + } + else + { + *flash = CLEAR_STAT_REG; + return UNKNOWN_ERR; + } +} +#endif + +/********************************************************/ +/* WRITE EEPROM */ +/* */ +/* returns OK if successful; otherwise returns ERROR */ +/* and sets cmd_stat to an error code */ +/* */ +/********************************************************/ +int +write_eeprom(ADDR start_addr, const void *data_arg, int data_size) +{ + void *err_addr; + + if (flash_program(start_addr, data_arg, data_size, &err_addr) != 0) { + cmd_stat = E_EEPROM_FAIL; + return ERR; + } + return OK; +} + + +/***************************************************************************** +* +* flash_test - System Flash ROM diagnostics +* +* A destructive Flash ROM Read/Write test. Note that the area of Flash +* which is tested changes based on whether the diagnostic is being invoked +* from the System code or from the Factory code (can't write over MON960). +* +* This test basically does a Longword Address test to the Flash area. +* +*/ +void flash_test(void) +{ + + ADDR start_addr = (ADDR)flash_addr; /* Original */ + + int i; + unsigned long *f_ptr = (unsigned long *)flash_addr; + int bytes_written = 0; + unsigned long flash_data; + char answer[20]; + +/* 10/31/00 */ + int status; + +#if 0 + printf ("Disabling Instruction Cache... "); + _disableICache(); /* disable instruction cache */ + printf ("Done\n\n"); + + /* switch the MMU over to use RAM-based page table entries */ + printf ("Switching MMU to RAM-based page table... "); + _switchMMUpageTables(); + printf ("Done\n\n"); +#endif + + +/* 10/31/00 */ +/* + check_lock_bit_status(); + + printf ("Setting Block Lock Bits... \n"); + printf("Do you wish to continue? (y/n)\n"); + sgets(answer); + printf("\n"); + if ((answer[0] != 'y') && (answer[0] != 'Y')) + return; + if( (status = set_all_lock_bits() ) == OK ) + printf("Done!\n"); + else + { + printf("Error!\n"); + printf( "error status = 0x%x\n", status ); + } + + check_lock_bit_status(); + + printf ("\nClearing Block Lock Bits... \n"); + printf("Do you wish to continue? (y/n)\n"); + sgets(answer); + printf("\n"); + if ((answer[0] != 'y') && (answer[0] != 'Y')) + return; + if( ( status=clear_all_lock_bits(NO_ADDR) ) == OK ) + printf("Done!\n"); + else + { + printf("Error!\n"); + printf( "error status = 0x%x\n", status ); + } + + check_lock_bit_status(); +*/ +/* 10/31/00 */ + + + init_eeprom(); + + printf("***********************************\n"); + printf("*** WARNING ***\n"); + printf("*** This test is destructive to ***\n"); + printf("*** all contents of the FLASH! ***\n"); + printf("***********************************\n"); + + printf("\nDo you wish to continue? (y/n)\n"); + sgets(answer); + printf("\n\n"); + if ((answer[0] != 'y') && (answer[0] != 'Y')) + return; + + + printf ("FLASH begins at 0x%X\n", flash_addr); + printf ("Total FLASH size = 0x%X\n\n", eeprom_size); + + printf ("Checking FLASH ...\n"); + if (check_eeprom(NO_ADDR, 0) == OK) + printf("FLASH is erased\n\n"); + else + { + printf("FLASH is programmed between 0x%X and 0x%X\n\n", + eeprom_prog_first, eeprom_prog_last); + } + + + printf ("\nClearing Block Lock Bits... \n"); + if(clear_all_lock_bits(NO_ADDR)==OK) + printf("Done!\n\n"); + else + printf("Error!\n\n"); + +/* check_lock_bit_status(); */ + + printf ("Erasing FLASH...\n"); + if (erase_eeprom(NO_ADDR, 0) != OK) + printf("Error on erase_eeprom()\n\n"); + else + printf("Done Erasing FLASH!\n\n"); + + (ADDR)flash_addr = FLASH_BLK4_BASE_ADDR; + (ADDR)start_addr = (ADDR)flash_addr; + + printf ("Writing Longword Data to FLASH...\n"); + + /* write to all of available Flash ROM. Don't do this thousands of times + since the Flash has only 100,000 write cycles in its lifespan */ + + while (bytes_written < (eeprom_size - RESERVED_AREA_SIZE)) + { + flash_data = (unsigned long)start_addr; + for (i=0; i<TEST_BUF_LONGS; i++) + { + flash_buffer[i] = flash_data; /* put address in buffer */ + flash_data += 4; /* increment address */ + } + if (write_eeprom (start_addr, (void *)flash_buffer, + TEST_BUF_CHARS) != OK) + { + printf("Error on write_eeprom()\n"); + goto finish; + } + start_addr = (unsigned long)start_addr + TEST_BUF_CHARS; + bytes_written += TEST_BUF_CHARS; + } + + printf ("Write Complete, Verifying Data...\n"); + bytes_written = 0; + + (ADDR)flash_addr = FLASH_BLK4_BASE_ADDR; + f_ptr = (unsigned long *)flash_addr; + + while (bytes_written < (eeprom_size - RESERVED_AREA_SIZE)) + { + if (*f_ptr != (unsigned long)f_ptr) + { + printf ("Data verification error at 0x%X\n", + (unsigned long)f_ptr); + printf ("Expected 0x%X Got 0x%X\n", (unsigned long)f_ptr, *f_ptr); + goto finish; + } + f_ptr++; + bytes_written += 4; + } + printf ("Done Verifying Longword Data!\n\n"); + + + printf ("Checking FLASH...\n"); + if (check_eeprom(NO_ADDR, 0) == OK) + printf("FLASH is erased\n\n"); + else + { + printf("FLASH is programmed between 0x%X and 0x%X\n\n", + eeprom_prog_first, eeprom_prog_last); + } + + + printf ("Erasing FLASH...\n"); + if (erase_eeprom(NO_ADDR, 0) != OK) + printf("Error on erase_eeprom()\n\n"); + else + printf("Done Erasing FLASH!\n\n"); + + + printf ("Checking FLASH...\n"); + if (check_eeprom(NO_ADDR, 0) == OK) + printf("FLASH is erased\n\n"); + else + { + printf("FLASH is programmed between 0x%X and 0x%X\n\n", + eeprom_prog_first, eeprom_prog_last); + } + + + /* reinitialize variables */ + bytes_written = 0; + + (ADDR)flash_addr = FLASH_BLK4_BASE_ADDR; + + start_addr = (ADDR)flash_addr; + f_ptr = (unsigned long *)flash_addr; + + printf ("Writing Inverted Longword Data to FLASH...\n"); + + /* write to all of available Flash ROM. Don't do this thousands of times + since the Flash has only 100,000 write cycles in its lifespan */ + + while (bytes_written < (eeprom_size - RESERVED_AREA_SIZE)) + { + flash_data = (unsigned long)start_addr; + for (i=0; i<TEST_BUF_LONGS; i++) + { + flash_buffer[i] = ~flash_data; /* put address BAR in buffer */ + flash_data += 4; /* increment address */ + } + if (write_eeprom (start_addr, (void *)flash_buffer, + TEST_BUF_CHARS) != OK) + { + printf("Error on write_eeprom()\n"); + goto finish; + } + start_addr = (unsigned long)start_addr + TEST_BUF_CHARS; + bytes_written += TEST_BUF_CHARS; + } + + printf ("Write Complete, Verifying Data...\n"); + bytes_written = 0; + + while (bytes_written < (eeprom_size - RESERVED_AREA_SIZE)) + { + if (*f_ptr != (~(unsigned long)f_ptr)) + { + printf ("Data verification error at 0x%X\n", + (unsigned long)f_ptr); + printf ("Expected 0x%X Got 0x%X\n", (~(unsigned long)f_ptr), *f_ptr); + goto finish; + } + f_ptr++; + bytes_written += 4; + } + printf ("Done Verifying Inverted Longword Data!\n\n"); + + + printf ("Checking FLASH...\n"); + if (check_eeprom(NO_ADDR, 0) == OK) + printf("FLASH is erased\n\n"); + else + { + printf("FLASH is programmed between 0x%X and 0x%X\n\n", + eeprom_prog_first, eeprom_prog_last); + } + + + printf ("Erasing FLASH...\n"); + if (erase_eeprom(NO_ADDR, 0) != OK) + printf("Error on erase_eeprom()\n\n"); + else + printf("Done Erasing FLASH!\n\n"); + + + printf ("Checking FLASH...\n"); + if (check_eeprom(NO_ADDR, 0) == OK) + printf("FLASH is erased\n\n"); + else + { + printf("FLASH is programmed between 0x%X and 0x%X\n\n", + eeprom_prog_first, eeprom_prog_last); + } + + +/* 11/02/00 */ + printf ("Setting Lock Bits for Blocks 0-3... \n"); + if( (status = set_all_lock_bits() ) == OK ) + { + printf("Done!\n"); + } + else + { + printf("Error!\n"); + printf( "error status = 0x%x\n", status ); + // check_lock_bit_status(); + } +/* + printf ("Setting Lock Bits for Blocks 0-3... \n"); + if(set_all_lock_bits()==OK) + { + printf("Done!\n\n"); + } + else + { + printf("Error!\n\n"); + check_lock_bit_status(); + } +*/ +/* 11/02/00 */ + + +finish: + _flushICache(); +#if 0 + _enableICache(); +#endif + + printf ("\nHit <CR> to Continue...\n"); + (void)hexIn(); + return; + +} +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/i557_eep.c @@ -0,0 +1,551 @@ +//============================================================================= +// +// i557_eep.c - Cyclone Diagnostics +// +//============================================================================= +//####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) 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-25 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +#include "i557_eep.h" + +/***************************************************************************** +* +* Serial EEPROM Access code for the i557/558 +* +* Revision History: +* ----------------- +* +* +* 05jun98, snc Added setup time for eeprom CS. Changed eeprom_delay to use the +* processor's internal timer. Fixed programming algorithm to poll +* the eeprom's DO line to look for the transition from BUSY to READY +* which indicates that the programming operation has completed. +* 03jun98, snc Added setup time delay on data writes (delay before asserting +* a rising edge on the SK. Fixed eeprom_get_word() to explicitly +* clear a bit position in the buffer after reading a low on the +* data lines. +* 23oct96, snc Ported to the PCI914 +* +*/ + +/* + * Timing information. According to the National Semiconductor manual, + * the SK High Minimum time = SK Low Minimum time = 250 nsec. However, + * the minimum SK cycle time is 1 usec, so a 250 nsec high/750 nsec. low + * sequence or equivalent would be required. + */ + +/* Serial clock line */ +#define SK_LOW_PERIOD 500 /* nsec, Time serial clock is low */ +#define SK_HIGH_PERIOD 500 /* nsec, Time serial clock is high */ + +/* Serial data line */ +#define DATA_IN_HOLD_TIME 20 /* nsec, SK low to EEDI change */ +#define DATA_IN_SETUP_TIME 100 /* nsec, EEDI change to SK high */ + +/* Serial clock and data line states (assumes ports are non-inverting) */ +#define HIGH 1 +#define LOW 0 + +/* Select setup time to rising edge of SK */ +#define SELECT_SETUP_TIME 50 /* nsec */ + +/* De-select time between consecutive commands */ +#define DESELECT_TIME 100 /* nsec */ + + +/* local functions */ + +static void set_sda_line (unsigned long pci_base, /* PCI Base address */ + int state); /* HIGH or LOW */ + +static int get_sda_line (unsigned long pci_base); /* PCI Base address */ + +static void set_scl_line (unsigned long pci_base, /* PCI Base address */ + int state); /* HIGH or LOW */ + +void eeprom_delay (int nsec); +static int eeprom_send_start (unsigned long pci_base, int command); +static int eeprom_send_addr (unsigned long pci_base, + unsigned char eeprom_addr); +static int eeprom_get_word (unsigned long pci_base, + unsigned short *word_addr); +static int eeprom_put_word (unsigned long pci_base, + unsigned short data); +static int eeprom_write_enable(unsigned long pci_base); +static int eeprom_write_disable(unsigned long pci_base); + +/* global variables */ +int powerup_wait_done = 0; /* set true after power-up wait done */ + + +/*------------------------------------------------------------- + * Function: int eeprom_read () + * + * Action: Read data from the eeprom, place it at p_data + * + * Returns: OK if read worked, EEPROM_NOT_RESPONDING if + * read fails. + *-------------------------------------------------------------*/ +int eeprom_read (unsigned long pci_base,/* PCI Base address */ + int eeprom_addr, /* word offset from start of eeprom */ + unsigned short *p_data,/* where to put data in memory */ + int nwords /* number of 16bit words to read */ + ) +{ + int status; /* result code */ + int i; /* loop variable */ + + /* + * Make sure caller isn't requesting a read beyond the end of the + * eeprom. + */ + if ((eeprom_addr + nwords) > EEPROM_WORD_SIZE) + return (EEPROM_TO_SMALL); + + + /* Read in desired number of words */ + for (i = 0; i < nwords; i++, eeprom_addr++) + { + /* Select the serial EEPROM */ + SELECT_557_EEP(pci_base); + + /* Wait CS setup time */ + eeprom_delay (SELECT_SETUP_TIME); + + /* Send start/read command to begin the read */ + if (((status = eeprom_send_start (pci_base, EEPROM_READ)) != OK) || + /* Send address */ + ((status = eeprom_send_addr (pci_base, eeprom_addr)) != OK)) + return (status); + + if ((status = eeprom_get_word (pci_base, p_data++)) != OK) + return (status); + + /* De-Select the serial EEPROM */ + DESELECT_557_EEP(pci_base); + + /* wait the required de-select time between commands */ + eeprom_delay (DESELECT_TIME); + } + + + return (OK); +} + +/*------------------------------------------------------------- + * Function: int eeprom_write () + * + * Action: Write data from p_data to the eeprom + * + * Returns: OK if write worked, EEPROM_NOT_RESPONDING if + * write failed. + *-------------------------------------------------------------*/ +int eeprom_write (unsigned long pci_base,/* PCI Base address */ + int eeprom_addr, /* word offset from start of eeprom */ + unsigned short *p_data,/* data source in memory */ + int nwords /* number of 16bit words to read */ + ) +{ + int status; /* result code */ + int i; /* loop variable */ + int check_cntr; + unsigned short data; + + /* + * Make sure caller isn't requesting a read beyond the end of the + * eeprom. + */ + if ((eeprom_addr + nwords) > EEPROM_WORD_SIZE) + return (EEPROM_TO_SMALL); + + /* enable eeprom writes */ + if ((status = eeprom_write_enable(pci_base)) != OK) + return(status); + + /* Read in desired number of words */ + for (i = 0; i < nwords; i++, eeprom_addr++) + { + /* Select the serial EEPROM */ + SELECT_557_EEP(pci_base); + + /* Wait CS setup time */ + eeprom_delay (SELECT_SETUP_TIME); + + /* Send start/write command to begin the read */ + if (((status = eeprom_send_start (pci_base, EEPROM_WRITE)) != OK) || + /* Send address */ + ((status = eeprom_send_addr (pci_base, eeprom_addr)) != OK)) + return (status); + + data = *p_data++; + if ((status = eeprom_put_word (pci_base, data)) != OK) + return (status); + + /* De-Select the serial EEPROM */ + DESELECT_557_EEP(pci_base); + + /* wait the required de-select time between commands */ + eeprom_delay (DESELECT_TIME); + + /* Re-Select the serial EEPROM */ + SELECT_557_EEP(pci_base); + + /* now that the write command/data have been clocked into the EEPROM + we must wait for the BUSY indicator (DO driven low) to indicate + READY (DO driven high) */ + check_cntr = 0; + + while (1) + { + check_cntr++; + + if (get_sda_line (pci_base) == HIGH) break; /* programming complete */ + + if (check_cntr > 100000) /* timeout */ + { + /* De-Select the serial EEPROM */ + DESELECT_557_EEP(pci_base); + /* wait the required de-select time between commands */ + eeprom_delay (DESELECT_TIME); + + return (EEPROM_ERROR); + } + } + + /* De-Select the serial EEPROM */ + DESELECT_557_EEP(pci_base); + + /* wait the required de-select time between commands */ + eeprom_delay (DESELECT_TIME); + } + + /* disable eeprom writes */ + if ((status = eeprom_write_disable(pci_base)) != OK) + return(status); + + return (OK); +} + +/*------------------------------------------------------------- + * Function: int eeprom_write_enable () + * + * Action: Enable writes to the eeprom + * + * Returns: OK if command sent, EEPROM_NOT_RESPONDING if not. + * + *-------------------------------------------------------------*/ +int eeprom_write_enable (unsigned long pci_base) +{ + int status; /* result code */ + + /* Select the serial EEPROM */ + SELECT_557_EEP(pci_base); + + /* Wait CS setup time */ + eeprom_delay (SELECT_SETUP_TIME); + + /* Send start/write enable command */ + if (((status = eeprom_send_start (pci_base, EEPROM_EWEN)) != OK) || + /* Send address */ + ((status = eeprom_send_addr (pci_base, EEPROM_EWEN_OP)) != OK)) + return (status); + + /* De-Select the serial EEPROM */ + DESELECT_557_EEP(pci_base); + + /* wait the required de-select time between commands */ + eeprom_delay (DESELECT_TIME); + + return (OK); +} + +/*------------------------------------------------------------- + * Function: int eeprom_write_disable () + * + * Action: Disable writes to the eeprom + * + * Returns: OK if command sent, EEPROM_NOT_RESPONDING if not. + * + *-------------------------------------------------------------*/ +int eeprom_write_disable (unsigned long pci_base) +{ + int status; /* result code */ + + /* Select the serial EEPROM */ + SELECT_557_EEP(pci_base); + + /* Wait CS setup time */ + eeprom_delay (SELECT_SETUP_TIME); + + /* Send start/write enable command */ + if (((status = eeprom_send_start (pci_base, EEPROM_EWDS)) != OK) || + /* Send address */ + ((status = eeprom_send_addr (pci_base, EEPROM_EWDS_OP)) != OK)) + return (status); + + /* De-Select the serial EEPROM */ + DESELECT_557_EEP(pci_base); + + /* wait the required de-select time between commands */ + eeprom_delay (DESELECT_TIME); + + return (OK); +} + + +/****************************************************************************** +* +* eeprom_delay - delay for a specified number of nanoseconds +* +* Note: this routine is a generous approximation as delays for eeproms +* are specified as minimums. +*/ +void eeprom_delay (int nsec) +{ + extern void polled_delay (int usec); + + /* generously delay 1 usec. for each nsec. */ + polled_delay (nsec); +} + +/****************************************************************************** +* +* eeprom_send_start - send a start bit with a read opcode to the '557 serial +* eeprom +* +*/ +static int eeprom_send_start (unsigned long pci_base, int command) +{ + int op_code[2]; + + switch (command) + { + case EEPROM_WRITE: + op_code[0] = LOW; + op_code[1] = HIGH; + break; + + case EEPROM_READ: + op_code[0] = HIGH; + op_code[1] = LOW; + break; + + case EEPROM_ERASE: + op_code[0] = HIGH; + op_code[1] = HIGH; + break; + + case EEPROM_EWEN: + case EEPROM_EWDS: + op_code[0] = LOW; + op_code[1] = LOW; + break; + + default: + return(EEPROM_INVALID_CMD); + } + + set_scl_line (pci_base, LOW); + set_sda_line (pci_base, HIGH); /* start bit */ + eeprom_delay (DATA_IN_SETUP_TIME); + set_scl_line (pci_base, HIGH); /* clock high */ + eeprom_delay (SK_HIGH_PERIOD); + set_scl_line (pci_base, LOW); /* clock low */ + eeprom_delay (SK_LOW_PERIOD); + + /* send the opcode */ + set_sda_line (pci_base, op_code[0]); /* MSB of opcode */ + eeprom_delay (DATA_IN_SETUP_TIME); + set_scl_line (pci_base, HIGH); /* clock high */ + eeprom_delay (SK_HIGH_PERIOD); + set_scl_line (pci_base, LOW); /* clock low */ + eeprom_delay (SK_LOW_PERIOD); + set_sda_line (pci_base, op_code[1]); /* LSB of opcode */ + eeprom_delay (DATA_IN_SETUP_TIME); + set_scl_line (pci_base, HIGH); /* clock high */ + eeprom_delay (SK_HIGH_PERIOD); + set_scl_line (pci_base, LOW); /* clock low */ + eeprom_delay (SK_LOW_PERIOD); + + return (OK); +} + +/****************************************************************************** +* +* eeprom_send_addr - send the read address to the '557 serial eeprom +* +*/ +static int eeprom_send_addr (unsigned long pci_base, + unsigned char eeprom_addr) +{ + register int i; + + /* Do each address bit, MSB => LSB - after each address bit is + sent, read the EEDO bit on the '557 to check for the "dummy 0 bit" + which when set to 0, indicates that the address field is complete */ + for (i = 5; i >= 0; i--) + { + /* If this bit is a 1, set SDA high. If 0, set it low */ + if (eeprom_addr & (1 << i)) + set_sda_line (pci_base, HIGH); + else + set_sda_line (pci_base, LOW); + + eeprom_delay (DATA_IN_SETUP_TIME); /* Data setup before raising clock */ + set_scl_line (pci_base, HIGH); /* Clock in this data bit */ + eeprom_delay (SK_HIGH_PERIOD); + set_scl_line (pci_base, LOW); /* Prepare for next bit */ + eeprom_delay (SK_LOW_PERIOD); + + /* check to see if "dummy 0 bit" is set to 0 indicating address + complete */ + if (get_sda_line (pci_base) == LOW) + break; /* address complete */ + } + return (OK); +} + +/****************************************************************************** +* +* eeprom_get_word - read a 16 bit word from the '557 serial eeprom +* +* Note: this routine assumes that the start/opcode/address have already +* been set up +*/ +static int eeprom_get_word (unsigned long pci_base, + unsigned short *word_addr) +{ + register int i; + + /* Do each data bit, MSB => LSB */ + for (i = 15; i >= 0; i--) + { + set_scl_line (pci_base, HIGH); + eeprom_delay (SK_HIGH_PERIOD); + + if (get_sda_line (pci_base) == HIGH) + *word_addr |= (1 << i); /* store bit as a '1' */ + else + *word_addr &= ~(1 << i); /* store bit as a '0' */ + + set_scl_line (pci_base, LOW); + eeprom_delay (SK_LOW_PERIOD); + } + return (OK); +} + +/****************************************************************************** +* +* eeprom_put_word - write a 16 bit word to the '557 serial eeprom +* +* Note: this routine assumes that the start/opcode/address have already +* been set up +*/ +static int eeprom_put_word (unsigned long pci_base, + unsigned short data) +{ + register int i; + + /* Do each data bit, MSB => LSB */ + for (i = 15; i >= 0; i--) + { + if (data & (1 << i)) + set_sda_line(pci_base, HIGH); + else + set_sda_line(pci_base, LOW); + + eeprom_delay (DATA_IN_SETUP_TIME); + set_scl_line (pci_base, HIGH); + eeprom_delay (SK_HIGH_PERIOD); + set_scl_line (pci_base, LOW); + eeprom_delay (SK_LOW_PERIOD); + } + return (OK); +} + +/*------------------------------------------------------------- + * Function: void set_scl_line () + * + * Action: Sets the value of the eeprom's serial clock line + * to the value HIGH or LOW. + * + * Returns: N/A. + *-------------------------------------------------------------*/ +static void set_scl_line (unsigned long pci_base, /* PCI address */ + int state) /* HIGH or LOW */ +{ + if (state == HIGH) + SK_HIGH_557_EEP (pci_base); + else if (state == LOW) + SK_LOW_557_EEP (pci_base); +} + +/*------------------------------------------------------------- + * Function: void set_sda_line () + * + * Action: Sets the value of the eeprom's serial data line + * to the value HIGH or LOW. + * + * Returns: N/A. + *-------------------------------------------------------------*/ +static void set_sda_line (unsigned long pci_base, /* PCI address */ + int state) /* HIGH or LOW */ +{ + if (state == HIGH) + EEDI_HIGH_557_EEP (pci_base); + else if (state == LOW) + EEDI_LOW_557_EEP (pci_base); +} + +/*------------------------------------------------------------- + * Function: int get_sda_line () + * + * Action: Returns the value of the eeprom's serial data line + * + * Returns: HIGH or LOW. + *-------------------------------------------------------------*/ +static int get_sda_line (unsigned long pci_base) /* PCI address */ +{ + int ret_val; /* result code */ + + if (EEDO_557_EEP (pci_base)) + ret_val = HIGH; + else + ret_val = LOW; + + return (ret_val); +}
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/i557_eep.h @@ -0,0 +1,89 @@ +//============================================================================= +// +// i557_eep.h - Cyclone Diagnostics +// +//============================================================================= +//####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) 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-25 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +/* Public define's and function prototypes */ +#define EEPROM_SIZE 128 /* Maximum # bytes in serial eeprom */ +#define EEPROM_WORD_SIZE 64 /* Maximum # shorts in serial eeprom */ + +/* result codes for the functions below */ +#define OK 0 /* Operation completed successfully */ +#define EEPROM_ERROR 1 /* generic error */ +#define EEPROM_NOT_RESPONDING 2 /* eeprom not resp/not installed */ +#define EEPROM_TO_SMALL 3 /* req write/read past end of eeprom */ +#define EEPROM_INVALID_CMD 4 /* op code not supported */ + +/* layout of the Serial EEPROM register */ +#define I557_EESK (1 << 0) +#define I557_EECS (1 << 1) +#define I557_EEDI (1 << 2) +#define I557_EEDO (1 << 3) + +/* EEPROM commands */ +#define EEPROM_WRITE 1 +#define EEPROM_READ 2 +#define EEPROM_ERASE 3 +#define EEPROM_EWEN 4 +#define EEPROM_EWDS 5 +#define EEPROM_EWEN_OP 0x30 +#define EEPROM_EWDS_OP 0x00 + +/* EEPROM Chip Select */ +#define SELECT_557_EEP(n) (*(unsigned char *)(n+0x0e) |= I557_EECS) +#define DESELECT_557_EEP(n) (*(unsigned char *)(n+0x0e) &= ~I557_EECS) + +/* EEPROM Serial Clock */ +#define SK_HIGH_557_EEP(n) (*(unsigned char *)(n+0x0e) |= I557_EESK) +#define SK_LOW_557_EEP(n) (*(unsigned char *)(n+0x0e) &= ~I557_EESK) + +/* EEPROM Serial Data In -> out to eeprom */ +#define EEDI_HIGH_557_EEP(n) (*(unsigned char *)(n+0x0e) |= I557_EEDI) +#define EEDI_LOW_557_EEP(n) (*(unsigned char *)(n+0x0e) &= ~I557_EEDI) + +/* EEPROM Serial Data Out -> in from eeprom */ +#define EEDO_557_EEP(n) ((*(unsigned char *)(n+0x0e) & I557_EEDO) >> 3) + +/* global functions declared in serial_eep.c */ + +int eeprom_read (unsigned long pci_addr, + int eeprom_addr, /* word offset from start of eeprom */ + unsigned short *p_data,/* buffer pointer */ + int nwords /* number of bytes to read */ + );
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/interrupts.c @@ -0,0 +1,1129 @@ +//============================================================================= +// +// interrupts.c - Cyclone Diagnostics +// +//============================================================================= +//####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) 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-25 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +/******************************************************************************/ +/* interrupts.c - Interrupt dispatcher routines for IQ80310 Board */ +/* */ +/* modification history */ +/* -------------------- */ +/* 07sep00, ejb, Written for IQ80310 Cygmon diagnostics */ +/* 11oct00, ejb, Switched FIQ and IRQ interrupt handlers */ +/* 18dec00 snc and jwf */ +/* 02feb01 jwf for snc */ +/******************************************************************************/ + +#include "iq80310.h" +#include "pci_bios.h" +#include "7_segment_displays.h" + +extern int(*board_fiq_handler)(void); +extern int(*board_irq_handler)(void); +extern long _cspr_enable_fiq_int(); +extern long _cspr_enable_irq_int(); +extern long _read_cpsr(); +extern long _scrub_ecc(); + + +#define AND_WORD(addr,val) *addr = *addr & val + + +void error_print(char *fmt, int arg0, int arg1, int arg2, int arg3); + + +extern int nmi_verbose; /* for NMI, only print NMI info if this is TRUE */ +extern int pci_config_cycle; /* don't handle NMI if in a config cycle */ +extern int pci_config_error; + +typedef struct +{ + FUNCPTR handler; + int arg; + int bus; + int device; +} INT_HANDLER; + +extern UINT secondary_busno; +extern UINT primary_busno; + +extern STATUS pci_to_xint(int device, int intpin, int *xint); +extern int isHost(); +extern int off_ppci_bus (int busno); + +#define MAX_SPURIOUS_CNT 5 +#define NUM_PCI_XINTS 4 /* SINTA - SINTD */ +#define MAX_PCI_HANDLERS 8 /* maximum handlers per PCI Xint */ + +/* 02/02/01 jwf */ +int ecc_error_reported = FALSE; + +static int isr_xint0_spurious = 0; +static int isr_xint1_spurious = 0; +static int isr_xint2_spurious = 0; +static int isr_xint3_spurious = 0; + +/* Table where the interrupt handler addresses are stored. */ +INT_HANDLER pci_int_handlers[4][MAX_PCI_HANDLERS]; + +/* Other User Interrupt Service Routines */ + +void (*usr_timer_isr)(int) = NULL; +int usr_timer_arg = 0; +void (*usr_enet_isr)(int) = NULL; +int usr_enet_arg = 0; +void (*usr_uart1_isr)(int) = NULL; +int usr_uart1_arg = 0; +void (*usr_uart2_isr)(int) = NULL; +int usr_uart2_arg = 0; +void (*usr_dma0_isr)(int) = NULL; +int usr_dma0_arg = 0; +void (*usr_dma1_isr)(int) = NULL; +int usr_dma1_arg = 0; +void (*usr_dma2_isr)(int) = NULL; +int usr_dma2_arg = 0; +void (*usr_pm_isr)(int) = NULL; +int usr_pm_arg = 0; +void (*usr_aa_isr)(int) = NULL; +int usr_aa_arg = 0; +void (*usr_i2c_isr)(int) = NULL; +int usr_i2c_arg = 0; +void (*usr_mu_isr)(int) = NULL; +int usr_mu_arg = 0; +void (*usr_patu_isr)(int) = NULL; +int usr_patu_arg = 0; + +int ecc_int_handler(); + + + +/********************************* +* PCI interrupt wrappers +*/ +int sinta_handler() +{ + int x, serviced = 0; + /* cycle through connected interrupt handlers to determine which caused int */ + for (x = 0; x < MAX_PCI_HANDLERS; x++) + { + if (pci_int_handlers[0][x].handler != NULL) /* Is a routine installed */ + if ((*pci_int_handlers[0][x].handler)(pci_int_handlers[0][x].arg) == 1) + { + serviced = 1; + break; + } + } + if (serviced == 0) + { + isr_xint0_spurious++; + + if (isr_xint0_spurious > MAX_SPURIOUS_CNT) + ; + } + else + isr_xint0_spurious = 0; + + return (serviced); + +} + +int sintb_handler() +{ + int x, serviced = 0; + + /* cycle through connected interrupt handlers to determine which caused int */ + for (x = 0; x < MAX_PCI_HANDLERS; x++) + { + if (pci_int_handlers[1][x].handler != NULL) /* Is a routine installed */ + if ((*pci_int_handlers[1][x].handler)(pci_int_handlers[1][x].arg) == 1) + { + serviced = 1; + break; + } + } + if (serviced == 0) + { + isr_xint1_spurious++; + + if (isr_xint1_spurious > MAX_SPURIOUS_CNT) + ; + } + else + isr_xint1_spurious = 0; + + return (serviced); + +} + +int sintc_handler() +{ + + int x, serviced = 0; + + /* cycle through connected interrupt handlers to determine which caused int */ + for (x = 0; x < MAX_PCI_HANDLERS; x++) + { + if (pci_int_handlers[2][x].handler != NULL) /* Is a routine installed */ + if ((*pci_int_handlers[2][x].handler)(pci_int_handlers[2][x].arg) == 1) + { + serviced = 1; + break; + } + } + if (serviced == 0) + { + isr_xint2_spurious++; + + if (isr_xint2_spurious > MAX_SPURIOUS_CNT) + ; + } + else + isr_xint2_spurious = 0; + + return (serviced); + +} + +int sintd_handler() +{ + + int x, serviced = 0; + + /* cycle through connected interrupt handlers to determine which caused int */ + for (x = 0; x < MAX_PCI_HANDLERS; x++) + { + if (pci_int_handlers[3][x].handler != NULL) /* Is a routine installed */ + if ((*pci_int_handlers[3][x].handler)(pci_int_handlers[3][x].arg) == 1) + { + serviced = 1; + break; + } + } + if (serviced == 0) + { + isr_xint3_spurious++; + + if (isr_xint3_spurious > MAX_SPURIOUS_CNT) + ; + } + else + isr_xint3_spurious = 0; + + return (serviced); + + +} + + +/****************************************************************************** +* +* Installs an interrupt handler in the PCI dispatch table, to be called +* by the appropriate PCI isr (above) when an interrupt occurs. +* +* Note: the intline parameter refers to which PCI interrupt INT A - INT D +* +* device identifies the PCI device number +* +* Note: isrs connected with this function must return 1 if an interrupt is +* serviced in order to support the PCI interrupt sharing mechanism +* +*/ +STATUS pci_isr_connect (int intline, int bus, int device, int (*handler)(int), int arg) +{ + int which_xint; + int handler_index; + + /* check to see if we are attempting to connect to a PPCI interrupt and we are not + a host card */ + if ((isHost() == FALSE) && (off_ppci_bus(bus) == TRUE)) + return (ERROR); + + if ((intline < INTA) || (intline > INTD)) + return (ERROR); + + (void)pci_to_xint(device, intline, &which_xint); + + for (handler_index = 0; handler_index < MAX_PCI_HANDLERS; handler_index++) + { + if (pci_int_handlers[which_xint][handler_index].handler == NULL) + { + pci_int_handlers[which_xint][handler_index].handler = handler; + pci_int_handlers[which_xint][handler_index].arg = arg; + pci_int_handlers[which_xint][handler_index].bus = bus; + pci_int_handlers[which_xint][handler_index].device = device; + break; + } + } + + /* if there is no more room in the table return an error */ + if (handler_index == MAX_PCI_HANDLERS) + return (ERROR); + + return (OK); +} + + +/****************************************************************************** +* +* Uninstalls an interrupt handler in the PCI dispatch table +* +* Note: the intline parameter refers to which PCI interrupt INTA - INTD +* +* the device parameter refers to which SPCI device number is sourcing the +* interrupt +* +*/ +STATUS pci_isr_disconnect (int intline, int bus, int device) +{ + int which_xint; + int handler_index; + + /* check to see if we are attempting to disconnect a PPCI interrupt and we are not + a host card */ + if ((isHost() == FALSE) && (off_ppci_bus(bus) == TRUE)) + return (ERROR); + + if ((intline < INTA) || (intline > INTD)) + return (ERROR); + + (void)pci_to_xint(device, intline, &which_xint); + + for (handler_index = 0; handler_index < MAX_PCI_HANDLERS; handler_index++) + { + if ((pci_int_handlers[which_xint][handler_index].bus == bus) && + (pci_int_handlers[which_xint][handler_index].device == device)) + { + pci_int_handlers[which_xint][handler_index].handler = NULL; + pci_int_handlers[which_xint][handler_index].arg = (int)NULL; + pci_int_handlers[which_xint][handler_index].bus = (int)NULL; + pci_int_handlers[which_xint][handler_index].device = (int)NULL; + } + } + + /* if the handler was not found in the table return an error */ + if (handler_index == MAX_PCI_HANDLERS) + return (ERROR); + + return (OK); +} + + +/********************************************************************************** +* iq80310_irq_handler - Interrupt dispatcher for IQ80310 IRQ Interrupts +* +* This function determines the source of the IRQ Interrupt, and calls the +* corresponding interrupt service routine. If multiple sources are interrupting +* the dispatcher will call all interrupt handles. Users must clear the interrupt +* within the interrupt service routine before exiting. +* +* IRQ Interrupts are multiplexed from SPCI INTA - INTD, External Device Interrupts, +* and XINT6 and XINT7 Internal device interrupts. +*/ +int iq80310_irq_handler() +{ +UINT8* int_status_reg; +UINT8 int_status; +int num_sources = 0; + + +/* 12/18/00 jwf */ +unsigned char ri_state; +unsigned char board_rev; +unsigned char sint_status; /* holds interrupt status for SINTA-SINTC */ + ri_state = *( unsigned char * ) 0xfe810006; /* access uart u2 msr reg at addr fe810006 */ + ri_state &= RI_MASK; + if(ri_state == RI_MASK) /* RI# pin on UART2 is grounded */ + { + board_rev = *BOARD_REV_REG_ADDR; /* read Board Revision register */ + board_rev &= BOARD_REV_MASK; /* isolate LSN */ + if (board_rev >= BOARD_REV_E) /* Board Rev is at E or higher */ + { + sint_status = *SINT_REG_ADDR; /* read current secondary pci interrupt status */ + sint_status &= SINT_MASK; /* isolate SINTA, SINTB, and SINTC */ + switch(sint_status) + { + case SINTA_INT: + num_sources += sinta_handler(); /* IRQ0 = SINTA? */ +/* printf(" sinta status = %#x\n", sint_status); */ + break; + case SINTB_INT: + num_sources += sintb_handler(); /* IRQ1 = SINTB? */ +/* printf(" sintb status = %#x\n", sint_status); */ + break; + case SINTC_INT: + num_sources += sintc_handler(); /* IRQ2 = SINTC? */ +/* printf(" sintc status = %#x\n", sint_status); */ + break; + default: +/* printf(" sint? status = %#x\n", sint_status); */ + break; /* probably should test for more conditions: 011b, 101b, 110b, 111b */ + } + } + } + else /* RI# pin on UART2 is pulled up to 3.3V. Cannot read board revision register, not implemented */ + { + num_sources += sinta_handler(); /* IRQ0 = SINTA? */ + num_sources += sintb_handler(); /* IRQ1 = SINTB? */ + num_sources += sintc_handler(); /* IRQ2 = SINTC? */ + } + + + /* 12/18/00 jwf */ + /* Original code */ + /* No S_INTA - S_INTC status register, call handlers always */ + /* This may change in next revision of board */ + /*num_sources += sinta_handler();*/ /* IRQ0 = SINTA? */ + /*num_sources += sintb_handler();*/ /* IRQ1 = SINTB? */ + /*num_sources += sintc_handler();*/ /* IRQ2 = SINTC? */ + + + /* Read IRQ3 Status Register, and if any of the multiple sources are + interrupting, call corresponding handler */ + int_status_reg = (UINT8 *)X3ISR_ADDR; + int_status = *int_status_reg; + { + if (int_status & TIMER_INT) /* timer interrupt? */ + { + /* call user ISR, if connected */ + if (usr_timer_isr != NULL) + (*usr_timer_isr)(usr_timer_arg); + else + printf ("\nUnhandled Timer Interrupt Detected!\n"); + + num_sources++; + } + + if (int_status & ENET_INT) /* ethernet interrupt? */ + { + /* call user ISR, if connected */ + if (usr_enet_isr != NULL) + (*usr_enet_isr)(usr_enet_arg); + else + printf ("\nUnhandled Ethernet Interrupt Detected!\n"); + + num_sources++; + } + + if (int_status & UART1_INT) /* uart1 interrupt? */ + { + /* call user ISR, if connected */ + if (usr_uart1_isr != NULL) + (*usr_uart1_isr)(usr_uart1_arg); + else + printf ("\nUnhandled UART1 Interrupt Detected!\n"); + + num_sources++; + } + + if (int_status & UART2_INT) /* uart2 interrupt? */ + { + /* call user ISR, if connected */ + if (usr_uart2_isr != NULL) + (*usr_uart2_isr)(usr_uart2_arg); + else + printf ("\nUnhandled UART2 Interrupt Detected!\n"); + num_sources++; + } + + if (int_status & SINTD_INT) /* SPCI_INTD? */ + { + num_sources += sintd_handler(); + } + } + + + /* Read XINT6 Status Register, and if any of the multiple sources are + interrupting, call corresponding handler */ + int_status_reg = (UINT8 *)X6ISR_ADDR; + int_status = *int_status_reg; + { + if (int_status & DMA0_INT) /* dma0 interrupt? */ + { + if (usr_dma0_isr != NULL) + (*usr_dma0_isr)(usr_dma0_arg); + else + printf ("\nUnhandled DMA Channel 0 Interrupt Detected!\n"); + num_sources++; + } + + if (int_status & DMA1_INT) /* dma1 interrupt? */ + { + if (usr_dma1_isr != NULL) + (*usr_dma1_isr)(usr_dma1_arg); + else + printf ("\nUnhandled DMA Channel 1 Interrupt Detected!\n"); + num_sources++; + } + + if (int_status & DMA2_INT) /* dma2 interrupt? */ + { + if (usr_dma2_isr != NULL) + (*usr_dma2_isr)(usr_dma2_arg); + else + printf ("\nUnhandled DMA Channel 2 Interrupt Detected!\n"); + num_sources++; + } + + if (int_status & PM_INT) /* performance monitoring interrupt? */ + { + if (usr_pm_isr != NULL) + (*usr_pm_isr)(usr_pm_arg); + else + printf ("\nUnhandled Performance Monitoring Unit Interrupt Detected!\n"); + num_sources++; + } + + if (int_status & AA_INT) /* application accelerator interrupt? */ + { + if (usr_aa_isr != NULL) + (*usr_aa_isr)(usr_aa_arg); + else + printf ("\nUnhandled Application Accelerating Unit Interrupt Detected!\n"); + num_sources++; + } + } + + + /* Read XINT7 Status Register, and if any of the multiple sources are + interrupting, call corresponding handler */ + int_status_reg = (UINT8 *)X7ISR_ADDR; + int_status = *int_status_reg; + { + if (int_status & I2C_INT) /* i2c interrupt? */ + { + if (usr_i2c_isr != NULL) + (*usr_i2c_isr)(usr_i2c_arg); + else + printf ("\nUnhandled I2C Unit Interrupt Detected!\n"); + num_sources++; + } + + if (int_status & MU_INT) /* messaging unit interrupt? */ + { + if (usr_mu_isr != NULL) + (*usr_mu_isr)(usr_mu_arg); + else + printf ("\nUnhandled Messaging Unit Interrupt Detected!\n"); + num_sources++; + } + + if (int_status & PATU_INT) /* primary ATU / BIST start interrupt? */ + { + if (usr_patu_isr != NULL) + (*usr_patu_isr)(usr_patu_arg); + else + printf ("\nUnhandled Primary ATU Interrupt Detected!\n"); + num_sources++; + } + } + + /* return the number of interrupt sources found */ + return (num_sources); +} + + + + + +/**************************************************************** +* nmi_ecc_isr - ECC NMI Interrupt Handler +* +* This module handles the NMI caused by an ECC error. +* For a Single-bit error it does a read-nodify-write +* to correct the error in memory. For a multi-bit or +* nibble error it does absolutely nothing. +*/ +void nmi_ecc_isr(void) +{ + UINT32 eccr_register; + UINT32* reg32; + + /* Read current state of ECC register */ + eccr_register = *(UINT32 *)ECCR_ADDR; + + /* Turn off all ecc error reporting */ + *(UINT32 *)ECCR_ADDR = 0x4; + + /* Check for ECC Error 0 */ + if(*(UINT32 *)MCISR_ADDR & 0x1) + { + reg32 = (UINT32*)ELOG0_ADDR; + error_print("ELOG0 = 0x%X\n",*reg32,0,0,0); + + reg32 = (UINT32*)ECAR0_ADDR; + error_print("ECC Error Detected at Address 0x%X\n",*reg32,0,0,0); + + /* Check for single-bit error */ + if(!(*(UINT32 *)ELOG0_ADDR & 0x00000100)) + { + /* call ECC restoration function */ + _scrub_ecc(*reg32); + + /* Clear the MCISR */ + *(UINT32 *)MCISR_ADDR = 0x1; + } + else + error_print("Multi-bit or nibble error\n",0,0,0,0); + } + + /* Check for ECC Error 1 */ + if(*(UINT32 *)MCISR_ADDR & 0x2) + { + reg32 = (UINT32*)ELOG1_ADDR; + error_print("ELOG0 = 0x%X\n",*reg32,0,0,0); + + reg32 = (UINT32*)ECAR1_ADDR; + error_print("ECC Error Detected at Address 0x%X\n",*reg32,0,0,0); + + /* Check for single-bit error */ + if(!(*(UINT32 *)ELOG1_ADDR & 0x00000100)) + { + /* call ECC restoration function */ + _scrub_ecc(*reg32); + + /* Clear the MCISR */ + *(UINT32 *)MCISR_ADDR = 0x2; + } + else + error_print("Multi-bit or nibble error\n",0,0,0,0); + } + + /* Check for ECC Error N */ + if(*(UINT32 *)MCISR_ADDR & 0x4) + { + /* Clear the MCISR */ + *(UINT32 *)MCISR_ADDR = 0x4; + error_print("Uncorrectable error during RMW\n",0,0,0,0); + } + + /* Turn on ecc error reporting */ + *(UINT32 *)ECCR_ADDR = eccr_register; +} + + + + +/****************************************************************************** +* iq80310_fiq_handler - Interrupt dispatcher for IQ80310 FIQ Interrupts +* +* +*/ +int iq80310_fiq_handler() +{ + +unsigned long nmi_status = *(volatile unsigned long *)NISR_ADDR; +unsigned long status; +int srcs_found = 0; + + if (nmi_status & MCU_ERROR) + { + status = *(volatile unsigned long *)MCISR_ADDR; + *MSB_DISPLAY_REG = LETTER_E; + if (status & 0x001) + *LSB_DISPLAY_REG = ONE; + if (status & 0x002) + *LSB_DISPLAY_REG = TWO; + if (status & 0x004) + *LSB_DISPLAY_REG = FOUR; + srcs_found++; +#if 0 + error_print ("**** 80312 Memory Controller Error ****\n",0,0,0,0); + if (status & 0x001) error_print ("One ECC Error Detected and Recorded in ELOG0\n",0,0,0,0); + if (status & 0x002) error_print ("Second ECC Error Detected and Recorded in ELOG1\n",0,0,0,0); + if (status & 0x004) error_print ("Multiple ECC Errors Detected\n",0,0,0,0); +#endif + + /* call ecc interrupt handler */ + nmi_ecc_isr(); + + /* clear the interrupt condition*/ + AND_WORD((volatile unsigned long *)MCISR_ADDR, 0x07); + +/* 02/02/01 jwf */ + ecc_error_reported = TRUE; + + } + + + if (nmi_status & PATU_ERROR) + { + srcs_found++; + error_print ("**** Primary ATU Error ****\n",0,0,0,0); + status = *(volatile unsigned long *)PATUISR_ADDR; + if (status & 0x001) error_print ("PPCI Master Parity Error\n",0,0,0,0); + if (status & 0x002) error_print ("PPCI Target Abort (target)\n",0,0,0,0); + if (status & 0x004) error_print ("PPCI Target Abort (master)\n",0,0,0,0); + if (status & 0x008) error_print ("PPCI Master Abort\n",0,0,0,0); + if (status & 0x010) error_print ("Primary P_SERR# Detected\n",0,0,0,0); + if (status & 0x080) error_print ("Internal Bus Master Abort\n",0,0,0,0); + if (status & 0x100) error_print ("PATU BIST Interrupt\n",0,0,0,0); + if (status & 0x200) error_print ("PPCI Parity Error Detected\n",0,0,0,0); + if (status & 0x400) error_print ("Primary P_SERR# Asserted\n",0,0,0,0); + + /* clear the interrupt conditions */ + AND_WORD((volatile unsigned long *)PATUISR_ADDR, 0x79f); + CLEAR_PATU_STATUS(); + + /* tell the config cleanup code about error */ + if (pci_config_cycle == 1) + pci_config_error = TRUE; + } + + if (nmi_status & SATU_ERROR) + { + srcs_found++; + error_print ("**** Secondary ATU Error ****\n",0,0,0,0); + status = *(volatile unsigned long *)SATUISR_ADDR; + if (status & 0x001) error_print ("SPCI Master Parity Error\n",0,0,0,0); + if (status & 0x002) error_print ("SPCI Target Abort (target)\n",0,0,0,0); + if (status & 0x004) error_print ("SPCI Target Abort (master)\n",0,0,0,0); + if (status & 0x008) error_print ("SPCI Master Abort\n",0,0,0,0); + if (status & 0x010) error_print ("Secondary P_SERR# Detected\n",0,0,0,0); + if (status & 0x080) error_print ("Internal Bus Master Abort\n",0,0,0,0); + if (status & 0x200) error_print ("SPCI Parity Error Detected\n",0,0,0,0); + if (status & 0x400) error_print ("Secondary S_SERR# Asserted\n",0,0,0,0); + + /* clear the interrupt conditions */ + AND_WORD((volatile unsigned long *)SATUISR_ADDR, 0x69f); + CLEAR_SATU_STATUS(); + + /* tell the config cleanup code about error */ + if (pci_config_cycle == 1) + pci_config_error = TRUE; + } + + if (nmi_status & PBRIDGE_ERROR) + { + srcs_found++; + error_print ("**** Primary Bridge Error ****\n",0,0,0,0); + status = *(volatile unsigned long *)PBISR_ADDR; + if (status & 0x001) error_print ("PPCI Master Parity Error\n",0,0,0,0); + if (status & 0x002) error_print ("PPCI Target Abort (Target)\n",0,0,0,0); + if (status & 0x004) error_print ("PPCI Target Abort (Master)\n",0,0,0,0); + if (status & 0x008) error_print ("PPCI Master Abort\n",0,0,0,0); + if (status & 0x010) error_print ("Primary P_SERR# Asserted\n",0,0,0,0); + if (status & 0x020) error_print ("PPCI Parity Error Detected\n",0,0,0,0); + + /* clear the interrupt condition */ + AND_WORD((volatile unsigned long *)PBISR_ADDR, 0x3f); + CLEAR_PBRIDGE_STATUS(); + + /* tell the config cleanup code about error */ + if (pci_config_cycle == 1) + pci_config_error = TRUE; + } + + if (nmi_status & SBRIDGE_ERROR) + { + srcs_found++; + + /* don't print configuration secondary bridge errors */ + + /* clear the interrupt condition */ + AND_WORD((volatile unsigned long *)SBISR_ADDR, 0x7f); + CLEAR_SBRIDGE_STATUS(); + + /* tell the config cleanup code about error */ + if (pci_config_cycle == 1) + pci_config_error = TRUE; + } + + if (nmi_status & DMA_0_ERROR) + { + srcs_found++; + error_print ("**** DMA Channel 0 Error ****\n",0,0,0,0); + status = *(volatile unsigned long *)CSR0_ADDR; + if (status & 0x001) error_print ("DMA Channel 0 PCI Parity Error\n",0,0,0,0); + if (status & 0x004) error_print ("DMA Channel 0 PCI Target Abort\n",0,0,0,0); + if (status & 0x008) error_print ("DMA Channel 0 PCI Master Abort\n",0,0,0,0); + if (status & 0x020) error_print ("Internal PCI Master Abort\n",0,0,0,0); + /* clear the interrupt condition */ + AND_WORD((volatile unsigned long *)CSR0_ADDR, 0x2D); + } + + if (nmi_status & DMA_1_ERROR) + { + srcs_found++; + error_print ("**** DMA Channel 1 Error ****\n",0,0,0,0); + status = *(volatile unsigned long *)CSR1_ADDR; + if (status & 0x001) error_print ("DMA Channel 1 PCI Parity Error\n",0,0,0,0); + if (status & 0x004) error_print ("DMA Channel 1 PCI Target Abort\n",0,0,0,0); + if (status & 0x008) error_print ("DMA Channel 1 PCI Master Abort\n",0,0,0,0); + if (status & 0x020) error_print ("Internal PCI Master Abort\n",0,0,0,0); + + /* clear the interrupt condition */ + AND_WORD((volatile unsigned long *)CSR1_ADDR, 0x2D); + } + + if (nmi_status & DMA_2_ERROR) + { + srcs_found++; + error_print ("**** DMA Channel 2 Error ****\n",0,0,0,0); + status = *(volatile unsigned long *)CSR2_ADDR; + if (status & 0x001) error_print ("DMA Channel 2 PCI Parity Error\n",0,0,0,0); + if (status & 0x004) error_print ("DMA Channel 2 PCI Target Abort\n",0,0,0,0); + if (status & 0x008) error_print ("DMA Channel 2 PCI Master Abort\n",0,0,0,0); + if (status & 0x020) error_print ("Internal PCI Master Abort\n",0,0,0,0); + + /* clear the interrupt condition */ + AND_WORD((volatile unsigned long *)CSR2_ADDR, 0x2D); + } + + if (nmi_status & MU_ERROR) + { + status = *(volatile unsigned long *)IISR_ADDR; + if (status & 0x20) + { + srcs_found++; + error_print ("Messaging Unit Outbound Free Queue Overflow\n",0,0,0,0); + + /* clear the interrupt condition; note that the clearing of the NMI doorbell + is handled by the PCI comms code */ + } AND_WORD((volatile unsigned long *)IISR_ADDR, 0x20); + } + + if (nmi_status & AAU_ERROR) + { + srcs_found++; + error_print ("**** Application Accelerator Unit Error ****\n",0,0,0,0); + status = *(volatile unsigned long *)ASR_ADDR; + if (status & 0x020) error_print ("Internal PCI Master Abort\n",0,0,0,0); + + /* clear the interrupt condition */ + AND_WORD((volatile unsigned long *)ASR_ADDR, 0x20); + } + + if (nmi_status & BIU_ERROR) + { + srcs_found++; + error_print ("**** Bus Interface Unit Error ****\n",0,0,0,0); + status = *(volatile unsigned long *)BIUISR_ADDR; + if (status & 0x004) error_print ("Internal PCI Master Abort\n",0,0,0,0); + + /* clear the interrupt condition */ + AND_WORD((volatile unsigned long *)BIUISR_ADDR, 0x04); + } + + return (srcs_found); + +} + + +/********************************************************************** +* isr_connect - Disconnect a user Interrupt Service Routine +* +* NOT TO BE USED FOR SPCI INTERRUPTS! - use pci_isr_connect instead +* +*/ +int isr_connect(int int_num, void (*handler)(int), int arg) +{ + switch (int_num) + { + + case DMA0_INT_ID: + usr_dma0_isr = handler; + usr_dma0_arg = arg; + break; + case DMA1_INT_ID: + usr_dma1_isr = handler; + usr_dma1_arg = arg; + break; + case DMA2_INT_ID: + usr_dma2_isr = handler; + usr_dma2_arg = arg; + break; + case PM_INT_ID: + usr_pm_isr = handler; + usr_pm_arg = arg; + break; + case AA_INT_ID: + usr_aa_isr = handler; + usr_aa_arg = arg; + break; + case I2C_INT_ID: + usr_i2c_isr = handler; + usr_i2c_arg = arg; + break; + case MU_INT_ID: + usr_mu_isr = handler; + usr_mu_arg = arg; + break; + case PATU_INT_ID: + usr_patu_isr = handler; + usr_patu_arg = arg; + break; + case TIMER_INT_ID: + usr_timer_isr = handler; + usr_timer_arg = arg; + break; + case ENET_INT_ID: + usr_enet_isr = handler; + usr_enet_arg = arg; + break; + case UART1_INT_ID: + usr_uart1_isr = handler; + usr_uart1_arg = arg; + break; + case UART2_INT_ID: + usr_uart2_isr = handler; + usr_uart2_arg = arg; + break; + default: + return (ERROR); + break; + } + + return (OK); +} + +/********************************************************************** +* isr_disconnect - Disconnect a user Interrupt Service Routine +* +* NOT TO BE USED FOR SPCI INTERRUPTS! - use pci_isr_disconnect instead +* +*/ +int isr_disconnect(int int_num) +{ + switch (int_num) + { + + case DMA0_INT_ID: + usr_dma0_isr = NULL; + usr_dma0_arg = 0; + break; + case DMA1_INT_ID: + usr_dma1_isr = NULL; + usr_dma1_arg = 0; + break; + case DMA2_INT_ID: + usr_dma2_isr = NULL; + usr_dma2_arg = 0; + break; + case PM_INT_ID: + usr_pm_isr = NULL; + usr_pm_arg = 0; + break; + case AA_INT_ID: + usr_aa_isr = NULL; + usr_aa_arg = 0; + break; + case I2C_INT_ID: + usr_i2c_isr = NULL; + usr_i2c_arg = 0; + break; + case MU_INT_ID: + usr_mu_isr = NULL; + usr_mu_arg = 0; + break; + case PATU_INT_ID: + usr_patu_isr = NULL; + usr_patu_arg = 0; + break; + case TIMER_INT_ID: + usr_timer_isr = NULL; + usr_timer_arg = 0; + break; + case ENET_INT_ID: + usr_enet_isr = NULL; + usr_enet_arg = 0; + break; + case UART1_INT_ID: + usr_uart1_isr = NULL; + usr_uart1_arg = 0; + break; + case UART2_INT_ID: + usr_uart2_isr = NULL; + usr_uart2_arg = 0; + break; + default: + return (ERROR); + break; + } + + /* i960 disabled interrupt here - should we? */ + + return (OK); +} + +/******************************************************************** +* disable_external_interrupt - Mask an external interrupt +* +*/ +int disable_external_interrupt(int int_id) +{ + +unsigned char* ext_mask_reg = (unsigned char*) X3MASK_ADDR; +unsigned char new_mask_value; + + /* make sure interrupt to enable is an external interrupt */ + if ((int_id < TIMER_INT_ID) || (int_id > SINTD_INT_ID)) + return (ERROR); + + new_mask_value = *ext_mask_reg; /* read current mask status */ + + switch (int_id) + { + case TIMER_INT_ID: + new_mask_value |= TIMER_INT; + break; + case ENET_INT_ID: + new_mask_value |= ENET_INT; + break; + case UART1_INT_ID: + new_mask_value |= UART1_INT; + break; + case UART2_INT_ID: + new_mask_value |= UART2_INT; + break; + case SINTD_INT_ID: + new_mask_value |= SINTD_INT; + break; + default: + break; /* leave mask register as it was */ + } + + *ext_mask_reg = new_mask_value; /* set new mask value */ + + return (OK); + +} + + + +/******************************************************************** +* enable_external_interrupt - Unmask an external interrupt +* +*/ +int enable_external_interrupt(int int_id) +{ + +unsigned char* ext_mask_reg = (unsigned char*) X3MASK_ADDR; +unsigned char new_mask_value; + + /* make sure interrupt to enable is an external interrupt */ + if ((int_id < TIMER_INT_ID) || (int_id > SINTD_INT_ID)) + return (ERROR); + + + new_mask_value = *ext_mask_reg; /* read current mask status */ + + switch (int_id) + { + case TIMER_INT_ID: + new_mask_value &= ~(TIMER_INT); + break; + case ENET_INT_ID: + new_mask_value &= ~(ENET_INT); + break; + case UART1_INT_ID: + new_mask_value &= ~(UART1_INT); + break; + case UART2_INT_ID: + new_mask_value &= ~(UART2_INT); + break; + case SINTD_INT_ID: + new_mask_value &= ~(SINTD_INT); + break; + default: + break; /* leave mask register as it was */ + } + + *ext_mask_reg = new_mask_value; /* set new mask value */ + + return (OK); +} + + +void error_print ( + char *fmt, + int arg0, + int arg1, + int arg2, + int arg3 + ) +{ + /* Wait until host configures the boards to start printing NMI errors */ + UINT32* atu_reg = (UINT32*)PIABAR_ADDR; + if ((*atu_reg & 0xfffffff0) == 0) + return; + if (nmi_verbose) printf (fmt, arg0, arg1, arg2, arg3); + return; +} + +extern void __diag_IRQ(void); +extern void __diag_FIQ(void); + +void config_ints() +{ +int xint, x; + + unsigned int* pirsr_ptr = (unsigned int*)PIRSR_ADDR; + *pirsr_ptr = 0xf; /* this is an errata in the original Yavapai manual. + The interrupt steering bits are reversed, so a '1' + routes XINT interrupts to FIQ + */ + + /* install diag IRQ handlers */ + ((volatile unsigned *)0x20)[6] = (unsigned)__diag_IRQ; + ((volatile unsigned *)0x20)[7] = (unsigned)__diag_FIQ; + _flushICache(); + + /* make sure interrupts are enabled in CSPR */ + + _cspr_enable_irq_int(); + + _cspr_enable_fiq_int(); + + /* initialize the PCI interrupt table */ + for (xint = 0; xint < NUM_PCI_XINTS; xint++) + { + for (x = 0; x < MAX_PCI_HANDLERS; x++) + { + pci_int_handlers[xint][x].handler = NULL; + pci_int_handlers[xint][x].arg = (int)NULL; + pci_int_handlers[xint][x].bus = (int)NULL; + pci_int_handlers[xint][x].device = (int)NULL; + } + } + + +} + + +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/io_utils.c @@ -0,0 +1,246 @@ +//============================================================================= +// +// io_utils.c - Cyclone Diagnostics +// +//============================================================================= +//####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) 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-25 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +/* + * i/o routines for tests. Greg Ames, 9/17/90. + * + * Version: @(#)test_io.c 1.2 8/26/93 + */ +#include <redboot.h> + +#define TRUE 1 +#define FALSE 0 + + +#define ASCII_TO_DEC 48 +void atod(char a, int* b) +{ + *b = (int)(a - ASCII_TO_DEC); +} + +char xgetchar(void) +{ + char ch; + hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); + + if (__chan) + ch = CYGACC_COMM_IF_GETC(*__chan); + else { + __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + ch = CYGACC_COMM_IF_GETC(*__chan); + } + return ch; +} + +/* + * naive implementation of "gets" + * (big difference from fgets == strips newline character) + */ +char* sgets(char *s) +{ + + char *retval = s; + char ch; + + while ((ch = (char)xgetchar())) + { + if (ch == 0x0d) /* user typed enter */ + { + printf("\n"); + break; + } + else if (ch == 0x08) /* user typed backspace */ + { + printf ("\b"); + printf (" "); + printf ("\b"); + s--; + } + else /* user typed another character */ + { + printf("%c", ch); + *s++ = ch; + } + + } + + *s = '\0'; + return retval; +} + + +/* Returns true if theChar is a valid hex digit, false if not */ +char ishex(char theChar) +{ + switch(theChar) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'a': + case 'B': + case 'b': + case 'C': + case 'c': + case 'D': + case 'd': + case 'E': + case 'e': + case 'F': + case 'f': + return 1; + default: + return 0; + } +} + + +/* Returns true if theChar is a valid decimal digit, false if not */ +char isdec(char theChar) +{ + switch(theChar) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return 1; + default: + return 0; + } +} + +/* Convert ascii code of hex digit to number (0-15) */ +char hex2dec(char hex) +{ + if ((hex >= '0') && (hex <= '9')) + return hex - '0'; + else if ((hex >= 'a') && (hex <= 'f')) + return hex - 'a' + 10; + else + return hex - 'A' + 10; +} + + +/* Convert number (0-15) to ascii code of hex digit */ +char dec2hex(char dec) +{ + return (dec <= 9) ? (dec + '0') : (dec - 10 + 'A'); +} + + +/* Output an 8 bit number as 2 hex digits */ +void hex8out(unsigned char num) +{ + printf("%02X",num); +} + + +/* Output an 32 bit number as 8 hex digits */ +void hex32out(unsigned long num) +{ + printf("%08X",num); +} + + +/* Input a number as (at most 8) hex digits - returns value entered */ +long hexIn(void) +{ + char input[40]; + long num; + register int i; + + i = 0; + num = 0; + + if (sgets (input)) /* grab a line */ + { + num = hex2dec(input[i++]); /* Convert MSD to dec */ + while(ishex(input[i]) && input[i]) /* Get next hex digit */ + { + num <<= 4; /* Make room for next digit */ + num += hex2dec(input[i++]); /* Add it in */ + } + } + return num; +} + + +/* Input a number as decimal digits - returns value entered */ +long decIn(void) +{ + char input[40]; + int num; + int tmp; + register int i; + + i = 0; + num = 0; + + if (sgets (input)) /* grab a line */ + { + atod(input[i++], &num); /* Convert MSD to decimal */ + while(isdec(input[i]) && input[i]) /* Get next decimal digit */ + { + num *= 10; /* Make room for next digit */ + atod(input[i++], &tmp); + num += tmp; /* Add it in */ + } + } + + return (num); +} + +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/iq80310.h @@ -0,0 +1,521 @@ +//============================================================================= +// +// iq80310.h - Cyclone Diagnostics +// +//============================================================================= +//####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) 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-25 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +/******************************************************************************/ +/* iq80310.h - Header file for Cyclone IQ80310 Evaluation Board */ +/* */ +/* modification history */ +/* -------------------- */ +/* 07sep00, ejb, Written for IQ80310 Cygmon diagnostics */ +/* 18dec00 jwf */ +/******************************************************************************/ + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#ifndef ERROR +#define ERROR -1 +#endif + +#ifndef OK +#define OK 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define RAM_FUNC_SECT + +typedef int STATUS; +typedef unsigned char UCHAR; +typedef unsigned char UINT8; +typedef unsigned short USHORT; +typedef unsigned short UINT16; +typedef unsigned long ULONG; +typedef unsigned int UINT; +typedef unsigned int UINT32; +typedef int (*FUNCPTR) (); +typedef void (*VOIDFUNCPTR) (); + +/* board specific definitions */ + + +#define MEMBASE_DRAM 0xa0000000 + + +/* UART definitions */ +#define SCALE 0x10000 /* distance between port addresses */ +#define TERMINAL 0xfe800000 /* Terminal base address */ +#define ACCESS_DELAY 5 +#define DFLTPORT 0 /* channel 2 on 16C552 */ +#define XTAL 1843200 /* frequency of baud rate generation crystal */ + +/* Backplane Detect Register */ +#define BACKPLANE_DET_REG (volatile unsigned char *)0xfe870000 +#define BP_HOST_BIT 0x1 + +/* PAL-based external timer definitions */ +#define TIMER_LA0_REG_ADDR (volatile unsigned char *)0xfe880000 +#define TIMER_LA1_REG_ADDR (volatile unsigned char *)0xfe890000 +#define TIMER_LA2_REG_ADDR (volatile unsigned char *)0xfe8a0000 +#define TIMER_LA3_REG_ADDR (volatile unsigned char *)0xfe8b0000 +#define TIMER_ENABLE_REG_ADDR (volatile unsigned char *)0xfe8c0000 + +#define TIMER_COUNT_MASK 0x5f /* 6 bits of timer data with the MSB in bit 6 not bit 5 */ +#define TIMER_CNT_ENAB 0x1 +#define TIMER_INT_ENAB 0x2 +#define EXT_TIMER_CLK_FREQ 33000000 /* external timer runs at 33 MHz */ +#define TICKS_10MSEC 100 /* 10msec = 100 ticks/sec */ +#define EXT_TIMER_10MSEC_COUNT (EXT_TIMER_CLK_FREQ / TICKS_10MSEC) +#define TICKS_5MSEC 200 /* 5msec = 200 ticks/sec */ +#define EXT_TIMER_5MSEC_COUNT (EXT_TIMER_CLK_FREQ / TICKS_5MSEC) + +#define EXT_TIMER_CNT_ENAB() (*TIMER_ENABLE_REG_ADDR |= TIMER_CNT_ENAB) +#define EXT_TIMER_CNT_DISAB() (*TIMER_ENABLE_REG_ADDR &= ~TIMER_CNT_ENAB) +#define EXT_TIMER_INT_ENAB() (*TIMER_ENABLE_REG_ADDR |= TIMER_INT_ENAB) +#define EXT_TIMER_INT_DISAB() (*TIMER_ENABLE_REG_ADDR &= ~TIMER_INT_ENAB) + +/* 80312 Interrupt Status Registers */ +#define X3ISR_ADDR 0xfe820000 /* XINT3 (external interrupts) Status Register */ +#define X3MASK_ADDR 0xfe860000 /* XINT3 Mask Register */ + + +/* 12/18/00 jwf */ +/* CPLD Read only Registers */ +#define BOARD_REV_REG_ADDR (volatile unsigned char *)0xfe830000 /* Board Revision Register, xxxxxbbb=0x2<-->Rev B Board, Note: This is not implemented in the CPLD yet */ +#define BOARD_REV_E (unsigned char)0x5 /* BOARD REV E */ +#define BOARD_REV_MASK (unsigned char)0xf /* use only b0-b3 */ +#define CPLD_REV_REG_ADDR (volatile unsigned char *)0xfe840000 /* CPLD Revision Register, data examples: xxxxxbbb=0x3<-->Rev C CPLD(used on PCI-700 Rev D Board), xxxxxbbb=0x4<-->Rev D CPLD(used on PCI-700 Rev E Board) */ +#define SINT_REG_ADDR (volatile unsigned char *)0xfe850000 /* SINTA-SINTC secondary PCI interrupt status register */ +/* SINT_REG_ADDR Register Interrupt Status bit definitions */ +#define SINTA_INT (unsigned char)0x1 /* b0=1, Secondary PCI (S_INTA) Interrupt Pending */ +#define SINTB_INT (unsigned char)0x2 /* b1=1, Secondary PCI (S_INTB) Interrupt Pending */ +#define SINTC_INT (unsigned char)0x4 /* b2=1, Secondary PCI (S_INTC) Interrupt Pending */ +#define SINT_MASK (unsigned char)0x7 /* isolate bits b0-b3 */ +#define RI_MASK (unsigned char)0x40 /* use to isolate bit 6, Ring Indicator, of MSR in UART 2 */ + +/* Intel 28F640J3A Strata Flash Memory Definitions */ +#define NUM_FLASH_BANKS 1 /* number of flash banks, there is only 1 flash memory chip on the pci-700 board */ +#define FLASH_WIDTH 1 /* width of flash in bytes */ +#define FLASH_BASE_ADDR 0x00000000 /* base address of flash block 0, avoid this area, vectors and cygmon code occupy addresses 0x2000h-0x28000h */ +#define DEV_CODE_ADDR (0x00000001 << 1) /* address of Device Code in Flash memory, note that address bit A0 is not used, must shift 0x00000001<<1=0x00000002 */ + +/* 10/17/00 jwf */ +#define FLASH_BLK4_BASE_ADDR 0x80000 + +#define FLASH_TOP_ADDR 0x7fffff /* last address of last block of flash memory */ +#define FLASH_ADDR 0x00000000 /* base address of flash block 0, avoid this area, vectors and cygmon code occupy addresses 0x2000h-0x28000h */ +#define FLASH_ADDR_INCR 0x00020000 /* address offset of each flash block, 128K block, byte-wide (X8) mode, device address range 0-7fffff */ +#define VALID_FLASH_ADDR 0x00000000 /* base address of flash block 0 */ +#define FLASH_TIME_ADJUST 1 /* delay adjustment factor for delay times */ + +/* 10/17/00 jwf */ +#define RESERVED_AREA1 0x0 /* 0h-1ffffh is partially occupied by Cygnus Cygmon monitor and debug code */ +#define RESERVED_AREA2 0x20000 /* 20000h-3ffffh is partially occupied by Cygnus Cygmon monitor and debug code */ +#define RESERVED_AREA3 0x40000 /* 40000h-5ffffh is partially occupied by Cygnus Cygmon debug code */ +#define RESERVED_AREA4 0x60000 /* 60000h-7ffffh is partially occupied by Cygnus Cygmon debug code */ +#define RESERVED_AREA_SIZE 0x80000 /* 20000h * 4h */ + +/* Definitions for Battery Backup SDRAM memory test */ +#define SDRAM_BATTERY_TEST_BASE 0xA1FFFFF0 /* base address of last 16 memory locations in 32MB SDRAM */ +/* #define BATTERY_TEST_PATTERN 0xBAEBAEBA */ +#define BATTERY_TEST_PATTERN 0x55555555 + +/* Definitions for data types and constants used in Flash.c */ +typedef unsigned long ADDR; +#define NO_ADDR ((ADDR)0x800000) /* last address of Flash memory + 1 */ +int cmd_stat; +#ifndef ERR +#define ERR -1 +#endif +/* Error code Constants */ +#define E_EEPROM_ADDR 12 +#define E_EEPROM_PROG 13 +#define E_EEPROM_FAIL 14 +#define E_NO_FLASH 29 + + +/* 10/17/00 jwf */ +#define BREEZE_BLOCK_0 0x0 +#define NUM_BREEZE_BLOCKS 4 +#define NUM_FLASH_BLOCKS 64 + + + + + + +/* 80310 IRQ Interrupt Identifiers (used for connecting and disconnecting ISRs) */ +#define DMA0_INT_ID 0 +#define DMA1_INT_ID 1 +#define DMA2_INT_ID 2 +#define PM_INT_ID 3 +#define AA_INT_ID 4 +#define I2C_INT_ID 5 +#define MU_INT_ID 6 +#define PATU_INT_ID 7 +#define TIMER_INT_ID 8 +#define ENET_INT_ID 9 +#define UART1_INT_ID 10 +#define UART2_INT_ID 11 +#define SINTA_INT_ID 12 +#define SINTB_INT_ID 13 +#define SINTC_INT_ID 14 +#define SINTD_INT_ID 15 + + + +/* XINT3 External Interrupt Status and Mask bit definitions */ +#define TIMER_INT (1 << 0) /* Timer Interrupt Pending */ +#define ENET_INT (1 << 1) /* Ethernet Interrupt Pending */ +#define UART1_INT (1 << 2) /* UART1 Interrupt Pending */ +#define UART2_INT (1 << 3) /* UART2 Interrupt Pending */ +#define SINTD_INT (1 << 4) /* Secondary PCI (S_INTD) Interrupt Pending */ + +/* XINT6 Interrupt Status bit definitions */ +#define DMA0_INT (1 << 0) /* DMA Channel 0 Interrupt Pending */ +#define DMA1_INT (1 << 2) /* DMA Channel 1 Interrupt Pending */ +#define DMA2_INT (1 << 3) /* DMA Channel 2 Interrupt Pending */ +#define PM_INT (1 << 5) /* Performance Monitoring Unit Interrupt Pending */ +#define AA_INT (1 << 6) /* Application Accelerator Interrupt Pending */ + +/* XINT7 Interrupt Status bit definitions */ +#define I2C_INT (1 << 1) /* I2C Interrupt Pending */ +#define MU_INT (1 << 2) /* Messaging Unit Interrupt Pending */ +#define PATU_INT (1 << 3) /* Primary ATU / BIST Start Interrupt Pending */ + +/* NISR bit definitions */ +#define MCU_ERROR (1 << 0) /* 80960 core Error within internal memory controller */ +#define PATU_ERROR (1 << 1) /* Primary ATU Error (PCI or local bus error) */ +#define SATU_ERROR (1 << 2) /* Secondary ATU Error (PCI or local bus error) */ +#define PBRIDGE_ERROR (1 << 3) /* Primary Bridge Interface Error */ +#define SBRIDGE_ERROR (1 << 4) /* Secondary Bridge Interface Error */ +#define DMA_0_ERROR (1 << 5) /* DMA Channel 0 Error (PCI or local bus error) */ +#define DMA_1_ERROR (1 << 6) /* DMA Channel 1 Error (PCI or local bus error) */ +#define DMA_2_ERROR (1 << 7) /* DMA Channel 2 Error (PCI or local bus error) */ +#define MU_ERROR (1 << 8) /* Messaging Unit NMI interrupt */ +#define AAU_ERROR (1 << 10) /* Application Accelerator Unit Error */ +#define BIU_ERROR (1 << 11) /* Bus Interface Unit Error */ + + + +/* macros to clear (S/P PCI Status register bits) */ +#define CLEAR_PATU_STATUS() (*(volatile UINT16 *)PATUSR_ADDR |= 0xf900) +#define CLEAR_SATU_STATUS() (*(volatile UINT16 *)SATUSR_ADDR |= 0xf900) +#define CLEAR_PBRIDGE_STATUS() (*(volatile UINT16 *)PSR_ADDR |= 0xf900) +#define CLEAR_SBRIDGE_STATUS() (*(volatile UINT16 *)SSR_ADDR |= 0xf900) + + + + + + + +/*** Yavapai Registers ***/ + +/* PCI-to-PCI Bridge Unit 0000 1000H through 0000 10FFH */ +#define VIDR_ADDR 0x00001000 +#define DIDR_ADDR 0x00001002 +#define PCR_ADDR 0x00001004 +#define PSR_ADDR 0x00001006 +#define RIDR_ADDR 0x00001008 +#define CCR_ADDR 0x00001009 +#define CLSR_ADDR 0x0000100C +#define PLTR_ADDR 0x0000100D +#define HTR_ADDR 0x0000100E +/* Reserved 0x0000100F through 0x00001017 */ +#define PBNR_ADDR 0x00001018 +#define SBNR_ADDR 0x00001019 +#define SUBBNR_ADDR 0x0000101A +#define SLTR_ADDR 0x0000101B +#define IOBR_ADDR 0x0000101C +#define IOLR_ADDR 0x0000101D +#define SSR_ADDR 0x0000101E +#define MBR_ADDR 0x00001020 +#define MLR_ADDR 0x00001022 +#define PMBR_ADDR 0x00001024 +#define PMLR_ADDR 0x00001026 +/* Reserved 0x00001028 through 0x00001033 */ +#define BSVIR_ADDR 0x00001034 +#define BSIR_ADDR 0x00001036 +/* Reserved 0x00001038 through 0x0000103D */ +#define BCR_ADDR 0x0000103E +#define EBCR_ADDR 0x00001040 +#define SISR_ADDR 0x00001042 +#define PBISR_ADDR 0x00001044 +#define SBISR_ADDR 0x00001048 +#define SACR_ADDR 0x0000104C +#define PIRSR_ADDR 0x00001050 +#define SIOBR_ADDR 0x00001054 +#define SIOLR_ADDR 0x00001055 +#define SCCR_ADDR 0x00001056 /* EAS inconsistent */ +#define SMBR_ADDR 0x00001058 +#define SMLR_ADDR 0x0000105A +#define SDER_ADDR 0x0000105C +#define QCR_ADDR 0x0000105E +#define CDTR_ADDR 0x00001060 /* EAS inconsistent */ +/* Reserved 0x00001064 through 0x000010FFH */ + +/* Performance Monitoring Unit 0000 1100H through 0000 11FFH */ +#define GMTR_ADDR 0x00001100 +#define ESR_ADDR 0x00001104 +#define EMISR_ADDR 0x00001108 +/* Reserved 0x0000110C */ /* EAS inconsistent */ +#define GTSR_ADDR 0x00001110 /* EAS inconsistent */ +#define PECR1_ADDR 0x00001114 /* EAS inconsistent */ +#define PECR2_ADDR 0x00001118 /* EAS inconsistent */ +#define PECR3_ADDR 0x0000111C /* EAS inconsistent */ +#define PECR4_ADDR 0x00001120 /* EAS inconsistent */ +#define PECR5_ADDR 0x00001124 /* EAS inconsistent */ +#define PECR6_ADDR 0x00001128 /* EAS inconsistent */ +#define PECR7_ADDR 0x0000112C /* EAS inconsistent */ +#define PECR8_ADDR 0x00001130 /* EAS inconsistent */ +#define PECR9_ADDR 0x00001134 /* EAS inconsistent */ +#define PECR10_ADDR 0x00001138 /* EAS inconsistent */ +#define PECR11_ADDR 0x0000113C /* EAS inconsistent */ +#define PECR12_ADDR 0x00001140 /* EAS inconsistent */ +#define PECR13_ADDR 0x00001144 /* EAS inconsistent */ +#define PECR14_ADDR 0x00001148 /* EAS inconsistent */ +/* Reserved 0x0000104C through 0x000011FFH */ /* EAS inconsistent */ + +/* Address Translation Unit 0000 1200H through 0000 12FFH */ +#define ATUVID_ADDR 0x00001200 +#define ATUDID_ADDR 0x00001202 +#define PATUCMD_ADDR 0x00001204 +#define PATUSR_ADDR 0x00001206 +#define ATURID_ADDR 0x00001208 +#define ATUCCR_ADDR 0x00001209 +#define ATUCLSR_ADDR 0x0000120C +#define ATULT_ADDR 0x0000120D +#define ATUHTR_ADDR 0x0000120E +#define ATUBISTR_ADDR 0x0000120F +#define PIABAR_ADDR 0x00001210 +/* Reserved 0x00001214 through 0x0000122B */ +#define ASVIR_ADDR 0x0000122C +#define ASIR_ADDR 0x0000122E +#define ERBAR_ADDR 0x00001230 +/* Reserved 0x00001234 */ +/* Reserved 0x00001238 */ +#define ATUILR_ADDR 0x0000123C +#define ATUIPR_ADDR 0x0000123D +#define ATUMGNT_ADDR 0x0000123E +#define ATUMLAT_ADDR 0x0000123F +#define PIALR_ADDR 0x00001240 +#define PIATVR_ADDR 0x00001244 +#define SIABAR_ADDR 0x00001248 +#define SIALR_ADDR 0x0000124C +#define SIATVR_ADDR 0x00001250 +#define POMWVR_ADDR 0x00001254 +/* Reserved 0x00001258 */ +#define POIOWVR_ADDR 0x0000125C +#define PODWVR_ADDR 0x00001260 +#define POUDR_ADDR 0x00001264 +#define SOMWVR_ADDR 0x00001268 +#define SOIOWVR_ADDR 0x0000126C +/* Reserved 0x00001270 */ +#define ERLR_ADDR 0x00001274 +#define ERTVR_ADDR 0x00001278 +/* Reserved 0x0000127C */ +/* Reserved 0x00001280 */ +/* Reserved 0x00001284 */ +#define ATUCR_ADDR 0x00001288 +/* Reserved 0x0000128C */ +#define PATUISR_ADDR 0x00001290 +#define SATUISR_ADDR 0x00001294 +#define SATUCMD_ADDR 0x00001298 +#define SATUSR_ADDR 0x0000129A +#define SODWVR_ADDR 0x0000129C +#define SOUDR_ADDR 0x000012A0 +#define POCCAR_ADDR 0x000012A4 +#define SOCCAR_ADDR 0x000012A8 +#define POCCDR_ADDR 0x000012AC +#define SOCCDR_ADDR 0x000012B0 +#define PAQCR_ADDR 0x000012B4 +#define SAQCR_ADDR 0x000012B8 +#define PAIMR_ADDR 0x000012BC +#define SAIMR_ADDR 0x000012C0 +/* Reserved 0x000012C4 through 0x000012FF */ + +/* Messaging Unit 0000 1300H through 0000 130FH */ +#define IMR0_ADDR 0x00001310 +#define IMR1_ADDR 0x00001314 +#define OMR0_ADDR 0x00001318 +#define OMR1_ADDR 0x0000131C +#define IDR_ADDR 0x00001320 +#define IISR_ADDR 0x00001324 +#define IIMR_ADDR 0x00001328 +#define ODR_ADDR 0x0000132C +#define OISR_ADDR 0x00001330 +#define OIMR_ADDR 0x00001334 +/* Reserved 0x00001338 through 0x0000134F */ +#define MUCR_ADDR 0x00001350 +#define QBAR_ADDR 0x00001354 +/* Reserved 0x00001358 */ +/* Reserved 0x0000135C */ +#define IFHPR_ADDR 0x00001360 +#define IFTPR_ADDR 0x00001364 +#define IPHPR_ADDR 0x00001368 +#define IPTPR_ADDR 0x0000136C +#define OFHPR_ADDR 0x00001370 +#define OFTPR_ADDR 0x00001374 +#define OPHPR_ADDR 0x00001378 +#define OPTPR_ADDR 0x0000137C +#define IAR_ADDR 0x00001380 +/* Reserved 0x00001384 through 0x000013FF */ + +/* DMA Controller 0000 1400H through 0000 14FFH */ +#define CCR0_ADDR 0x00001400 +#define CSR0_ADDR 0x00001404 +/* Reserved 0x00001408 */ +#define DAR0_ADDR 0x0000140C +#define NDAR0_ADDR 0x00001410 +#define PADR0_ADDR 0x00001414 +#define PUADR0_ADDR 0x00001418 +#define LADR0_ADDR 0x0000141C +#define BCR0_ADDR 0x00001420 +#define DCR0_ADDR 0x00001424 +/* Reserved 0x00001428 through 0x0000143F */ +#define CCR1_ADDR 0x00001440 +#define CSR1_ADDR 0x00001444 +/* Reserved 0x00001448 */ +#define DAR1_ADDR 0x0000144C +#define NDAR1_ADDR 0x00001450 +#define PADR1_ADDR 0x00001454 +#define PUADR1_ADDR 0x00001458 +#define LADR1_ADDR 0x0000145C +#define BCR1_ADDR 0x00001460 +#define DCR1_ADDR 0x00001464 +/* Reserved 0x00001468 through 0x0000147F */ +#define CCR2_ADDR 0x00001480 +#define CSR2_ADDR 0x00001484 +/* Reserved 0x00001488 */ +#define DAR2_ADDR 0x0000148C +#define NDAR2_ADDR 0x00001490 +#define PADR2_ADDR 0x00001494 +#define PUADR2_ADDR 0x00001498 +#define LADR2_ADDR 0x0000149C +#define BCR2_ADDR 0x000014A0 +#define DCR2_ADDR 0x000014A4 +/* Reserved 0x000014A8 through 0x000014FF */ + +/* Memory Controller 0000 1500H through 0000 15FFH */ +#define SDIR_ADDR 0x00001500 +#define SDCR_ADDR 0x00001504 +#define SDBR_ADDR 0x00001508 +#define SBR0_ADDR 0x0000150C +#define SBR1_ADDR 0x00001510 +#define SDPR0_ADDR 0x00001514 +#define SDPR1_ADDR 0x00001518 +#define SDPR2_ADDR 0x0000151C +#define SDPR3_ADDR 0x00001520 +#define SDPR4_ADDR 0x00001524 +#define SDPR5_ADDR 0x00001528 +#define SDPR6_ADDR 0x0000152C +#define SDPR7_ADDR 0x00001530 +#define ECCR_ADDR 0x00001534 +#define ELOG0_ADDR 0x00001538 +#define ELOG1_ADDR 0x0000153C +#define ECAR0_ADDR 0x00001540 +#define ECAR1_ADDR 0x00001544 +#define ECTST_ADDR 0x00001548 +#define FEBR0_ADDR 0x0000154C +#define FEBR1_ADDR 0x00001550 +#define FBSR0_ADDR 0x00001554 +#define FBSR1_ADDR 0x00001558 +#define FWSR0_ADDR 0x0000155C +#define FWSR1_ADDR 0x00001560 +#define MCISR_ADDR 0x00001564 +#define RFR_ADDR 0x00001568 +/* Reserved 0x0000156C through 0x000015FF */ + +/* Arbitration Control Unit 0000 1600H through 0000 167FH */ +#define IACR_ADDR 0x00001600 +#define MLTR_ADDR 0x00001604 +#define MTTR_ADDR 0x00001608 +/* Reserved 0x0000160C through 0x0000163F */ + +/* Bus Interface Control Unit 0000 1640H through 0000 167FH */ +#define BIUCR_ADDR 0x00001640 +#define BIUISR_ADDR 0x00001644 +/* Reserved 0x00001648 through 0x0000167F */ + +/* I2C Bus Interface Unit 0000 1680H through 0000 16FFH */ +#define ICR_ADDR 0x00001680 +#define ISR_ADDR 0x00001684 +#define ISAR_ADDR 0x00001688 +#define IDBR_ADDR 0x0000168C +#define ICCR_ADDR 0x00001690 +#define IBMR_ADDR 0x00001694 +/* Reserved 0x00001698 through 0x000016FF */ + +/* PCI And Peripheral Interrupt Controller 0000 1700H through 0000 17FFH */ +#define NISR_ADDR 0x00001700 +#define X7ISR_ADDR 0x00001704 +#define X6ISR_ADDR 0x00001708 +#define PDIDR_ADDR 0x00001710 /* EAS inconsistent */ +/* Reserved 0x00001714 through 0x0000177F */ + +/* Application Accelerator Unit 0000 1800H through 0000 18FFH */ +#define ACR_ADDR 0x00001800 +#define ASR_ADDR 0x00001804 +#define ADAR_ADDR 0x00001808 +#define ANDAR_ADDR 0x0000180C +#define SAR1_ADDR 0x00001810 +#define SAR2_ADDR 0x00001814 +#define SAR3_ADDR 0x00001818 +#define SAR4_ADDR 0x0000181C +#define DAR_ADDR 0x00001820 +#define ABCR_ADDR 0x00001824 +#define ADCR_ADDR 0x00001828 +#define SAR5_ADDR 0x0000182C +#define SAR6_ADDR 0x00001830 +#define SAR7_ADDR 0x00001834 +#define SAR8_ADDR 0x00001838 + +/* Reserved 0x0000183C through 0x000018FF */ + +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/irq.S @@ -0,0 +1,107 @@ +//============================================================================= +// +// irq.S - Cyclone Diagnostics +// +//============================================================================= +//####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) 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-25 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +/* + * Low-lebvel interrupt support for IQ80310 diags + */ + .extern iq80310_irq_handler + .extern iq80310_fiq_handler + + .text + .globl __diag_IRQ + __diag_IRQ: + ldr sp, =__irq_stack /* point stack pointer at IRQ stack */ + sub lr, lr, #4 /* adjust lr (return to last address) */ + stmfd sp!, {r12, lr} /* push r12 and link reg onto stack */ + mrs r12, spsr /* store spsr in r12 */ + stmfd sp!, {r12} /* push spsr onto stack */ + stmfd sp!, {r0-r11} /* push all registers onto stack */ + bl iq80310_irq_handler + ldmfd sp!, {r0-r12} /* restore r0 thru r12 */ + msr spsr, r12 /* restore SPSR */ + ldmfd sp!, {r12,pc}^ /* restore r12 and PC, return */ + + .globl __diag_FIQ + __diag_FIQ: + /* Cyclone FIQ handler */ + /* save registers onto stack */ + ldr sp, =__fiq_stack /* point stack pointer at FIQ stack */ + sub lr, lr, #4 /* adjust link register (return to last address) */ + stmfd sp!, {r12, lr} /* push r12 and link reg onto stack */ + mrs r12, spsr /* store spsr in r12 */ + stmfd sp!, {r12} /* push spsr onto stack */ + stmfd sp!, {r0-r7} /* push r0 thru r7 (r8 - r14 are banked) */ + bl iq80310_fiq_handler + /* restore registers and return */ + ldmfd sp!, {r0-r7} /* restore r0 thru r7 (r8 - r14 are banked) */ + ldmfd sp!, {r12} + msr spsr, r12 /* restore SPSR */ + ldmfd sp!, {r12,pc}^ /* restore r12 and PC, return to inst before exception occurred */ + + .globl __ignore_abort +__ignore_abort: + subs pc,lr,#4 + + .globl _cspr_enable_fiq_int +_cspr_enable_fiq_int: + mrs r0, cpsr + bic r0, r0, #0x40 + msr cpsr, r0 + mov pc, lr + + .globl _cspr_enable_irq_int +_cspr_enable_irq_int: + mrs r0, cpsr + bic r0, r0, #0x80 + msr cpsr, r0 + mov pc, lr + + .bss + .rept 1024 + .word 0 + .endr + __irq_stack: + .rept 1024 + .word 0 + .endr + __fiq_stack: + +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/memtest.c @@ -0,0 +1,698 @@ +//============================================================================= +// +// memtest.c - Cyclone Diagnostics +// +//============================================================================= +//####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) 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-25 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +/************************************************************************* +* Memtest.c - this file performs an address/address bar memory test. +* +* Modification History +* -------------------- +* 01sep00 ejb Ported to StrongARM2 +* 18dec00 snc +* 02feb01 jwf for snc +*/ + +#include "7_segment_displays.h" + +#if 0 +extern void store_double (unsigned long, unsigned long, unsigned long); +extern void read_double (unsigned long, unsigned long Data[]); +extern int quadtest(long startaddr); +#endif + +extern void hex32out (unsigned int num); +extern int printf(char*,...); +extern load_runtime_reg(); +extern store_runtime_reg(); + +/* 02/02/01 jwf */ +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + + + +#define FAILED 1 +#define PASSED 0 + + + +/* Do walking one's test */ +static int +onesTest( + long testAddr /* address to test */ + ) +{ + long testData = 1; /* Current pattern being used */ + long dataRead; + int fail = 0; /* Test hasn't failed yet */ + int loopCount = 0; /* To keep track of when to print CR */ + + printf("\n"); + + while(testData && !fail) + { /* Loop until bit shifted out */ + *((long *) testAddr) = testData; /* Write test data */ + *((long *) (testAddr + 4)) = 0xFFFFFFFF; /* Drive d0-d31 hi */ + dataRead = *((long *) testAddr); /* Read back data */ + + hex32out(dataRead); + if (!(++loopCount % 8) && (loopCount != 32)) + printf("\n"); + else + printf(" "); + + if (dataRead != testData) /* Verify data */ + return FAILED; /* Signal failure */ + else + testData <<= 1; /* Shift data over one bit */ + } + + return PASSED; +} + + + + +#if 0 +/************************************************************************* +* +* onesTest - perform a 64 bit walking one's test on a specified address +* +* +* RETURNS: PASSED if the test passes or FAILED otherwise +* +*/ +static int onesTest(long testAddr) +{ + /* need to be arrays of sequential words in order to be + able to test a 64bit wide memory bus */ + unsigned long testData[2]; /* Current pattern being used */ + unsigned long dataRead[2]; /* Data read back from memory */ + int bitsTested = 0; /* To keep track of when to print CR and + when to switch words */ + + printf("\n"); + + /* test variable initialization */ + testData[0] = 0x00000001; /* lower 32 bit word */ + testData[1] = 0x00000000; /* upper 32 bit word */ + + bitsTested = 0; + + + /* Loop until all 64 data bits are tested */ + while (bitsTested < 64) + { + /* perform a double word write to cause a 64bit memory access */ + store_double (testAddr, testData[0], testData[1]); + + /* drive 64 bit data bus high and flush bus unit */ + store_double (testAddr + 8, 0xffffffff, 0xffffffff); + + /* perform a double word read to cause a 64bit memory access */ + read_double (testAddr, dataRead); + + hex32out((long)dataRead[1]); /* print out MS word */ + hex32out((long)dataRead[0]); /* print out LS word */ + + if (!(++bitsTested % 4) && (bitsTested != 64)) + printf("\n"); + else + printf(" "); + + /* verify the data */ + if ((dataRead[0] != testData[0]) || (dataRead[1] != testData[1])) + return (FAILED); /* Signal failure */ + else + { + if (bitsTested < 32) /* data bits 0 - 31 */ + { + testData[0] <<= 1; /* shift data through LS word */ + } + else if (bitsTested == 32) /* start testing MS word */ + { + testData[0] = 0x00000000; /* clear LS word */ + testData[1] = 0x00000001; /* shift into MS word */ + } + else /* data bits 32 - 63 */ + { + testData[1] <<= 1; /* shift data through MS word */ + } + } + } + return (PASSED); +} + +#endif + + + +/* Do long word address test */ + +static int LWAddr ( + long start, /* Starting address of test */ + long end, /* Ending address */ + long *badAddr /* Failure address */ + ) +{ + register long currentAddr; /* Current address being tested */ + register long data; + char fail = 0; /* Test hasn't failed yet */ + + for(currentAddr = start; currentAddr < end; currentAddr += 4) + *((long *) currentAddr) = currentAddr; + + for (currentAddr = start; + (currentAddr < end); + currentAddr += 4) + { + data = *(long *) currentAddr; + if (data != currentAddr) + { + fail = 1; + printf ("\n\nLWAddr Bad Read, Address = 0x%08x, Data Read = 0x%08x\n\n", currentAddr, data); + break; + } + } + + if (fail) + { + *badAddr = currentAddr; + return FAILED; + } + else + return PASSED; +} + +/* Do inverse long word address test */ + +static int LWBar (long start, /* Starting address of test */ + long end, /* Ending address */ + long *badAddr /* Failure address */ + ) +{ + register long currentAddr; /* Current address being tested */ + register long data; + int fail = 0; /* Test hasn't failed yet */ + + for(currentAddr = start; currentAddr < end; currentAddr += 4) + *((long *) currentAddr) = ~currentAddr; + + for (currentAddr = start; + (currentAddr < end); + currentAddr += 4) + { + data = *(long *) currentAddr; + if (data != ~currentAddr) + { + fail = 1; + printf ("\n\nLWBar Bad Read, Address = 0x%08x, Data Read = 0x%08x\n\n", currentAddr, data); + break; + } + } + if (fail) + { + *badAddr = currentAddr; + return FAILED; + } + else + return PASSED; +} + +/* Do byte address test */ + +static int +ByteAddr ( + long start, /* Starting address of test */ + long end, /* Ending address */ + long *badAddr /* Failure address */ + ) +{ + long currentAddr; /* Current address being tested */ + int fail = 0; /* Test hasn't failed yet */ + + for(currentAddr = start; currentAddr < end; currentAddr++) + *((char *) currentAddr) = (char) currentAddr; + + for(currentAddr = start; (currentAddr < end) && (!fail); currentAddr++) + if (*((char *) currentAddr) != (char) currentAddr) + fail = 1; + + if (fail) + { + *badAddr = currentAddr - 1; + return FAILED; + } + else + return PASSED; +} + +/* Do inverse byte address test */ + +static int ByteBar ( + long start, /* Starting address of test */ + long end, /* Ending address */ + long *badAddr /* Failure address */ + ) +{ + long currentAddr; /* Current address being tested */ + int fail = 0; /* Test hasn't failed yet */ + + for(currentAddr = start; currentAddr < end; currentAddr++) + *((char *) currentAddr) = (char) ~currentAddr; + + for(currentAddr = start; (currentAddr < end) && (!fail); currentAddr++) + if (*((char *) currentAddr) != (char) ~currentAddr) + fail = 1; + if (fail) { + *badAddr = currentAddr - 1; + return FAILED; + } + else + return PASSED; +} + +/* + * This routine is called if one of the memory tests fails. It dumps + * the 8 32-bit words before and the 8 after the failure address + */ + +void dumpMem ( + long badAddr /* Failure address */ + ) +{ + unsigned long *addr; + unsigned short *saddr; + + printf("\n"); /* Print out first line of mem dump */ + hex32out(badAddr - 32); /* Starting address */ + printf(": "); + hex32out(*((long *) (badAddr - 32))); /* First longword */ + printf(" "); + hex32out(*((long *) (badAddr - 28))); + printf(" "); + hex32out(*((long *) (badAddr - 24))); + printf(" "); + hex32out(*((long *) (badAddr - 20))); + + printf("\n"); + hex32out(badAddr - 16); + printf(": "); + hex32out(*((long *) (badAddr - 16))); + printf(" "); + hex32out(*((long *) (badAddr - 12))); + printf(" "); + hex32out(*((long *) (badAddr - 8))); + printf(" "); + hex32out(*((long *) (badAddr - 4))); + + printf("\n"); /* Print out contents of fault addr */ + hex32out(badAddr); + printf(": "); + hex32out(*((long *) badAddr)); + + + printf("\n"); /* Print out next line of mem dump */ + hex32out(badAddr + 4); /* Starting address */ + printf(": "); + hex32out(*((long *) (badAddr + 4))); /* First longword */ + printf(" "); + hex32out(*((long *) (badAddr + 8))); + printf(" "); + hex32out(*((long *) (badAddr + 12))); + printf(" "); + hex32out(*((long *) (badAddr + 16))); + + printf("\n"); + hex32out(badAddr + 20); + printf(": "); + hex32out(*((long *) (badAddr + 20))); + printf(" "); + hex32out(*((long *) (badAddr + 24))); + printf(" "); + hex32out(*((long *) (badAddr + 28))); + printf(" "); + hex32out(*((long *) (badAddr + 32))); + + /* DEBUG */ + printf ("\n\nReading back data in 32bit chunks:\n"); + addr = (unsigned long *)(badAddr - 16); + printf ("Address = 0x%08x, Data = 0x%08x\n", addr, *addr); + addr = (unsigned long *)(badAddr - 12); + printf ("Address = 0x%08x, Data = 0x%08x\n", addr, *addr); + addr = (unsigned long *)(badAddr - 8); + printf ("Address = 0x%08x, Data = 0x%08x\n", addr, *addr); + addr = (unsigned long *)(badAddr - 4); + printf ("Address = 0x%08x, Data = 0x%08x\n", addr, *addr); + addr = (unsigned long *)(badAddr); + printf ("Address = 0x%08x, Data = 0x%08x\n", addr, *addr); + addr = (unsigned long *)(badAddr + 4); + printf ("Address = 0x%08x, Data = 0x%08x\n", addr, *addr); + addr = (unsigned long *)(badAddr + 8); + printf ("Address = 0x%08x, Data = 0x%08x\n", addr, *addr); + addr = (unsigned long *)(badAddr + 12); + printf ("Address = 0x%08x, Data = 0x%08x\n", addr, *addr); + addr = (unsigned long *)(badAddr + 16); + printf ("Address = 0x%08x, Data = 0x%08x\n", addr, *addr); + printf ("\n"); + + printf ("Reading back data in 16bit chunks:\n"); + saddr = (unsigned short *)(badAddr - 16); + printf ("Address = 0x%08x, Data = 0x%04x\n", saddr, *saddr); + saddr = (unsigned short *)(badAddr - 14); + printf ("Address = 0x%08x, Data = 0x%04x\n", saddr, *saddr); + saddr = (unsigned short *)(badAddr - 12); + printf ("Address = 0x%08x, Data = 0x%04x\n", saddr, *saddr); + saddr = (unsigned short *)(badAddr - 10); + printf ("Address = 0x%08x, Data = 0x%04x\n", saddr, *saddr); + saddr = (unsigned short *)(badAddr - 8); + printf ("Address = 0x%08x, Data = 0x%04x\n", saddr, *saddr); + saddr = (unsigned short *)(badAddr - 6); + printf ("Address = 0x%08x, Data = 0x%04x\n", saddr, *saddr); + saddr = (unsigned short *)(badAddr - 4); + printf ("Address = 0x%08x, Data = 0x%04x\n", saddr, *saddr); + saddr = (unsigned short *)(badAddr - 2); + printf ("Address = 0x%08x, Data = 0x%04x\n", saddr, *saddr); + saddr = (unsigned short *)(badAddr); + printf ("Address = 0x%08x, Data = 0x%04x\n", saddr, *saddr); + saddr = (unsigned short *)(badAddr + 2); + printf ("Address = 0x%08x, Data = 0x%04x\n", saddr, *saddr); + saddr = (unsigned short *)(badAddr + 4); + printf ("Address = 0x%08x, Data = 0x%04x\n", saddr, *saddr); + saddr = (unsigned short *)(badAddr + 6); + printf ("Address = 0x%08x, Data = 0x%04x\n", saddr, *saddr); + saddr = (unsigned short *)(badAddr + 8); + printf ("Address = 0x%08x, Data = 0x%04x\n", saddr, *saddr); + saddr = (unsigned short *)(badAddr + 10); + printf ("Address = 0x%08x, Data = 0x%04x\n", saddr, *saddr); + saddr = (unsigned short *)(badAddr + 12); + printf ("Address = 0x%08x, Data = 0x%04x\n", saddr, *saddr); + saddr = (unsigned short *)(badAddr + 14); + printf ("Address = 0x%08x, Data = 0x%04x\n", saddr, *saddr); + saddr = (unsigned short *)(badAddr + 16); + printf ("Address = 0x%08x, Data = 0x%04x\n", saddr, *saddr); + printf ("\n"); + +} + +/* + * Returns 1 if passed, 0 if failed. + */ + +int +memTest ( + long startAddr, /* Start address of test */ + long endAddr /* End address + 1 */ + ) +{ + long badAddr; /* Addr test failed at */ + + printf("\n"); + + if (onesTest(startAddr) == FAILED) + { + printf("\nWalking 1's test: failed"); + return 0; + } + printf("\nWalking 1's test: passed\n"); + + /* rval = quadtest(startAddr); + + switch (rval) + { + case 0: + printf("\nQuadword test passed\n"); + break; + + case 1: + printf("\nQuadword test failed: Quadword Write, Longword Read\n"); + dumpMem(startAddr); + return 0; + + case 2: + printf("\nQuadword test failed: Longword Write, Quadword Read\n"); + dumpMem(startAddr); + return 0; + + default: + printf("\nQuadword test: Unknown return value 0x%X\n", rval); + return 0; + } + */ + + printf("\nLong word address test: "); + if (LWAddr(startAddr, endAddr, &badAddr) == FAILED) + { + printf("failed"); + dumpMem(badAddr); + return 0; + } + printf("passed"); + + printf("\nLong word address bar test: "); + if (LWBar(startAddr, endAddr, &badAddr) == FAILED) + { + printf("failed"); + dumpMem(badAddr); + return 0; + } + printf("passed"); + + printf("\nByte address test: "); + if (ByteAddr(startAddr, endAddr, &badAddr) == FAILED) + { + printf("failed"); + dumpMem(badAddr); + return 0; + } + printf("passed"); + + printf("\nByte address bar test: "); + if (ByteBar(startAddr, endAddr, &badAddr) == FAILED) + { + printf("failed"); + dumpMem(badAddr); + return 0; + } + printf("passed"); + + return 1; +} + + +/* 02/02/01 jwf */ +/* Do alternating inverse long word address test */ +static int +LWABar(long start, /* Starting address of test */ + long end, /* Ending address */ + long *badAddr) /* Failure address */ +{ + register long currentAddr; /* Current address being tested */ + int fail = 0; /* Test hasn't failed yet */ + register long data; + + /* In this test, the contents of each longword address toggles + between the Address and the Address BAR */ + for(currentAddr = start; currentAddr < end; currentAddr += 4) + { + /* Address ending in 0x4 or 0xc */ + if (currentAddr & 4) + *((long *) currentAddr) = ~currentAddr; + + /* Address ending in 0x0 or 0x8 */ + else + *((long *) currentAddr) = currentAddr; + } + + for (currentAddr = start; (currentAddr < end) && (!fail); currentAddr += 4) + { + data = *(long *) currentAddr; + + switch (currentAddr & 0xf) + { + case 0x0: + case 0x8: + if (data != currentAddr) + { + fail = 1; + printf ("\nFailed at Address 0x%08X, Expected 0x%08X, Read 0x%08X\n", + currentAddr, currentAddr, data); + } + break; + + case 0x4: + case 0xc: + if (data != ~currentAddr) + { + fail = 1; + printf ("\nFailed at Address 0x%08X, Expected 0x%08X, Read 0x%08X\n", + currentAddr, ~currentAddr, data); + } + break; + + default: + fail = 1; + printf ("\nFailed at Address 0x%08X, Unaligned address\n", currentAddr); + break; + } + } + + if (fail) { + *badAddr = currentAddr - 4; + return FAILED; + } else + return PASSED; +} + + +/* 02/02/01 jwf */ +/* + * Returns 1 if passed, 0 if failed. + */ +int +LoopMemTest ( + long startAddr, /* Start address of test */ + long endAddr /* End address + 1 */ + ) +{ + long badAddr; /* Addr test failed at */ + volatile int junk; + extern int ecc_error_reported; + + /* indicate no ECC errors recorded */ + *MSB_DISPLAY_REG = DISPLAY_OFF; + + /* indicate passing test */ + *LSB_DISPLAY_REG = LETTER_P; + + while (1) + { + printf("\n"); + + printf("\nLong word address test: "); + if (LWAddr(startAddr, endAddr, &badAddr) == FAILED) + { + /* indicate failing test */ + *LSB_DISPLAY_REG = LETTER_F; + + printf("failed at Address 0x%08x\n", badAddr); + printf("Performing Continuous Write/Read/!Write/Read...\n\n"); + while (1) + { + *(volatile int *)badAddr = badAddr; + junk = *(volatile int *)badAddr; + *(volatile int *)badAddr = ~badAddr; + junk = *(volatile int *)badAddr; + + if (ecc_error_reported) + { + printf ("Disabling ECC reporting\n"); + /* disable single and multi-bit reporting */ + *(volatile unsigned long *)0x1534 = 0x4; + ecc_error_reported = FALSE; + } + } + return 0; /* not reached */ + } + printf("passed"); + + printf("\nLong word address bar test: "); + if (LWBar(startAddr, endAddr, &badAddr) == FAILED) + { + /* indicate failing test */ + *LSB_DISPLAY_REG = LETTER_F; + + printf("failed at Address 0x%08x\n", badAddr); + printf("Performing Continuous Write/Read/!Write/Read...\n\n"); + while (1) + { + *(volatile int *)badAddr = badAddr; + junk = *(volatile int *)badAddr; + *(volatile int *)badAddr = ~badAddr; + junk = *(volatile int *)badAddr; + + if (ecc_error_reported) + { + printf ("Disabling ECC reporting\n"); + /* disable single and multi-bit reporting */ + *(volatile unsigned long *)0x1534 = 0x4; + ecc_error_reported = FALSE; + } + } + return 0; /* not reached */ + } + printf("passed"); + + printf("\nAlternating Long word, Long word address bar test: "); + if (LWABar(startAddr, endAddr, &badAddr) == FAILED) + { + /* indicate failing test */ + *LSB_DISPLAY_REG = LETTER_F; + + printf("failed at Address 0x%08x\n", badAddr); + printf("Performing Continuous Write/Read/!Write/Read...\n\n"); + while (1) + { + *(volatile int *)badAddr = badAddr; + junk = *(volatile int *)badAddr; + *(volatile int *)badAddr = ~badAddr; + junk = *(volatile int *)badAddr; + + if (ecc_error_reported) + { + printf ("Disabling ECC reporting\n"); + /* disable single and multi-bit reporting */ + *(volatile unsigned long *)0x1534 = 0x4; + ecc_error_reported = FALSE; + } + } + return 0; /* not reached */ + } + printf("passed"); + } + + return 1; +} + +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/pci_bios.h @@ -0,0 +1,486 @@ +//============================================================================= +// +// pci_bios.h - Cyclone Diagnostics +// +//============================================================================= +//####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) 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-25 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +/****************************************************************************/ +/* File: pci_bios.h */ +/* */ +/* Use: mon960 */ +/* */ +/* $Source: /dev/shm/cvs2hg/cvs/ecos/packages/hal/arm/iq80310/current/src/diag/Attic/pci_bios.h,v $ */ +/* $Revision: 1.1 $ */ +/* Last $Author: jlarmour $ */ +/* $Date: 2001/02/15 18:18:15 $ */ +/* */ +/* Purpose: PCI BIOS Routines */ +/* */ +/* Remarks: Conforming to the Revision 2.1 PCI BIOS Specfication */ +/* */ +/* Functions Supported: */ +/* */ +/* pci_bios_present() */ +/* find_pci_device() */ +/* find_pci_class_code() */ +/* generate_special_cycle() */ +/* read_config_byte() */ +/* read_config_word() */ +/* read_config_dword() */ +/* write_config_byte() */ +/* write_config_word() */ +/* write_config_dword() */ +/* get_irq_routing_options() */ +/* set_pci_irq() */ +/* */ +/* History: */ +/* 06Sep00 Scott Coulter Changed NUM_PCI_BUSES from 31 to 2 */ +/* 09Sep97 Jim Otto Defined NUM_PCI_BUSES */ +/* */ +/* */ +/* */ +/****************************************************************************/ + +#include "iq80310.h" + +#define XINT0 0 +#define XINT1 1 +#define XINT2 2 +#define XINT3 3 + +/* primary PCI bus definitions */ +#define PRIMARY_BUS_NUM 0 +#define PRIMARY_MEM_BASE 0x80000000 +#define PRIMARY_DAC_BASE 0x84000000 +#define PRIMARY_IO_BASE 0x90000000 +#define PRIMARY_MEM_LIMIT 0x83ffffff +#define PRIMARY_DAC_LIMIT 0x87ffffff +#define PRIMARY_IO_LIMIT 0x9000ffff + + +/* secondary PCI bus definitions */ +#define SECONDARY_BUS_NUM 1 +#define SECONDARY_MEM_BASE 0x88000000 +#define SECONDARY_DAC_BASE 0x8c000000 +#define SECONDARY_IO_BASE 0x90010000 +#define SECONDARY_MEM_LIMIT 0x8bffffff +#define SECONDARY_DAC_LIMIT 0x8fffffff +#define SECONDARY_IO_LIMIT 0x9001ffff + + +#define LAST_SYSPROC 260 + +#define NUM_PCI_BUSES 2 + +#ifndef ASM_LANGUAGE + +/****************************************************************************** +* +* Required PCI BIOS Data Structures +* +*/ +typedef struct +{ + int num_devices; + int num_functions; +} PCI_DATA; + +typedef struct +{ + int present_status; /* set to 0x00 for BIOS present */ + int hardware_mech_config; /* for accessing config. space */ + int hardware_mech_special; /* for performing special cycles */ + int if_level_major_ver; /* in BCD, 0x02 for version 2.1 */ + int if_level_minor_ver; /* in BCD, 0x01 for version 2.1 */ + int last_pci_bus; /* numbers start at 0 */ +} PCI_BIOS_INFO; + +/******************************************************************************* +* +* Type 0 PCI Configuration Space Header +* +*/ + +typedef struct +{ + unsigned short vendor_id; + unsigned short device_id; + unsigned short command; + unsigned short status; + unsigned char revision_id; + unsigned char prog_if; + unsigned char sub_class; + unsigned char base_class; + unsigned char cache_line_size; + unsigned char latency_timer; + unsigned char header_type; + unsigned char bist; + unsigned long pcibase_addr0; + unsigned long pcibase_addr1; + unsigned long pcibase_addr2; + unsigned long pcibase_addr3; + unsigned long pcibase_addr4; + unsigned long pcibase_addr5; + unsigned long cardbus_cis_ptr; + unsigned short sub_vendor_id; + unsigned short sub_device_id; + unsigned long pcibase_exp_rom; + unsigned long reserved2[2]; + unsigned char int_line; + unsigned char int_pin; + unsigned char min_gnt; + unsigned char max_lat; +} PCI_CONFIG_SPACE_0; + +/******************************************************************************* +* +* PCI Bridge Configuration Space Header +* +*/ + +typedef struct +{ + unsigned short vendor_id; + unsigned short device_id; + unsigned short command; + unsigned short status; + unsigned char revision_id; + unsigned char prog_if; + unsigned char sub_class; + unsigned char base_class; + unsigned char cache_line_size; + unsigned char latency_timer; + unsigned char header_type; + unsigned char bist; + unsigned long pcibase_addr0; + unsigned long pcibase_addr1; + unsigned char primary_busno; + unsigned char secondary_busno; + unsigned char subordinate_busno; + unsigned char secondary_latency_timer; + unsigned char io_base; + unsigned char io_limit; + unsigned short secondary_status; + unsigned short mem_base; + unsigned short mem_limit; + unsigned short pfmem_base; + unsigned short pfmem_limit; + unsigned long pfbase_upper32; + unsigned long pflimit_upper32; + unsigned short iobase_upper16; + unsigned short iolimit_upper16; + unsigned short sub_vendor_id; + unsigned short sub_device_id; + unsigned long pcibase_exp_rom; + unsigned char int_line; + unsigned char int_pin; + unsigned short bridge_control; +} PCI_CONFIG_SPACE_1; + +typedef union +{ + PCI_CONFIG_SPACE_0 pci0_config; + PCI_CONFIG_SPACE_1 pci1_config; +} PCI_CONFIG_SPACE; + +#define CONFIG_MECHANISM_1 1 +#define CONFIG_MECHANISM_2 2 + +typedef struct +{ + int bus_number; /* 0...255 */ + int device_number; /* Device number on bus */ + int function_number; /* Function number on device */ +} PCI_DEVICE_LOCATION; + + +typedef struct +{ + int bus_number; /* 0...255 */ + int device_number; /* Device number on bus */ + int inta_link; /* Which ints. are or'd together */ + int inta_bitmap; /* Which XINT connected to */ + int intb_link; /* Which ints. are or'd together */ + int intb_bitmap; /* Which XINT connected to */ + int intc_link; /* Which ints. are or'd together */ + int intc_bitmap; /* Which XINT connected to */ + int intd_link; /* Which ints. are or'd together */ + int intd_bitmap; /* Which XINT connected to */ + int slot_number; /* Physical slot (1 - NUM_PCI_SLOTS) */ +} SLOT_IRQ_ROUTING; + + +/* Link values used to indicate which PCI interrupts are wire OR'ed together, the + value 0 indicates no connection to an interrupt controller and should not be used */ + +#define LINK_XINT0 1 +#define LINK_XINT1 2 +#define LINK_XINT2 3 +#define LINK_XINT3 4 +#define LINK_XINT4 5 +#define LINK_XINT5 6 +#define LINK_XINT6 7 +#define LINK_XINT7 8 + +#define INTA 1 +#define INTB 2 +#define INTC 3 +#define INTD 4 + +#define INTA_PTR 0 +#define INTB_PTR 1 +#define INTC_PTR 2 +#define INTD_PTR 3 + +#define SLOT0 0 +#define SLOT1 1 +#define SLOT2 2 +#define SLOT3 3 + +/* PCI Errors - Status Registers */ +#define PARITY_ERROR 0x8000 +#define SERR_ERROR 0x4000 +#define MASTER_ABORT 0x2000 +#define TARGET_ABORT_M 0x1000 +#define TARGET_ABORT_T 0x0800 +#define MASTER_PAR_ERR 0x0100 + +/* PCI Errors - PCI Interrupt Status Registers */ +#define SERR_ASSERTED 0x00000400 +#define ATU_PERR 0x00000200 +#define ATU_BIST_ERR 0x00000100 +#define IB_MA_ABORT 0x00000080 +#define BRIDGE_PERR 0x00000020 +#define PSERR_FAULT 0x00000010 +#define MA_FAULT 0x00000008 +#define TA_M_FAULT 0x00000004 +#define TA_T_FAULT 0x00000002 +#define PAR_FAULT 0x00000001 + +/* Generic PCI Constants */ +#define MAX_PCI_BUSES 31 +#define MAX_DEVICE_NUMBER 31 +#define MAX_FUNCTION_NUMBER 8 +#define DEVS_PER_BRIDGE 6 +#define STANDARD_HEADER 0 +#define PCITOPCI_HEADER 1 +#define NUM_PCI_SLOTS 4 +#define MULTIFUNCTION_DEVICE (1 << 7) +#define MAX_SUB_BUSNO 0xff +#define LATENCY_VALUE 0x0f +#define FIRST_DEVICE_NUM 5 +#define LAST_DEVICE_NUM 8 +#define SLOTS_PER_BUS 4 + +/* PCI command register bits */ +#define PCI_CMD_IOSPACE (1 << 0) +#define PCI_CMD_MEMSPACE (1 << 1) +#define PCI_CMD_BUS_MASTER (1 << 2) +#define PCI_CMD_SPECIAL (1 << 3) +#define PCI_CMD_MWI_ENAB (1 << 4) +#define PCI_CMD_VGA_SNOOP (1 << 5) +#define PCI_CMD_PARITY (1 << 6) +#define PCI_CMD_WAIT_CYC (1 << 7) +#define PCI_CMD_SERR_ENAB (1 << 8) +#define PCI_CMD_FBB_ENAB (1 << 9) + +/* Bridge Command Register Bit Definitions*/ +#define BRIDGE_IOSPACE_ENAB (1 << 0) +#define BRIDGE_MEMSPACE_ENAB (1 << 1) +#define BRIDGE_MASTER_ENAB (1 << 2) +#define BRIDGE_WAIT_CYCLE (1 << 7) +#define BRIDGE_SERR_ENAB (1 << 8) + +/* Bridge Control Register Bit Definitions */ +#define BRIDGE_PARITY_ERR (1 << 0) +#define BRIDGE_SEER_ENAB (1 << 1) +#define BRIDGE_MASTER_ABORT (1 << 5) + +/* configuration offsets */ +#define VENDOR_ID_OFFSET 0x00 +#define DEVICE_ID_OFFSET 0x02 +#define COMMAND_OFFSET 0x04 +#define STATUS_OFFSET 0x06 +#define REVISION_OFFSET 0x08 +#define PROG_IF_OFFSET 0x09 +#define SUB_CLASS_OFFSET 0x0a +#define BASE_CLASS_OFFSET 0x0b +#define CACHE_LINE_OFFSET 0x0c +#define LATENCY_TIMER_OFFSET 0x0d +#define HEADER_TYPE_OFFSET 0x0e +#define BIST_OFFSET 0x0f +#define REGION0_BASE_OFFSET 0x10 +#define REGION1_BASE_OFFSET 0x14 +#define REGION2_BASE_OFFSET 0x18 +#define PRIMARY_BUSNO_OFFSET 0x18 +#define SECONDARY_BUSNO_OFFSET 0x19 +#define SUBORD_BUSNO_OFFSET 0x1a +#define SECONDARY_LAT_OFFSET 0x1b +#define REGION3_BASE_OFFSET 0x1c +#define IO_BASE_OFFSET 0x1c +#define IO_LIMIT_OFFSET 0x1d +#define SECONDARY_STAT_OFFSET 0x1e +#define REGION4_BASE_OFFSET 0x20 +#define MEMORY_BASE_OFFSET 0x20 +#define MEMORY_LIMIT_OFFSET 0x22 +#define REGION5_BASE_OFFSET 0x24 +#define PREF_MEM_BASE_OFFSET 0x24 +#define PREF_MEM_LIMIT_OFFSET 0x26 +#define CARDBUS_CISPTR_OFFSET 0x28 +#define PREF_BASE_UPPER_OFFSET 0x28 +#define SUB_VENDOR_ID_OFFSET 0x2c +#define PREF_LIMIT_UPPER_OFFSET 0x2c +#define SUB_DEVICE_ID_OFFSET 0x2e +#define EXP_ROM_OFFSET 0x30 +#define IO_BASE_UPPER_OFFSET 0x30 +#define IO_LIMIT_UPPER_OFFSET 0x32 +#define CAP_PTR_OFFSET 0x34 +#define TYPE1_EXP_ROM_OFFSET 0x38 +#define INT_LINE_OFFSET 0x3c +#define INT_PIN_OFFSET 0x3d +#define MIN_GNT_OFFSET 0x3e +#define BRIDGE_CTRL_OFFSET 0x3e +#define MAX_LAT_OFFSET 0x3f + +typedef struct +{ + SLOT_IRQ_ROUTING info[NUM_PCI_SLOTS]; +} PCI_IRQ_ROUTING_TABLE; + + +/****************************************************************************** +* +* Return values from BIOS Calls +* +*/ + +#define SUCCESSFUL 0 +#define DEVICE_NOT_FOUND -1 +#define BAD_VENDOR_ID -2 +#define FUNC_NOT_SUPPORTED -3 +#define BUFFER_TOO_SMALL -4 +#define SET_FAILED -5 +#define BAD_REGISTER_NUMBER -6 + + +/****************************************************************************** +* +* BIOS Function Prototypes +* +*/ + +STATUS pci_bios_present (PCI_BIOS_INFO *info); + +STATUS find_pci_device (int device_id, int vendor_id, int index); + +STATUS find_pci_class_code (int class_code, int index); + +STATUS generate_special_cycle (int bus_number, int special_cycle_data); + +STATUS read_config_byte (int bus_number, int device_number, int function_number, int register_number, /* 0,1,2,...,255 */ + UINT8 *data); + +STATUS read_config_word (int bus_number, int device_number, int function_number, int register_number, /* 0,2,4,...,254 */ + UINT16 *data); + +STATUS read_config_dword (int bus_number, int device_number, int function_number, int register_number, /* 0,4,8,...,252 */ + UINT32 *data); + +STATUS write_config_byte (int bus_number, int device_number, int function_number, int register_number, /* 0,1,2,...,255 */ + UINT8 data); + +STATUS write_config_word (int bus_number, int device_number, int function_number, int register_number, /* 0,2,4,...,254 */ + UINT16 data); + +STATUS write_config_dword (int bus_number, int device_number, int function_number, int register_number, /* 0,4,8,...,252 */ + UINT32 data); + +STATUS get_irq_routing_options (PCI_IRQ_ROUTING_TABLE *table); + +STATUS set_pci_irq (int int_pin, int irq_num, int bus_dev); + + +/****************************************************************************** +* +* sysPciIsrConnect - connect a routine to an PCI interrupt +* +* This function uses the Breeze System Services. Parameters are left +* unchanged in the global registers just as the service call expects. +* Likewise, the return value of the service call is left unmodified. +* +* intline is the PCI interrupt line PCI_INTA - PCI_INTD +* +* bus is the PCI bus the targeted device is on +* +* device is the targeted device for the PCI interrupt +* +* handler is an interrupt handler which accepts an integer as an argument and +* returns 0 if no interrupt was serviced and 1 if an interrupt was +* serviced (necessary for interrupt sharing). +* +* arg is the argument to be passed to the handler when called. +* +*/ +STATUS sysPciIsrConnect (int intline, + int bus, + int device, + int (*handler)(int), + int arg); + + +/****************************************************************************** +* +* sysPciIsrDisconnect - disconnect a routine from an PCI interrupt +* +* This function uses the Breeze System Services. Parameters are left +* unchanged in the global registers just as the service call expects. +* Likewise, the return value of the service call is left unmodified. +* +* intline is the PCI interrupt line INTA - INTD +* +* bus is the PCI bus the targeted device is on +* +* device is the PCI device sourcing the interrupt +* + */ +STATUS sysPciIsrDisconnect (int intline, + int bus, + int device); + +#endif /* ASM_LANGUAGE */ +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/pci_serv.c @@ -0,0 +1,2585 @@ +//============================================================================= +// +// pci_serv.c - Cyclone Diagnostics +// +//============================================================================= +//####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) 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-25 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +/********************************************************************************/ +/* PCI_SERV.C - PCI driver for IQ80310 */ +/* */ +/* History: */ +/* 15sep00 ejb Ported to Cygmon on IQ80310 */ +/* 18dec00 snc */ +/********************************************************************************/ +#include "iq80310.h" +#include "pci_bios.h" + + + +#undef DEBUG_PCI + +#define IB_MA_ERROR 0x2000 + +/*==========================================================================*/ +/* Globals */ +/*==========================================================================*/ +ULONG memspace_ptr[NUM_PCI_BUSES]; +ULONG iospace_ptr[NUM_PCI_BUSES]; +ULONG memspace_limit[NUM_PCI_BUSES]; +ULONG iospace_limit[NUM_PCI_BUSES]; +UINT nextbus; +UINT secondary_busno = SECONDARY_BUS_NUM; +UINT primary_busno = PRIMARY_BUS_NUM; +UINT lastbus; +unsigned long dram_size; /* global storing the size of DRAM */ +int bus0_lastbus; /* last secondary bus number behind bus 0 */ +int bus1_lastbus; /* last secondary bus number behind bus 1 */ + +int nmi_verbose; /* global flag to indicate whether or not PCI Error messages should be + printed. This flag is used to prevent a painful deluge of messages + when performing PCI configuration reads/writes to possibly non-existant + devices. */ + +int pci_config_error = FALSE; /* becomes TRUE if an NMI interrupt occurs due to a PCI config cycle */ + +#define PRINT_ON() nmi_verbose = TRUE +#define PRINT_OFF() nmi_verbose = FALSE + +/*==========================================================================*/ +/* Function prototypes */ +/*==========================================================================*/ +static void sys_pci_bus_init (UINT bus, UINT root_bus, PCI_DATA* pci_data); +void print_config_space (int bus, int device, int function); + + +void show_pci(void); +void show_bus(int); +void init_312_pci(void); + +typedef int (*FUNCPTR) (); /* ptr to function returning int */ + +typedef struct +{ + FUNCPTR handler; + int arg; + int bus; + int device; +} INT_HANDLER; + +#define NUM_PCI_XINTS 4 /* XINT0 - XINT3 */ +#define MAX_PCI_HANDLERS 8 /* maximum handlers per PCI Xint */ + +/* Table where the interrupt handler addresses are stored. */ +INT_HANDLER pci_int_handlers[4][MAX_PCI_HANDLERS]; + + +extern void printf(); +extern void hexIn(); + +extern int pci_config_cycle; + +extern void _enableFiqIrq(); +extern void config_ints(void); /* configure interrupts */ + +/********************************************************************************* +* pci_to_xint - convert a PCI device number and Interrupt line to an 80312 XINT +* +* This function converts a PCI slot number (0 - 7) and an Interrupt line +* (INTA - INTD) to a i960 processor XINT number (0 - 3) +* +* RETURNS: OK or ERROR if arguments are invalid +* +*/ +STATUS pci_to_xint(int device, int intpin, int *xint) +{ + int device_base; /* all devices mod 4 follow same interrupt mapping scheme */ + + /* check validity of arguments */ + if ((intpin < INTA) || (intpin > INTD) || (device > 31)) + return (ERROR); + + device_base = device % 4; + + /* interrupt mapping scheme as per PCI-to-PCI Bridge Specification */ + switch (device_base) + { + case 0: + switch (intpin) + { + case INTA: + *xint = XINT0; + break; + case INTB: + *xint = XINT1; + break; + case INTC: + *xint = XINT2; + break; + case INTD: + *xint = XINT3; + break; + } + break; + case 1: + switch (intpin) + { + case INTA: + *xint = XINT1; + break; + case INTB: + *xint = XINT2; + break; + case INTC: + *xint = XINT3; + break; + case INTD: + *xint = XINT0; + break; + } + break; + case 2: + switch (intpin) + { + case INTA: + *xint = XINT2; + break; + case INTB: + *xint = XINT3; + break; + case INTC: + *xint = XINT0; + break; + case INTD: + *xint = XINT1; + break; + } + break; + case 3: + switch (intpin) + { + case INTA: + *xint = XINT3; + break; + case INTB: + *xint = XINT0; + break; + case INTC: + *xint = XINT1; + break; + case INTD: + *xint = XINT2; + break; + } + break; + } + return (OK); +} + + +/****************************************************************************** +* +* Checks to see if the "bus" argument identifies a PCI bus which is located +* off of the Primary PCI bus of the board. +*/ +int off_ppci_bus (int busno) +{ + if (busno == primary_busno) + return (TRUE); + else if (busno == secondary_busno) + return (FALSE); + else if (busno <= bus0_lastbus) + return (TRUE); + else + return (FALSE); +} + +static unsigned old_abort_vec; + +/************************************************************************* +* pci_cycle_cleanup - cleanup after a PCI configuration cycle +* +* This function will clear the various PCI abort bits if a configuration +* cycle to a non-existant device is attempted. Covers both ATU and +* bridge functions. +* +* RETURNS: OK if no PCI abort bits were set or ERROR if abort bits were +* detected. +*/ +static int pci_cycle_cleanup (ULONG busno) +{ + UINT16 *pci_status_reg16; + UINT16 pci_status16; + UINT32 *pci_status_reg; + UINT32 pci_status; + UINT8 status; + UINT8 bus_select = 0; /* quiet the compiler warning */ + + pci_status16 = 0; + pci_status = 0; + status = 0; + + /* this if-else structure must be done in the correct order to + ensure that the correct ATU is chosen */ + if (busno == primary_busno) + bus_select = PRIMARY_BUS_NUM; + else if (busno == secondary_busno) + bus_select = SECONDARY_BUS_NUM; + else if (busno <= bus0_lastbus) + bus_select = PRIMARY_BUS_NUM; + else if (busno <= bus1_lastbus) + bus_select = SECONDARY_BUS_NUM; + else return (ERROR); + + + /* Read/clear bus status and bus interrupt status registers */ + + switch (bus_select) + { + case 0: /* Primary Bus */ + pci_status_reg16 = (UINT16 *) PATUSR_ADDR; + pci_status16 = *pci_status_reg16; + + if ((pci_status16 & 0xF900) == 0) goto skip1; + + #ifdef DEBUG_PCI + if (pci_status16 & PARITY_ERROR) printf("Parity Error Detected - Primary Bus - ATU\n"); + if (pci_status16 & SERR_ERROR) printf("P_SERR# Asserted - Primary Bus - ATU\n"); + if (pci_status16 & MASTER_ABORT) printf("Master Abort Detected - Primary Bus - ATU\n"); + if (pci_status16 & TARGET_ABORT_M) printf("Target Abort Detected - Primary Bus - ATU is master\n"); + if (pci_status16 & TARGET_ABORT_T) printf("Target Abort Detected - Primary Bus - ATU is target\n"); + if (pci_status16 & MASTER_PAR_ERR) printf("Master Parity Error - Primary Bus - ATU\n"); + #endif + status = 1; + pci_status16 &= 0xF980; + *pci_status_reg16 = pci_status16; + +skip1: + pci_status_reg16 = (UINT16 *) PSR_ADDR; + pci_status16 = *pci_status_reg16; + + if ((pci_status16 & 0xF900) == 0) goto skip2; + + #ifdef DEBUG_PCI + if (pci_status16 & PARITY_ERROR) printf("Parity Error Detected - Primary Bus - Bridge\n"); + if (pci_status16 & SERR_ERROR) printf("P_SERR# Asserted - Primary Bus - Bridge\n"); + if (pci_status16 & MASTER_ABORT) printf("Master Abort Detected - Primary Bus - Bridge\n"); + if (pci_status16 & TARGET_ABORT_M) printf("Target Abort Detected - Primary Bus - Bridge is master\n"); + if (pci_status16 & TARGET_ABORT_T) printf("Target Abort Detected - Primary Bus - Bridge is target\n"); + if (pci_status16 & MASTER_PAR_ERR) printf("Master Parity Error - Primary Bus - Bridge\n"); + #endif + status = 1; + pci_status16 &= 0xF980; + *pci_status_reg16 = pci_status16; + +skip2: + + pci_status_reg = (UINT32 *) PATUISR_ADDR; + pci_status = *pci_status_reg; + + if ((pci_status & 0x0000079F) == 0) goto skip3; + + #ifdef DEBUG_PCI + if (pci_status & ATU_BIST_ERR) printf("ATU BIST Error - Primary Bus\n"); + if (pci_status & IB_MA_ERROR) printf("Internal Bus Master Abort - Primary Bus - ATU\n"); + #endif + status = 1; + pci_status &= 0x0000079f; + *pci_status_reg = pci_status; +skip3: + + pci_status_reg = (UINT32 *) PBISR_ADDR; + pci_status = *pci_status_reg; + + if ((pci_status & 0x0000003F) == 0) goto skip4; + + #ifdef DEBUG_PCI + if (pci_status16 & BRIDGE_PERR) printf("Parity Error Detected - Primary Bus - Bridge\n"); + if (pci_status16 & SERR_ERROR) printf("P_SERR# Asserted - Primary Bus - Bridge\n"); + if (pci_status16 & MASTER_ABORT) printf("Master Abort Detected - Primary Bus - Bridge\n"); + if (pci_status16 & TARGET_ABORT_M) printf("Target Abort Detected - Primary Bus - Bridge is master\n"); + if (pci_status16 & TARGET_ABORT_T) printf("Target Abort Detected - Primary Bus - Bridge is target\n"); + if (pci_status16 & MASTER_PAR_ERR) printf("Master Parity Error - Primary Bus - Bridge\n"); + #endif + status = 1; + pci_status &= 0x0000003F; + *pci_status_reg = pci_status; +skip4: + break; + + + case 1: /* Secondary Bus */ + pci_status_reg16 = (UINT16 *) SATUSR_ADDR; + pci_status16 = *pci_status_reg16; + + if ((pci_status16 & 0xF900) == 0) goto skip5; + #ifdef DEBUG_PCI + if (pci_status16 & PARITY_ERROR) printf("Parity Error Detected - Secondary Bus - ATU\n"); + if (pci_status16 & SERR_ERROR) printf("S_SERR# Asserted - Secondary Bus - ATU\n"); + if (pci_status16 & MASTER_ABORT) printf("Master Abort Detected - Secondary Bus - ATU\n"); + if (pci_status16 & TARGET_ABORT_M) printf("Target Abort Detected - Secondary Bus - ATU is master\n"); + if (pci_status16 & TARGET_ABORT_T) printf("Target Abort Detected - Secondary Bus - ATU is target\n"); + if (pci_status16 & MASTER_PAR_ERR) printf("Master Parity Error - Secondary Bus - ATU\n"); + #endif + status = 1; + pci_status16 &= 0xF900; + *pci_status_reg16 = pci_status16; +skip5: + pci_status_reg16 = (UINT16 *) SSR_ADDR; + pci_status16 = *pci_status_reg16; + + if ((pci_status16 & 0xF900) == 0) goto skip6; + + #ifdef DEBUG_PCI + if (pci_status16 & PARITY_ERROR) printf("Parity Error Detected - Secondary Bus - Bridge\n"); + if (pci_status16 & SERR_ERROR) printf("S_SERR# Asserted - Secondary Bus - Bridge\n"); + if (pci_status16 & MASTER_ABORT) printf("Master Abort Detected - Secondary Bus - Bridge\n"); + if (pci_status16 & TARGET_ABORT_M) printf("Target Abort Detected - Secondary Bus - Bridge is master\n"); + if (pci_status16 & TARGET_ABORT_T) printf("Target Abort Detected - Secondary Bus - Bridge is target\n"); + if (pci_status16 & MASTER_PAR_ERR) printf("Master Parity Error - Secondary Bus - Bridge\n"); + #endif + status = 1; + pci_status16 &= 0xF980; + *pci_status_reg16 = pci_status16; + +skip6: + pci_status_reg = (UINT32 *) SATUISR_ADDR; + pci_status = *pci_status_reg; + + if ((pci_status & 0x0000069F) == 0) goto skip7; + + #ifdef DEBUG_PCI + if (pci_status & IB_MA_ERROR) printf("Internal Bus Master Abort - Secondary Bus - ATU\n"); + #endif + status = 1; + pci_status &= 0x0000069F; + *pci_status_reg = pci_status; +skip7: + break; + + default: return (ERROR); + } + + if (pci_config_error) /* check to see if the NMI handler during the config cycle */ + status = 1; + + pci_config_cycle = 0; /* turn on exception handling after pci config cycle */ + + if (old_abort_vec) + { + ((volatile unsigned *)0x20)[4] = old_abort_vec; + old_abort_vec = 0; + _flushICache(); + } + + if (status) return (ERROR); + else return (OK); +} + +extern void __ignore_abort(void); + +/************************************************************************** +* sys_config_setup - this function sets up a PCI configuration cycle +* +* This function sets up either the primary or secondary outbound configuration +* cycle address register. It is called by all the sys_*_config_* functions. +* +*/ +static int sys_config_setup(ULONG busno, ULONG devno, ULONG funcno, ULONG regno, UINT32 **pci_occ_addr, + UINT32 **pci_occ_data) +{ + + /* First check the parameters for sanity */ + if ((busno > 255) || (devno > 31) || (funcno> 7) || (regno > 63)) return (ERROR); + + if (busno == primary_busno) + { + *pci_occ_addr = (UINT32 *) POCCAR_ADDR; + *pci_occ_data = (UINT32 *) POCCDR_ADDR; + } + else if (busno == secondary_busno) + { + *pci_occ_addr = (UINT32 *) SOCCAR_ADDR; + *pci_occ_data = (UINT32 *) SOCCDR_ADDR; + } + else if (busno <= bus0_lastbus) + { + *pci_occ_addr = (UINT32 *) POCCAR_ADDR; + *pci_occ_data = (UINT32 *) POCCDR_ADDR; + } + else if (busno <= bus1_lastbus) + { + *pci_occ_addr = (UINT32 *) SOCCAR_ADDR; + *pci_occ_data = (UINT32 *) SOCCDR_ADDR; + } + else return (ERROR); + + (void)pci_cycle_cleanup(busno); /* start with clean slate */ + + pci_config_cycle = 1; /* turn off exception handling during pci config cycle */ + + if (old_abort_vec) { + printf("recursive config setup\n"); + while (1); + } + + old_abort_vec = ((volatile unsigned *)0x20)[4]; + ((volatile unsigned *)0x20)[4] = (unsigned)__ignore_abort; + _flushICache(); + + pci_config_error = FALSE; + + /* turn off error messages which could be generated by non-existant devices */ + PRINT_OFF(); + + if ((busno == PRIMARY_BUS_NUM) || (busno == SECONDARY_BUS_NUM)) + { + /* set up the config access register for type 0 config cycles */ + **pci_occ_addr = + ( + (1 << ((devno & 0x1f) + 16)) | + ((funcno & 0x07) << 8) | + ((regno & 0x3f) << 2) | + (0) ); + } + else + { + /* set up the config access register for type 1 config cycles */ + **pci_occ_addr = + ( + ((busno & 0xff) << 16) | + ((devno & 0x1f) << 11) | + ((funcno& 0x07) << 8) | + ((regno & 0x3f) << 2) | + (1) ); + } + + return (OK); +} + +/************************************************************************** +* sys_read_config_byte - this function performs a PCI configuration cycle +* and returns a byte. +* +* This function will read a byte from config space on the PCI bus. It is +* a user service intended to be called through the calls interface. +*/ +ULONG sys_read_config_byte (UINT32 busno, UINT32 devno, UINT32 funcno, UINT32 offset, UINT8 *data) +{ + UINT32 *pci_occ_data; + UINT32 regno; + UINT32 *pci_occ_addr; + + /* initialize here to keep compiler happy */ + pci_occ_addr = (UINT32 *) POCCAR_ADDR; + pci_occ_data = (UINT32 *) POCCDR_ADDR; + + /* Register numbers are DWORD indexes */ + regno = offset / 0x4; + + /* Set up the cycle. */ + if (sys_config_setup (busno, devno, funcno, regno, &pci_occ_addr, &pci_occ_data) != OK) + return (ERROR); + + /* Now do the read */ + *data = (UINT8)(((*pci_occ_data) >> ((offset % 0x4) * 8)) & 0xff); + + if (pci_cycle_cleanup (busno) == OK) + { + PRINT_ON(); + return (OK); + } + else + { + PRINT_ON(); + return (ERROR); + } +} + +/************************************************************************** +* sys_read_config_word - this function performs a PCI configuration cycle +* and returns a 16-bit word. +* +* This function will read a word from config space on the PCI bus. It is +* a user service intended to be called through the calls interface. +*/ +ULONG sys_read_config_word (UINT32 busno, UINT32 devno, UINT32 funcno, UINT32 offset, UINT16 *data) +{ + UINT32 *pci_occ_data; + UINT32 regno; + UINT32 *pci_occ_addr; + + /* initialize here to keep compiler happy */ + pci_occ_addr = (UINT32 *) POCCAR_ADDR; + pci_occ_data = (UINT32 *) POCCDR_ADDR; + + /* Offsets must be word-aligned */ + if (offset % 0x2) return (ERROR); + + /* Register numbers are DWORD indexes */ + regno = offset / 0x4; + + /* Set up the cycle. */ + if (sys_config_setup (busno, devno, funcno, regno, &pci_occ_addr, &pci_occ_data) != OK) return (ERROR); + + /* Now do the read */ + *data = (UINT16)(((*pci_occ_data) >> ((offset % 0x4) * 8)) & 0xffff); + + if (pci_cycle_cleanup(busno) == OK) + { + PRINT_ON(); + return (OK); + } + else + { + PRINT_ON(); + return (ERROR); + } +} + +/************************************************************************** +* sys_read_config_dword - this function performs a PCI configuration cycle +* and returns a 32-bit word. +* +* This function will read a dword from config space on the PCI bus. It is +* a user service intended to be called through the calls interface. +*/ +ULONG sys_read_config_dword ( + UINT32 busno, + UINT32 devno, + UINT32 funcno, + UINT32 offset, + UINT32 *data + ) +{ + UINT32 *pci_occ_data; + UINT32 regno; + UINT32 *pci_occ_addr; + + /* initialize here to keep compiler happy */ + pci_occ_addr = (UINT32 *) POCCAR_ADDR; + pci_occ_data = (UINT32 *) POCCDR_ADDR; + + /* Offsets must be dword-aligned */ + if (offset % 0x4) return (ERROR); + + /* Register numbers are DWORD indexes */ + regno = offset / 0x4; + + /* Set up the cycle. */ + if (sys_config_setup (busno, devno, funcno, regno, &pci_occ_addr, &pci_occ_data) != OK) + return (ERROR); + + /* Now do the read */ + *data = *pci_occ_data; + + if (pci_cycle_cleanup (busno) == OK) + { + PRINT_ON(); + return (OK); + } + else + { + PRINT_ON(); + return (ERROR); + } +} + +/************************************************************************** +* sys_write_config_byte - this function performs a PCI configuration cycle +* and writes a byte. +* +* This function will write a byte to config space on the PCI bus. It is +* a user service intended to be called through the calls interface. +*/ +ULONG sys_write_config_byte ( + UINT32 busno, + UINT32 devno, + UINT32 funcno, + UINT32 offset, + UINT8 *data + ) +{ + UINT32 *pci_occ_data; + UINT32 regno, temp; + UINT32 *pci_occ_addr; + UINT32 data_mask; + + /* initialize here to keep compiler happy */ + pci_occ_addr = (UINT32 *) POCCAR_ADDR; + pci_occ_data = (UINT32 *) POCCDR_ADDR; + + /* Register numbers are DWORD indexes */ + regno = offset / 0x4; + + /* build mask for byte of interest */ + data_mask = ~(0x000000ff << ((offset % 0x4) * 8)); + + /* Set up the cycle. */ + if (sys_config_setup (busno, devno, funcno, regno, &pci_occ_addr, &pci_occ_data) != OK) + return (ERROR); + + /* set up 32-bit word, clear old data, OR in new data */ + temp = (UINT32)(((UINT32) *data) << ((offset % 0x4) * 8)); + *pci_occ_data &= data_mask; + *pci_occ_data |= temp; + + if (pci_cycle_cleanup (busno) == OK) + { + PRINT_ON(); + return (OK); + } + else + { + PRINT_ON(); + return (ERROR); + } +} + +/************************************************************************** +* sys_write_config_word - this function performs a PCI configuration cycle +* and writes a 16-bit word. +* +* This function will write a word to config space on the PCI bus. It is +* a user service intended to be called through the calls interface. +*/ +ULONG sys_write_config_word ( + UINT32 busno, + UINT32 devno, + UINT32 funcno, + UINT32 offset, + UINT16 *data + ) +{ + UINT32 *pci_occ_data; + UINT32 regno, temp; + UINT32 *pci_occ_addr; + UINT32 data_mask; + + /* initialize here to keep compiler happy */ + pci_occ_addr = (UINT32 *) POCCAR_ADDR; + pci_occ_data = (UINT32 *) POCCDR_ADDR; + + /* Offsets must be word-aligned */ + if (offset % 0x2) return (ERROR); + + /* Register numbers are DWORD indexes */ + regno = offset / 0x4; + + /* build mask for word of interest */ + data_mask= ~(0x0000ffff << ((offset % 0x4) * 8)); + + /* Set up the cycle. */ + if (sys_config_setup (busno, devno, funcno, regno, &pci_occ_addr, &pci_occ_data) != OK) + return (ERROR); + + /* set up 32-bit word */ + temp = (UINT32)(((UINT32) *data) << ((offset % 0x4) * 8)); + *pci_occ_data &= data_mask; + *pci_occ_data |= temp; + + if (pci_cycle_cleanup (busno) == OK) + { + PRINT_ON(); + return (OK); + } + else + { + PRINT_ON(); + return (ERROR); + } +} + +/************************************************************************** +* sys_write_config_dword - this function performs a PCI configuration cycle +* and writes a 32-bit word. +* +* This function will write a dword to config space on the PCI bus. It is +* a user service intended to be called through the calls interface. +*/ +ULONG sys_write_config_dword ( + UINT32 busno, + UINT32 devno, + UINT32 funcno, + UINT32 offset, + UINT32 *data + ) +{ + UINT32 *pci_occ_data; + UINT32 regno; + UINT32 *pci_occ_addr; + + /* initialize here to keep compiler happy */ + pci_occ_addr = (UINT32 *) POCCAR_ADDR; + pci_occ_data = (UINT32 *) POCCDR_ADDR; + + /* Offsets must be dword-aligned */ + if (offset % 0x4) return (ERROR); + + /* Register numbers are DWORD indexes */ + regno = offset / 0x4; + + /* Set up the cycle. */ + if (sys_config_setup (busno, devno, funcno, regno, &pci_occ_addr, &pci_occ_data) != OK) + return (ERROR); + + /* Now do the write */ + *pci_occ_data = *data; + + if (pci_cycle_cleanup (busno) == OK) + { + PRINT_ON(); + return (OK); + } + else + { + PRINT_ON(); + return (ERROR); + } +} + +/****************************************************************************** +* sys_find_pci_device - find a PCI device based on Vendor ID and Device ID +* +* This function returns the location of PCI devices that have a specific +* Device ID and Vendor ID. Given a Vendor ID, Device ID, and an Index, the +* function returns the Bus Number, Device Number, and Function Number of the +* Nth Device/Function whose Vendor ID and Device ID match the input parameters. +* +* Calling software can find all devices having the same Vendor ID and Device ID +* by making successive calls to this function starting with the index set to 0, +* and incrementing the index until the function returns DEVICE_NOT_FOUND. A +* return value of BAD_VENDOR_ID indicates that the Vendor ID value passed had +* a value of all 1's. +* +*/ +STATUS sys_find_pci_device (int vendor_id, int device_id, int index, PCI_DEVICE_LOCATION *devloc) +{ + int found; + int multifunction = FALSE; + USHORT vendid, devid; + ULONG bus, device, function; + UCHAR header_type; + + if (vendor_id == 0xffff) return (BAD_VENDOR_ID); + + found = 0; + + for (bus = 0; bus <= lastbus; bus++) + { + for (device = 0; device < MAX_DEVICE_NUMBER; device++) + { + for (function = 0; function < MAX_FUNCTION_NUMBER; function++) + { + + /* before we go beyond function 0, make sure that the + device is truly a multi-function device, otherwise we may + get aliasing */ + if (function == 0) + { + sys_read_config_byte (bus,device,function,HEADER_TYPE_OFFSET,&header_type); + if (!(header_type & MULTIFUNCTION_DEVICE)) + multifunction = FALSE; + else multifunction = TRUE; + } + + + /* If no device there, go on to next device */ + if ((sys_read_config_word (bus,device,function,VENDOR_ID_OFFSET,&vendid)== ERROR) || + (sys_read_config_word (bus,device,function,DEVICE_ID_OFFSET,&devid)== ERROR)) + { + break; /* go on to next device */ + } + + /* If not a match */ + if ((devid != device_id) || (vendid != vendor_id)) + { + if (multifunction == FALSE) break; /* go on to next device */ + else continue; /* go on to next function */ + } + + /* If we've gotten this far we've found a match */ + + /* check to see if we need to look for another occurrance */ + if (index-- != 0) + { + if (multifunction == FALSE) break; /* go on to next device */ + else continue; /* go on to next function */ + } + + /* found the correct occurrance (index) */ + else + { + devloc->bus_number = bus; + devloc->device_number = device; + devloc->function_number = function; + return (OK); + } + } /* function */ + } /* device */ + } /* bus */ + + /* If we haven't returned by this point, no match was found */ + return (DEVICE_NOT_FOUND); +} + +/****************************************************************************** +* sys_find_pci_class_code - find a PCI device based on a specific Class Code +* +* This function returns the location of PCI devices that have a specific +* Class Code. Given a Class Code and an Index, the function returns the Bus +* Number, Device Number, and Function Number of the Nth Device/Function whose +* Class Code matches the input parameters. +* +* Calling software can find all devices having the same Class Code +* by making successive calls to this function starting with the index set to 0, +* and incrementing the index until the function returns DEVICE_NOT_FOUND. +* +*/ +STATUS sys_find_pci_class_code ( + int class_code, + int index, + PCI_DEVICE_LOCATION *devloc + ) +{ + USHORT vendid; + ULONG bus, device, function; + UCHAR dev_class, header_type; + int multifunction = FALSE; + + for (bus = 0; bus <= lastbus; bus++) + { + for (device = 0; device <= MAX_DEVICE_NUMBER; device++) + { + + for (function = 0; function < MAX_FUNCTION_NUMBER; function++) + { + + /* before we go beyond function 0, make sure that the + device is truly a multi-function device, otherwise we may + get aliasing */ + if (function == 0) + { + sys_read_config_byte (bus,device,function,HEADER_TYPE_OFFSET,&header_type); + if (!(header_type & MULTIFUNCTION_DEVICE)) multifunction = FALSE; + else multifunction = TRUE; + } + + /* If no device there, go on to next device */ + if ((sys_read_config_word (bus,device,function,VENDOR_ID_OFFSET,&vendid)== ERROR) || + (sys_read_config_byte (bus,device,function,BASE_CLASS_OFFSET,&dev_class)== ERROR)) + { + break; /* go on to next device */ + } + + /* If not a match */ + if (dev_class != class_code) + { + if (multifunction == FALSE) break; /* go on to next device */ + else continue; /* go on to next function */ + } + + /* If we've gotten this far we've found a match */ + + /* check to see if we need to look for another occurrance */ + if (index-- != 0) + { + if (multifunction == FALSE) break; /* go on to next device */ + else continue; /* go on to next function */ + } + + /* found the correct occurrance (index) */ + else + { + devloc->bus_number = bus; + devloc->device_number = device; + devloc->function_number = function; + return (OK); + } + } + } + } + /* If we haven't returned by this point, no match was found */ + return (DEVICE_NOT_FOUND); +} + +/****************************************************************************** +* sys_pci_bios_present - determine if a PCI BIOS is present +* +* This function allows the caller to determine whether the PCI BIOS interface +* function set is present, and what the current interface version level is. +* It also provides information about what hardware mechanism is used for +* accessing configuration space and whether or not the hardware supports +* generation of PCI Special Cycles. +* +*/ +STATUS sys_pci_bios_present (PCI_BIOS_INFO *info) +{ + /* 0x00 indicates PCI BIOS functions present */ + info->present_status = 0x00; + + /* Config types 0 or 1, no special cycle mechanisms */ + info->hardware_mech_config = CONFIG_MECHANISM_1 | CONFIG_MECHANISM_2; + info->hardware_mech_special = 0x00; + + info->if_level_major_ver = 0x02; + info->if_level_minor_ver = 0x01; + + info->last_pci_bus = lastbus; + + return (OK); +} + + +/****************************************************************************** +* sys_generate_special_cycle - generate a PCI Special Cycle +* +* This function allows for generation of PCI Special Cycles. The generated +* special cycle will be broadcast on a specific PCI Bus in the system. +* +* PCI Special Cycles are not supported by Cyclone Hardware. +* +*/ +STATUS sys_generate_special_cycle (int bus_number, int special_cycle_data) +{ + return (FUNC_NOT_SUPPORTED); +} + +/****************************************************************************** +* sys_get_irq_routing_options - get the PCI interrupt routing options +* +* The PCI Interrupt routing fabric on the Cyclone Hardware is not +* reconfigurable (fixed mapping relationships). +* +*/ +STATUS sys_get_irq_routing_options (PCI_IRQ_ROUTING_TABLE *table) +{ + return (FUNC_NOT_SUPPORTED); +} + +/****************************************************************************** +* sys_set_pci_irq - connect a PCI interrupt to a processor IRQ. +* +* The PCI Interrupt routing fabric on the Cyclone Hardware is not +* reconfigurable (fixed mapping relationships) and therefore, this function +* is not supported. +* +*/ +STATUS sys_set_pci_irq ( + int int_pin, + int irq_num, + int bus_dev + ) +{ + return (FUNC_NOT_SUPPORTED); +} + +/****************************************************************************** +* +* print_config_space - print contents of config space +* +* This function prints out the contents of the PCI configuration space for +* the selected PCI device. The local RN functions are accessible using bus= -1 +* and function=0 for the Bridge and bus = -1 function=1 for the ATU. +* +*/ +void print_config_space (int busno, int devno, int function) +{ + ULONG offset; + UINT32 long_data; + UINT16 short_data; + UINT8 byte_data; + register PCI_CONFIG_SPACE *cptr = 0; + USHORT vendor_id = 0xffff; + USHORT device_id = 0xffff; + USHORT subvendor_id = 0xffff; + USHORT subdevice_id = 0xffff; + int header_type; + + if ((busno > (int)lastbus) || (busno < -1)) + { + printf("Invalid bus number = %d\n", busno); + return; + } + + if (devno < -1) + { + printf("Invalid device number = %d\n", devno); + return; + } + + if ((busno == -1) && (devno == -1) && (function == 0)) /* local Bridge device */ + { + cptr = (PCI_CONFIG_SPACE *) VIDR_ADDR; + printf("\n\n\nReading Configuration Space for 80960RN PCI-PCI Bridge\n"); + } + else if ((busno == -1) && (devno == -1) && (function == 1)) /* local ATU device */ + { + cptr = (PCI_CONFIG_SPACE *) ATUVID_ADDR; + printf("\n\n\nReading Configuration Space for 80960RN ATU\n"); + } + + if ((busno == -1) && (devno == -1) && (function == 0)) + { + /* this is the bridge function */ + printf("-----------------------------------------------------------------\n\n"); + printf("Vendor ID = 0x%04X ",cptr->pci1_config.vendor_id); + printf("Device ID = 0x%04X\n",cptr->pci1_config.device_id); + printf("Command Register = 0x%04X ",cptr->pci1_config.command); + printf("Status Register = 0x%04X\n",cptr->pci1_config.status); + printf("Revision ID = 0x%02X ",cptr->pci1_config.revision_id); + printf("Programming Interface = 0x%02X\n",cptr->pci1_config.prog_if); + printf("Sub Class = 0x%02X ",cptr->pci1_config.sub_class); + printf("Base Class = 0x%02X\n",cptr->pci1_config.base_class); + printf("Cache Line Size = 0x%02X ",cptr->pci1_config.cache_line_size); + printf("Latency Timer = 0x%02X\n",cptr->pci1_config.latency_timer); + printf("Header Type = 0x%02X ",cptr->pci1_config.header_type); + printf("BIST = 0x%02X\n",cptr->pci1_config.bist); + printf("Primary Bus Number = 0x%02X ",cptr->pci1_config.primary_busno); + printf("Secondary Bus Number = 0x%02X\n",cptr->pci1_config.secondary_busno); + printf("Sub Bus Number = 0x%02X ",cptr->pci1_config.subordinate_busno); + printf("Secondary Latency = 0x%02X\n",cptr->pci1_config.secondary_latency_timer); + printf("Secondary I/O Base = 0x%02X ",cptr->pci1_config.io_base); + printf("Secondary I/O Limit = 0x%02X\n",cptr->pci1_config.io_limit); + printf("Secondary Status = 0x%04X ",cptr->pci1_config.secondary_status); + printf("Secondary Memory Base = 0x%04X\n",cptr->pci1_config.mem_base); + printf("Secondary Mem Limit = 0x%04X ",cptr->pci1_config.mem_limit); + printf("Prefetch Memory Base = 0x%04X\n",cptr->pci1_config.pfmem_base); + printf("Prefetch Memory Limit = 0x%04X ",cptr->pci1_config.pfmem_limit); + printf("I/O Base (Upper) = 0x%04X\n",cptr->pci1_config.iobase_upper16); + printf("I/O Limit (Upper) = 0x%04X ",cptr->pci1_config.iolimit_upper16); + printf("Subsystem Vendor ID = 0x%04X\n",cptr->pci1_config.sub_vendor_id); + printf("Subsystem ID = 0x%04X ",cptr->pci1_config.sub_device_id); + printf("Interrupt Line = 0x%02X\n",cptr->pci1_config.int_line); + printf("Interrupt Pin = 0x%02X ",cptr->pci1_config.int_pin); + printf("Bridge Control = 0x%04X\n",cptr->pci1_config.bridge_control); + printf("PCI Range 0 Base = 0x%08X\n",cptr->pci1_config.pcibase_addr0); + printf("PCI Range 1 Base = 0x%08X\n",cptr->pci1_config.pcibase_addr1); + printf("Prefetch Base (Upper) = 0x%08X\n",cptr->pci1_config.pfbase_upper32); + printf("Prefetch Limit(Upper) = 0x%08X\n",cptr->pci1_config.pflimit_upper32); + printf("Expansion ROM Base = 0x%08X\n",cptr->pci1_config.pcibase_exp_rom); + } + else if ((busno == -1) && (devno == -1) && (function == 1)) + { + /* this is the ATU function */ + printf("------------------------------------------------------------------\n\n"); + printf("Vendor ID = 0x%04X ",cptr->pci0_config.vendor_id); + printf("Device ID = 0x%04X\n",cptr->pci0_config.device_id); + printf("Command Register = 0x%04X ",cptr->pci0_config.command); + printf("Status Register = 0x%04X\n",cptr->pci0_config.status); + printf("Revision ID = 0x%02X ",cptr->pci0_config.revision_id); + printf("Programming Interface = 0x%02X\n",cptr->pci0_config.prog_if); + printf("Sub Class = 0x%02X ",cptr->pci0_config.sub_class); + printf("Base Class = 0x%02X\n",cptr->pci0_config.base_class); + printf("Cache Line Size = 0x%02X ",cptr->pci0_config.cache_line_size); + printf("Latency Timer = 0x%02X\n",cptr->pci0_config.latency_timer); + printf("Header Type = 0x%02X ",cptr->pci0_config.header_type); + printf("BIST = 0x%02X\n",cptr->pci0_config.bist); + printf("Interrupt Line = 0x%02X ",cptr->pci0_config.int_line); + printf("Interrupt Pin = 0x%02X\n",cptr->pci0_config.int_pin); + printf("Minimum Grant = 0x%02X ",cptr->pci0_config.min_gnt); + printf("Maximum Latency = 0x%02X\n",cptr->pci0_config.max_lat); + printf("Subsystem Vendor ID = 0x%04X ",cptr->pci0_config.sub_vendor_id); + printf("Subsystem ID = 0x%04X\n",cptr->pci0_config.sub_device_id); + printf("Base Address 0 = 0x%08X\n",cptr->pci0_config.pcibase_addr0); + printf("Base Address 1 = 0x%08X\n",cptr->pci0_config.pcibase_addr1); + printf("Base Address 2 = 0x%08X\n",cptr->pci0_config.pcibase_addr2); + printf("Base Address 3 = 0x%08X\n",cptr->pci0_config.pcibase_addr3); + printf("Base Address 4 = 0x%08X\n",cptr->pci0_config.pcibase_addr4); + printf("Base Address 5 = 0x%08X\n",cptr->pci0_config.pcibase_addr5); + printf("Cardbus CIS Pointer = 0x%08X\n",cptr->pci0_config.cardbus_cis_ptr); + printf("Expansion ROM Base = 0x%08X\n",cptr->pci0_config.pcibase_exp_rom); + + } + + else /* device on PCI bus */ + { + printf("\n\n\nReading Configuration Space for PCI Bus 0x%02X, Device 0x%02X, Function 0x%02X\n", + busno, devno, function); + printf("------------------------------------------------------------------------\n\n"); + + /* get Vendor Id */ + offset = VENDOR_ID_OFFSET; + if (sys_read_config_word (busno,devno,function,offset,&short_data) + == ERROR) + { + printf("Error reading Vendor Id\n"); + return; + } + if (short_data == 0xffff) /* non-existant device */ + { + printf("No such device.\n"); + return; + } + printf("Vendor ID = 0x%04X ",short_data); + vendor_id = short_data; + + /* get Device Id */ + offset = DEVICE_ID_OFFSET; + if (sys_read_config_word (busno,devno,function,offset,&short_data) + == ERROR) + { + printf("Error reading Device Id\n"); + return; + } + printf("Device ID = 0x%04X\n",short_data); + device_id = short_data; + + /* get Command Register */ + offset = COMMAND_OFFSET; + if (sys_read_config_word (busno,devno,function,offset,&short_data) + == ERROR) + { + printf("Error reading Command Register\n"); + return; + } + printf("Command Register = 0x%04X ",short_data); + + /* get Status Register */ + offset = STATUS_OFFSET; + if (sys_read_config_word (busno,devno,function,offset,&short_data) + == ERROR) + { + printf("Error reading Status Register\n"); + return; + } + printf("Status Register = 0x%04X\n",short_data); + + /* get Revision Id */ + offset = REVISION_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading Revision Id\n"); + return; + } + printf("Revision ID = 0x%02X ",byte_data); + + /* get Programming Interface */ + offset = PROG_IF_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading Programming Interface\n"); + return; + } + printf("Programming Interface = 0x%02X\n",byte_data); + + /* get Sub Class */ + offset = SUB_CLASS_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading Sub Class\n"); + return; + } + printf("Sub Class = 0x%02X ",byte_data); + + /* get Base Class */ + offset = BASE_CLASS_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading Base Class\n"); + return; + } + printf("Base Class = 0x%02X\n",byte_data); + + /* get Cache Line Size */ + offset = CACHE_LINE_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading Cache Line Size\n"); + return; + } + printf("Cache Line Size = 0x%02X ",byte_data); + + /* get Latency Timer */ + offset = LATENCY_TIMER_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading Latency Timer\n"); + return; + } + printf("Latency Timer = 0x%02X\n",byte_data); + + /* get Header Type */ + offset = HEADER_TYPE_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading Header Type\n"); + return; + } + printf("Header Type = 0x%02X ",byte_data); + header_type = (((int)byte_data) & 0x7f); /* strip multifunction bit */ + + /* get BIST */ + offset = BIST_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading BIST\n"); + return; + } + printf("BIST = 0x%02X\n",byte_data); + + /* get Interrupt Line info */ + offset = INT_LINE_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading Interrupt Line\n"); + return; + } + printf("Interrupt Line = 0x%02X ",byte_data); + + /* get Interrupt Pin info */ + offset = INT_PIN_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading Interrupt Pin\n"); + return; + } + printf("Interrupt Pin = 0x%02X\n",byte_data); + + /* get Capabilities Pointer info */ + offset = CAP_PTR_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading Capabilities Pointer register\n"); + return; + } + printf("Capabilities Pointer = 0x%02X\n",byte_data); + + if (header_type == 0) /* type 0 header-specific info */ + { + /* get Min Gnt info */ + offset = MIN_GNT_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading Minimum Grant\n"); + return; + } + printf("Minimum Grant = 0x%02X ",byte_data); + + /* get Max Lat info */ + offset = MAX_LAT_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading Maximum Latency\n"); + return; + } + printf("Maximum Latency = 0x%02X\n",byte_data); + + /* get subsystem vendor ID */ + offset = SUB_VENDOR_ID_OFFSET; + if (sys_read_config_word (busno,devno,function,offset,&short_data) + == ERROR) + { + printf("Error reading Subsystem Vendor ID\n"); + return; + } + printf("Subsystem Vendor ID = 0x%04X ",short_data); + subvendor_id = short_data; + + /* get subsystem device ID */ + offset = SUB_DEVICE_ID_OFFSET; + if (sys_read_config_word (busno,devno,function,offset,&short_data) + == ERROR) + { + printf("Error reading Subsystem Device ID\n"); + return; + } + printf("Subsystem Device ID = 0x%04X\n",short_data); + subdevice_id = short_data; + + /* get Region 0 Base Address */ + offset = REGION0_BASE_OFFSET; + if (sys_read_config_dword (busno,devno,function,offset,&long_data) + == ERROR) + { + printf("Error reading Region 0 Base\n"); + return; + } + printf("PCI Region 0 Base = 0x%08X\n",long_data); + + /* get Region 1 Base Address */ + offset = REGION1_BASE_OFFSET; + if (sys_read_config_dword (busno,devno,function,offset,&long_data) + == ERROR) + { + printf("Error reading Region 1 Base\n"); + return; + } + printf("PCI Region 1 Base = 0x%08X\n",long_data); + + /* get Region 2 Base Address */ + offset = REGION2_BASE_OFFSET; + if (sys_read_config_dword (busno,devno,function,offset,&long_data) + == ERROR) + { + printf("Error reading Region 2 Base\n"); + return; + } + printf("PCI Region 2 Base = 0x%08X\n",long_data); + + /* get Region 3 Base Address */ + offset = REGION3_BASE_OFFSET; + if (sys_read_config_dword (busno,devno,function,offset,&long_data) + == ERROR) + { + printf("Error reading Region 3 Base\n"); + return; + } + printf("PCI Region 3 Base = 0x%08X\n",long_data); + + /* get Region 4 Base Address */ + offset = REGION4_BASE_OFFSET; + if (sys_read_config_dword (busno,devno,function,offset,&long_data) + == ERROR) + { + printf("Error reading Region 4 Base\n"); + return; + } + printf("PCI Region 4 Base = 0x%08X\n",long_data); + + /* get Region 5 Base Address */ + offset = REGION5_BASE_OFFSET; + if (sys_read_config_dword (busno,devno,function,offset,&long_data) + == ERROR) + { + printf("Error reading Region 5 Base\n"); + return; + } + printf("PCI Region 5 Base = 0x%08X\n",long_data); + + /* get Expansion ROM Base Address */ + offset = EXP_ROM_OFFSET; + if (sys_read_config_dword (busno,devno,function,offset,&long_data) + == ERROR) + { + printf("Error reading Expansion ROM Base\n"); + return; + } + printf("Expansion ROM Base = 0x%08X\n",long_data); + + /* get Cardbus CIS pointer */ + offset = CARDBUS_CISPTR_OFFSET; + if (sys_read_config_dword (busno,devno,function,offset,&long_data) + == ERROR) + { + printf("Error reading Cardbus CIS Pointer\n"); + return; + } + printf("Cardbus CIS Pointer = 0x%08X\n",long_data); + } /* end type 0 header */ + + else /* type 1 header_specific info */ + { + /* get Bridge Control */ + offset = BRIDGE_CTRL_OFFSET; + if (sys_read_config_word (busno,devno,function,offset,&short_data) + == ERROR) + { + printf("Error reading Bridge Control Register\n"); + return; + } + printf("Bridge Control Reg = 0x%04X ",short_data); + + /* get Secondary Status */ + offset = SECONDARY_STAT_OFFSET; + if (sys_read_config_word (busno,devno,function,offset,&short_data) + == ERROR) + { + printf("Error reading Secondary Status Register\n"); + return; + } + printf("Secondary Status Reg = 0x%04X\n",short_data); + + /* get Primary Bus Number */ + offset = PRIMARY_BUSNO_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading Primary Bus Number\n"); + return; + } + printf("Primary Bus No. = 0x%02X ",byte_data); + + /* get Secondary Bus Number */ + offset = SECONDARY_BUSNO_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading Secondary Bus Number\n"); + return; + } + printf("Secondary Bus No. = 0x%02X\n",byte_data); + + /* get Subordinate Bus Number */ + offset = SUBORD_BUSNO_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading Subordinate Bus Number\n"); + return; + } + printf("Subordinate Bus No. = 0x%02X ",byte_data); + + /* get Secondary Latency Timer */ + offset = SECONDARY_LAT_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading Secondary Latency Timer\n"); + return; + } + printf("Secondary Latency Tmr = 0x%02X\n",byte_data); + + /* get IO Base */ + offset = IO_BASE_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading IO Base\n"); + return; + } + printf("IO Base = 0x%02X ",byte_data); + + /* get IO Limit */ + offset = IO_LIMIT_OFFSET; + if (sys_read_config_byte (busno,devno,function,offset,&byte_data) + == ERROR) + { + printf("Error reading IO Limit\n"); + return; + } + printf("IO Limit = 0x%02X\n",byte_data); + + /* get Memory Base */ + offset = MEMORY_BASE_OFFSET; + if (sys_read_config_word (busno,devno,function,offset,&short_data) + == ERROR) + { + printf("Error reading Memory Base\n"); + return; + } + printf("Memory Base = 0x%04X ",short_data); + + /* get Memory Limit */ + offset = MEMORY_LIMIT_OFFSET; + if (sys_read_config_word (busno,devno,function,offset,&short_data) + == ERROR) + { + printf("Error reading Memory Limit\n"); + return; + } + printf("Memory Limit = 0x%04X\n",short_data); + + /* get Prefetchable Memory Base */ + offset = PREF_MEM_BASE_OFFSET; + if (sys_read_config_word (busno,devno,function,offset,&short_data) + == ERROR) + { + printf("Error reading Prefetchable Memory Base\n"); + return; + } + printf("Pref. Memory Base = 0x%04X ",short_data); + + /* get Prefetchable Memory Limit */ + offset = PREF_MEM_LIMIT_OFFSET; + if (sys_read_config_word (busno,devno,function,offset,&short_data) + == ERROR) + { + printf("Error reading Prefetchable Memory Limit\n"); + return; + } + printf("Pref. Memory Limit = 0x%04X\n",short_data); + + /* get IO Base Upper 16 Bits */ + offset = IO_BASE_UPPER_OFFSET; + if (sys_read_config_word (busno,devno,function,offset,&short_data) + == ERROR) + { + printf("Error reading IO Base Upper 16 Bits\n"); + return; + } + printf("IO Base Upper 16 Bits = 0x%04X ",short_data); + + /* get IO Limit Upper 16 Bits */ + offset = IO_LIMIT_UPPER_OFFSET; + if (sys_read_config_word (busno,devno,function,offset,&short_data) + == ERROR) + { + printf("Error reading IO Limit Upper 16 Bits\n"); + return; + } + printf("IO Limit Upper 16 Bits= 0x%04X\n",short_data); + + /* get Prefetchable Base Upper 32 Bits */ + offset = PREF_BASE_UPPER_OFFSET; + if (sys_read_config_dword (busno,devno,function,offset,&long_data) + == ERROR) + { + printf("Error reading Prefetchable Base Upper 32 Bits\n"); + return; + } + printf("Pref. Base Up. 32 Bits= 0x%08X\n",long_data); + + /* get Prefetchable Limit Upper 32 Bits */ + offset = PREF_LIMIT_UPPER_OFFSET; + if (sys_read_config_dword (busno,devno,function,offset,&long_data) + == ERROR) + { + printf("Error reading Prefetchable Limit Upper 32 Bits\n"); + return; + } + printf("Pref. Lmt. Up. 32 Bits= 0x%08X\n",long_data); + + + /* get Region 0 Base Address */ + offset = REGION0_BASE_OFFSET; + if (sys_read_config_dword (busno,devno,function,offset,&long_data) + == ERROR) + { + printf("Error reading Region 0 Base\n"); + return; + } + printf("PCI Region 0 Base = 0x%08X\n",long_data); + + /* get Region 1 Base Address */ + offset = REGION1_BASE_OFFSET; + if (sys_read_config_dword (busno,devno,function,offset,&long_data) + == ERROR) + { + printf("Error reading Region 1 Base\n"); + return; + } + printf("PCI Region 1 Base = 0x%08X\n",long_data); + + /* get Expansion ROM Base Address */ + offset = TYPE1_EXP_ROM_OFFSET; + if (sys_read_config_dword (busno,devno,function,offset,&long_data) + == ERROR) + { + printf("Error reading Expansion ROM Base\n"); + return; + } + printf("Expansion ROM Base = 0x%08X\n",long_data); + + } /* end type 1 header */ + + } +} + +/* check if host of backplane */ +int isHost() +{ + if (*BACKPLANE_DET_REG & BP_HOST_BIT) + return TRUE; + else + return FALSE; +} + + + + +/***************************************************************************** +* sys_pci_device_initialization - initialize PCI I/O devices +* +* This function is responsible for initializing all PCI I/O devices for proper +* PCI operation. All I/O devices are mapped into appropriate locations in the +* PCI address space (based on size and alignment requirements). This function +* must ensure that no bus conflicts exist. This function is also responsible +* for initializing cache line size, latency timer, DEVSEL# timing, and parity +* error response. This function fills out the data structure which is passed +* in to it. This function will return SUCCESSFUL if at least one I/O +* controller can be successfully configured. This function will return ERROR +* if no I/O controllers can be initialized. +* +*/ +void sys_pci_device_initialization (PCI_DATA* pci_data) +{ + + volatile int i; + + bus0_lastbus = PRIMARY_BUS_NUM; /* last bus number behind bus 0 (primary bus ) */ + bus1_lastbus = SECONDARY_BUS_NUM; /* last bus number behind bus 1 (secondary bus) */ + + pci_data->num_devices = 0; /* total number of devices configured */ + pci_data->num_functions = 0; /* total number of functions configured */ + + init_312_pci(); /* initialize the ATU, MU and bridge on the 80312 */ + + if (isHost()) + { + /* If the IQ80310 board is connected to the backplane it has to initialize the Primary PCI bus */ + + /* set PCI base addresses for primary bus */ + + memspace_ptr[PRIMARY_BUS_NUM] = PRIMARY_MEM_BASE; + memspace_limit[PRIMARY_BUS_NUM] = PRIMARY_MEM_LIMIT; + + iospace_ptr[PRIMARY_BUS_NUM] = PRIMARY_IO_BASE; + iospace_limit[PRIMARY_BUS_NUM] = PRIMARY_IO_LIMIT; + + PRINT_OFF(); + + /* Initialize Primary PCI bus */ + sys_pci_bus_init (PRIMARY_BUS_NUM, PRIMARY_BUS_NUM, pci_data); + } + + /* Initialization of the Secondary PCI bus */ + + /* set PCI base addresses for secondary bus */ + + memspace_ptr[SECONDARY_BUS_NUM] = SECONDARY_MEM_BASE; + memspace_limit[SECONDARY_BUS_NUM] = SECONDARY_MEM_LIMIT; + + iospace_ptr[SECONDARY_BUS_NUM] = SECONDARY_IO_BASE; + iospace_limit[SECONDARY_BUS_NUM] = SECONDARY_IO_LIMIT; + + PRINT_OFF(); + + /* Initialize Secondary PCI bus */ + sys_pci_bus_init (SECONDARY_BUS_NUM, SECONDARY_BUS_NUM, pci_data); + + + /* Set absolute last secondary bus */ + if (bus0_lastbus > bus1_lastbus) + lastbus = bus0_lastbus; + else + lastbus = bus1_lastbus; + + PRINT_OFF(); + + /* before exiting, configure and enable FIQ and IRQ interrupts */ + + _enableFiqIrq(); /* enable FIQ and IRQ interrupts in CP13 */ + + config_ints(); /* configure interrupts */ + + /* wait a while to clear out any unwanted NMI interrupts */ + for (i = 0; i < 100000; i++) + ; + + PRINT_ON(); + + /* enable ECC single bit correction and multi-bit reporting + - initialization code only enables correction */ + *(volatile unsigned long *)ECCR_ADDR = 0x6; +} + + +/***************************************************************************** +* sys_pci_bus_init - initialize PCI I/O devices +* +* This function is responsible for initializing all PCI I/O devices for proper +* PCI operation. All I/O devices are mapped into appropriate locations in the +* PCI address space (based on size and alignment requirements). This function +* must ensure that no bus conflicts exist. This function is also responsible +* for initializing cache line size, latency timer, DEVSEL# timing, and parity +* error response. This function fills out the data structure which is passed +* in to it. This function will return SUCCESSFUL if at least one I/O +* controller can be successfully configured. This function will return ERROR +* if no I/O controllers can be initialized. +*/ +static void sys_pci_bus_init(UINT bus, UINT root_bus, PCI_DATA* pci_data) +{ + UINT device, function; + USHORT vendor, device_id; + UINT regno; + ULONG regvalue; + USHORT regshort; + UCHAR regchar; + UCHAR intpin, intline; + UINT line; + UCHAR header_type; + ULONG rom_enabled; + UINT base_addr_reg_start; + UINT base_addr_reg_end; + UINT exp_rom_baseaddr; + int multifunction; + +/* bridge initialization variables */ + ULONG class_code; + UINT secondary_bus_number; + UCHAR iospace_type; + UCHAR data_byte; + USHORT data_word; + ULONG membase, iobase; + ULONG memlimit, iolimit; + int no_memory, no_io; + +#ifdef DEBUG_PCI + printf ("Configuring PCI Bus %d.\n", bus); + printf ("PCI Root Bus %d.\n", root_bus); + PRINT_OFF(); +#endif + +for (device = 0; device <= MAX_DEVICE_NUMBER; device++) +{ +#ifdef DEBUG_PCI + printf ("\nConfiguring device %d.\n\n", device); +#endif + + /* assume non-multifunction device at start */ + multifunction = FALSE; + + for (function = 0; function < MAX_FUNCTION_NUMBER; function ++) + { + +#ifdef DEBUG_PCI + printf ("Configuring function %d.\n", function); +#endif + /* To determine whether a device is installed in a particular slot, */ + /* we attempt to read the vendor ID from that slot. If there's */ + /* nothing there, the bridge should return 0xffff (and signal a */ + /* master abort). Otherwise, there is something there and we need */ + /* to configure it. */ + if ((sys_read_config_word(bus, device, function, VENDOR_ID_OFFSET, &vendor) == ERROR) || (vendor == 0xffff)) + { + /* This means no device found */ +#ifdef DEBUG_PCI + printf ("\nNo device.\n"); +#endif + break; /* Go on to the next device */ + } + + /* We'll only get here if we got a real device/function */ + + /* Count the number of devices */ + if (function == 0) (pci_data->num_devices)++; + + /* Count the number of functions */ + (pci_data->num_functions)++; + +#ifdef DEBUG_PCI + printf ("Vendor: %x\n", vendor); +#endif + + /* Read the Device ID */ + sys_read_config_word (bus,device,function,DEVICE_ID_OFFSET,&device_id); + +#ifdef DEBUG_PCI + printf("\n"); + printf("Configuring PCI Bus : %d\n", bus); + printf(" PCI Device: %d\n", device); + printf(" Vendor Id : 0x%08X\n", vendor); + printf(" Device Id : 0x%08X\n", device_id); +#endif + + /* Read the Configuration Header Type to determine configuration */ + if (sys_read_config_byte (bus,device,function,HEADER_TYPE_OFFSET,&header_type)== ERROR) continue; + + /* determine if multifunction device */ + if ((header_type & MULTIFUNCTION_DEVICE) && (function == 0)) + { +#ifdef DEBUG_PCI + printf ("Multifunction Device Found...\n"); +#endif + multifunction = TRUE; + } + + /* strip off multifunction device indicator bit */ + header_type &= 0x7f; + + switch (header_type) + { + case STANDARD_HEADER: + base_addr_reg_start = 0x10; /* Base Address Reg. Start Offset */ + base_addr_reg_end = 0x24; /* Base Address Reg. End Offset */ + exp_rom_baseaddr = 0x30; /* Expansion ROM Base Addr. Reg Offset */ + break; + + case PCITOPCI_HEADER: + base_addr_reg_start = 0x10; /* Base Address Reg. Start Offset */ + base_addr_reg_end = 0x14; /* Base Address Reg. End Offset */ + exp_rom_baseaddr = 0x38; /* Expansion ROM Base Addr. Reg Offset */ + break; + + default: + printf ("Header Type Not Supported, 0x%02X\n", header_type); + continue; /* skip over device */ + break; + } + + /* We cycle through the base registers, first writing out all */ + /* ones to the register, then reading it back to determine the */ + /* requested size in either I/O or memory space. Then we */ + /* align the top of memory or i/o space pointer, write it to */ + /* the register, and increment it. I say we so you won't feel */ + /* excluded. */ + for (regno = base_addr_reg_start; regno <= base_addr_reg_end; regno += 4) + { + + /* Write out all 1's to the base register, then read it back */ + regvalue = 0xffffffff; + sys_write_config_dword(bus,device,function,regno,(UINT32*)®value); + sys_read_config_dword (bus,device,function,regno,(UINT32*)®value); + + /* Some number of the lower bits of regvalue will be clear */ + /* indicating a don't care position. The more clear bits, */ + /* the larger the requested mapping space. */ + + if (regvalue == 0) /* ...this reg not used. */ + ; + + /*---------------------------------------------------------*/ + /* I/O space mapping */ + /*---------------------------------------------------------*/ + else if ((regvalue & 3) == 1) /* ...this is I/O space */ + { + ULONG requested_size; + + /* Align iospace_ptr for the requested size. All bit */ + /* positions clear in regvalue must be clear in */ + /* iospace_ptr. */ + requested_size = ~(regvalue & 0xfffffffe); + +#ifdef DEBUG_PCI + printf ("Configuration for I/O space...\n"); + printf ("Size request: %x; ", requested_size); + printf ("IOspace_ptr: %x\n", iospace_ptr[root_bus]); +#endif + + /* check to make sure that there is enought iospace left to grant */ + if ((iospace_ptr[root_bus] + requested_size) > iospace_limit[root_bus]) + { + printf ("\nPCI Configuration ERROR: Out of I/O Space on Bus %d!\n", bus); + printf (" No I/O Space Allocated to Device %d, Function %d.\n", device, function); + return; + } + + /* Align the space pointer if necessary */ + if (iospace_ptr[root_bus] & requested_size) + { + iospace_ptr[root_bus] &= ~requested_size; + iospace_ptr[root_bus] += requested_size + 1; + } +#ifdef DEBUG_PCI + printf("Adjusted I/O Space Ptr: %x\n", iospace_ptr[root_bus]); + printf(" I/O Space Size : 0x%08X\n", requested_size); + printf(" I/O Space Base : 0x%08X\n", iospace_ptr[root_bus]); +#endif /* Write out the adjusted iospace pointer. */ + + sys_write_config_dword (bus,device,function,regno,(UINT32*)&iospace_ptr[root_bus]); + + /* Update space pointer */ + iospace_ptr[root_bus] += requested_size + 1; + } + + /*---------------------------------------------------------*/ + /* Memory space mapping */ + /*---------------------------------------------------------*/ + else if ((regvalue & 1) == 0) /* ...this is memory space */ + { + ULONG requested_size; + + /* Type is encoded in bits 1 and 2 */ + /* 64 bit space (10) is an error for the moment, as is */ + /* the reserved value, 11. */ + if (regvalue & 0x4) + { + printf ("Type error in base register.\n"); + break; + } + + /* Align memspace_ptr for the requested size. All bit */ + /* positions clear in regvalue must be clear in */ + /* memspace_ptr. */ + requested_size = ~(regvalue & 0xfffffff0); + +#ifdef DEBUG_PCI + printf ("Configuration for memory space.\n"); + printf ("Size request: %x; ", requested_size); + printf ("Membase_ptr: %x\n", memspace_ptr[root_bus]); +#endif + + + /* check to make sure that there is enough memspace left to grant */ + if ((memspace_ptr[root_bus] + requested_size) > memspace_limit[root_bus]) + { + printf ("\nPCI Configuration ERROR: Out of Memory Space on Bus %d!\n", bus); + printf (" No Memory Space Allocated to Device %d, Function %d.\n", device, function); + printf ("Root Bus = %d, Memory Ptr = 0x%08X, Requested Size = 0x%08X, Memory Limit = 0x%08X\n", + root_bus, memspace_ptr[root_bus], requested_size, memspace_limit[root_bus]); + + return; + } + + if (memspace_ptr[root_bus] & requested_size) + { + memspace_ptr[root_bus] &= ~requested_size; + memspace_ptr[root_bus] += requested_size + 1; + } + +#ifdef DEBUG_PCI + printf ("Adjusted Membase_ptr: %x\n", memspace_ptr[root_bus]); + printf(" Memory Space Size : 0x%08X\n", requested_size); + printf(" Memory Space Base : 0x%08X\n", memspace_ptr[root_bus]); +#endif + /* Write out the adjusted memory pointer */ + sys_write_config_dword (bus,device,function,regno,(UINT32*)&memspace_ptr[root_bus]); + memspace_ptr[root_bus] += requested_size + 1; + } + } + + /*-------------------------------------------------------------*/ + /* Expansion ROM mapping */ + /* The expansion ROM is handled in the same way as the other */ + /* PCI base registers. If the lowest bit in this register is */ + /* set, memory-mapped accesses are not possible, since the ROM */ + /* is active. (Only one decoder). */ + /*-------------------------------------------------------------*/ + + /* Store the state of the ROM enabled bit so we can restore it */ + sys_read_config_dword (bus,device,function,exp_rom_baseaddr,(UINT32*)®value); + rom_enabled = regvalue & 1; + + /* Write out all 1's to the non-reserved bits of the base register, then read it back */ + regvalue = 0xffffffff; + sys_write_config_dword(bus,device,function,EXP_ROM_OFFSET,(UINT32*)®value); + sys_read_config_dword (bus,device,function,EXP_ROM_OFFSET,(UINT32*)®value); + + /* Some number of the lower bits of regvalue will be clear */ + /* indicating a don't care position. The more clear bits, */ + /* the larger the requested mapping space. */ + + if ((regvalue & 0xffff800) != 0) /* No mapping if it's 0 */ + { + ULONG requested_size; + +#ifdef DEBUG_PCI + printf ("Expansion ROM detected.\n"); +#endif + + /* Expansion ROMs will map into memory space, so... */ + /* Align memspace_ptr for the requested size. All bit */ + /* positions clear in regvalue must be clear in */ + /* memspace_ptr. */ + requested_size = ~(regvalue & 0xfffff800); + +#ifdef DEBUG_PCI + printf ("Size request: %x; ", requested_size); + printf ("Membase_ptr: %x\n", memspace_ptr[root_bus]); +#endif + + /* check to make sure that there is enought memspace left to grant */ + if ((memspace_ptr[root_bus] + requested_size) > memspace_limit[root_bus]) + { + printf ("\nPCI Configuration ERROR: Out of Memory Space on Bus %d!\n", bus); + printf (" No Expansion ROM Space Allocated to Device %d, Function %d.\n", device, function); + return; + } + + if (memspace_ptr[root_bus] & requested_size) + { + memspace_ptr[root_bus] &= ~requested_size; + memspace_ptr[root_bus] += requested_size + 1; + } + +#ifdef DEBUG_PCI + printf("Adjusted Membase_ptr: %x\n", memspace_ptr[root_bus]); + printf(" Exp. ROM Space Size : 0x%08X\n", requested_size); + printf(" Exp. ROM Space Base : 0x%08X\n", memspace_ptr[root_bus]); +#endif + /* Write out the adjusted memory pointer */ + regvalue = memspace_ptr[root_bus] | rom_enabled; + sys_write_config_dword (bus,device,function,EXP_ROM_OFFSET,(UINT32*)®value); + memspace_ptr[root_bus] += requested_size + 1; + + } /* End of expansion ROM mapping. */ + + /* No expansion ROM to map so disable expansion ROM address decodes */ + else /* If no ROM space, clear the decode bit */ + { + regvalue = 0; + sys_write_config_dword (bus,device,function,EXP_ROM_OFFSET,(UINT32*)®value); + } + + + /*-------------------------------------------------------------*/ + /* Miscellaneous settings */ + /*-------------------------------------------------------------*/ + + /* Read interrupt pin, write interrupt line according to PCI spec */ + sys_read_config_byte (bus,device,function,INT_PIN_OFFSET,&intpin); + pci_to_xint(device, intpin, (int*)&line); + intline = line; + sys_write_config_byte (bus,device,function,INT_LINE_OFFSET,&intline); + + /* Set Latency value to relatively and arbitrary small number */ + regchar = LATENCY_VALUE; + sys_write_config_byte (bus,device,function,LATENCY_TIMER_OFFSET,®char); + + if (header_type != PCITOPCI_HEADER) + { + /* Set the master enable bit, and enable I/O and Mem spaces */ + /* in the device Command Register only for non-bridge devices */ + sys_read_config_word (bus,device,function,COMMAND_OFFSET,®short); + + regshort |= PCI_CMD_IOSPACE | PCI_CMD_MEMSPACE | PCI_CMD_BUS_MASTER; + sys_write_config_word(bus,device,function,COMMAND_OFFSET,®short); + + } + + /****** Bridge Configuration *******/ + + /* To determine whether an installed device is a PCI-to-PCI Bridge + device, read the Base Class and the Sub Class from the device's + Configuration header. If the Base Class = 0x06 and the + Sub Class = 0x04, the device is a PCI-to-PCI Bridge and requires + additional initialization including the initialization of its + Secondary PCI bus. */ + + if (sys_read_config_dword (bus,device,function,REVISION_OFFSET,(UINT32*)&class_code) != ERROR) + { + /* Parse the class code into Base Class and Sub Class */ + if ((((class_code >> 16) & 0x0000ffff) == 0x0604) && + (header_type == PCITOPCI_HEADER)) + { + + #ifdef DEBUG_PCI + printf ("PCI-to-PCI Bridge Device.\n"); + printf ("Hit a Key to Continue...\n"); + hexIn(); + #endif + + if (root_bus == 0) /* root bus = primary bus */ + { + + if (bus0_lastbus == 0) + bus0_lastbus = 2; + else + bus0_lastbus = bus0_lastbus + 1; + + /* assign new PCI bus number */ + secondary_bus_number = bus0_lastbus; + } + + else /* root bus = secondary bus */ + { + if (bus1_lastbus == 1) + { + if (bus0_lastbus != 0) + bus1_lastbus = bus0_lastbus + 1; + else + bus1_lastbus = 2; + } + else + bus1_lastbus = bus1_lastbus + 1; + + /* assign new PCI bus number */ + secondary_bus_number = bus1_lastbus; + } + + + + #ifdef DEBUG_PCI + printf ("Secondary Bus Number = %d.\n",secondary_bus_number); + #endif + + /* set up the bus numbers in the bridge's config. space */ + + /* Primary Bus Number */ + data_byte = (UCHAR)root_bus; + sys_write_config_byte (bus,device,function,PRIMARY_BUSNO_OFFSET,&data_byte); + + /* Secondary Bus Number */ + data_byte = (UCHAR)secondary_bus_number; + sys_write_config_byte (bus,device,function,SECONDARY_BUSNO_OFFSET,&data_byte); + + /* Set Subordinate Bus Number to a maximum so that config cycles + will be passed on to devices located on subordinate buses */ + data_byte = (UCHAR)MAX_SUB_BUSNO; + sys_write_config_byte (bus,device,function,SUBORD_BUSNO_OFFSET,&data_byte); + + #ifdef DEBUG_PCI + sys_read_config_byte (bus,device,function,PRIMARY_BUSNO_OFFSET,&data_byte); + printf ("Primary Bus = %d\n", data_byte); + sys_read_config_byte (bus,device,function,SECONDARY_BUSNO_OFFSET,&data_byte); + printf ("Secondary Bus = %d\n", data_byte); + sys_read_config_byte (bus,device,function,SUBORD_BUSNO_OFFSET,&data_byte); + printf ("Subordinate Bus = %d\n", data_byte); + #endif + + /* To figure out the PCI Memory space and PCI I/O space + windows on the bridge, read the memory and I/O space + information before the secondary bus is configured + and then read it afterwards to determine the window + size for each PCI region + + For secondary busses, the Memory space window of the + PCI-to-PCI bridge must start and end on a 1 Mbyte boundary + + For secondary busses, the I/O space window of the + PCI-to-PCI bridge must start and end on a 4 Kbyte boundary + */ + + /* round up start of PCI memory space to a 1 Mbyte start address */ + if (memspace_ptr[root_bus] & 0xfffff) + { + memspace_ptr[root_bus] &= ~(0xfffff); + memspace_ptr[root_bus] += 0x100000; + } + + /* round up start of PCI I/O space to a 4 Kbyte start address */ + if (iospace_ptr[root_bus] & 0xfff) + { + iospace_ptr[root_bus] &= ~(0xfff); + iospace_ptr[root_bus] += 0x1000; + } + + membase = memspace_ptr[root_bus]; + iobase = iospace_ptr[root_bus]; + + #ifdef DEBUG_PCI + printf ("*** About to do a recursive call ***\n"); + printf ("Hit a Key to Continue...\n"); + hexIn(); + #endif + + /* initialize the subordinate PCI bus */ + sys_pci_bus_init (secondary_bus_number, root_bus, pci_data); + + #ifdef DEBUG_PCI + printf ("Returned from previous recursive call.\n"); + #endif + + /* Upon return, set the correct Subordinate Bus Number */ + if (root_bus == 0) + data_byte = (UCHAR) bus0_lastbus; + else + data_byte = (UCHAR) bus1_lastbus; + + #ifdef DEBUG_PCI + printf ("Subordinate Bus Number Now = %d\n", (int)data_byte); + printf ("Hit a Key to Continue...\n"); + hexIn(); + #endif + sys_write_config_byte (bus,device,function,SUBORD_BUSNO_OFFSET,&data_byte); + + /* round up end of PCI memory space to a 1 Mbyte start address */ + if (memspace_ptr[root_bus] & 0xfffff) + { + memspace_ptr[root_bus] &= ~(0xfffff); + memspace_ptr[root_bus] += 0x100000; + } + + /* round up end of PCI I/O space to a 4 Kbyte start address */ + if (iospace_ptr[root_bus] & 0xfff) + { + iospace_ptr[root_bus] &= ~(0xfff); + iospace_ptr[root_bus] += 0x1000; + } + + memlimit = memspace_ptr[root_bus] - 1; + iolimit = iospace_ptr[root_bus] - 1; + + /* Assume bridge has memory request unless told otherwise */ + no_memory = FALSE; + no_io = FALSE; + + /* if there is no requested memory range, set the membase and + memlimit values to zero and set the no_memory range flag */ + if (membase == (memspace_ptr[root_bus])) + { + membase = 0; + memlimit = 0; + no_memory = TRUE; + } + + /* if there is no requested IO range, set the iobase and + iolimit values to zero and set the no_io range flag */ + if (iobase == (iospace_ptr[root_bus])) + { + iobase = 0; + iolimit = 0; + no_io = TRUE; + } + + /* Determine if the Bridge supports 16 or 32 bit I/O space decodes */ + sys_read_config_byte (bus,device,function,IO_BASE_OFFSET,&iospace_type); + + /* 16 Bit I/O space for ISA compatibility + - fill in only the IO Base and IO Limit registers */ + if (((iospace_type & 0x0f) == 0x00) && + (!(iolimit & 0xffff0000))) + { + #ifdef DEBUG_PCI + printf ("Bridge supports 16 Bit I/O Space\n"); + #endif + /* I/O Base Register */ + data_byte = (UCHAR)((iobase & 0x0000f000) >> 8); + sys_write_config_byte (bus,device,function,IO_BASE_OFFSET,&data_byte); + #ifdef DEBUG_PCI + printf ("I/O Base Register = 0x%02X\n", data_byte); + #endif + + /* I/O Limit Register */ + data_byte = (UCHAR)((iolimit & 0x0000f000) >> 8); + sys_write_config_byte (bus,device,function,IO_LIMIT_OFFSET,&data_byte); + #ifdef DEBUG_PCI + printf ("I/O Limit Register = 0x%02X\n", data_byte); + #endif + } + + /* 32 Bit I/O space + - fill in the IO Base and IO Limit registers + - fill in the IO Base Upper and IO Limit Upper registers */ + else if ((iospace_type & 0x0f) == 0x01) + { + #ifdef DEBUG_PCI + printf ("Bridge supports 32 Bit I/O Space\n"); + #endif + + /* I/O Base Register */ + data_byte = (UCHAR)((iobase & 0x0000f000) >> 8); + sys_write_config_byte (bus,device,function,IO_BASE_OFFSET,&data_byte); + #ifdef DEBUG_PCI + printf ("I/O Base Register = 0x%02X\n", data_byte); + #endif + + /* I/O Limit Register */ + data_byte = (UCHAR)((iolimit & 0x0000f000) >> 8); + sys_write_config_byte (bus,device,function,IO_LIMIT_OFFSET,&data_byte); + #ifdef DEBUG_PCI + printf ("I/O Limit Register = 0x%02X\n", data_byte); + #endif + + /* I/O Base Upper 16 Bits Register */ + data_word = (USHORT)((iobase & 0xffff0000) >> 16); + sys_write_config_word (bus,device,function,IO_BASE_UPPER_OFFSET,&data_word); + #ifdef DEBUG_PCI + printf ("I/O Base Upper 16 Bits Register = 0x%04X\n", data_word); + #endif + + /* I/O Limit Upper 16 Bits Register */ + data_word = (USHORT)((iolimit & 0xffff0000) >> 16); + sys_write_config_word (bus,device,function,IO_LIMIT_UPPER_OFFSET,&data_word); + #ifdef DEBUG_PCI + printf ("I/O Limit Upper 16 Bits Register = 0x%04X\n", data_word); + #endif + } + + /* Memory Base Register */ + data_word = (USHORT)((membase & 0xfff00000) >> 16); + sys_write_config_word (bus,device,function,MEMORY_BASE_OFFSET,&data_word); + #ifdef DEBUG_PCI + printf ("Memory Base Register = 0x%04X\n", data_word); + #endif + + /* Memory and Prefetchable Memory Limit Registers */ + data_word = (USHORT)((memlimit & 0xfff00000) >> 16); + sys_write_config_word (bus,device,function,MEMORY_LIMIT_OFFSET,&data_word); + sys_write_config_word (bus,device,function,PREF_MEM_LIMIT_OFFSET,&data_word); + #ifdef DEBUG_PCI + printf ("Memory Limit Register = 0x%04X\n", data_word); + #endif + + + /* Currently does not support prefetchable memory. + Set the prefetchable memory range to an unused value so that + a user can not make a prefetchable memory access */ + + /* Prefetchable Memory Base Register*/ + data_word = 0xffff; + sys_write_config_word (bus,device,function,PREF_MEM_BASE_OFFSET,&data_word); + #ifdef DEBUG_PCI + printf ("Prefetchable Memory Base Register = 0x%04X\n", data_word); + #endif + + + /* Prefetchable Memory Limit Register*/ + data_word = 0xffff; + sys_write_config_word (bus,device,function,PREF_MEM_LIMIT_OFFSET,&data_word); + #ifdef DEBUG_PCI + printf ("Prefetchable Memory Limit Register = 0x%04X\n", data_word); + #endif + + /* Set the secondary latency timer on the device. We use the value 0x0f,*/ + /* which is approximately what you might get if you used the */ + /* formula found in the NCR SCSI adapter documentation: */ + /* Latency Timer = 2 + (Burst size * (typical wait states + 1)) */ + regchar = LATENCY_VALUE; + sys_write_config_byte (bus,device,function,SECONDARY_LAT_OFFSET,®char); + + /* Reset the Command Register for PCI to PCI bridges */ + /* (bridges have different settings in command register) */ + sys_read_config_word (bus,device,function,COMMAND_OFFSET,®short); + regshort |= BRIDGE_MASTER_ENAB | BRIDGE_SERR_ENAB; + /* if memory space is requested, memory transactions should + be turned on */ + if (!no_memory) + regshort |= BRIDGE_MEMSPACE_ENAB; + /* if io space is requested, memory transactions should + be turned on */ + if (!no_io) + regshort |= BRIDGE_IOSPACE_ENAB; + sys_write_config_word(bus,device,function,COMMAND_OFFSET,®short); + + /* Set the Bridge Control Register */ + sys_read_config_word (bus,device,function,BRIDGE_CTRL_OFFSET,®short); + regshort |= BRIDGE_PARITY_ERR | BRIDGE_SEER_ENAB | BRIDGE_MASTER_ABORT; + sys_write_config_word(bus,device,function,BRIDGE_CTRL_OFFSET,®short); + + } + } + + #ifdef DEBUG_PCI + printf ("\nHit a Key to Continue...\n"); + hexIn(); + #endif + + /* if not a multifunction device, go on to next device */ + if (multifunction == FALSE) + break; + } /* End for (function...) */ +} /* End for (device...) */ + +#ifdef DEBUG_PCI + printf ("Leaving the init function for bus %d.\n", bus); + printf ("\nHit a Key to Continue...\n"); + hexIn(); +#endif + +return; +} + +/*************************************************************************** +* +* show_pci - print out Device/Vendor ID of all PCI devices in system +* +*/ +void show_pci(void) +{ +unsigned char header_type; +unsigned short vendor, device_id; +unsigned int bus, device, function; + + + printf (" Bus Device Function Vendor ID Device ID\n"); + printf ("----- ------ -------- --------- ---------\n"); + + for (bus = 0; bus < MAX_PCI_BUSES; bus++) + { + for (device = 0; device <= MAX_DEVICE_NUMBER; device++) + { + for (function = 0; function <= MAX_FUNCTION_NUMBER; function++) + { + if ((sys_read_config_word (bus, device, function, VENDOR_ID_OFFSET, &vendor) == ERROR) || (vendor == 0xffff)) + /* This means no device found */ + break; /* Go on to the next device */ + else + { + sys_read_config_word (bus, device, function, DEVICE_ID_OFFSET, &device_id); + printf (" 0x%02X 0x%02X 0x%02X",bus,device,function); + printf (" 0x%04X 0x%04X\n", vendor,device_id); + } + + /* before we go on to the next function, make sure that the + device is truly a multi-function device, otherwise we may + get aliasing */ + sys_read_config_byte (bus, device, function, HEADER_TYPE_OFFSET, &header_type); + + if (!(header_type & MULTIFUNCTION_DEVICE)) break; + + } /* End for (function) */ + } /* End for (device) */ + } /* End for (bus) */ +} + +extern unsigned hal_dram_size; + +/********************************************************************************* +* init_312_pci - Initialize the Primary and Secondary ATUs, Messaging Unit, and +* PCI-to-PCI bridge on the 80312 Companion chip +* +*/ +void init_312_pci(void) +{ + UINT32 *ATU_reg; + UINT32 *MU_reg; + UINT16 *ATU_reg_16; + UINT8 *ATU_reg_8; + UINT32 limit_reg; + UINT32 adj_dram_size; + UINT16 *BR_reg_16; + UINT8 *BR_reg_8; + + /********* vendor / device id **********/ + + /* set subsytem vendor ID */ + ATU_reg_16 = (UINT16 *) ASVIR_ADDR; + *ATU_reg_16 = 0x113C; + + /* set subsytem ID = 700 hex for PCI700 */ + ATU_reg_16 = (UINT16 *) ASIR_ADDR; + *ATU_reg_16 = 0x0700; + + + /******* Primary Inbound ATU *********/ + + /* set primary inbound ATU translate value register to point to base of local DRAM */ + ATU_reg = (UINT32 *) PIATVR_ADDR; + *ATU_reg = MEMBASE_DRAM & 0xFFFFFFFC; + + /* set primary inbound ATU limit register to include all of installed DRAM. + This value used as a mask. */ + ATU_reg = (UINT32 *) PIALR_ADDR; + adj_dram_size = hal_dram_size; + limit_reg = (0xFFFFFFFF-(adj_dram_size-1)) & 0xFFFFFFF0; + *ATU_reg = limit_reg; + + if (isHost() == TRUE) + { + /* set the primary inbound ATU base address to the start of DRAM */ + ATU_reg = (UINT32 *) PIABAR_ADDR; + *ATU_reg = MEMBASE_DRAM & 0xFFFFF000; + + /********* Set Primary Outbound Windows *********/ + + /* Note: The primary outbound ATU memory window value register + and i/o window value registers are defaulted to 0 */ + + /* set the primary outbound windows to directly map Local - PCI requests */ + /* outbound memory window */ + ATU_reg = (UINT32 *) POMWVR_ADDR; + *ATU_reg = PRIMARY_MEM_BASE; + + /* outbound DAC Window */ + ATU_reg = (UINT32 *) PODWVR_ADDR; + *ATU_reg = PRIMARY_DAC_BASE; + + /* outbound I/O window */ + ATU_reg = (UINT32 *) POIOWVR_ADDR; + *ATU_reg = PRIMARY_IO_BASE; + } + + /******** Secondary Inbound ATU ***********/ + + /* set secondary inbound ATU translate value register to point to base of local DRAM */ + ATU_reg = (UINT32 *) SIATVR_ADDR; + *ATU_reg = MEMBASE_DRAM & 0xFFFFFFFC; + + /* set secondary inbound ATU base address to start of DRAM */ + ATU_reg = (UINT32 *) SIABAR_ADDR; + *ATU_reg = MEMBASE_DRAM & 0xFFFFF000; + + /* set secondary inbound ATU limit register to include all of + installed DRAM. This value used as a mask. */ + + /* cyclone merge 1/21/97 */ + /* always allow secondary pci access to all memory (even with A0 step) */ + limit_reg = (0xFFFFFFFF - (adj_dram_size - 1)) & 0xFFFFFFF0; + ATU_reg = (UINT32 *) SIALR_ADDR; + *ATU_reg = limit_reg; + + + /********** Set Secondary Outbound Windows ***********/ + + /* Note: The secondary outbound ATU memory window value register + and i/o window value registers are defaulted to 0 */ + + /* set the secondary outbound window to directly map Local - PCI requests */ + /* outbound memory window */ + ATU_reg = (UINT32 *) SOMWVR_ADDR; + *ATU_reg = SECONDARY_MEM_BASE; + + /* outbound DAC Window */ + ATU_reg = (UINT32 *) SODWVR_ADDR; + *ATU_reg = SECONDARY_DAC_BASE; + + /* outbound I/O window */ + ATU_reg = (UINT32 *) SOIOWVR_ADDR; + *ATU_reg = SECONDARY_IO_BASE; + + /*********** command / config / latency registers ************/ + + if (isHost() == TRUE) + { + /* allow primary ATU to act as a bus master, respond to PCI + memory accesses, assert P_SERR#, and enable parity checking */ + ATU_reg_16 = (UINT16 *) PATUCMD_ADDR; + *ATU_reg_16 = (PCI_CMD_SERR_ENAB | PCI_CMD_PARITY | PCI_CMD_BUS_MASTER | PCI_CMD_MEMSPACE); + } + + /* allow secondary ATU to act as a bus master, respond to PCI memory accesses, and assert S_SERR# */ + ATU_reg_16 = (UINT16 *) SATUCMD_ADDR; + *ATU_reg_16 = (PCI_CMD_SERR_ENAB | PCI_CMD_PARITY | PCI_CMD_BUS_MASTER | PCI_CMD_MEMSPACE); + + /* enable primary and secondary outbound ATUs, BIST, and primary bus direct addressing */ + ATU_reg = (UINT32 *) ATUCR_ADDR; + *ATU_reg = 0x00000006; /* no direct addressing window - enable both ATUs */ + + + /************* bridge registers *******************/ + + if (isHost() == TRUE) + { + /* set the bridge command register */ + BR_reg_16 = (UINT16 *) PCR_ADDR; + *BR_reg_16 = (PCI_CMD_SERR_ENAB | PCI_CMD_PARITY | PCI_CMD_BUS_MASTER | PCI_CMD_MEMSPACE); + + /* set the secondary bus number to 1 */ + BR_reg_8 = (UINT8 *) SBNR_ADDR; + *BR_reg_8 = SECONDARY_BUS_NUM; + + /* set the bridge control register */ + BR_reg_16 = (UINT16 *) BCR_ADDR; + *BR_reg_16 = 0x0823; + + /* set the primary bus number to 0 */ + BR_reg_8 = (UINT8 *) PBNR_ADDR; + *BR_reg_8 = PRIMARY_BUS_NUM; + } + + /* suppress secondary bus idsels to provide */ + /* private secondary devices */ + BR_reg_16 = (UINT16 *) SISR_ADDR; + *BR_reg_16 = 0x03FF; +} + +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/test_menu.c @@ -0,0 +1,230 @@ +//============================================================================= +// +// test_menu.c - Cyclone Diagnostics +// +//============================================================================= +//####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) 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-25 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +/***************************************************************************** +* test_menu.c - Menu dispatching routine +* +* modification history +* -------------------- +* 30aug00 ejb Ported to IQ80310 Cygmon +*/ + +/* +DESCRIPTION: + +A table-driven menu dispatcher +*/ + +#include "test_menu.h" +#include "iq80310.h" + +#define QUIT -1 +#define MAX_INPUT_LINE_SIZE 80 + +extern long decIn(void); + +/* + * Internal routines + */ +static int menuGetChoice (MENU_ITEM menuTable[], + int numMenuItems, + char *title, + unsigned long options); +static void printMenu (MENU_ITEM menuTable[], + int numMenuItems, + char *title); + + +/*************************************************************************** +* +* menu - a table-driven menu dispatcher +* +* RETURNS: +* +* The menu item argument, or NULL if the item chosen is QUIT. +*/ +MENU_ARG menu ( + MENU_ITEM menuTable[], + int numMenuItems, + char *title, + unsigned long options + ) +{ +int item; /* User's menu item choice */ + + /* + * Get the user's first choice. Always display the menu the first time. + */ + item = menuGetChoice (menuTable, numMenuItems, title, MENU_OPT_NONE); + if (item == QUIT) + return (NULL); + + /* + * If the user just wants a value returned, return the argument. If the + * argument is null, return the item number itself. + */ + if (options & MENU_OPT_VALUE) + { + if (menuTable[item].arg == NULL) + return ((void *)item); + else + return (menuTable[item].arg); + } + + /* + * Process menu items until the user selects QUIT + */ + while (TRUE) + { + /* + * Call the action routine for the chosen item. If the argument is + * NULL, pass the item number itself. + */ + if (menuTable[item].actionRoutine != NULL) + { + if (menuTable[item].arg == NULL) + { + printf("\n"); + (*menuTable[item].actionRoutine) ((void *)item); + } + else + { + printf("\n"); + (*menuTable[item].actionRoutine) (menuTable[item].arg); + } + } + + /* + * Get the next choice, using any display options the user specified. + */ + item = menuGetChoice (menuTable, numMenuItems, title, options); + if (item == QUIT) + return (NULL); + } + +} /* end menu () */ + + +/*************************************************************************** +* +* menuGetChoice - Get the user's menu choice. +* +* If display is not suppressed, display the menu, then prompt the user for +* a choice. If the choice is out of range or invalid, display the menu and +* prompt again. Continue to display and prompt until a valid choice is made. +* +* RETURNS: +* The item number of the user's menu choice. (-1 if they chose QUIT) +*/ + +static int +menuGetChoice ( + MENU_ITEM menuTable[], + int numMenuItems, + char *title, + unsigned long options + ) +{ +/*char inputLine[MAX_INPUT_LINE_SIZE];*/ + +int choice; + + /* + * Suppress display of the menu the first time if we're asked + */ + if (!(options & MENU_OPT_SUPPRESS_DISP)) + printMenu (menuTable, numMenuItems, title); + + /* + * Prompt for a selection. Redisplay the menu and prompt again + * if there's an error in the selection. + */ + choice = -1; + + while (choice < 0 || choice > numMenuItems) + { + + printf ("\nEnter the menu item number (0 to quit): "); + + choice = decIn (); + + if (choice < 0 || choice > numMenuItems) + + printMenu (menuTable, numMenuItems, title); + + } + + if (choice == 0) + + return (QUIT); + + return (choice - 1); + +} /* end menuGetChoice () */ + + +/*************************************************************************** +* +* printMenu - Print the menu +* +* +*/ + +static void +printMenu ( + MENU_ITEM menuTable[], + int numMenuItems, + char *title + ) +{ + int i; + + + printf("\n%s\n\n", title); + + for (i = 0; i < numMenuItems; i++) + { + printf ("%2d - %s\n", i+1, menuTable[i].itemName); + } + + printf(" 0 - quit"); + +} /* end printMenu () */
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/test_menu.h @@ -0,0 +1,135 @@ +//============================================================================= +// +// test_menu.h - Cyclone Diagnostics +// +//============================================================================= +//####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) 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-25 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +/***************************************************************************** +* test_menu.h - Menu dispatching header +* +* modification history +* -------------------- +* 30aug00 ejb Ported from MPC8240 Breeze to StrongARM2 Cygmon +*/ +/* +DESCRIPTION + +Include file for the table-driven menu module menu.c. This module displays +a menu of numbered items, prompts the user for a choice, then calls an action +routine associated with the choice. It then redisplays the menu and prompts +for another choice. A choice of zero (0) exits the menu routine. + +To use this menu module, construct a table of type MENU_ITEM, with one entry +for each menu item. An entry consists of a string to print out with the +menu, an action routine, and an argument for the action routine. There is +no need to have an "exit" or "quit" item, since the menu routine handles +that by assigning at the zero (0) item number. For example, a simple menu +of tests would be constructed this way: + + IMPORT VOID doTestA (); + IMPORT VOID doTestB (); + + #define TESTA_ARG 0 + #define TESTB_ARG 1 + + LOCAL MENU_ITEM testMenu[] = + { + {"Test A", doTestA, (MENU_ARG)TESTA_ARG}, + {"Test B", doTestB, (MENU_ARG)TESTB_ARG}, + }; + + #define NUM_ITEMS NELEMENTS(testMenu) + #define MENU_TITLE "Test Menu" + +Then, in the test top level routine, call the routine menu(), declared as: + + STATUS menu (menuTable, numMenuItems, title, options) + MENU_ITEM menuTable[]; + int numMenuItems; + char *title; + ULONG options; + +For example: + + status = menu (testMenu, NUM_ITEMS, MENU_TITLE, MENU_OPT_NONE); + +*/ + +/* + * The following types define an entry in the menu table. Each entry describes + * one menu item, including a string to describe that item, an action + * routine to call when that item is chosen, and an argument to pass when the + * action routine is called. + */ +typedef void (*MENU_RTN) (); +typedef volatile void *MENU_ARG; +typedef struct menuItem +{ + char *itemName; /* string to print with the menu */ + MENU_RTN actionRoutine; /* routine to call when item is chosen */ + MENU_ARG arg; /* argument to actionRoutine */ +} MENU_ITEM; + + +/* + * Menu options + * + * These options control the display of the menu. + * + * MENU_OPT_NONE - The normal behavior. The menu is always displayed before + * prompting the user for a choice. + * + * MENU_OPT_SUPPRESS_DISP - The menu is displayed before prompting the user + * for a choice except after executing a previously valid choice. This option + * is useful for large menus consisting of simple commands that produce only + * a line or two of output. In this case, after the user executes a valid + * choice, the redisplay of a large menu may cause output to scroll off the + * screen. The menu is redisplayed if the user enters an invalid choice. + */ +#define MENU_OPT_NONE 0x00 +#define MENU_OPT_SUPPRESS_DISP 0x01 +#define MENU_OPT_VALUE 0x02 + + + + +MENU_ARG menu (MENU_ITEM menuTable[], + int numMenuItems, + char *title, + unsigned long options); +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/diag/xscale_test.c @@ -0,0 +1,1801 @@ +//============================================================================= +// +// xscale_test.c - Cyclone Diagnostics +// +//============================================================================= +//####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) 2001 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden +// Contributors: +// Date: 2001-01-25 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +/************************************************************************/ +/* iq80310_test.c - Main diagnostics for IQ80310 board */ +/* */ +/* Modification History */ +/* -------------------- */ +/* 11oct00, ejb, Created for IQ80310 StrongARM2 */ +/* 18dec00 jwf */ +/* 02feb01 jwf for snc */ +/************************************************************************/ + + +#include "7_segment_displays.h" +#include "test_menu.h" +#include "iq80310.h" +#include "pci_bios.h" + +extern void read_int_status(); +extern void _disableDCache(); +extern void _enableDCache(); +extern void _enableFiqIrq(); +extern void _usec_delay(); +extern void _msec_delay(); +extern void _enable_timer(); +extern void _disable_timer(); +extern long _read_timer(); +extern long _read_cpsr(); + +/* 02/02/01 jwf */ +extern void _coy_tight_loop(); + +extern long decIn(void); +extern long hexIn(void); +extern void hex32out(unsigned long num); +extern char* sgets(char *s); + +extern void flash_test(void) RAM_FUNC_SECT; + +extern STATUS pci_isr_connect (int intline, int bus, int device, int (*handler)(int), int arg); +extern STATUS pci_to_xint(int device, int intpin, int *xint); +extern void timer_test (void); +extern int memTest (long startAddr, long endAddr); + +/* 02/02/01 jwf */ +extern int LoopMemTest (long startAddr, long endAddr); + +extern void uart_test(void); +extern void pci_ether_test (UINT32 busno, UINT32 devno, UINT32 funcno); +extern void config_ints(void); /* configure interrupts */ +extern void sys_pci_device_initialization (PCI_DATA* pci_data); +extern STATUS sys_find_pci_device (int vendor_id, int device_id, int index, PCI_DEVICE_LOCATION *devloc); +extern int eeprom_write (unsigned long pci_base, int eeprom_addr, unsigned short *p_data, int nwords); +extern ULONG sys_read_config_dword (UINT32 busno,UINT32 devno,UINT32 funcno,UINT32 offset,UINT32 *data); +extern int enable_external_interrupt (int int_id); +extern int disable_external_interrupt (int int_id); +extern int isr_connect(int int_num, void (*handler)(int), int arg); +extern int isr_disconnect(int int_num); +extern void init_external_timer(); +extern void uninit_external_timer(); +extern int isHost(); + +void pci_int_test (void); +void hdwr_diag (void); +void rotary_switch (void); +void seven_segment_display (void); +void backplane_detection(void); +void battery_status(void); +/* void timer_test (void); */ +void ether_test (void); +void gpio_test (void); + +/* 02/02/01 jwf */ +void cache_loop (void); + +static void battery_test_menu (void); +static void battery_test_write (void); +static void battery_test_read (void); + +/* 01/11/01 jwf */ +void select_host_test_system (void); + +void internal_timer(void); +static void enet_setup (void); +static void memory_tests (void); +static void repeat_mem_test (void); + +/* 02/02/01 jwf */ +static void special_mem_test (void); + +static void spci_tests (void), ppci_tests (void); +STATUS Device_Seek( + int verbose, + unsigned long adapter_vendor, + unsigned long adapter_device_id, + unsigned long dev_index, + PCI_DEVICE_LOCATION *dev_info + ); + +#define VENDOR_INTEL 0x8086 +#define INTEL_NAME "Intel Corporation Inc." + +#define I80303_BRIDGE 0x0309 +#define I80303_NAME0 "80303 PCI-PCI Bridge" + +#define I80303_ATU 0x5309 +#define I80303_NAME1 "80303 Address Translation Unit" + +#define I82557 0x1229 +#define I82557_NAME "82557/82558/82559 10/100 LAN Controller" + +#define I82559ER 0x1209 +#define I82559ER_NAME "82559ER 10/100 LAN Controller" + + +/* Test Menu Table */ +static MENU_ITEM testMenu[] = +{ + {"Memory Tests", memory_tests, 0}, + {"Repeating Memory Tests", repeat_mem_test, 0}, + {"16C552 DUART Serial Port Tests", uart_test, 0}, + {"Rotary Switch S1 Test", rotary_switch, 0}, + {"7 Segment LED Tests", seven_segment_display,0}, + {"Backplane Detection Test", backplane_detection, 0}, + {"Battery Status Test", battery_status, 0}, + {"External Timer Test", timer_test, 0}, + {"Flash Test", flash_test, 0}, + {"i82559 Ethernet Configuration", enet_setup, 0}, + {"i82559 Ethernet Test", ether_test, 0}, + {"i960Rx/303 PCI Interrupt Test", pci_int_test, 0}, + {"Internal Timer Test", internal_timer, 0}, + {"Secondary PCI Bus Test", spci_tests, 0}, + {"Primary PCI Bus Test", ppci_tests, 0}, + {"Battery Backup SDRAM Memory Test", battery_test_menu, 0}, + {"GPIO Test", gpio_test, 0}, +/* 02/02/01 jwf */ + {"Repeat-On-Fail Memory Test", special_mem_test, 0}, + {"Coyonosa Cache Loop (No return)", cache_loop, 0} +}; + +#define NUM_MENU_ITEMS (sizeof (testMenu) / sizeof (testMenu[0])) + +#define MENU_TITLE "\n IQ80310 Hardware Tests" + + +PCI_DATA pci_devices = {0, 0}; +extern void __reset(void); + +void hdwr_diag (void) +{ +unsigned char* led0 = (unsigned char*)MSB_DISPLAY_REG; +unsigned char* led1 = (unsigned char*)LSB_DISPLAY_REG; + + *led0 = LETTER_S; + *led1 = LETTER_S; + + printf ("Entering Hardware Diagnostics - Disabling Data Cache!\n\n"); + + __disableDCache(); + + sys_pci_device_initialization (&pci_devices); + + _enableFiqIrq(); /* enable FIQ and IRQ interrupts */ + + config_ints(); /* configure interrupts for diagnostics */ + + init_external_timer(); + + /* 01/11/01 jwf */ + select_host_test_system(); + + menu (testMenu, NUM_MENU_ITEMS, MENU_TITLE, MENU_OPT_NONE); + + printf ("Exiting Hardware Diagnostics - Reenabling Data Cache!\n\n"); + + // _enableDCache(); /* reenable DCache */ + + uninit_external_timer(); + + + *led0 = ZERO; + *led1 = ZERO; + + __reset(); /* reset the board so RedBoot starts with a clean slate */ +} + +// Use "naked" attribute to suppress C prologue/epilogue +static void __attribute__ ((naked)) _coy_tight_loop(void) +{ + asm ( "0: mov r0,r0\n" + "b 0b\n"); +} + + +/* 02/02/01 jwf */ +static void cache_loop (void) +{ + printf ("Putting Processor in a Tight Loop Forever...\n\n"); + + _coy_tight_loop(); + + /* not reached */ +} + + +/************************************************/ +/* Secondary PCI Bus Test */ +/* */ +/* This test assumes that a IQ80303 eval board */ +/* is installed in a secondary PCI slot. This */ +/* second board must be configured with 32 Meg */ +/* of SDRAM minimum. */ +/* */ +/************************************************/ +static void spci_tests (void) +{ + long start_addr; + long mem_size; + long end_addr; + int first_ctrlr = 0; + PCI_DEVICE_LOCATION dev_loc; + + /* Look for ATU on the secondary PCI Bus */ + printf("\nLooking for a IQ80303 board on the Secondary PCI bus:\n"); + while (TRUE) + { + if (Device_Seek (FALSE, VENDOR_INTEL, I80303_ATU, first_ctrlr, &dev_loc) == OK) + { + if (dev_loc.bus_number != SECONDARY_BUS_NUM) + { + continue; + } + else + { + printf("An IQ80303 board has been detected on the Secondary PCI bus."); + break; + } + } + else + { + printf("No IQ80303 board detected on the SPCI bus!\n"); + return; + } + } + + printf ("i80303 ATU located at bus = 0x%02X, dev = 0x%02X, func = 0x%02X\n", + dev_loc.bus_number, dev_loc.device_number, dev_loc.function_number); + + /* read the PCI address which corresponds to the start of DRAM */ + if (sys_read_config_dword (dev_loc.bus_number, dev_loc.device_number, dev_loc.function_number, 0x10, (UINT32 *)&start_addr) == ERROR) + { + printf ("Error reading PCI BAR for ATU\n"); + return; + } + + /* strip off indicator bits */ + start_addr &= 0xfffffff0; + + printf ("i80303 DRAM starts at PCI address 0x%08X\n", start_addr); + + /* skip over 1st Mbyte of target DRAM */ + start_addr += 0x100000; + + mem_size = 0x1f00000; + end_addr = start_addr + mem_size; + + printf("\n\nTesting memory from $"); + hex32out(start_addr); + printf(" to $"); + hex32out(end_addr); + printf(".\n"); + + memTest(start_addr, end_addr); + printf("\n"); + + printf ("\nMemory test done.\n"); + printf ("Press return to continue.\n"); + (void) hexIn(); +} + +/************************************************/ +/* Primary PCI Bus Test */ +/* */ +/* This test assumes that a IQ80303 eval board */ +/* is installed in a primary PCI slot. This */ +/* second board must be configured with 32 Meg */ +/* of SDRAM minimum. */ +/* */ +/************************************************/ +static void ppci_tests (void) +{ + long start_addr; + long mem_size; + long end_addr; + int first_ctrlr = 0; + PCI_DEVICE_LOCATION dev_loc; + + /* check to see if we are the host of the backplane, if not + return an error */ + if (isHost() == FALSE) + { + printf ("Invalid test configuration, must be PCI host!\n"); + return; + } + + /* Look for ATU on the primary PCI Bus */ + printf("\nLooking for a IQ80303 board on the Primary PCI bus:\n"); + while (TRUE) + { + if (Device_Seek (FALSE, VENDOR_INTEL, I80303_ATU, first_ctrlr, &dev_loc) == OK) + { + if (dev_loc.bus_number != PRIMARY_BUS_NUM) + { + continue; + } + else + { + printf("An IQ80303 board has been detected on the Primary PCI bus\n"); + break; + } + } + else + { + printf("No IQ80303 board detected on the PPCI bus!\n"); + return; + } + } + + printf ("i80303 ATU located at bus = 0x%02X, dev = 0x%02X, func = 0x%02X\n", + dev_loc.bus_number, dev_loc.device_number, dev_loc.function_number); + + /* read the PCI address which corresponds to the start of DRAM */ + if (sys_read_config_dword (dev_loc.bus_number, dev_loc.device_number, dev_loc.function_number, 0x10, (UINT32 *)&start_addr) == ERROR) + { + printf ("Error reading PCI BAR for ATU\n"); + return; + } + + /* strip off indicator bits */ + start_addr &= 0xfffffff0; + + printf ("i80303 DRAM starts at PCI address 0x%08X\n", start_addr); + + /* skip over 1st Mbyte of target DRAM */ + start_addr += 0x100000; + + mem_size = 0x1f00000; + end_addr = start_addr + mem_size; + + printf("\n\nTesting memory from $"); + hex32out(start_addr); + printf(" to $"); + hex32out(end_addr); + printf(".\n"); + + memTest(start_addr, end_addr); + printf("\n"); + + printf ("\nMemory test done.\n"); + printf ("Press return to continue.\n"); + (void) hexIn(); +} + + +/***************************************************************************** +* memory_tests - Basic Memory Tests +* +* Memory tests can be run one of two ways - with the cache turned OFF to test +* physical memory, or with cache turned ON to test the caching +*/ +static void memory_tests (void) +{ + long start_addr; + long mem_size; + long end_addr; + + printf ("Base address of memory to test (in hex): "); + start_addr = hexIn(); + printf("\n"); + printf ("Size of memory to test (in hex): "); + mem_size = hexIn(); + printf("\n"); + end_addr = start_addr + mem_size; + + printf("Testing memory from $"); + hex32out(start_addr); + printf(" to $"); + hex32out(end_addr); + printf(".\n"); + memTest(start_addr, end_addr); + printf("\n"); + + printf ("\nMemory test done.\n"); + printf ("Press return to continue.\n"); + (void) xgetchar(); +} + + +/***************************************************************************** +* repeat_mem_test - Repeating Memory Tests +* +*/ +static void repeat_mem_test (void) +{ + unsigned long start_addr, mem_size, end_addr; + char cache_disable[10]; + + printf ("Turn off Data Cache? (y/n): "); + sgets (cache_disable); + printf ("\n"); + printf ("Base address of memory to test (in hex): "); + start_addr = hexIn(); + printf("\n"); + printf ("Size of memory to test (in hex): "); + mem_size = hexIn(); + printf("\n"); + end_addr = start_addr + mem_size; + printf("Testing memory from $"); + hex32out(start_addr); + printf(" to $"); + hex32out(end_addr); + while (memTest (start_addr, end_addr)) + ; +} + +/* 02/02/01 jwf */ +/***************************************************************************** +* special_mem_test - Repeat-On-Fail Memory Test +* +* Memory tests can be run one of two ways - with the cache turned OFF to test +* physical memory, or with cache turned ON to test the caching +*/ +static void special_mem_test (void) +{ + long start_addr; + long mem_size; + long end_addr; + + printf ("Base address of memory to test (in hex): "); + start_addr = hexIn(); + printf("\n"); + printf ("Size of memory to test (in hex): "); + mem_size = hexIn(); + printf("\n"); + end_addr = start_addr + mem_size; + + printf("Testing memory from $"); + hex32out(start_addr); + printf(" to $"); + hex32out(end_addr); + printf(".\n"); + LoopMemTest(start_addr, end_addr); + printf("\n"); + + printf ("\nMemory test done.\n"); + printf ("Press return to continue.\n"); + (void) xgetchar(); +} + +/* sequential test for LSD and MSD 7 segment Leds */ +void seven_segment_display (void) +{ + + unsigned char SevSegDecode; + int DisplaySequence; + int SelectLed; + const unsigned long TIME_OUT=6000000; + +/* 02/02/01 jwf */ + volatile unsigned long Dwell; + + *( unsigned char * ) 0xfe840000 = DISPLAY_OFF; /* blank MSD 7 segment LEDS */ + + *( unsigned char * ) 0xfe850000 = DISPLAY_OFF; /* blank LSD 7 segment LEDS */ + + + SelectLed=0; /* initialize 7 segment LED selection */ + + do + { + /* run test data sequence for a 7 segment LED */ + for (DisplaySequence = 0; DisplaySequence <= 17; ++DisplaySequence ) + { + /* fetch 7 segment decode byte */ + switch( DisplaySequence ) + { + case 0: + SevSegDecode = ZERO; + break; + + case 1: + SevSegDecode = ONE; + break; + + case 2: + SevSegDecode = TWO; + break; + + case 3: + SevSegDecode = THREE; + break; + + case 4: + SevSegDecode = FOUR; + break; + + case 5: + SevSegDecode = FIVE; + break; + + case 6: + SevSegDecode = SIX; + break; + + case 7: + SevSegDecode = SEVEN; + break; + + case 8: + SevSegDecode = EIGHT; + break; + + case 9: + SevSegDecode = NINE; + break; + + case 10: + SevSegDecode = LETTER_A; + break; + + case 11: + SevSegDecode = LETTER_B; + break; + + case 12: + SevSegDecode = LETTER_C; + break; + + case 13: + SevSegDecode = LETTER_D; + break; + + case 14: + SevSegDecode = LETTER_E; + break; + + case 15: + SevSegDecode = LETTER_F; + break; + + case 16: + SevSegDecode = DECIMAL_POINT; + break; + + case 17: + SevSegDecode = DISPLAY_OFF; + + default: + break; + + } /* end switch( DisplaySequence ) */ + + + /* display test data on selected 7 segment LED */ + /* the test data sequence for a 7 segment led will be seen as:*/ + /* 0 1 2 3 4 5 6 7 8 9 A b C d e F . */ + switch( SelectLed ) + { + case 0: + *( unsigned char * ) 0xfe850000 = SevSegDecode; /* write value on 7 segment LSD LED display */; + break; + + case 1: + *( unsigned char * ) 0xfe840000 = SevSegDecode; /* write value on 7 segment MSD LED display */; + break; + + default: + break; + } /* end switch( SelectLed ) */ + + /* time delay, allows user enough time to read a value on display */ + for (Dwell=TIME_OUT; Dwell > 0; --Dwell ); + + } /* end for(DisplaySequence~) */ + + ++SelectLed; /* select next 7 segment LED */ + } + while (SelectLed < 2); /* tests a pair of 7 segment LEDs */ + + *( unsigned char * ) 0xfe840000 = LETTER_S; /* show S on the 7 segment MSD LED */ + *( unsigned char * ) 0xfe850000 = LETTER_S; /* show S on the 7 segment LSD LED */ +} /* end seven_segment_display() */ + + +/* 12/18/00 jwf */ +/* tests rotary switch status, S1 positions 0-3, a 2 bit output code */ +void rotary_switch (void) +{ + + /* CYGMON serial port J9 */ + unsigned char recv_data; /* RHR */ + unsigned char recv_lsr; /* LSR */ + + const unsigned char MAX_SWITCH_SAMPLES = 9; + unsigned char RotarySwitch[MAX_SWITCH_SAMPLES]; /* holds multiple samples of a 4 bit switch code */ + unsigned char index; /* index for Rotary Switch array */ + unsigned char debounce; /* keeps tally of equal rotary switch data reads in a loop */ + unsigned char SevSegDecode; /* holds decode data for a 7 segment LED display */ + + unsigned char ri_state; + unsigned char board_rev; + + const unsigned long TIME_OUT = 4000000; + +/* 02/02/01 jwf */ + volatile unsigned int Dwell; + + *( unsigned char * ) 0xfe840000 = DISPLAY_OFF; /* turn off the 7 segment MSD LED */ + *( unsigned char * ) 0xfe850000 = DISPLAY_OFF; /* turn off the 7 segment LSD LED */ + + ri_state = *( unsigned char * ) 0xfe810006; /* access CYGMON serial port J9 MSR at addr fe810006 */ + ri_state &= RI_MASK; + if(ri_state == RI_MASK) /* RI# pin on UART2 is grounded */ + { + board_rev = *BOARD_REV_REG_ADDR; /* read Board Revision register */ + board_rev &= BOARD_REV_MASK; /* isolate LSN */ + if (board_rev >= BOARD_REV_E) /* Board Rev is at E or higher */ + { + printf("\n\nThe 7-Segment LSD LED shows the Rotary Switch position selected, i.e., 0-F."); + printf("\n\nSlowly dial the Rotary Switch through each position 0-F and confirm reading."); + } + } + else /* RI# pin on UART2 is pulled up to 3.3V. Cannot read board revision register, not implemented */ + { + printf("\n\nThe 7-Segment LSD LED shows the Rotary Switch position selected, i.e., 0-3."); + printf("\n\nSlowly dial the Rotary Switch through each position 0-3 and confirm reading."); + } + printf( "\n\nStrike <CR> to exit this test." ); + while ( recv_data != 0x0d ) /* run until User types a <CR> to exit */ + { + + do /* debounce the switch contacts */ + { + for(index = 0; index <= MAX_SWITCH_SAMPLES; index++) /* sample rotary switch code */ + { + RotarySwitch[index] = *( unsigned char * ) 0xfe8d0000; /* read rotary switch code */ + RotarySwitch[index] &= 0x0f; /* mask out bits b7-b4, preserve bits b0-b3 */ + } + debounce = 0; + for(index = 1; index <= MAX_SWITCH_SAMPLES; index++) /* test rotary switch code samples */ + { + if (RotarySwitch[0] == RotarySwitch[index]) + debounce++; /* keep tally of equal rotary switch code samples */ + } + } + while ( debounce < (MAX_SWITCH_SAMPLES - 1) ); /* exit when all rotary switch code readings are equal, when debounce = MAX_SWITCH_SAMPLES-1 */ + + /* decipher state of rotary switch position */ + switch( RotarySwitch[0] ) + /* examine rotary switch position then display its position number on the 7 segment LSD LED */ + { + case 0x00: + SevSegDecode = ZERO; + break; + + case 0x01: + SevSegDecode = ONE; + break; + + case 0x02: + SevSegDecode = TWO; + break; + + case 0x03: + SevSegDecode = THREE; + break; + + case 0x4: + SevSegDecode = FOUR; + break; + + case 0x5: + SevSegDecode = FIVE; + break; + + case 0x6: + SevSegDecode = SIX; + break; + + case 0x7: + SevSegDecode = SEVEN; + break; + + case 0x8: + SevSegDecode = EIGHT; + break; + + case 0x9: + SevSegDecode = NINE; + break; + + case 0xa: + SevSegDecode = LETTER_A; + break; + + case 0xb: + SevSegDecode = LETTER_B; + break; + + case 0xc: + SevSegDecode = LETTER_C; + break; + + case 0xd: + SevSegDecode = LETTER_D; + break; + + case 0xe: + SevSegDecode = LETTER_E; + break; + + case 0xf: + SevSegDecode = LETTER_F; + break; + + default: + SevSegDecode = DECIMAL_POINT; + break; + } + + *( unsigned char * ) 0xfe850000 = SevSegDecode; /* display the rotary switch position on the 7 segment LSD LED as: 0, 1, 2, 3 */ + + recv_lsr = *(volatile unsigned char *) 0xfe810005; /* read J9 serial port LSR */ + recv_lsr &= 0x1; + if ( recv_lsr == 0x1) /* a character is ready in receiver buffer */ + { + recv_data = *(volatile unsigned char *) 0xfe810000; /* read character from J9 serial port receiver buffer */ + } + for (Dwell=TIME_OUT; Dwell > 0; --Dwell ); + } + + *( unsigned char * ) 0xfe840000 = LETTER_S; /* show S on the 7 segment MSD LED */ + *( unsigned char * ) 0xfe850000 = LETTER_S; /* show S on the 7 segment LSD LED */ + +} /* end rotary_switch() */ + + +/* test backplane detection, connector socket J19 pin 7 */ +/* BP_DET#=0, no backplane */ +/* BP_DET#=1, backplane installed */ +/* b0 <--> BP_DET# */ +void backplane_detection(void) +{ + unsigned char BpDetStatus; /* L = pci700 board installed on backplane */ + + BpDetStatus = *( unsigned char * ) 0xfe870000; /* read backplane detection status port */ + + BpDetStatus &= 0x01; /* isolate bit b0 */ + + /* examine bit 0 */ + switch( BpDetStatus ) + + { + case 0x00: /* BpDetStatus = !(BP_DET#=1) = 0 */ + printf("\nBackplane detection bit read Low, no backplane installed\n"); + printf("\nPlace a jumper across J19.7 to J19.1, then run this test again.\n"); + break; + + case 0x01: /* BpDetStatus = !(BP_DET#=0) = 1 */ + printf("\nBackplane detection bit read High, 1 backplane detected.\n"); + printf("\nRemove jumper from J19\n"); + break; + + default: + break; + } + +/* 12/18/00 jwf */ + printf ("\n\nStrike <CR> to exit this test.\n\n"); + hexIn(); + +} + + +/* test battery status */ +/* b0 - !(BATT_PRES#=0). A battery is installed.*/ +/* b1 - BATT_CHRG=1. The battery is fully charged. */ +/* b2 - BATT_DISCHRG=1. The battery is fully discharged. */ +void battery_status(void) +{ + unsigned char BatteryStatus; + + unsigned char TestBit; + + BatteryStatus = *( unsigned char * ) 0xfe8f0000; /* read battery status port */ + + BatteryStatus &= 0x07; /* isolate bits b0, b1, and b2 */ + + TestBit = BatteryStatus; + + /* examine bit b0 BATT_PRES# */ + + TestBit &= 0x01; + + if (TestBit == 0x01) /* TestBit=!(BATT_PRES#=0)=1 */ + { + + printf("\nBATT_PRES#=0. A battery was detected.\n"); + } + + else /* TestBit=!(BATT_PRES#=1)=0 */ + { + + printf("\nBATT_PRES#=1. No battery installed.\n"); /* skip testing bits b2 and b3 (BATT_CHRG and BATT_DISCHRG) here since no battery is installed yet */ + } + + /* examine bit b1 BATT_CHRG */ + TestBit |= BatteryStatus; + + TestBit &= 0x02; + + if (TestBit == 0x02) /* BATT_CHRG=1 */ /* Assume V_BATT float=4.2V, then 1.2V<V(U20.5)<=1.33V so V_BATT>3.78V,*/ + + printf("\nBATT_CHRG=1. Battery is fully charged.\n"); + + else /* BATT_CHRG=0 */ /* Assume V_BATT float=4.2V, then V(U20.5)<=1.2V so V_BATT<=3.78V */ + + printf("\nBATT_CHRG=0. Battery is charging.\n"); + + + /* examine bit b2 BATT_DISCHRG */ + TestBit |= BatteryStatus; + + TestBit &= 0x04; + + + if (TestBit == 0x04) /* BATT_DISCHRG=1 */ /* Assume V_BATT float=4.2V, then V(U30.2)=<1.2V so V_BATT<=3.0V */ + + printf("\nBATT_DISCHRG=1. Battery is fully discharged.\n"); + + else /* BATT_DISCHRG=0 */ /* Assume V_BATT float=4.2V, then 1.2V<V(U30.2)=<1.68V so V_BATT>3.0V */ + + printf("\nBATT_DISCHRG=0. Battery voltage measures with in normal operating range.\n"); + + printf ("\n\nStrike <CR> to exit this test.\n\n"); + + hexIn(); + +} + + + + + + +/* GPIO test */ +/* Header J16 pin out is: J16.1=b0, J16.3=b1, J16.5=b2, J16.7=b3, J16.9=b4, J16.11=b5, J16.13=b6, J16.15=b7 */ +/* This test will require use of 2 special test sockets wired as follows for the output and input tests. */ +/* Intel specifies that each GPIO pin must be pulled down after P_RST# deasserts to swamp out their weak internal active pull up */ +/* Note that the internal weak active pull up tends to have more of an affect on the GPIO input port rather than the output port */ +/* Therefore for the input test, jumper J16 pins: 1-2, 3-4, 5-6, 7-8, 9-10, 11-12, 13-14, 15-16, and (TBD) provide an input source for each bit */ +/* For the output test, jumper J16 pins: 1-2, 3-4, 5-6, 7-8, 9-10, 11-12, 13-14, 15-16 */ +/* each jumpered pin connects a weak pull down resistor, resident on board, to each GPIO pin */ +void gpio_test (void) +{ + /*unsigned char GpioInputPort;*/ + unsigned char GpioOutputPort; + unsigned char GpioOutputEnablePort; + + /* GPIO output port test */ + + printf("\n\nPlug output test socket into header J16, strike 'Enter' to continue" ); + while(xgetchar()!=0x0d); + + /* write test data pattern to GPIO Output Enable Register at address 0x0000171c */ + *( unsigned char * ) 0x0000171c = 0x55; + + /* read GPIO Output Enable Register from address 0x0000171c */ + GpioOutputEnablePort = *( unsigned char * ) 0x0000171c; + + if (GpioOutputEnablePort==0x55) + printf("\nGPIO Output Enable first write/read test PASSED."); + else + printf("\nGPIO Output Enable first write/read test FAILED."); + +/* + printf("\n\nStrike Enter to continue" ); + printf("\n0x55" ); + while(xgetchar()!=0x0d); +*/ + + /* write test data pattern to GPIO Output Enable Register at address 0x0000171c */ + *( unsigned char * ) 0x0000171c = 0xaa; + + /* read GPIO Output Enable Register from address 0x0000171c */ + GpioOutputEnablePort = *( unsigned char * ) 0x0000171c; + + if (GpioOutputEnablePort==0xaa) + printf("\nGPIO Output Enable second write/read test PASSED."); + else + printf("\nGPIO Output Enable second write/read test FAILED."); + + + + /* enable output bits b0-b7, write test pattern to GPIO Output Enable Register at address 0x0000171c */ + *( unsigned char * ) 0x0000171c = 0x00; + + /* write test data pattern to GPIO Output Data Register at address 00001724h */ + *( unsigned char * ) 0x00001724 = 0x55; + + /* read test data pattern from GPIO Output Data Register at address 00001724h */ + GpioOutputPort = *( unsigned char * ) 0x00001724; + + if (GpioOutputPort==0x55) + printf("\nGPIO Output Data Register first write/read test PASSED."); + else + printf("\nGPIO Output Data Register first write/read test FAILED."); + +/* + printf("\n\nStrike Enter to continue" ); + printf("\n0x55" ); + while(xgetchar()!=0x0d); +*/ + + /* write output data pattern to GPIO Output Data Register at address 00001724h */ + *( unsigned char * ) 0x00001724 = 0xaa; + + /* read output data pattern from GPIO Output Data Register at address 00001724h */ + GpioOutputPort = *( unsigned char * ) 0x00001724; + + if (GpioOutputPort==0xaa) + printf("\nGPIO Output Data Register second write/read test PASSED."); + else + printf("\nGPIO Output Data Register second write/read test FAILED."); + + + printf("\n\nRemove output test socket from header J16, strike 'Enter' to continue" ); + while(xgetchar()!=0x0d); + + + + /* GPIO input port test */ +/* + printf("\n\nPlug input test socket into header J16, strike 'Enter' to continue" ); + while(xgetchar()!=0x0d); +*/ + + /* GPIO Input Data Register address is 00001720h */ /* read port */ +/* + GpioInputPort = *( unsigned char * ) 0x00001720; + if ( GpioInputPort==0x55 ) + printf("\nGPIO Input Data Register first read test PASSED"); + else + printf("\nGPIO Input Data Register first read test FAILED"); +*/ + + + /* GPIO Input Data Register address is 00001720h */ /* read port */ +/* + GpioInputPort = *( unsigned char * ) 0x00001720; + + if ( GpioInputPort==0xaa ) + printf("\nGPIO Input Data Register second read test PASSED"); + else + printf("\nGPIO Input Data Register second read test FAILED"); +*/ +/* + printf("\n\nRemove input test socket from header J16, strike 'Enter' to continue" ); + while(xgetchar()!=0x0d); +*/ + +} /* end gpio_test() */ + + + +/************************************************************************* +* Device_Seek - look for a PCI device +* +* During initialization, a device driver must call this function +* (or a similar one) with the specific PCI Vendor Id and Device Id +* of the device to be supported to determine its location (or lack +* thereof) on the PCI bus. If multiple devices are to be supported, +* this function must be called repeatedly with an increasing dev_index +* until the function returns ERROR. Each instance (if any) of the device +* will then have been identified. +* +* Once the device is located, the device driver can then call the +* appropriate PCI BIOS function to read device information from PCI +* Configuration Space (i.e. Runtime Register PCI Base address, Local +* Memory PCI Base address, etc.) +* +*/ +STATUS Device_Seek( + int verbose, + unsigned long adapter_vendor, + unsigned long adapter_device_id, + unsigned long dev_index, + PCI_DEVICE_LOCATION *dev_info + ) +{ + if (verbose) + { + printf("Looking for Adapter on PCI Bus with:\n"); + printf("Vendor Id = 0x%04x\n",adapter_vendor); + printf("Device Id = 0x%04x\n",adapter_device_id); + printf("Index = %x\n",dev_index); + } + + if (sys_find_pci_device (adapter_vendor, + adapter_device_id, + dev_index, dev_info) != OK) + { + if (verbose) printf("Failed to Find Adapter\n"); + return (ERROR); + } + else + { + if (verbose) + { + printf("Adapter found at :\n"); + printf(" PCI Bus Number : %d\n", dev_info->bus_number); + printf(" Device Number : %d\n", dev_info->device_number); + } + return (OK); + } +} + + +/* i82559 Ethernet test */ +void ether_test (void) +{ + + PCI_DEVICE_LOCATION dev_loc[6]; /* 6 is the max Enet for now */ + int unit = 0; + int i, num_enet; + + + for (i = 0, num_enet = 0; i < 6; i++, num_enet++) + { + if (Device_Seek (FALSE, VENDOR_INTEL, + I82557, + i, + &(dev_loc[num_enet])) != OK) + { + break; + } + + } + + for (i = 0; i < 6; i++, num_enet++) + { + if (Device_Seek (FALSE, VENDOR_INTEL, + I82559ER, + i, + &(dev_loc[num_enet])) != OK) + { + break; + } + + } + + if (num_enet == 0) + { + printf ("No supported Ethernet devices found\n"); + return; + } + + printf ("Supported Ethernet Devices:\n\n"); + + printf (" Unit# Bus# Device#\n"); + printf (" ----- ---- -------\n"); + for (i = 0; i < num_enet; i++) + { + printf (" %d %d %d\n", i, dev_loc[i].bus_number, dev_loc[i].device_number); + } + + printf ("\nEnter the unit number to test : "); + unit = decIn(); + printf ("\n"); + + pci_ether_test (dev_loc[unit].bus_number, + dev_loc[unit].device_number, + dev_loc[unit].function_number); + +} + + + + +/* Setup Serial EEPROM for Ethernet Configuration */ +static void enet_setup (void) +{ + UINT32 adapter_ptr; /* Ptr to PCI Ethernet adapter */ + + PCI_DEVICE_LOCATION dev_loc; + UINT16 eepromData[3] = + { + 0x4801, /* Valid EEPROM, No Expansion ROM, Rev = ?, PHY Addr = 1 */ + 0x0700, /* Subsystem Id - PCI700 */ + 0x113c /* Subsystem Vendor Id - Cyclone Microsystems */ + }; + int config_data_offset = 0x0a; /* offset into EEPROM for config. data storage */ + int ia_offset = 0x00; /* offset into EEPROM for IA storage */ + UINT8 buffer[6]; /* temporary storage for IA */ + UINT16 temp_node_addr[3] = {0,0,0}; + UINT16 serial_no; + UINT8 revision_id = 0, port_id = 0; + char rev_string[8]; + + /* Cyclone identifier */ + buffer[0] = 0x00; + buffer[1] = 0x80; + buffer[2] = 0x4D; + buffer[3] = 0x46; /* board identifier - PCI700 = 70 = 0x46 */ + + serial_no = 10000; + while (serial_no >= 10000) + { + printf ("\nEnter the board serial number (1 - 9999): "); + serial_no = decIn(); + printf ("\n"); + } + revision_id = 8; + while ((revision_id < 1) || (revision_id > 7)) + { + printf ("\nEnter the board revison (A - G) : "); + sgets (rev_string); + rev_string[0] = (rev_string[0] & 0xdf); /* convert to upper case */ + revision_id = (rev_string[0] - 'A') + 1; /* convert to a number 1 - 7 */ + printf ("\n"); + } + revision_id &= 0x7; + eepromData[0] |= (revision_id << 8); /* add the rev. id to data */ + + /* we only want to set up on-board 559 */ + dev_loc.bus_number = 2; + dev_loc.device_number = 0; + dev_loc.function_number = 0; + + /* Get the PCI Base Address for mem. runtime registers */ + if (sys_read_config_dword (dev_loc.bus_number, + dev_loc.device_number, + dev_loc.function_number, + 0x10, &adapter_ptr) == ERROR) + { + printf("Unable to read i82559 PCI Base Address\n"); + return; + } + + /* strip off indicator bits */ + adapter_ptr = adapter_ptr & 0xfffffff0; + + printf ("Writing the Configuration Data to the Serial EEPROM... "); + if (eeprom_write (adapter_ptr,config_data_offset,eepromData,3) != OK) + { + printf ("Error writing the Configuration Data to Serial EEPROM\n"); + return; + } + printf ("Done\n"); + + /* setup node's Ethernet address */ + port_id = ((0 << 6) & 0xc0); /* two bits of port number ID */ + buffer[4] = (UINT8) (((serial_no & 0x3FFF) >> 8) | port_id); + buffer[5] = (UINT8) (serial_no & 0x00FF); + + temp_node_addr[0] = (UINT16) ((buffer[1] << 8) + buffer[0]); + temp_node_addr[1] = (UINT16) ((buffer[3] << 8) + buffer[2]); + temp_node_addr[2] = (UINT16) ((buffer[5] << 8) + buffer[4]); + + printf ("Writing the Individual Address to the Serial EEPROM... "); + if (eeprom_write (adapter_ptr,ia_offset,temp_node_addr,3) != OK) + { + printf ("\nError writing the IA address to Serial EEPROM.\n"); + return; + } + printf ("Done\n"); + + + /* now that we have finished writing the configuration data, we must ask the + operator to reset the PCI916 to have the configuration changes take effect. + After the reset, the standard Enet. port diagnostics can be run on the 916 + under test */ + + printf ("\n\n******** Reset the IQ80310 Now to Have Changes Take Effect ********\n\n"); + + /* wait forever as a reset will bring us back */ + while ((volatile int)TRUE) + ; +} + + + +/* use the clock in the Performance Monitoring Unit to do delays */ +void polled_delay (int usec) +{ +volatile int i; + + _enable_timer(); + + for (i = 0; i < usec; i++) + _usec_delay(); + + _disable_timer(); +} + + + +void internal_timer() +{ + int j, i; + + printf ("\n"); + + _enable_timer(); + + printf ("Timer enabled...\n"); + + for (j = 0; j < 20; j++) + { + printf ("."); + for (i = 0; i < 1000; i++) + _msec_delay(); + } + + _disable_timer(); + + printf ("\nTimer disabled...\n"); +} + + + + + + +#define I80960RP_BRIDGE 0x0960 +#define I80960RP_NAME0 "80960RP PCI-PCI Bridge" + +#define I80960RP_ATU 0x1960 +#define I80960RP_NAME1 "80960RP Address Translation Unit" + +#define I80960RM_BRIDGE 0x0962 +#define I80960RM_NAME0 "80960RM PCI-PCI Bridge" + +#define I80960RM_ATU 0x1962 +#define I80960RM_NAME1 "80960RM Address Translation Unit" + +#define I80960RN_BRIDGE 0x0964 +#define I80960RN_NAME0 "80960RN PCI-PCI Bridge" + +#define I80960RN_ATU 0x1964 +#define I80960RN_NAME1 "80960RN Address Translation Unit" + +#define I80303_BRIDGE 0x0309 +#define I80303_NAME0 "80303 PCI-PCI Bridge" + +#define I80303_ATU 0x5309 +#define I80303_NAME1 "80303 Address Translation Unit" + + + +/******************************************************************/ +/* The following functions are all part of the PCI Interrupt Test */ +/******************************************************************/ +/* definitions pertaining to PCI interrupt test */ +#define MAX_I960RX 31 +typedef struct +{ + UINT32 device_id; + UINT32 busno; + UINT32 devno; + UINT32 funcno; +} I960RX_DEVICES; +I960RX_DEVICES i960Rx_devices[MAX_I960RX]; +UINT32 num_rx_devices = 0; +UINT32 messagingUnitBase = (UINT32)NULL; + +/* Outbound Interrupt Status Register bits */ +#define OB_STAT_INTA (1 << 4) +#define OB_STAT_INTB (1 << 5) +#define OB_STAT_INTC (1 << 6) +#define OB_STAT_INTD (1 << 7) + +/* Outbound Doorbell Register bits */ +#define OB_DBELL_INTA (1 << 28) +#define OB_DBELL_INTB (1 << 29) +#define OB_DBELL_INTC (1 << 30) +#define OB_DBELL_INTD (1 << 31) + +/*********************************************************************** +* +* line_to_string - Returns name as string of particular XINT number +* +*/ +static char *line_to_string (int intline) +{ + switch (intline) + { + case XINT0: return("XINT0"); + case XINT1: return("XINT1"); + case XINT2: return("XINT2"); + case XINT3: return("XINT3"); + default: return("ERROR"); + } +} + + +/*************************************************************************** +* +* PCI_IntHandler - Interrupt handler for PCI interrupt test +* +* Used to verify that an interrupt was recieved during the PCI interrupt +* test by the IQ80310 from the add-in i960Rx board. This handler prints out +* which interrupt was recieved, and then clears the interrupt by clearing +* the doorbell register on the i960Rx card. +* +*/ +int PCI_IntHandler (int IntPin) +{ + UINT32 *OutboundDbReg = (UINT32 *)(messagingUnitBase + 0x2c); + UINT32 *OutboundIstatReg = (UINT32 *)(messagingUnitBase + 0x30); + + switch (IntPin) + { + case INTA: + + /* check to see if we are looking at the correct interrupt */ + if (!(*OutboundIstatReg & OB_STAT_INTA)) + { + #if 0 + printf ("OISR Mismatch!\n"); + printf ("OISR = 0x%X\n", *OutboundIstatReg); + printf ("**** PCI INTA Error ****\n\n"); + + /* try to clear all sources */ + *OutboundDbReg = (OB_DBELL_INTA|OB_DBELL_INTB|OB_DBELL_INTC|OB_DBELL_INTD); + #endif + return (0); + } + else + { + printf ("PCI INTA generated/received\n\n"); + printf ("OISR OK!\n"); + printf ("OISR = 0x%X\n", *OutboundIstatReg); + printf ("**** PCI INTA Success ****\n\n"); + *OutboundDbReg |= OB_DBELL_INTA; /* try to clear specific source */ + return (1); + } + + break; + + case INTB: + + /* check to see if we are looking at the correct interrupt */ + if (!(*OutboundIstatReg & OB_STAT_INTB)) + { + #if 0 + printf ("OISR Mismatch!\n"); + printf ("OISR = 0x%X\n", *OutboundIstatReg); + printf ("**** PCI INTB Error ****\n\n"); + + /* try to clear all sources */ + *OutboundDbReg = (OB_DBELL_INTA|OB_DBELL_INTB|OB_DBELL_INTC|OB_DBELL_INTD); + #endif + return (0); + } + else + { + printf ("PCI INTB generated/received\n\n"); + printf ("OISR OK!\n"); + printf ("OISR = 0x%X\n", *OutboundIstatReg); + printf ("**** PCI INTB Success ****\n\n"); + *OutboundDbReg |= OB_DBELL_INTB; /* try to clear specific source */ + return (1); + } + + break; + + case INTC: + + /* check to see if we are looking at the correct interrupt */ + if (!(*OutboundIstatReg & OB_STAT_INTC)) + { + #if 0 + printf ("OISR Mismatch!\n"); + printf ("OISR = 0x%X\n", *OutboundIstatReg); + printf ("**** PCI INTC Error ****\n\n"); + + /* try to clear all sources */ + *OutboundDbReg = (OB_DBELL_INTA|OB_DBELL_INTB|OB_DBELL_INTC|OB_DBELL_INTD); + #endif + return (0); + } + else + { + printf ("PCI INTC generated/received\n\n"); + printf ("OISR OK!\n"); + printf ("OISR = 0x%X\n", *OutboundIstatReg); + printf ("**** PCI INTC Success ****\n\n"); + *OutboundDbReg |= OB_DBELL_INTC; /* try to clear specific source */ + return (1); + } + + break; + + case INTD: + + /* check to see if we are looking at the correct interrupt */ + if (!(*OutboundIstatReg & OB_STAT_INTD)) + { + #if 0 + printf ("OISR Mismatch!\n"); + printf ("OISR = 0x%X\n", *OutboundIstatReg); + printf ("**** PCI INTD Error ****\n\n"); + + /* try to clear all sources */ + *OutboundDbReg = (OB_DBELL_INTA|OB_DBELL_INTB|OB_DBELL_INTC|OB_DBELL_INTD); + #endif + return (0); + } + else + { + printf ("PCI INTD generated/received\n\n"); + printf ("OISR OK!\n"); + printf ("OISR = 0x%X\n", *OutboundIstatReg); + printf ("**** PCI INTD Success ****\n\n"); + *OutboundDbReg |= OB_DBELL_INTD; /* try to clear specific source */ + return (1); + } + + break; + + default: + printf ("Unknown interrupt received\n"); + return (0); + break; + } + return (1); /* interrupt sharing support requirement */ +} + + +/******************************************************************************* +* +* i960Rx_seek - look for i960Rx CPUs on the PCI Bus +* +* This function is used by the PCI interrupt test to find and print out +* all PCI location of a particular i960Rx processor on the PCI bus. Thses include +* boards based on the RP, RD, RM, and RN processors. The device ID of one of +* these processors is the input to the function. +* +*/ +static void i960Rx_seek (UINT32 adapter_device_id) +{ +int dev_index = 0; +PCI_DEVICE_LOCATION dev_info; +static char *i960Rx_name; + + /* get the common name for the current Rx processor */ + switch (adapter_device_id) + { + case I80960RN_ATU: + i960Rx_name = " i960RN "; + break; + case I80960RM_ATU: + i960Rx_name = " i960RM "; + break; + case I80960RP_ATU: + i960Rx_name = "i960RP/RD"; + break; + case I80303_ATU: + default: + i960Rx_name = " i80303 "; + break; + } + + while (Device_Seek (FALSE, VENDOR_INTEL, + adapter_device_id, + dev_index, &dev_info) == OK) + { + /* set up this entry into the device array */ + i960Rx_devices[num_rx_devices].device_id = adapter_device_id; + i960Rx_devices[num_rx_devices].busno = dev_info.bus_number; + i960Rx_devices[num_rx_devices].devno = dev_info.device_number; + i960Rx_devices[num_rx_devices].funcno = dev_info.function_number; + + + printf (" %d %s %d %d %d\n", + num_rx_devices, i960Rx_name, + i960Rx_devices[num_rx_devices].busno, + i960Rx_devices[num_rx_devices].devno, + i960Rx_devices[num_rx_devices].funcno); + + dev_index++; /* increment number of current i960Rx devices found */ + num_rx_devices++; /* increment total number of i960Rx devices found */ + } +} + + +/********************************************************************************* +* +* pci_int_test - tests PCI interrupts on IQ80310 PCI buses +* +* This test allows full testing of PCI interrupt routing to a particular +* slot on the PCI bus. It runs in conjunction with a Cyclone i960Rx-based +* board plugged into the target slot. A default interrupt handler is connected +* for all four PCI interrupt pins on the target board. The test then waits for +* the target board to trigger each interrupt using the i960Rx doorbell registers. +* The test passes if all four interrupts are recieved and properly handled by the +* IQ80310. +* +*/ +void pci_int_test (void) +{ + PCI_DEVICE_LOCATION devloc; + int indexChoice = 0; + UINT32 long_data; + UINT32 *OutboundImaskReg; + int intline_INTA, intline_INTB, intline_INTC, intline_INTD; + + num_rx_devices = 0; + + printf ("Scanning PCI Bus for all supported i960Rx ATU Devices.....\n\n"); + + printf (" Index Processor Bus Device Function\n"); + printf (" ----- --------- --- ------ --------\n"); + + + + i960Rx_seek (I80960RN_ATU); + i960Rx_seek (I80960RM_ATU); + i960Rx_seek (I80960RP_ATU); + i960Rx_seek (I80303_ATU); + + if (num_rx_devices == 0) + { + printf ("\n*** No i960Rx ATU Found on PCI Bus ***\n"); + return; + } + + printf ("Enter index number to use for test : "); + indexChoice = decIn(); + printf ("\n\n"); + + if (indexChoice >= num_rx_devices) + { + printf ("Invalid index chosen, exiting\n"); + return; + } + + devloc.bus_number = i960Rx_devices[indexChoice].busno; + devloc.device_number = i960Rx_devices[indexChoice].devno; + devloc.function_number = i960Rx_devices[indexChoice].funcno; + + + sys_read_config_dword (devloc.bus_number, + devloc.device_number, + devloc.function_number, + REGION0_BASE_OFFSET,(UINT32*)&long_data); + + messagingUnitBase = long_data & 0xfffffff0; + printf ("Messaging Unit PCI Base Address = 0x%X\n", messagingUnitBase); + OutboundImaskReg = (UINT32 *)(messagingUnitBase + 0x34); + + /* Normally, we would just read the intline value from the configuration + space to determine where the interrupt is routed. However, the i960Rx + only requested interrupt resources for one interrupt at a time... */ + + /* compute interrupt routing values */ + if ((pci_to_xint(devloc.device_number, INTA, (int*)&intline_INTA)) || + (pci_to_xint(devloc.device_number, INTB, (int*)&intline_INTB)) || + (pci_to_xint(devloc.device_number, INTC, (int*)&intline_INTC)) || + (pci_to_xint(devloc.device_number, INTD, (int*)&intline_INTD)) == ERROR) + { + printf ("Error: Unable to connect PCI interrupts with IQ80310 interrupts\n"); + return; + } + + printf ("i960Rx INTA pin mapped to intLine %s on IQ80310\n", line_to_string(intline_INTA)); + printf ("i960Rx INTB pin mapped to intLine %s on IQ80310\n", line_to_string(intline_INTB)); + printf ("i960Rx INTC pin mapped to intLine %s on IQ80310\n", line_to_string(intline_INTC)); + printf ("i960Rx INTD pin mapped to intLine %s on IQ80310\n", line_to_string(intline_INTD)); + + + /* Connect i960Rx PCI INTA Handler */ + if (pci_isr_connect (INTA, devloc.bus_number, devloc.device_number, PCI_IntHandler, INTA) + == ERROR ) + { + printf ("Error Connecting INTA interrupt handler\n"); + return; + } + printf ("INTA Service Routine installed...\n"); + + /* enable PCI INTA */ + enable_external_interrupt(SINTA_INT_ID); + + /* Connect i960Rx PCI INTB Handler */ + if (pci_isr_connect (INTB, devloc.bus_number, devloc.device_number, PCI_IntHandler, INTB) + == ERROR) + { + printf ("Error Connecting INTB interrupt handler\n"); + return; + } + printf ("INTB Service Routine installed...\n"); + + /* enable PCI INTB */ + enable_external_interrupt(SINTB_INT_ID); + + /* Connect i960Rx PCI INTC Handler */ + if (pci_isr_connect (INTC, devloc.bus_number, devloc.device_number, PCI_IntHandler, INTC) + == ERROR) + { + printf ("Error Connecting INTC interrupt handler\n"); + return; + } + printf ("INTC Service Routine installed...\n"); + + /* enable PCI INTC */ + enable_external_interrupt(SINTC_INT_ID); + + /* Connect i960Rx PCI INTD Handler */ + if (pci_isr_connect (INTD, devloc.bus_number, devloc.device_number, PCI_IntHandler, INTD) + == ERROR) + { + printf ("Error Connecting INTD interrupt handler\n"); + return; + } + printf ("INTD Service Routine installed...\n"); + + /* enable PCI INTD */ + enable_external_interrupt(SINTD_INT_ID); + + /* make sure that the Outbound interrupts aren't masked */ + *OutboundImaskReg &= ~(OB_STAT_INTA | OB_STAT_INTB | OB_STAT_INTC | OB_STAT_INTD); + + /* let the ISR do the rest of the work... */ + printf ("Waiting for the PCI Interrupts to be received...\n\n"); + printf ("Hit <CR> when the test is complete\n\n\n"); + + hexIn(); + + return; +} + + +/*******************************************/ +/* Battery Backup SDRAM memory write test */ +/*******************************************/ +static void battery_test_write (void) +{ + unsigned long start_addr = SDRAM_BATTERY_TEST_BASE; /* Address to write to */ + + /* Data to be written to address and read after the board has been powered off and powered back on */ + UINT32 junk = BATTERY_TEST_PATTERN; + + *(volatile UINT32 *)start_addr = junk; + + printf("\nThe value '"); + hex32out(BATTERY_TEST_PATTERN); + printf ("' is now written in DRAM at address $"); + hex32out(SDRAM_BATTERY_TEST_BASE); + printf(".\n\nYou can now power the board off, wait 60 seconds and power it back on."); + printf("\nThen come back in the battery test menu and select option 2 to check data from DRAM.\n"); + + printf ("\nPress return to continue.\n"); + (void) hexIn(); +} + + +/******************************************/ +/* Battery Backup SDRAM memory read test */ +/******************************************/ +static void battery_test_read (void) +{ + unsigned long start_addr = SDRAM_BATTERY_TEST_BASE; /* Address to read from */ + UINT32 value_written = BATTERY_TEST_PATTERN; /* Data that was written */ + UINT32 value_read; + + value_read = *(volatile UINT32 *)start_addr; + + printf ("Value written at address $"); + hex32out(SDRAM_BATTERY_TEST_BASE); + printf (": "); + hex32out(BATTERY_TEST_PATTERN); + printf ("\nValue read at address $"); + hex32out(SDRAM_BATTERY_TEST_BASE); + printf(" : "); + hex32out(value_read); + + if (value_read == value_written) printf ("\n\nThe battery test is a success !\n"); + else + { + printf ("\n\n****************************\n"); + printf ("* The battery test failed. *\n"); + printf ("****************************\n"); + } + + printf ("\nBattery test done.\n"); + printf ("Press return to continue.\n"); + (void) hexIn(); +} + + +/*************************************/ +/* Battery Backup SDRAM memory menu */ +/*************************************/ +static void battery_test_menu (void) +{ + /* Test Menu Table */ + static MENU_ITEM batteryMenu[] = + { + {"Write data to SDRAM", battery_test_write, NULL}, + {"Check data from SDRAM", battery_test_read, NULL}, + }; + + unsigned int num_menu_items = (sizeof (batteryMenu) / sizeof (batteryMenu[0])); + +/* char menu_title[15] = "\n Battery Backup SDRAM memory test."; */ + char menu_title[36] = "\n Battery Backup SDRAM memory test."; + + printf ("\n*************************************************************************\n"); + printf ("* This test will enable you to perform a battery test in 4 steps: *\n"); + printf ("* 1/ Select option 1 to write the value '"); + hex32out(BATTERY_TEST_PATTERN); + printf ("' to DRAM at address *\n* $"); + hex32out(SDRAM_BATTERY_TEST_BASE); + printf (", *\n"); + printf ("* 2/ Power the board off and wait 60 seconds, *\n"); + printf ("* 3/ Power the board back on, *\n"); + printf ("* 4/ Select option 2 to read at address $"); + hex32out(SDRAM_BATTERY_TEST_BASE); + printf (" and compare the *\n* value to the value written '"); + hex32out(BATTERY_TEST_PATTERN); + printf ("'. *\n"); + printf ("*************************************************************************"); + + menu (batteryMenu, num_menu_items, menu_title, MENU_OPT_NONE); + printf ("\n"); +} + +/* 01/11/01 jwf */ +void select_host_test_system (void) +{ + char selection; + + printf("Select your Host test system\n\n"); + printf("Make a selection by typing a number.\n\n"); + printf("1 - Cyclone SB923\n"); + printf("2 - Personal Computer or other\n"); + + do + { + selection = xgetchar(); + } + while( (selection != '1') && (selection != '2') ); + + if (selection == '1') + { + /* Modify the Outbound PCI Translate Register for a SB923, at address 0x1254 */ + *(volatile UINT32 *) POMWVR_ADDR = 0xa0000000; + } +} + +
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/hal_diag.c @@ -0,0 +1,623 @@ +/*============================================================================= +// +// 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): msalter +// Contributors:msalter +// Date: 2000-10-10 +// Purpose: HAL diagnostic output +// Description: Implementations of HAL diagnostic output support. +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +#include <pkgconf/hal.h> +#include <pkgconf/system.h> +#include CYGBLD_HAL_PLATFORM_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_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> // calling interface API +#include <cyg/hal/hal_misc.h> // helper functions +#include <cyg/hal/hal_diag.h> +#include <cyg/hal/hal_iq80310.h> // Hardware definitions +#include <cyg/hal/drv_api.h> // cyg_drv_interrupt_acknowledge + + +static void cyg_hal_plf_serial_init(void); + +void +cyg_hal_plf_comms_init(void) +{ + static int initialized = 0; + + if (initialized) + return; + + initialized = 1; + + cyg_hal_plf_serial_init(); +// cyg_hal_plf_lcd_init(); +} + +//============================================================================= +// Serial driver +//============================================================================= + +//----------------------------------------------------------------------------- +// There are two serial ports. +#define CYG_DEV_SERIAL_BASE_A 0xfe800000 // port A +#define CYG_DEV_SERIAL_BASE_B 0xfe810000 // port B + +//----------------------------------------------------------------------------- +// Default baud rate is 38400 +// Based on 3.6864 MHz xtal +#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==9600 +#define CYG_DEV_SERIAL_BAUD_MSB 0x00 +#define CYG_DEV_SERIAL_BAUD_LSB 0x0c +#endif +#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==19200 +#define CYG_DEV_SERIAL_BAUD_MSB 0x00 +#define CYG_DEV_SERIAL_BAUD_LSB 0x06 +#endif +#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==38400 +#define CYG_DEV_SERIAL_BAUD_MSB 0x00 +#define CYG_DEV_SERIAL_BAUD_LSB 0x03 +#endif +#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==57600 +#define CYG_DEV_SERIAL_BAUD_MSB 0x00 +#define CYG_DEV_SERIAL_BAUD_LSB 0x02 +#endif +#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==115200 +#define CYG_DEV_SERIAL_BAUD_MSB 0x00 +#define CYG_DEV_SERIAL_BAUD_LSB 0x01 +#endif + +#ifndef CYG_DEV_SERIAL_BAUD_MSB +#error Missing/incorrect serial baud rate defined - CDL error? +#endif + +//----------------------------------------------------------------------------- +// Define the serial registers. The Cogent board is equipped with a 16552 +// serial chip. +#define CYG_DEV_SERIAL_RBR 0x00 // receiver buffer register, read, dlab = 0 +#define CYG_DEV_SERIAL_THR 0x00 // transmitter holding register, write, dlab = 0 +#define CYG_DEV_SERIAL_DLL 0x00 // divisor latch (LS), read/write, dlab = 1 +#define CYG_DEV_SERIAL_IER 0x01 // interrupt enable register, read/write, dlab = 0 +#define CYG_DEV_SERIAL_DLM 0x01 // divisor latch (MS), read/write, dlab = 1 +#define CYG_DEV_SERIAL_IIR 0x02 // interrupt identification register, read, dlab = 0 +#define CYG_DEV_SERIAL_FCR 0x02 // fifo control register, write, dlab = 0 +#define CYG_DEV_SERIAL_LCR 0x03 // line control register, write +#define CYG_DEV_SERIAL_MCR 0x04 // modem control register, write +#define CYG_DEV_SERIAL_LSR 0x05 // line status register, read +#define CYG_DEV_SERIAL_MSR 0x06 // modem status register, read +#define CYG_DEV_SERIAL_SCR 0x07 // scratch pad register + +// The interrupt enable register bits. +#define SIO_IER_ERDAI 0x01 // enable received data available irq +#define SIO_IER_ETHREI 0x02 // enable THR empty interrupt +#define SIO_IER_ELSI 0x04 // enable receiver line status irq +#define SIO_IER_EMSI 0x08 // enable modem status interrupt + +// The interrupt identification register bits. +#define SIO_IIR_IP 0x01 // 0 if interrupt pending +#define SIO_IIR_ID_MASK 0x0e // mask for interrupt ID bits +#define ISR_Tx 0x02 +#define ISR_Rx 0x04 + +// The line status register bits. +#define SIO_LSR_DR 0x01 // data ready +#define SIO_LSR_OE 0x02 // overrun error +#define SIO_LSR_PE 0x04 // parity error +#define SIO_LSR_FE 0x08 // framing error +#define SIO_LSR_BI 0x10 // break interrupt +#define SIO_LSR_THRE 0x20 // transmitter holding register empty +#define SIO_LSR_TEMT 0x40 // transmitter register empty +#define SIO_LSR_ERR 0x80 // any error condition + +// The modem status register bits. +#define SIO_MSR_DCTS 0x01 // delta clear to send +#define SIO_MSR_DDSR 0x02 // delta data set ready +#define SIO_MSR_TERI 0x04 // trailing edge ring indicator +#define SIO_MSR_DDCD 0x08 // delta data carrier detect +#define SIO_MSR_CTS 0x10 // clear to send +#define SIO_MSR_DSR 0x20 // data set ready +#define SIO_MSR_RI 0x40 // ring indicator +#define SIO_MSR_DCD 0x80 // data carrier detect + +// The line control register bits. +#define SIO_LCR_WLS0 0x01 // word length select bit 0 +#define SIO_LCR_WLS1 0x02 // word length select bit 1 +#define SIO_LCR_STB 0x04 // number of stop bits +#define SIO_LCR_PEN 0x08 // parity enable +#define SIO_LCR_EPS 0x10 // even parity select +#define SIO_LCR_SP 0x20 // stick parity +#define SIO_LCR_SB 0x40 // set break +#define SIO_LCR_DLAB 0x80 // divisor latch access bit + +// The FIFO control register +#define SIO_FCR_FCR0 0x01 // enable xmit and rcvr fifos +#define SIO_FCR_FCR1 0x02 // clear RCVR FIFO +#define SIO_FCR_FCR2 0x04 // clear XMIT FIFO + + +//----------------------------------------------------------------------------- +typedef struct { + cyg_uint8* base; + cyg_int32 msec_timeout; + int isr_vector; +} channel_data_t; + +//----------------------------------------------------------------------------- +static void +init_serial_channel(const channel_data_t* __ch_data) +{ + cyg_uint8* base = __ch_data->base; + cyg_uint8 lcr; + + // 8-1-no parity. + lcr = SIO_LCR_WLS0 | SIO_LCR_WLS1; + + lcr |= SIO_LCR_DLAB; + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_LCR, lcr); + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_DLL, CYG_DEV_SERIAL_BAUD_LSB); + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_DLM, CYG_DEV_SERIAL_BAUD_MSB); + lcr &= ~SIO_LCR_DLAB; + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_LCR, lcr); + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_FCR, 0x07); // Enable & clear FIFO +} + +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_uint8 lsr; + + HAL_READ_UINT8(base+CYG_DEV_SERIAL_LSR, lsr); + if ((lsr & SIO_LSR_DR) == 0) + return false; + + HAL_READ_UINT8(base+CYG_DEV_SERIAL_RBR, *ch); + + 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; +} + +void +cyg_hal_plf_serial_putc(void* __ch_data, cyg_uint8 c) +{ + cyg_uint8* base = ((channel_data_t*)__ch_data)->base; + cyg_uint8 lsr; + CYGARC_HAL_SAVE_GP(); + + do { + HAL_READ_UINT8(base+CYG_DEV_SERIAL_LSR, lsr); + } while ((lsr & SIO_LSR_THRE) == 0); + + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_THR, c); + + // Hang around until the character has been safely sent. + do { + HAL_READ_UINT8(base+CYG_DEV_SERIAL_LSR, lsr); + } while ((lsr & SIO_LSR_THRE) == 0); + + CYGARC_HAL_RESTORE_GP(); +} + +static const channel_data_t channels[2] = { + { (cyg_uint8*)CYG_DEV_SERIAL_BASE_A, 1000, CYGNUM_HAL_INTERRUPT_SERIAL_A}, + { (cyg_uint8*)CYG_DEV_SERIAL_BASE_B, 1000, CYGNUM_HAL_INTERRUPT_SERIAL_B} +}; + +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; + cyg_uint8 ier; + int ret = 0; + CYGARC_HAL_SAVE_GP(); + + switch (__func) { + case __COMMCTL_IRQ_ENABLE: + HAL_INTERRUPT_UNMASK(chan->isr_vector); + HAL_INTERRUPT_SET_LEVEL(chan->isr_vector, 1); + HAL_READ_UINT8(chan->base+CYG_DEV_SERIAL_IER, ier); + ier |= SIO_IER_ERDAI; + HAL_WRITE_UINT8(chan->base+CYG_DEV_SERIAL_IER, ier); + irq_state = 1; + break; + case __COMMCTL_IRQ_DISABLE: + ret = irq_state; + irq_state = 0; + HAL_INTERRUPT_MASK(chan->isr_vector); + HAL_READ_UINT8(chan->base+CYG_DEV_SERIAL_IER, ier); + ier &= ~SIO_IER_ERDAI; + HAL_WRITE_UINT8(chan->base+CYG_DEV_SERIAL_IER, ier); + 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) +{ + channel_data_t* chan = (channel_data_t*)__ch_data; + cyg_uint8 _iir; + int res = 0; + CYGARC_HAL_SAVE_GP(); + + HAL_READ_UINT8(chan->base+CYG_DEV_SERIAL_IIR, _iir); + _iir &= SIO_IIR_ID_MASK; + + *__ctrlc = 0; + if ( ISR_Rx == _iir ) { + cyg_uint8 c, lsr; + HAL_READ_UINT8(chan->base+CYG_DEV_SERIAL_LSR, lsr); + if (lsr & SIO_LSR_DR) { + + HAL_READ_UINT8(chan->base+CYG_DEV_SERIAL_RBR, c); + + if( cyg_hal_is_break( &c , 1 ) ) + *__ctrlc = 1; + } + + // Acknowledge the interrupt + HAL_INTERRUPT_ACKNOWLEDGE(chan->isr_vector); + 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(channels[0].isr_vector); + HAL_INTERRUPT_MASK(channels[1].isr_vector); + + // Init channels + init_serial_channel(&channels[0]); + init_serial_channel(&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, &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, &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); +} + + +//============================================================================= +// Compatibility with older stubs +//============================================================================= + +#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG + + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +#include <cyg/hal/drv_api.h> +#include <cyg/hal/hal_stub.h> // cyg_hal_gdb_interrupt +#endif + +// 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 + +/*---------------------------------------------------------------------------*/ +#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL==0 +// This is the base address of the A-channel +#define CYG_DEV_SERIAL_BASE CYG_DEV_SERIAL_BASE_A +#define CYG_DEV_SERIAL_INT CYGNUM_HAL_INTERRUPT_SERIAL_A +#else +// This is the base address of the B-channel +#define CYG_DEV_SERIAL_BASE CYG_DEV_SERIAL_BASE_B +#define CYG_DEV_SERIAL_INT CYGNUM_HAL_INTERRUPT_SERIAL_B +#endif + +static channel_data_t ser_channel = { (cyg_uint8*)CYG_DEV_SERIAL_BASE, 0, 0}; + +#ifdef HAL_DIAG_USES_HARDWARE + +void hal_diag_init(void) +{ + static int init = 0; + char *msg = "\n\rARM eCos\n\r"; + + if (init++) return; + + init_serial_channel(&ser_channel); + + while (*msg) hal_diag_write_char(*msg++); +} + +#ifdef DEBUG_DIAG +#if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) +#define DIAG_BUFSIZE 32 +#else +#define DIAG_BUFSIZE 2048 +#endif +static char diag_buffer[DIAG_BUFSIZE]; +static int diag_bp = 0; +#endif + +void hal_diag_write_char(char c) +{ + cyg_uint8 lsr; + + hal_diag_init(); + + cyg_hal_plf_serial_putc(&ser_channel, c); + +#ifdef DEBUG_DIAG + diag_buffer[diag_bp++] = c; + if (diag_bp == DIAG_BUFSIZE) { + while (1) ; + diag_bp = 0; + } +#endif +} + +void hal_diag_read_char(char *c) +{ + *c = cyg_hal_plf_serial_getc(&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) init_serial_channel(&ser_channel); // avoid warning +} + +// Actually send character down the wire +static void +hal_diag_write_char_serial(char c) +{ + cyg_hal_plf_serial_putc(&ser_channel, c); +} + +static bool +hal_diag_read_serial(char *c) +{ + long timeout = 1000000000; // A long time... + while (!cyg_hal_plf_serial_getc_nonblock(&ser_channel, c)) + if (0 == --timeout) return false; + + return true; +} + +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_DEV_SERIAL_INT); + if( c1 == 3 ) { + // Ctrl-C: breakpoint. + cyg_hal_gdb_interrupt (__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/iq80310/current/src/iq80310_misc.c @@ -0,0 +1,1073 @@ +//========================================================================== +// +// iq80310_misc.c +// +// HAL misc board support code for XScale IQ80310 +// +//========================================================================== +//####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): msalter +// Contributors: msalter +// Date: 2000-10-10 +// Purpose: HAL board support +// Description: Implementations of HAL board interfaces +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include <pkgconf/hal.h> +#include <pkgconf/system.h> +#include CYGBLD_HAL_PLATFORM_H +#include CYGHWR_MEMORY_LAYOUT_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_stub.h> // Stub macros +#include <cyg/hal/hal_if.h> // calling interface API +#include <cyg/hal/hal_arch.h> // Register state info +#include <cyg/hal/hal_diag.h> +#include <cyg/hal/hal_intr.h> // Interrupt names +#include <cyg/hal/hal_cache.h> +#include <cyg/hal/hal_iq80310.h> // Hardware definitions +#include <cyg/infra/diag.h> // diag_printf +#include <cyg/hal/drv_api.h> // CYG_ISR_HANDLED + +static cyg_uint32 nfiq_ISR(cyg_vector_t vector, cyg_addrword_t data); +static cyg_uint32 nirq_ISR(cyg_vector_t vector, cyg_addrword_t data); +static cyg_uint32 nmi_mcu_ISR(cyg_vector_t vector, cyg_addrword_t data); +static cyg_uint32 nmi_patu_ISR(cyg_vector_t vector, cyg_addrword_t data); +static cyg_uint32 nmi_satu_ISR(cyg_vector_t vector, cyg_addrword_t data); +static cyg_uint32 nmi_pb_ISR(cyg_vector_t vector, cyg_addrword_t data); +static cyg_uint32 nmi_sb_ISR(cyg_vector_t vector, cyg_addrword_t data); + +// Some initialization has already been done before we get here. +// +// Set up the interrupt environment. +// Set up the MMU so that we can use caches. +// Enable caches. +// - All done! + +void hal_hardware_init(void) +{ + unsigned rtmp = 0; + + // Route INTA-INTD to IRQ pin + // The Yavapai manual is incorrect in that a '1' value + // routes to the IRQ line, not a '0' value. + *PIRSR_REG = 0x0f; + + // Disable all interrupt sources: + *IIMR_REG = 0x7f; + *OIMR_REG = 0x7f; // don't mask INTD which is really xint3 + *X3MASK_REG = XINT3_TIMER | XINT3_ETHERNET | XINT3_UART_1 | \ + XINT3_UART_2 | XINT3_PCI_INTD; + + // Let the timer run at a default rate (for delays) + hal_clock_initialize(CYGNUM_HAL_RTC_PERIOD); + + // Set up eCos/ROM interfaces + hal_if_init(); + + // attach some builtin interrupt handlers + HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_NIRQ, &nirq_ISR, CYGNUM_HAL_INTERRUPT_NIRQ, 0); + HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_NIRQ); + + HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_NFIQ, &nfiq_ISR, CYGNUM_HAL_INTERRUPT_NFIQ, 0); + HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_NFIQ); + + HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_MCU_ERR, &nmi_mcu_ISR, CYGNUM_HAL_INTERRUPT_MCU_ERR, 0); + HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_MCU_ERR); + + HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_PATU_ERR, &nmi_patu_ISR, CYGNUM_HAL_INTERRUPT_PATU_ERR, 0); + HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_PATU_ERR); + + HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_SATU_ERR, &nmi_satu_ISR, CYGNUM_HAL_INTERRUPT_SATU_ERR, 0); + HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_SATU_ERR); + + HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_PBDG_ERR, &nmi_pb_ISR, CYGNUM_HAL_INTERRUPT_PBDG_ERR, 0); + HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_PBDG_ERR); + + HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_SBDG_ERR, &nmi_sb_ISR, CYGNUM_HAL_INTERRUPT_SBDG_ERR, 0); + HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_SBDG_ERR); + + // Enable FIQ +#if 0 + asm volatile ("mrs %0,cpsr\n" + "bic %0,%0,#0x40\n" + "msr cpsr,%0\n" + : "=r"(rtmp) : ); +#endif +} + +#include CYGHWR_MEMORY_LAYOUT_H +typedef void code_fun(void); +void iq80310_program_new_stack(void *func) +{ + register CYG_ADDRESS stack_ptr asm("sp"); + register CYG_ADDRESS old_stack asm("r4"); + register code_fun *new_func asm("r0"); + old_stack = stack_ptr; + stack_ptr = CYGMEM_REGION_ram + CYGMEM_REGION_ram_SIZE - sizeof(CYG_ADDRESS); + new_func = (code_fun*)func; + new_func(); + stack_ptr = old_stack; + return; +} + +// ------------------------------------------------------------------------- + +// Clock can come from the PMU or from an external timer. +// The external timer is the preferred choice. + +#if CYGNUM_HAL_INTERRUPT_RTC == CYGNUM_HAL_INTERRUPT_PMU_CCNT_OVFL + +// Proper version that uses the clock counter in the PMU to do proper +// interrupts that require acknowledgement and all that good stuff. + +static cyg_uint32 hal_clock_init_period; // The START value, it counts up + +void hal_clock_initialize(cyg_uint32 period) +{ + // event types both zero; clear all 3 interrupts; + // disable all 3 counter interrupts; + // CCNT counts every processor cycle; reset all counters; + // enable PMU. + register cyg_uint32 init = 0x00000707; + asm volatile ( + "mcr p14,0,%0,c0,c0,0;" // write into PMNC + : + : "r"(init) + /*:*/ + ); + // the CCNT in the PMU counts *up* then interrupts at overflow + // ie. at 0x1_0000_0000 as it were. + // So init to 0xffffffff - period + 1 to get the right answer. + period = (~period) + 1; + hal_clock_init_period = period; + hal_clock_reset( 0, 0 ); +} + +// This routine is called during a clock interrupt. +// (before acknowledging the interrupt) +void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period) +{ + asm volatile ( + "mrc p14,0,r0,c1,c0,0;" // read from CCNT - how long since OVFL + "add %0, %0, r0;" // synchronize with previous overflow + "mcr p14,0,%0,c1,c0,0;" // write into CCNT + : + : "r"(hal_clock_init_period) + : "r0" + ); +} + +// Read the current value of the clock, returning the number of hardware +// "ticks" that have occurred (i.e. how far away the current value is from +// the start) + +void hal_clock_read(cyg_uint32 *pvalue) +{ + register cyg_uint32 now; + asm volatile ( + "mrc p14,0,%0,c1,c0,0;" // read from CCNT + : "=r"(now) + : + /*:*/ + ); + *pvalue = now - hal_clock_init_period; +} + +// Delay for some usecs. +void hal_delay_us(cyg_uint32 delay) +{ + int i; + // the loop is going to take 3 ticks. At 600 MHz, to give uS, multiply + // by 600/3 = 200. No volatile is needed on i; gcc recognizes delay + // loops and does NOT elide them. + for ( i = 200 * delay; i ; i--) + ; +} + +#else // external timer + +static cyg_uint32 _period; + +void hal_clock_initialize(cyg_uint32 period) +{ + _period = period; + + // disable timer + EXT_TIMER_INT_DISAB(); + EXT_TIMER_CNT_DISAB(); + + *TIMER_LA0_REG_ADDR = period; + *TIMER_LA1_REG_ADDR = period >> 8; + *TIMER_LA2_REG_ADDR = period >> 16; + + EXT_TIMER_INT_ENAB(); + EXT_TIMER_CNT_ENAB(); +} + +// This routine is called during a clock interrupt. + +void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period) +{ + // to clear the timer interrupt, clear the timer interrupt + // enable, then re-set the int. enable bit + EXT_TIMER_INT_DISAB(); + EXT_TIMER_INT_ENAB(); +} + +// Read the current value of the clock, returning the number of hardware +// "ticks" that have occurred (i.e. how far away the current value is from +// the start) + +void hal_clock_read(cyg_uint32 *pvalue) +{ + cyg_uint8 cnt0, cnt1, cnt2, cnt3; + cyg_uint32 timer_val;; + + // first read latches the count + // Actually, it looks like there is a hardware problem where + // invalid counts get latched. This do while loop appears + // to get around the problem. + do { + cnt0 = *TIMER_LA0_REG_ADDR & TIMER_COUNT_MASK; + } while (cnt0 == 0); + cnt1 = *TIMER_LA1_REG_ADDR & TIMER_COUNT_MASK; + cnt2 = *TIMER_LA2_REG_ADDR & TIMER_COUNT_MASK; + cnt3 = *TIMER_LA3_REG_ADDR & 0xf; /* only 4 bits in most sig. */ + + /* now build up the count value */ + timer_val = ((cnt0 & 0x40) >> 1) | (cnt0 & 0x1f); + timer_val |= (((cnt1 & 0x40) >> 1) | (cnt1 & 0x1f)) << 6; + timer_val |= (((cnt2 & 0x40) >> 1) | (cnt2 & 0x1f)) << 12; + timer_val |= cnt3 << 18; + + *pvalue = timer_val; +} + +// Delay for some usecs. +void hal_delay_us(cyg_uint32 delay) +{ +#define _CNT_MASK 0x3fffff +#define _TICKS_PER_USEC (EXT_TIMER_CLK_FREQ / 1000000) + cyg_uint32 now, last, diff, ticks; + + hal_clock_read(&last); + diff = ticks = 0; + + while (delay > ticks) { + hal_clock_read(&now); + + if (now < last) + diff += ((_period - last) + now); + else + diff += (now - last); + + last = now; + + if (diff >= _TICKS_PER_USEC) { + ticks += (diff / _TICKS_PER_USEC); + diff %= _TICKS_PER_USEC; + } + } +} + +#endif + +// ------------------------------------------------------------------------- + +typedef cyg_uint32 cyg_ISR(cyg_uint32 vector, CYG_ADDRWORD data); + +extern void cyg_interrupt_post_dsr( CYG_ADDRWORD intr_obj ); + +static inline cyg_uint32 +hal_call_isr (cyg_uint32 vector) +{ + cyg_ISR *isr; + CYG_ADDRWORD data; + cyg_uint32 isr_ret; + + isr = (cyg_ISR*) hal_interrupt_handlers[vector]; + data = hal_interrupt_data[vector]; + + isr_ret = (*isr) (vector, data); + +#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT + if (isr_ret & CYG_ISR_CALL_DSR) { + cyg_interrupt_post_dsr (hal_interrupt_objects[vector]); + } +#endif + + return isr_ret & ~CYG_ISR_CALL_DSR; +} + +void _scrub_ecc(unsigned p) +{ + asm volatile ("ldrb r4, [%0]\n" + "strb r4, [%0]\n" : : "r"(p) ); +} + +static cyg_uint32 nmi_mcu_ISR(cyg_vector_t vector, cyg_addrword_t data) +{ + cyg_uint32 eccr_reg; + + // Read current state of ECC register + eccr_reg = *ECCR_REG; + + // Turn off all ecc error reporting + *ECCR_REG = 0x4; + + // Check for ECC Error 0 + if(*MCISR_REG & 0x1) { + +#ifdef DEBUG_NMI + diag_printf("ELOG0 = 0x%X\n", *ELOG0_REG); + diag_printf("ECC Error Detected at Address 0x%X\n",*ECAR0_REG); +#endif + + // Check for single-bit error + if(!(*ELOG0_REG & 0x00000100)) { + // call ECC restoration function + _scrub_ecc(*ECAR0_REG); + + // Clear the MCISR + *MCISR_REG = 0x1; + } else { +#ifdef DEBUG_NMI + diag_printf("Multi-bit or nibble error\n"); +#endif + } + } + + // Check for ECC Error 1 + if(*MCISR_REG & 0x2) { + +#ifdef DEBUG_NMI + diag_printf("ELOG0 = 0x%X\n",*ELOG1_REG); + diag_printf("ECC Error Detected at Address 0x%X\n",*ECAR1_REG); +#endif + + // Check for single-bit error + if(!(*ELOG1_REG & 0x00000100)) { + // call ECC restoration function + _scrub_ecc(*ECAR1_REG); + + // Clear the MCISR + *MCISR_REG = 0x2; + } + else { +#ifdef DEBUG_NMI + diag_printf("Multi-bit or nibble error\n"); +#endif + } + } + + // Check for ECC Error N + if(*MCISR_REG & 0x4) { + // Clear the MCISR + *MCISR_REG = 0x4; + diag_printf("Uncorrectable error during RMW\n"); + } + + // Restore ECCR register + *ECCR_REG = eccr_reg; + + // clear the interrupt condition + *MCISR_REG = *MCISR_REG & 7; + + return CYG_ISR_HANDLED; +} + +static cyg_uint32 nmi_patu_ISR(cyg_vector_t vector, cyg_addrword_t data) +{ + cyg_uint32 status; + + status = *PATUISR_REG; + +#ifdef DEBUG_NMI + if (status & 0x001) diag_printf ("PPCI Master Parity Error\n"); + if (status & 0x002) diag_printf ("PPCI Target Abort (target)\n"); + if (status & 0x004) diag_printf ("PPCI Target Abort (master)\n"); + if (status & 0x008) diag_printf ("PPCI Master Abort\n"); + if (status & 0x010) diag_printf ("Primary P_SERR# Detected\n"); + if (status & 0x080) diag_printf ("Internal Bus Master Abort\n"); + if (status & 0x100) diag_printf ("PATU BIST Interrupt\n"); + if (status & 0x200) diag_printf ("PPCI Parity Error Detected\n"); + if (status & 0x400) diag_printf ("Primary P_SERR# Asserted\n"); +#endif + + *PATUISR_REG = status & 0x79f; + *PATUSR_REG |= 0xf900; + + return CYG_ISR_HANDLED; +} + + +static cyg_uint32 nmi_satu_ISR(cyg_vector_t vector, cyg_addrword_t data) +{ + cyg_uint32 status; + + status = *SATUISR_REG; + +#ifdef DEBUG_NMI + if (status & 0x001) diag_printf ("SPCI Master Parity Error\n"); + if (status & 0x002) diag_printf ("SPCI Target Abort (target)\n"); + if (status & 0x004) diag_printf ("SPCI Target Abort (master)\n"); + if (status & 0x008) diag_printf ("SPCI Master Abort\n"); + if (status & 0x010) diag_printf ("Secondary P_SERR# Detected\n"); + if (status & 0x080) diag_printf ("Internal Bus Master Abort\n"); + if (status & 0x200) diag_printf ("SPCI Parity Error Detected\n"); + if (status & 0x400) diag_printf ("Secondary P_SERR# Asserted\n"); +#endif + + *SATUISR_REG = status & 0x69f; + *SATUSR_REG |= 0xf900; + + return CYG_ISR_HANDLED; +} + +static cyg_uint32 nmi_pb_ISR(cyg_vector_t vector, cyg_addrword_t data) +{ + cyg_uint32 status; + + status = *PBISR_REG; + +#ifdef DEBUG_NMI + if (status & 0x001) diag_printf ("PPCI Master Parity Error\n"); + if (status & 0x002) diag_printf ("PPCI Target Abort (target)\n"); + if (status & 0x004) diag_printf ("PPCI Target Abort (master)\n"); + if (status & 0x008) diag_printf ("PPCI Master Abort\n"); + if (status & 0x010) diag_printf ("Primary P_SERR# Asserted\n"); + if (status & 0x020) diag_printf ("PPCI Parity Error Detected\n"); +#endif + + *PBISR_REG = status & 0x3f; + *PSR_REG |= 0xf900; + + return CYG_ISR_HANDLED; +} + + +static cyg_uint32 nmi_sb_ISR(cyg_vector_t vector, cyg_addrword_t data) +{ + cyg_uint32 status; + + status = *SBISR_REG; + + *SBISR_REG = status & 0x7f; + *SSR_REG |= 0xf900; + + return CYG_ISR_HANDLED; +} + + +static cyg_uint32 nfiq_ISR(cyg_vector_t vector, cyg_addrword_t data) +{ + cyg_uint32 sources; + int i, isr_ret; + + // Check NMI + sources = *NISR_REG; + for (i = 0; i < 12; i++) { + if (sources & (1<<i)) { + isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_MCU_ERR + i); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); + return isr_ret; + } + } + return 0; +} + +static cyg_uint32 nirq_ISR(cyg_vector_t vector, cyg_addrword_t data) +{ + cyg_uint32 sources; + int i, isr_ret; + + // Check XINT3 + sources = *X3ISR_REG & ~(*X3MASK_REG); + for (i = 0; i < 5; i++) { + if (sources & (1 << i)) { + isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_TIMER + i); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); + return isr_ret; + } + } + // What to do about S_INTA-S_INTC? + + // Check XINT6 + sources = *X6ISR_REG; + for (i = 0; i < 3; i++) { + // check DMA irqs + if (sources & (1<<i)) { + isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_DMA_0 + i); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); + return isr_ret; + } + } + if (sources & 0x10) { + // performance monitor + _80312_EMISR = *EMISR_REG; + if (_80312_EMISR & 1) { + isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_GTSC); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); + } + if (_80312_EMISR & 0x7ffe) { + isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_PEC); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); + } + return 0; + } + if (sources & 0x20) { + // Application Accelerator Unit + isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_AAIP); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); + return isr_ret; + } + + // Check XINT7 + sources = *X7ISR_REG; + if (sources & 2) { + // I2C Unit + cyg_uint32 i2c_sources = *ISR_REG; + + if (i2c_sources & (1<<7)) { + isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_I2C_RX_FULL); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); + } + if (i2c_sources & (1<<6)) { + isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_I2C_TX_EMPTY); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); + } + if (i2c_sources & (1<<10)) { + isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_I2C_BUS_ERR); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); + } + if (i2c_sources & (1<<4)) { + isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_I2C_STOP); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); + } + if (i2c_sources & (1<<5)) { + isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_I2C_LOSS); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); + } + if (i2c_sources & (1<<9)) { + isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_I2C_ADDRESS); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); + } + return 0; + } + if (sources & 4) { + // Messaging Unit + cyg_uint32 inb_sources = *IISR_REG; + + if (inb_sources & (1<<0)) { + isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_MESSAGE_0); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); + } + if (inb_sources & (1<<1)) { + isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_MESSAGE_1); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); + } + if (inb_sources & (1<<2)) { + isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_DOORBELL); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); + } + if (inb_sources & (1<<4)) { + isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_QUEUE_POST); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); + } + if (inb_sources & (1<<6)) { + isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_INDEX_REGISTER); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); + } + return 0; + } + if (sources & 8) { + // BIST + isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_BIST); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); + } + + return 0; +} + +// 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) +{ + int sources, masks; + + asm volatile ( // read the interrupt source reg INTSRC + "mrc p13,0,%0,c4,c0,0;" + : "=r"(sources) + : + /*:*/ + ); + asm volatile ( // read the interrupt control reg INTCTL + "mrc p13,0,%0,c0,c0,0;" + : "=r"(masks) + : + /*:*/ + ); + // is a source both unmasked and active? + if ( (0 != (1 & masks)) && (0 != ((8 << 28) & sources)) ) + return CYGNUM_HAL_INTERRUPT_NFIQ; + if ( (0 != (2 & masks)) && (0 != ((4 << 28) & sources)) ) + return CYGNUM_HAL_INTERRUPT_NIRQ; + if ( (0 != (8 & masks)) && (0 != ((2 << 28) & sources)) ) + return CYGNUM_HAL_INTERRUPT_BCU_INTERRUPT; + if ( (0 != (4 & masks)) && (0 != ((1 << 28) & sources)) ) { + // more complicated; it's the PMU. + asm volatile ( // read the PMNC perfmon control reg + "mrc p14,0,%0,c0,c0,0;" + : "=r"(sources) + : + /*:*/ + ); + // sources is now the PMNC performance monitor control register + // enable bits are 4..6, status bits are 8..10 + sources = (sources >> 4) & (sources >> 8); + if ( 1 & sources ) + return CYGNUM_HAL_INTERRUPT_PMU_PMN0_OVFL; + if ( 2 & sources ) + return CYGNUM_HAL_INTERRUPT_PMU_PMN1_OVFL; + if ( 4 & sources ) + return CYGNUM_HAL_INTERRUPT_PMU_CCNT_OVFL; + } + + return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen! +} + +// +// Interrupt control +// + +void hal_interrupt_mask(int vector) +{ + int mask = 0; + int submask = 0; + switch ( vector ) { + case CYGNUM_HAL_INTERRUPT_PMU_PMN0_OVFL: + case CYGNUM_HAL_INTERRUPT_PMU_PMN1_OVFL: + case CYGNUM_HAL_INTERRUPT_PMU_CCNT_OVFL: + submask = vector - CYGNUM_HAL_INTERRUPT_PMU_PMN0_OVFL; // 0 to 2 + // select interrupt enable bit and also enable the perfmon per se + submask = (1 << (submask + 4)); // bits 4-6 are masks + asm volatile ( + "mrc p14,0,r1,c0,c0,0;" + "bic r1, r1, #0x700;" // clear the overflow/interrupt flags + "bic r1, r1, #0x006;" // clear the reset bits + "bic %0, r1, %0;" // preserve r1; better for debugging + "tsts %0, #0x070;" // are all 3 sources now off? + "biceq %0, %0, #1;" // if so, disable entirely. + "mcr p14,0,%0,c0,c0,0;" + : + : "r"(submask) + : "r1" + ); + mask = 4; + break; + case CYGNUM_HAL_INTERRUPT_BCU_INTERRUPT: + // Nothing specific to do here + mask = 8; + break; + case CYGNUM_HAL_INTERRUPT_NIRQ : + mask = 2; + break; + case CYGNUM_HAL_INTERRUPT_NFIQ : + mask = 1; + break; + case CYGNUM_HAL_INTERRUPT_GTSC: + *GTMR_REG &= ~1; + return; + case CYGNUM_HAL_INTERRUPT_PEC: + *ESR_REG &= ~(1<<16); + return; + case CYGNUM_HAL_INTERRUPT_AAIP: + *ADCR_REG &= ~1; + return; + case CYGNUM_HAL_INTERRUPT_I2C_TX_EMPTY...CYGNUM_HAL_INTERRUPT_I2C_ADDRESS: + *ICR_REG &= ~(1<<(vector - CYGNUM_HAL_INTERRUPT_I2C_TX_EMPTY)); + return; + case CYGNUM_HAL_INTERRUPT_MESSAGE_0...CYGNUM_HAL_INTERRUPT_INDEX_REGISTER: + *IIMR_REG &= ~(1<<(vector - CYGNUM_HAL_INTERRUPT_MESSAGE_0)); + return; + case CYGNUM_HAL_INTERRUPT_BIST: + *ATUCR_REG &= ~(1<<3); + return; + case CYGNUM_HAL_INTERRUPT_P_SERR: // FIQ + *ATUCR_REG &= ~(1<<9); + return; + case CYGNUM_HAL_INTERRUPT_S_SERR: // FIQ + *ATUCR_REG &= ~(1<<10); + return; + case CYGNUM_HAL_INTERRUPT_TIMER...CYGNUM_HAL_INTERRUPT_PCI_S_INTD: + *X3MASK_REG |= (1<<(vector - CYGNUM_HAL_INTERRUPT_TIMER)); + return; + + // The hardware doesn't (yet?) provide masking or status for these + // even though they can trigger cpu interrupts. ISRs will need to + // poll the device to see if the device actually triggered the + // interrupt. + case CYGNUM_HAL_INTERRUPT_PCI_S_INTC: + case CYGNUM_HAL_INTERRUPT_PCI_S_INTB: + case CYGNUM_HAL_INTERRUPT_PCI_S_INTA: + default: + /* do nothing */ + return; + } + asm volatile ( + "mrc p13,0,r1,c0,c0,0;" + "bic r1, r1, %0;" + "mcr p13,0,r1,c0,c0,0;" + : + : "r"(mask) + : "r1" + ); +} + +void hal_interrupt_unmask(int vector) +{ + int mask = 0; + int submask = 0; + switch ( vector ) { + case CYGNUM_HAL_INTERRUPT_PMU_PMN0_OVFL: + case CYGNUM_HAL_INTERRUPT_PMU_PMN1_OVFL: + case CYGNUM_HAL_INTERRUPT_PMU_CCNT_OVFL: + submask = vector - CYGNUM_HAL_INTERRUPT_PMU_PMN0_OVFL; // 0 to 2 + // select interrupt enable bit and also enable the perfmon per se + submask = 1 + (1 << (submask + 4)); // bits 4-6 are masks + asm volatile ( + "mrc p14,0,r1,c0,c0,0;" + "bic r1, r1, #0x700;" // clear the overflow/interrupt flags + "bic r1, r1, #0x006;" // clear the reset bits + "orr %0, r1, %0;" // preserve r1; better for debugging + "mcr p14,0,%0,c0,c0,0;" + "mrc p13,0,r2,c8,c0,0;" // steer PMU interrupt to IRQ + "and r2, r2, #2;" // preserve the other bit (BCU steer) + "mcr p13,0,r2,c8,c0,0;" + : + : "r"(submask) + : "r1","r2" + ); + mask = 4; + break; + case CYGNUM_HAL_INTERRUPT_BCU_INTERRUPT: + asm volatile ( + "mrc p13,0,r2,c8,c0,0;" // steer BCU interrupt to IRQ + "and r2, r2, #1;" // preserve the other bit (PMU steer) + "mcr p13,0,r2,c8,c0,0;" + : + : + : "r2" + ); + mask = 8; + break; + case CYGNUM_HAL_INTERRUPT_NIRQ : + mask = 2; + break; + case CYGNUM_HAL_INTERRUPT_NFIQ : + mask = 1; + break; + case CYGNUM_HAL_INTERRUPT_GTSC: + *GTMR_REG |= 1; + return; + case CYGNUM_HAL_INTERRUPT_PEC: + *ESR_REG |= (1<<16); + return; + case CYGNUM_HAL_INTERRUPT_AAIP: + *ADCR_REG |= 1; + return; + case CYGNUM_HAL_INTERRUPT_I2C_TX_EMPTY...CYGNUM_HAL_INTERRUPT_I2C_ADDRESS: + *ICR_REG |= (1<<(vector - CYGNUM_HAL_INTERRUPT_I2C_TX_EMPTY)); + return; + case CYGNUM_HAL_INTERRUPT_MESSAGE_0...CYGNUM_HAL_INTERRUPT_INDEX_REGISTER: + *IIMR_REG |= (1<<(vector - CYGNUM_HAL_INTERRUPT_MESSAGE_0)); + return; + case CYGNUM_HAL_INTERRUPT_BIST: + *ATUCR_REG |= (1<<3); + return; + case CYGNUM_HAL_INTERRUPT_P_SERR: // FIQ + *ATUCR_REG |= (1<<9); + return; + case CYGNUM_HAL_INTERRUPT_S_SERR: // FIQ + *ATUCR_REG |= (1<<10); + return; + case CYGNUM_HAL_INTERRUPT_TIMER...CYGNUM_HAL_INTERRUPT_PCI_S_INTD: + *X3MASK_REG &= ~(1<<(vector - CYGNUM_HAL_INTERRUPT_TIMER)); + return; + + // The hardware doesn't (yet?) provide masking or status for these + // even though they can trigger cpu interrupts. ISRs will need to + // poll the device to see if the device actually triggered the + // interrupt. + case CYGNUM_HAL_INTERRUPT_PCI_S_INTC: + case CYGNUM_HAL_INTERRUPT_PCI_S_INTB: + case CYGNUM_HAL_INTERRUPT_PCI_S_INTA: + default: + /* do nothing */ + return; + } + asm volatile ( + "mrc p13,0,r1,c0,c0,0;" + "orr %0, r1, %0;" + "mcr p13,0,%0,c0,c0,0;" + : + : "r"(mask) + : "r1" + ); +} + +void hal_interrupt_acknowledge(int vector) +{ + int submask = 0; + switch ( vector ) { + case CYGNUM_HAL_INTERRUPT_PMU_PMN0_OVFL: + case CYGNUM_HAL_INTERRUPT_PMU_PMN1_OVFL: + case CYGNUM_HAL_INTERRUPT_PMU_CCNT_OVFL: + submask = vector - CYGNUM_HAL_INTERRUPT_PMU_PMN0_OVFL; // 0 to 2 + // select interrupt enable bit and also enable the perfmon per se + submask = (1 << (submask + 8)); // bits 8-10 are status; write 1 clr + // Careful not to ack other interrupts or zero any counters: + asm volatile ( + "mrc p14,0,r1,c0,c0,0;" + "bic r1, r1, #0x700;" // clear the overflow/interrupt flags + "bic r1, r1, #0x006;" // clear the reset bits + "orr %0, r1, %0;" // preserve r1; better for debugging + "mcr p14,0,%0,c0,c0,0;" + : + : "r"(submask) + : "r1" + ); + break; + case CYGNUM_HAL_INTERRUPT_BCU_INTERRUPT: + case CYGNUM_HAL_INTERRUPT_NIRQ : + case CYGNUM_HAL_INTERRUPT_NFIQ : + default: + /* do nothing */ + return; + } +} + +void hal_interrupt_configure(int vector, int level, int up) +{ +} + +void hal_interrupt_set_level(int vector, int level) +{ +} + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +/*------------------------------------------------------------------------*/ +// HW Debug support + +static inline void set_ibcr0(unsigned x) +{ + asm volatile ("mcr p15,0,%0,c14,c8,0" : : "r"(x) ); +} + +static inline unsigned get_ibcr0(void) +{ + unsigned x; + asm volatile ("mrc p15,0,%0,c14,c8,0" : "=r"(x) : ); + return x; +} + +static inline void set_ibcr1(unsigned x) +{ + asm volatile ("mcr p15,0,%0,c14,c9,0" : : "r"(x) ); +} + +static inline unsigned get_ibcr1(void) +{ + unsigned x; + asm volatile ("mrc p15,0,%0,c14,c9,0" : "=r"(x) : ); + return x; +} + +static inline void set_dbr0(unsigned x) +{ + asm volatile ("mcr p15,0,%0,c14,c0,0" : : "r"(x) ); +} + +static inline unsigned get_dbr0(void) +{ + unsigned x; + asm volatile ("mrc p15,0,%0,c14,c0,0" : "=r"(x) : ); + return x; +} + +static inline void set_dbr1(unsigned x) +{ + asm volatile ("mcr p15,0,%0,c14,c3,0" : : "r"(x) ); +} + +static inline unsigned get_dbr1(void) +{ + unsigned x; + asm volatile ("mrc p15,0,%0,c14,c3,0" : "=r"(x) : ); + return x; +} + +static inline void set_dbcon(unsigned x) +{ + asm volatile ("mcr p15,0,%0,c14,c4,0" : : "r"(x) ); +} + +static inline unsigned get_dbcon(void) +{ + unsigned x; + asm volatile ("mrc p15,0,%0,c14,c4,0" : "=r"(x) : ); + return x; +} + +static inline void set_dcsr(unsigned x) +{ + asm volatile ("mcr p14,0,%0,c10,c0,0" : : "r"(x) ); +} + +static inline unsigned get_dcsr(void) +{ + unsigned x; + asm volatile ("mrc p14,0,%0,c10,c0,0" : "=r"(x) : ); + return x; +} + + +int cyg_hal_plf_hw_breakpoint(int setflag, void *vaddr, int len) +{ + unsigned int addr = (unsigned)vaddr; + + if (setflag) { + if (!(get_ibcr0() & 1)) + set_ibcr0(addr | 1); + else if (!(get_ibcr1() & 1)) + set_ibcr1(addr | 1); + else + return -1; + } else { + unsigned x = (addr | 1); + if (get_ibcr0() == x) + set_ibcr0(0); + else if (get_ibcr0() == x) + set_ibcr1(0); + else + return -1; + } + return 0; +} + +int cyg_hal_plf_hw_watchpoint(int setflag, void *vaddr, int len, int type) +{ + unsigned int mask, bit_nr, mode, addr = (unsigned)vaddr; + unsigned dbcon = get_dbcon(); + + mask = 0x80000000; + bit_nr = 31; + while (bit_nr) { + if (len & mask) + break; + bit_nr--; + mask >>= 1; + } + mask = ~(0xffffffff << bit_nr); + + if (setflag) { + /* set a watchpoint */ + if (type == 2) + mode = 1; // break on write + else if (type == 3) + mode = 3; // break on read + else if (type == 4) + mode = 2; // break on any access + else + return 1; + + if (!(dbcon & 3)) { + set_dbr0(addr); + set_dbr1(mask); + set_dbcon(dbcon | mode | 0x100); + } else + return 1; + } else { + /* clear a watchpoint */ + if (dbcon & 3) + set_dbcon(dbcon & ~3); + else + return 1; + } + return 0; +} + +// Return indication of whether or not we stopped because of a +// watchpoint or hardware breakpoint. If stopped by a watchpoint, +// also set '*data_addr_p' to the data address which triggered the +// watchpoint. +int cyg_hal_plf_is_stopped_by_hardware(void **data_addr_p) +{ + unsigned fsr, dcsr, dbcon, kind = 0; + + // Check for debug event + asm volatile ("mrc p15,0,%0,c5,c0,0" : "=r"(fsr) : ); + if ((fsr & 0x200) == 0) + return HAL_STUB_HW_STOP_NONE; + + // There was a debug event. Check the MOE for details + dcsr = get_dcsr(); + switch ((dcsr >> 2) & 7) { + case 1: // HW breakpoint + case 3: // BKPT breakpoint + return HAL_STUB_HW_STOP_BREAK; + case 2: // Watchpoint + dbcon = get_dbcon(); + if (dbcon & 0x100) { + // dbr1 is used as address mask + kind = dbcon & 3; + *data_addr_p = (void *)get_dbr0(); + } + if (kind == 1) + return HAL_STUB_HW_STOP_WATCH; + if (kind == 2) + return HAL_STUB_HW_STOP_AWATCH; + if (kind == 3) + return HAL_STUB_HW_STOP_RWATCH; + // should never get here + break; + } + return HAL_STUB_HW_STOP_NONE; +} +#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +/*------------------------------------------------------------------------*/ +// EOF iq80310_misc.c
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/iq80310/current/src/iq80310_pci.c @@ -0,0 +1,427 @@ +//========================================================================== +// +// iq80310_pci.c +// +// HAL board support code for XScale IQ80310 PCI +// +//========================================================================== +//####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): msalter +// Contributors: msalter +// Date: 2000-10-10 +// Purpose: PCI support +// Description: Implementations of HAL PCI interfaces +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include <pkgconf/hal.h> +#include <pkgconf/system.h> +#include CYGBLD_HAL_PLATFORM_H +#include CYGHWR_MEMORY_LAYOUT_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_if.h> // calling interface API +#include <cyg/hal/hal_arch.h> // Register state info +#include <cyg/hal/hal_diag.h> +#include <cyg/hal/hal_intr.h> // Interrupt names +#include <cyg/hal/hal_cache.h> +#include <cyg/hal/hal_iq80310.h> // Hardware definitions +#include <cyg/io/pci_hw.h> +#include <cyg/io/pci.h> + +static cyg_uint8 pbus_nr; +static cyg_uint8 sbus_nr; + +void cyg_hal_plf_pci_init(void) +{ + cyg_uint32 limit_reg, adj_dram_size; + cyg_uint8 next_bus; + + // Initialize Secondary PCI bus (bus 1) + *(volatile cyg_uint16 *)BCR_ADDR |= 0x40; // reset secondary bus + hal_delay_us(10 * 1000); // 10ms enough?? + *(volatile cyg_uint16 *)BCR_ADDR &= ~0x40; // release reset + + // ********* vendor / device id ********** + *(cyg_uint16 *)ASVIR_ADDR = 0x113C; + *(cyg_uint16 *)ASIR_ADDR = 0x0700; + + // suppress secondary bus idsels to provide private secondary devices + *(cyg_uint16 *)SISR_ADDR = 0x03FF; + + // ******* Primary Inbound ATU ********* + + // set primary inbound ATU translate value register to point to + // base of local DRAM + *(cyg_uint32 *)PIATVR_ADDR = MEMBASE_DRAM & 0xFFFFFFFC; + // set primary inbound ATU limit register to include all of installed DRAM. + // This value used as a mask. + adj_dram_size = hal_dram_size; + limit_reg = (0xFFFFFFFF-(adj_dram_size-1)) & 0xFFFFFFF0; + *(cyg_uint32 *)PIALR_ADDR = limit_reg; + + if (iq80310_is_host()) { + + // set the primary inbound ATU base address to the start of DRAM + *(cyg_uint32 *)PIABAR_ADDR = MEMBASE_DRAM & 0xFFFFF000; + + // ********* Set Primary Outbound Windows ********* + + // Note: The primary outbound ATU memory window value register + // and i/o window value registers are defaulted to 0 + + // set the primary outbound windows to directly map Local - PCI + // requests + // outbound memory window + *(cyg_uint32 *)POMWVR_ADDR = PRIMARY_MEM_BASE; + + // outbound DAC Window + *(cyg_uint32 *)PODWVR_ADDR = PRIMARY_DAC_BASE; + + // outbound I/O window + *(cyg_uint32 *)POIOWVR_ADDR = PRIMARY_IO_BASE; + } + + // clear RETRY + *(cyg_uint16 *)EBCR_ADDR = 0x0008; + + // ******** Secondary Inbound ATU *********** + + // set secondary inbound ATU translate value register to point to base + // of local DRAM + *(cyg_uint32 *)SIATVR_ADDR = MEMBASE_DRAM & 0xFFFFFFFC; + + // set secondary inbound ATU base address to start of DRAM + *(cyg_uint32 *)SIABAR_ADDR = MEMBASE_DRAM & 0xFFFFF000; + + // set secondary inbound ATU limit register to include all of + // installed DRAM. This value used as a mask. + + // always allow secondary pci access to all memory (even with A0 step) + limit_reg = (0xFFFFFFFF - (adj_dram_size - 1)) & 0xFFFFFFF0; + *(cyg_uint32 *)SIALR_ADDR = limit_reg; + + + // ********** Set Secondary Outbound Windows *********** + + // Note: The secondary outbound ATU memory window value register + // and i/o window value registers are defaulted to 0 + + // set the secondary outbound window to directly map Local - PCI requests + // outbound memory window + *(cyg_uint32 *)SOMWVR_ADDR = SECONDARY_MEM_BASE; + + // outbound DAC Window + *(cyg_uint32 *)SODWVR_ADDR = SECONDARY_DAC_BASE; + + // outbound I/O window + *(cyg_uint32 *)SOIOWVR_ADDR = SECONDARY_IO_BASE; + + // *********** command / config / latency registers ************ + + if (iq80310_is_host()) { + // allow primary ATU to act as a bus master, respond to PCI + // memory accesses, assert P_SERR#, and enable parity checking + *(cyg_uint16 *)PATUCMD_ADDR = (CYG_PCI_CFG_COMMAND_SERR | \ + CYG_PCI_CFG_COMMAND_PARITY | \ + CYG_PCI_CFG_COMMAND_MASTER | \ + CYG_PCI_CFG_COMMAND_MEMORY); + } + + // allow secondary ATU to act as a bus master, respond to PCI memory + // accesses, and assert S_SERR# + *(cyg_uint16 *)SATUCMD_ADDR = (CYG_PCI_CFG_COMMAND_SERR | \ + CYG_PCI_CFG_COMMAND_PARITY | \ + CYG_PCI_CFG_COMMAND_MASTER | \ + CYG_PCI_CFG_COMMAND_MEMORY); + + // enable primary and secondary outbound ATUs, BIST, and primary bus + // direct addressing + *(cyg_uint32 *)ATUCR_ADDR = 0x00000006; + + // ************ bridge registers ******************* + if (iq80310_is_host()) { + + // set the bridge command register + *(cyg_uint16 *)PCR_ADDR = (CYG_PCI_CFG_COMMAND_SERR | \ + CYG_PCI_CFG_COMMAND_PARITY | \ + CYG_PCI_CFG_COMMAND_MASTER | \ + CYG_PCI_CFG_COMMAND_MEMORY); + + // set the secondary bus number to 1 + *(cyg_uint8 *)SBNR_ADDR = SECONDARY_BUS_NUM; + *(cyg_uint16 *)BCR_ADDR = 0x0823; + // set the primary bus number to 0 + *(cyg_uint8 *)PBNR_ADDR = PRIMARY_BUS_NUM; + } else { + // Wait for PC BIOS to initialize bus number + int i; + + for (i = 0; i < 15000; i++) { + if (*((volatile cyg_uint8 *)SBNR_ADDR) != 0) + break; + hal_delay_us(1000); // 1msec + } + + if (*((volatile cyg_uint8 *)SBNR_ADDR) == 0) + *(cyg_uint8 *)SBNR_ADDR = SECONDARY_BUS_NUM; + } + + pbus_nr = *(cyg_uint8 *)PBNR_ADDR; + sbus_nr = *(cyg_uint8 *)SBNR_ADDR; + + // Now initialize the PCI busses. + + // Next assignable bus number. Yavapai primary bus is fixed as + // bus zero and yavapai secondary is fixed as bus 1. + next_bus = sbus_nr + 1; + + // If we are the host on the Primary bus, then configure it. + if (iq80310_is_host()) { + + // Initialize Primary PCI bus (bus 0) + cyg_pci_set_memory_base(PRIMARY_MEM_BASE); + cyg_pci_set_io_base(PRIMARY_IO_BASE); + cyg_pci_configure_bus(0, &next_bus); + } + + // Initialize Secondary PCI bus (bus 1) + cyg_pci_set_memory_base(SECONDARY_MEM_BASE); + cyg_pci_set_io_base(SECONDARY_IO_BASE); + cyg_pci_configure_bus(sbus_nr, &next_bus); + + // clear RETRY + *(cyg_uint16 *)EBCR_ADDR = 0x0008; +} + +void cyg_hal_plf_pci_config_setup( cyg_uint32 bus, + cyg_uint32 devfn, + cyg_uint32 offset) +{ +} + +// Use "naked" attribute to suppress C prologue/epilogue +static void __attribute__ ((naked)) __pci_abort_handler(void) +{ + asm ( "subs pc, lr, #4\n" ); +} + +static cyg_uint32 orig_abort_vec; + +static inline cyg_uint32 *pci_config_setup(cyg_uint32 bus, + cyg_uint32 devfn, + cyg_uint32 offset) +{ + cyg_uint32 *pdata, *paddr; + cyg_uint32 dev = CYG_PCI_DEV_GET_DEV(devfn); + cyg_uint32 fn = CYG_PCI_DEV_GET_FN(devfn); + + if (bus == 0) { + paddr = (cyg_uint32 *)POCCAR_ADDR; + pdata = (cyg_uint32 *)POCCDR_ADDR; + } else { + paddr = (cyg_uint32 *)SOCCAR_ADDR; + pdata = (cyg_uint32 *)SOCCDR_ADDR; + } + + /* Offsets must be dword-aligned */ + offset &= ~3; + + /* Primary or secondary bus use type 0 config */ + /* all others use type 1 config */ + if (bus == pbus_nr || bus == sbus_nr) + *paddr = ( (1 << (dev + 16)) | (fn << 8) | offset | 0 ); + else + *paddr = ( (bus << 16) | (dev << 11) | (fn << 8) | offset | 1 ); + + orig_abort_vec = ((volatile cyg_uint32 *)0x20)[4]; + ((volatile unsigned *)0x20)[4] = (unsigned)__pci_abort_handler; + HAL_ICACHE_SYNC(); + + return pdata; +} + +static inline int pci_config_cleanup(cyg_uint32 bus) +{ + cyg_uint32 status = 0, err = 0; + + if (bus == pbus_nr) { + status = *(cyg_uint16 *) PATUSR_ADDR; + if ((status & 0xF900) != 0) { + err = 1; + *(cyg_uint16 *)PATUSR_ADDR = status & 0xF980; + } + status = *(cyg_uint16 *) PSR_ADDR; + if ((status & 0xF900) != 0) { + err = 1; + *(cyg_uint16 *)PSR_ADDR = status & 0xF980; + } + status = *(cyg_uint32 *) PATUISR_ADDR; + if ((status & 0x79F) != 0) { + err = 1; + *(cyg_uint32 *) PATUISR_ADDR = status & 0x79f; + } + status = *(cyg_uint32 *) PBISR_ADDR; + if ((status & 0x3F) != 0) { + err = 1; + *(cyg_uint32 *) PBISR_ADDR = status & 0x3F; + } + } else { + status = *(cyg_uint16 *) SATUSR_ADDR; + if ((status & 0xF900) != 0) { + err = 1; + *(cyg_uint16 *) SATUSR_ADDR = status & 0xF900; + } + status = *(cyg_uint16 *) SSR_ADDR; + if ((status & 0xF900) != 0) { + err = 1; + *(cyg_uint16 *) SSR_ADDR = status & 0xF980; + } + status = *(cyg_uint32 *) SATUISR_ADDR; + if ((status & 0x69F) != 0) { + err = 1; + *(cyg_uint32 *) SATUISR_ADDR = status & 0x69F; + } + } + + ((volatile unsigned *)0x20)[4] = orig_abort_vec; + HAL_ICACHE_SYNC(); + + return err; +} + + + +cyg_uint32 cyg_hal_plf_pci_cfg_read_dword (cyg_uint32 bus, + cyg_uint32 devfn, + cyg_uint32 offset) +{ + cyg_uint32 *pdata, config_data; + + pdata = pci_config_setup(bus, devfn, offset); + + config_data = *pdata; + + if (pci_config_cleanup(bus)) + return 0xffffffff; + else + return config_data; +} + + +void cyg_hal_plf_pci_cfg_write_dword (cyg_uint32 bus, + cyg_uint32 devfn, + cyg_uint32 offset, + cyg_uint32 data) +{ + cyg_uint32 *pdata; + + pdata = pci_config_setup(bus, devfn, offset); + + *pdata = data; + + pci_config_cleanup(bus); +} + + +cyg_uint16 cyg_hal_plf_pci_cfg_read_word (cyg_uint32 bus, + cyg_uint32 devfn, + cyg_uint32 offset) +{ + cyg_uint32 *pdata; + cyg_uint16 config_data; + + pdata = pci_config_setup(bus, devfn, offset); + + config_data = (cyg_uint16)(((*pdata) >> ((offset % 0x4) * 8)) & 0xffff); + + if (pci_config_cleanup(bus)) + return 0xffff; + else + return config_data; +} + +void cyg_hal_plf_pci_cfg_write_word (cyg_uint32 bus, + cyg_uint32 devfn, + cyg_uint32 offset, + cyg_uint16 data) +{ + cyg_uint32 *pdata, mask, temp; + + pdata = pci_config_setup(bus, devfn, offset); + + mask = ~(0x0000ffff << ((offset % 0x4) * 8)); + + temp = (cyg_uint32)(((cyg_uint32)data) << ((offset % 0x4) * 8)); + *pdata = (*pdata & mask) | temp; + + pci_config_cleanup(bus); +} + +cyg_uint8 cyg_hal_plf_pci_cfg_read_byte (cyg_uint32 bus, + cyg_uint32 devfn, + cyg_uint32 offset) +{ + cyg_uint32 *pdata; + cyg_uint8 config_data; + + pdata = pci_config_setup(bus, devfn, offset); + + config_data = (cyg_uint8)(((*pdata) >> ((offset % 0x4) * 8)) & 0xff); + + if (pci_config_cleanup(bus)) + return 0xff; + else + return config_data; +} + + +void cyg_hal_plf_pci_cfg_write_byte (cyg_uint32 bus, + cyg_uint32 devfn, + cyg_uint32 offset, + cyg_uint8 data) +{ + cyg_uint32 *pdata, mask, temp; + + pdata = pci_config_setup(bus, devfn, offset); + + mask = ~(0x000000ff << ((offset % 0x4) * 8)); + temp = (cyg_uint32)(((cyg_uint32)data) << ((offset % 0x4) * 8)); + *pdata = (*pdata & mask) | temp; + + pci_config_cleanup(bus); +} + + +
--- a/packages/hal/arm/pid/current/ChangeLog +++ b/packages/hal/arm/pid/current/ChangeLog @@ -1,3 +1,8 @@ +2001-02-13 Gary Thomas <gthomas@redhat.com> + + * src/pid_misc.c (hal_IRQ_handler): + Return CYGNUM_HAL_INTERRUPT_NONE for spurious interrupts. + 2001-02-08 Jesper Skov <jskov@redhat.com> * src/hal_diag.c: Replace CYGSEM_HAL_DIAG_MANGLER_None with
--- a/packages/hal/arm/pid/current/src/pid_misc.c +++ b/packages/hal/arm/pid/current/src/pid_misc.c @@ -23,7 +23,7 @@ // // The Initial Developer of the Original Code is Red Hat. // Portions created by Red Hat are -// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc. // All Rights Reserved. // ------------------------------------------- // @@ -149,7 +149,7 @@ int hal_IRQ_handler(void) for (vector = 1; vector < 16; vector++) { if (irq_status & (1<<vector)) return vector; } - return CYGNUM_HAL_INTERRUPT_unused; // This shouldn't happen! + return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen! } //
--- a/packages/redboot/current/ChangeLog +++ b/packages/redboot/current/ChangeLog @@ -1,3 +1,8 @@ +2001-02-13 Hugo Tyson <hmt@redhat.com> + + * src/flash.c: Fix token/string pasting thinko: ## operators are + not needed and do confuse some compilers. + 2001-02-12 Jesper Skov <jskov@redhat.com> * src/main.c: Use CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL instead
--- a/packages/redboot/current/src/flash.c +++ b/packages/redboot/current/src/flash.c @@ -842,7 +842,7 @@ RedBoot_config_option("Boot script", "" ); // Some preprocessor magic for building the [constant] prompt string -#define __cat(s1,c2,s3) s1 ## #c2 ## s3 +#define __cat(s1,c2,s3) s1 #c2 s3 #define _cat(s1,c2,s3) __cat(s1,c2,s3) RedBoot_config_option(_cat("Boot script timeout (", CYGNUM_REDBOOT_FLASH_SCRIPT_TIMEOUT_RESOLUTION,
