/* ia_pci.c */

/* Flipper chip initialization */

/* Copyright (c) 2000  James M. Westall, Dept of Computer Science,
 *                     Clemson University, Clemson SC 29634 USA
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * To obtain a copy of the GNU General Public License write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * This software is derived from software developed by the Interphase
 * corporation and released by them in September 2000. The software
 * released by Interphase carried the following copyright notice:
 *
 *
 *                          Copyright (C) 1993
 *                Interphase Corporation, Dallas, TX 75234
 *                          All Rights Reserved
 *
 * This code contains confidential information and  trade  secrets  of
 * Interphase Corporation which shall not be reproduced or transferred
 * to other programs or disclosed to others or used for  manufacturing
 * or any other purpose without prior written permission of Interphase
 * Corporation.  Use of copyright notice is precautionary and does not
 * imply publication or intent thereof.
 */

/*H
 * FILE: ia_pci.c
 *
 * DESCRIPTION:
 *   This file contains PCI Bus related routines.
 *
 * FUNCTIONS:
 * EXPORTED:
 *   see below.
 *
 * STATIC:
 *   fsee below.
 *
 * GLOBAL DATA:
 *
 */

#include "ia_defs.h"
static int once = 0;

/*F
 * FUNCTION: ia_card_type
 *
 * DESCRIPTION:
 *   This routine is called to find out the card type (Flipper of
 *   Atlantic) from the config space.
 *
 * ARGUMENTS:
 *   softc     soft state structure
 *
 * ENVIRONMENT:
 *
 * RETURN:
 *   nothing
 *
 * NOTES:
 *
 */

/**/
void
ia_card_type (ia_softc_t *softc)
{
   u_short     dev_id;

   dev_id = softc->ia_dev->device;
   printk("IA 5515: Device id is %d \n", dev_id);

   if (dev_id == PCI_CONFIG_DEVID_N)
      softc->atlantic = 1;
   else
      softc->atlantic = 0;
}


/*F
 * FUNCTION: ia_card_reset
 *
 * DESCRIPTION:
 *   This routine is called to reset the adapter.
 *
 * ARGUMENTS:
 *   softc     soft state structure
 *
 * ENVIRONMENT:
 *
 * RETURN:
 *
 * NOTES:
 *
 */

/**/
void
ia_card_reset (ia_softc_t *softc)
{
   uint32_t save[sizeof (fl_config_2_t) / sizeof (uint32_t)];
   int      cnt;
   int      i;

   cnt = sizeof (fl_config_2_t) / sizeof (uint32_t);

   for (i=0; i<cnt; i++)
      pci_config_getl(i*sizeof(uint32_t), &save[i]);

   ia_put32(&softc->brd_regs.flipper->fl_ext_reset, 0);
   udelay((clock_t)100);

   for (i=0; i<cnt; i++)
      pci_config_putl(i*sizeof(uint32_t), save[i]);

   udelay((clock_t)100);
}


/*F
 * FUNCTION: ia_flip_init
 *
 * DESCRIPTION:
 *   This routine is called to initialize flipper.
 *
 * ARGUMENTS:
 *   softc     soft state structure
 *
 * ENVIRONMENT:
 *
 * RETURN:
 *   nothing
 *
 * NOTES:
 *
 */

/**/
int
ia_flip_init (ia_softc_t *softc)
{
   ia_flip_t      *flipper = softc->brd_regs.flipper;
   ia_dle_list_t  *list;
   ia_dma_t       *dma;
   uint           ncookie;
   u32            dmac_address;
   int            offset;
   int            err;

   /*
    * Reset the flipper
    */
   ia_card_reset(softc);

   /*
    * Set up the flipper control register
    */
   if (softc->atlantic) {
      ia_and32 (&flipper->fl_ctrl, (FL_CTRL_LED | FL_CTRL_RESET));
      ia_or32  (&flipper->fl_ctrl,
            FL_CTRL_B08_N |
            FL_CTRL_B16_N |
            FL_CTRL_B32_N |
            FL_CTRL_B64_N |
            FL_CTRL_B128_N |
            FL_CTRL_DLERMASK |
            FL_CTRL_FFREDMASK |
            FL_CTRL_RFREDMASK |
            FL_CTRL_FEMASK |
            FL_CTRL_FSPREEMPT);
   }
   else {
      ia_put32 (&flipper->fl_ctrl,
            FL_CTRL_B08 |
            FL_CTRL_B16 |
            FL_CTRL_B32 |
            FL_CTRL_B64 |
            FL_CTRL_DLERMASK |
            FL_CTRL_DLETMASK |
            FL_CTRL_FFREDMASK |
            FL_CTRL_RFREDMASK |
        /*  FL_CTRL_FEMASK |     */
            FL_CTRL_FSPREEMPT |
            FL_CTRL_TEST);
   }

   /*
    *-------------------------
    * Set up transmit DMA list
    *-------------------------
    */
   dma = &softc->tx_list_dma;
   dma->len = SIZE_DLE_SPACE * 2;
   dma->addr = kmalloc(dma->len, GFP_DMA);
   dma->real_len = dma->len;
   dma->taddr = dma->addr;

   dma->alloc_handle_done = 1;
   dma->mem_alloc_done = 1;

   offset = ROUND_UP(dma->addr, SIZE_DLE_SPACE) - (int)dma->addr;
   dma->addr += offset;
   dma->real_len -= offset;
   dmac_address = virt_to_bus(dma->addr);
   ia_put32(&flipper->fl_transmit_list, dmac_address);

   list = &softc->list[TX_LIST];
   list->list_start = (DLE *)dma->addr;
   list->list_end   = (DLE *)(dma->addr + SIZE_DLE_SPACE);
   list->list_read  = (DLE *)dma->addr;
   list->list_write = (DLE *)dma->addr;

   /*
    *-------------------------
    * Set up receive DMA list
    *-------------------------
    */
   dma = &softc->rx_list_dma;
   dma->len = SIZE_DLE_SPACE * 2;
   dma->addr = kmalloc(dma->len, GFP_DMA);
   dma->real_len = dma->len;
   dma->taddr = dma->addr;

   dma->alloc_handle_done = 1;
   dma->mem_alloc_done = 1;

   offset = ROUND_UP(dma->addr, SIZE_DLE_SPACE) - (int)dma->addr;
   dma->addr += offset;
   dma->real_len -= offset;
   dmac_address = virt_to_bus(dma->addr);

   dma->mem_alloc_done = 1;

   ia_put32 (&flipper->fl_receive_list, dmac_address);

   list = &softc->list[RX_LIST];
   list->list_start = (DLE *)dma->addr;
   list->list_end   = (DLE *)(dma->addr + SIZE_DLE_SPACE);
   list->list_read  = (DLE *)dma->addr;
   list->list_write = (DLE *)dma->addr;
}


