/*
    Copyright 2000 (c) by Oliver Pfister,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.
 
    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.
 
    For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
    This software is provided under the terms of the GNU General Public 
    Licence. A full copy of the GNU GPL is provided in the file COPYING 
    found in the development root of Topsy.
*/
/*
	
    File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/IO/ia32/Drivers/IOPciAm79c97x.h,v $
    Author(s):             
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2922 $
    Creation Date:         
    Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $      by: $Author: baderma $
*/
#ifndef _IOPCIAM79C97X_H
#define _IOPCIAM79C97X_H

#include "IODevice.h"
#include "IOPci.h"
#include "Messages.h"
#include "IOPciNetDeviceStats.h"

#define AM79C97X_LOG_TX_BUFFERS 4 /* min. value is 3 */
#define AM79C97X_LOG_RX_BUFFERS 4 /* min. value is 3 */

#define AM79C97X_TX_RING_SIZE        (1 << (AM79C97X_LOG_TX_BUFFERS))
#define AM79C97X_TX_RING_MOD_MASK    (AM79C97X_TX_RING_SIZE - 1)
#define AM79C97X_TX_RING_LEN_BITS    ((AM79C97X_LOG_TX_BUFFERS) << 12)

#define AM79C97X_RX_RING_SIZE        (1 << (AM79C97X_LOG_RX_BUFFERS))
#define AM79C97X_RX_RING_MOD_MASK    (AM79C97X_RX_RING_SIZE - 1)
#define AM79C97X_RX_RING_LEN_BITS    ((AM79C97X_LOG_RX_BUFFERS) << 4)

#define AM79C97X_PKT_BUF_SZ    1544

/* Offsets from base Memory Mapped I/O address, DWord IO */
#define AM79C97X_RDP 0x10 // Register Data Port
#define AM79C97X_RAP 0x14 // Register Address Port,
// shared by RDP und BDP
#define AM79C97X_RESET 0x18
#define AM79C97X_BDP 0x1C // Bus Data Port

/* Offsets from base Memory Mapped I/O address, Word IO */
#define AM79C97X_RDP_W 0x10 // Register Data Port
#define AM79C97X_RAP_W 0x12 // Register Address Port,
// shared by RDP und BDP
#define AM79C97X_RESET_W 0x14
#define AM79C97X_BDP_W 0x16 // Bus Data Port


/* The Rx ring descriptors for SWSTYLE 3 */
typedef struct am79c97xRxDesc_t
{
  u16 msg_length;  // This length is "normal"
  u16 rc_rp_count; // Receive collision and runt packet counts
  s16 buf_length;  // This length is 2s complement (negative)!
  s16 flags;
  u32 baseAddr;
  u32 res;         // Reserved
}
am79c97xRxDesc;

/* The Tx ring descriptors for SWSTYLE 3 */
typedef struct am79c97xTxDesc_t
{
  u32 flags2;
  s16 msg_length;  // Length is 2s complement (negative)!
  s16 flags;
  u32 baseAddr;
  u32 res;         //reserved
}
am79c97xTxDesc;

/* The initialization block */
typedef struct am79c97xInitBlock_t
{
  u16 mode;        // Pre-set mode for CSR15
  u16 lens;        // TLEN=lens[31:28] and RLEN=lens[23:20]
  u8  macAddr[8];  // MAC ethernet address, macAddr[6] and macAddr[7] not used
  u32 filter[2];   // Multicast filter (unused)
  u32 rxRing;      // Rx ring base pointer, must be Phys. Addr.
  u32 txRing;      // Tx ring base pointer, must be Phys. Addr.
}
am79c97xInitBlock;

/* The main network structure pointed to by the extension pointer of IOPciDeviceDesc */
typedef struct IOAm79c97x_t
{
  // The Tx and Rx ring entries must be aligned on 16-byte boundaries
  am79c97xRxDesc rxRing[AM79C97X_RX_RING_SIZE];
  am79c97xTxDesc txRing[AM79C97X_TX_RING_SIZE];
  am79c97xInitBlock initBlock; // The initialization Block
  u64 rxQueueHead; // The next free rx ring entry (updated by RX ISR)
  u64 txQueueHead; // The next free tx ring entry (updated by the write sys call)
  u64 rxQueueTail; // The start of received Frames (updated by the read sys call)
  u64 txQueueTail; // The start of sent Frames (updated by TX Done ISR)
  netDeviceStats stats; // The Statistics and Errors
  u8 macAddr[8];   // MAC ethernet address, macAddr[6] and macAddr[7] not used
  ThreadId subscribed;  // The upper layer ThreadId
}
IOAm79c97x;


Error am79c97x_init(IODevice devPtr);
Boolean am79c97xInitRing(IODevice devPtr);
Boolean am79c97xPurgeTxRing(IODevice devPtr);
Boolean am79c97xPurgeRxRing(IODevice devPtr);
void am79c97xRestart(IODevice devPtr);
Error am79c97x_read(IODevice devPtr, ThreadId threadId, char* bufPtr, long int* sizePtr);
Error am79c97x_write(IODevice devPtr, ThreadId threadId, char* bufPtr, long int* sizePtr);
void am79c97x_interrupt(IODevice devPtr);
int am79c97xRxISR(IODevice devPtr);
int am79c97xTxDoneISR(IODevice devPtr);
Error am79c97x_close(IODevice devPtr);
void am79c97x_handleMsg(IODevice devPtr, Message *msg);

#endif _IOPCIAM79C97X_H