/*F
 * FUNCTION: ia_hw_type
 *
 * DESCRIPTION:
 *   Find out the size of buffer memory and the fron end type
 *   and set some parameters accordingly.
 *
 * ARGUMENTS:
 *   softc     soft state structure
 *
 * ENVIRONMENT:
 *
 * RETURN:
 *
 * NOTES:
 *
 */

/**/
void
ia_hw_type (ia_softc_t *softc)
{
   u_short  hw_conf;

   if (softc->atlantic)
      hw_conf = ia_eeprom_get (softc, HW_CONF_OFFSET_ATLANTIC/sizeof(u_short));
   else
      hw_conf = ia_eeprom_get (softc, HW_CONF_OFFSET/sizeof(u_short));

   printk("IA 5515: Hardware configuration word is %x \n", hw_conf);

   if ((hw_conf & MEM_SIZE_MASK) == MEM_SIZE_1M)
   {
      softc->num_tx_desc = NUM_TX_DESC;
      softc->num_rx_desc = NUM_RX_DESC;
      softc->num_tx_bufs = NUM_TX_BUFS;
      softc->ram_size = RAM_SIZE;
      softc->rx_packet_ram = TX_PACKET_RAM +
               (TX_BUF_SIZE * NUM_TX_DESC);
   }
   else if ((hw_conf & MEM_SIZE_MASK) == MEM_SIZE_512K)
   {
      softc->num_tx_desc = NUM_TX_DESC_512;
      softc->num_rx_desc = NUM_RX_DESC_512;
      softc->num_tx_bufs = NUM_TX_BUFS_512;
      softc->ram_size = RAM_SIZE_512;
      softc->rx_packet_ram =  TX_PACKET_RAM +
               (TX_BUF_SIZE * NUM_TX_DESC_512);
   }
   else if ((hw_conf & MEM_SIZE_MASK) == MEM_SIZE_128K)
   {
      softc->num_tx_desc = NUM_TX_DESC_128;
      softc->num_rx_desc = NUM_RX_DESC_128;
      softc->num_tx_bufs = NUM_TX_BUFS_128;
      softc->ram_size = RAM_SIZE_128;
      softc->rx_packet_ram =  TX_PACKET_RAM +
               (TX_BUF_SIZE * NUM_TX_DESC_128);
   }
   else
   {
   /*
    * For now just assume it is 128K board
    */
      softc->num_tx_desc = NUM_TX_DESC_128;
      softc->num_rx_desc = NUM_RX_DESC_128;
      softc->num_tx_bufs = NUM_TX_BUFS_128;
      softc->ram_size = RAM_SIZE_128;
      softc->rx_packet_ram =  TX_PACKET_RAM +
               (TX_BUF_SIZE * NUM_TX_DESC_128);
   }

   if ((hw_conf & FE_MASK) == FE_SINGLE_MODE)
      softc->phy_type = FE_SINGLE_MODE;
   else if ((hw_conf & FE_MASK) == FE_UTP_OPTION)
      softc->phy_type = FE_UTP_OPTION;
   else
      softc->phy_type = FE_MULTI_MODE;

/* printk("IA 5515: Number Tx bufs is %d \n", softc->num_tx_bufs); */
   softc->line_crs = LINE_CELL_RATE_155;
}
