Merge from projects/mips to head by hand:

Copy over the support files (except sys/conf and sys/mips/conf) for
RMI XLR processor support.  This port has been contributed by RMI and
brought up to date by Randal Stewart (rrs@).  This port is a work in
progress, and there might still be significant changes.  The port
makes it to multi-user, but is still early beta.
This commit is contained in:
Warner Losh 2010-01-09 18:29:35 +00:00
commit 6e9fd5e257
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=201917
44 changed files with 11736 additions and 0 deletions

View File

@ -0,0 +1,14 @@
RM = rm
MSGRNG_CFG = msgring.cfg
MSGRNG_CFG_C = $(patsubst %.cfg,%.c,$(MSGRNG_CFG))
#all: msgring.l msgring.y msgring.cfg
all: $(MSGRNG_CFG)
flex -omsgring.lex.c msgring.l
bison -d -omsgring.yacc.c msgring.y
gcc -g3 msgring.lex.c msgring.yacc.c -o msgring
./msgring -i $(MSGRNG_CFG) -o $(MSGRNG_CFG_C)
clean:
$(RM) -f msgring.lex.c msgring.yacc.c msgring.yacc.h msgring msgring.o*

180
sys/mips/rmi/board.c Normal file
View File

@ -0,0 +1,180 @@
/*********************************************************************
*
* Copyright 2003-2006 Raza Microelectronics, Inc. (RMI). All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY Raza Microelectronics, Inc. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RMI OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES, LOSS OF USE, DATA, OR PROFITS, OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* *****************************RMI_2**********************************/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <machine/cpufunc.h>
#include <mips/rmi/msgring.h>
#include <mips/rmi/board.h>
#include <mips/rmi/pic.h>
#include <mips/rmi/shared_structs.h>
static int xlr_rxstn_to_txstn_map[128] = {
[0 ... 7] = TX_STN_CPU_0,
[8 ... 15] = TX_STN_CPU_1,
[16 ... 23] = TX_STN_CPU_2,
[24 ... 31] = TX_STN_CPU_3,
[32 ... 39] = TX_STN_CPU_4,
[40 ... 47] = TX_STN_CPU_5,
[48 ... 55] = TX_STN_CPU_6,
[56 ... 63] = TX_STN_CPU_7,
[64 ... 95] = TX_STN_INVALID,
[96 ... 103] = TX_STN_GMAC,
[104 ... 107] = TX_STN_DMA,
[108 ... 111] = TX_STN_INVALID,
[112 ... 113] = TX_STN_XGS_0,
[114 ... 115] = TX_STN_XGS_1,
[116 ... 119] = TX_STN_INVALID,
[120 ... 127] = TX_STN_SAE
};
static int xls_rxstn_to_txstn_map[128] = {
[0 ... 7] = TX_STN_CPU_0,
[8 ... 15] = TX_STN_CPU_1,
[16 ... 23] = TX_STN_CPU_2,
[24 ... 31] = TX_STN_CPU_3,
[32 ... 63] = TX_STN_INVALID,
[64 ... 71] = TX_STN_PCIE,
[72 ... 79] = TX_STN_INVALID,
[80 ... 87] = TX_STN_GMAC1,
[88 ... 95] = TX_STN_INVALID,
[96 ... 103] = TX_STN_GMAC0,
[104 ... 107] = TX_STN_DMA,
[108 ... 111] = TX_STN_CDE,
[112 ... 119] = TX_STN_INVALID,
[120 ... 127] = TX_STN_SAE
};
struct stn_cc *xlr_core_cc_configs[] = {&cc_table_cpu_0, &cc_table_cpu_1,
&cc_table_cpu_2, &cc_table_cpu_3,
&cc_table_cpu_4, &cc_table_cpu_5,
&cc_table_cpu_6, &cc_table_cpu_7};
struct stn_cc *xls_core_cc_configs[] = {&xls_cc_table_cpu_0, &xls_cc_table_cpu_1,
&xls_cc_table_cpu_2, &xls_cc_table_cpu_3};
struct xlr_board_info xlr_board_info;
/*
* All our knowledge of chip and board that cannot be detected by probing
* at run-time goes here
*/
int
xlr_board_info_setup()
{
if (xlr_is_xls()) {
xlr_board_info.is_xls = 1;
xlr_board_info.nr_cpus = 8;
xlr_board_info.usb = 1;
xlr_board_info.cfi =
(xlr_boot1_info.board_major_version != RMI_XLR_BOARD_ARIZONA_VIII);
xlr_board_info.pci_irq = 0;
xlr_board_info.credit_configs = xls_core_cc_configs;
xlr_board_info.bucket_sizes = &xls_bucket_sizes;
xlr_board_info.msgmap = xls_rxstn_to_txstn_map;
xlr_board_info.gmacports = 8;
/* network block 0 */
xlr_board_info.gmac_block[0].type = XLR_GMAC;
xlr_board_info.gmac_block[0].enabled = 0xf;
xlr_board_info.gmac_block[0].credit_config = &xls_cc_table_gmac0;
xlr_board_info.gmac_block[0].station_txbase = MSGRNG_STNID_GMACTX0;
xlr_board_info.gmac_block[0].station_rfr = MSGRNG_STNID_GMACRFR_0;
if (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_VI)
xlr_board_info.gmac_block[0].mode = XLR_PORT0_RGMII;
else
xlr_board_info.gmac_block[0].mode = XLR_SGMII;
xlr_board_info.gmac_block[0].baseaddr = XLR_IO_GMAC_0_OFFSET;
xlr_board_info.gmac_block[0].baseirq = PIC_GMAC_0_IRQ;
xlr_board_info.gmac_block[0].baseinst = 0;
/* network block 1 */
xlr_board_info.gmac_block[1].type = XLR_GMAC;
xlr_board_info.gmac_block[1].enabled = 0xf;
xlr_board_info.gmac_block[1].credit_config = &xls_cc_table_gmac1;
xlr_board_info.gmac_block[1].station_txbase = MSGRNG_STNID_GMAC1_TX0;
xlr_board_info.gmac_block[1].station_rfr = MSGRNG_STNID_GMAC1_FR_0;
xlr_board_info.gmac_block[1].mode = XLR_SGMII;
xlr_board_info.gmac_block[1].baseaddr = XLR_IO_GMAC_4_OFFSET;
xlr_board_info.gmac_block[1].baseirq = PIC_XGS_0_IRQ;
xlr_board_info.gmac_block[1].baseinst = 4;
/* network block 2 */
xlr_board_info.gmac_block[2].enabled = 0; /* disabled on XLS */
} else {
xlr_board_info.is_xls = 0;
xlr_board_info.nr_cpus = 32;
xlr_board_info.usb = 0;
xlr_board_info.cfi = 1;
xlr_board_info.pci_irq = 0;
xlr_board_info.credit_configs = xlr_core_cc_configs;
xlr_board_info.bucket_sizes = &bucket_sizes;
xlr_board_info.msgmap = xlr_rxstn_to_txstn_map;
xlr_board_info.gmacports = 4;
/* GMAC0 */
xlr_board_info.gmac_block[0].type = XLR_GMAC;
xlr_board_info.gmac_block[0].enabled = 0xf;
xlr_board_info.gmac_block[0].credit_config = &cc_table_gmac;
xlr_board_info.gmac_block[0].station_txbase = MSGRNG_STNID_GMACTX0;
xlr_board_info.gmac_block[0].station_rfr = MSGRNG_STNID_GMACRFR_0;
xlr_board_info.gmac_block[0].mode = XLR_RGMII;
xlr_board_info.gmac_block[0].baseaddr = XLR_IO_GMAC_0_OFFSET;
xlr_board_info.gmac_block[0].baseirq = PIC_GMAC_0_IRQ;
xlr_board_info.gmac_block[0].baseinst = 0;
/* XGMAC0 */
xlr_board_info.gmac_block[1].type = XLR_XGMAC;
xlr_board_info.gmac_block[1].enabled = 1;
xlr_board_info.gmac_block[1].credit_config = &cc_table_xgs_0;
xlr_board_info.gmac_block[1].station_txbase = MSGRNG_STNID_XGS0_TX;
xlr_board_info.gmac_block[1].station_rfr = MSGRNG_STNID_XGS0FR;
xlr_board_info.gmac_block[1].mode = -1;
xlr_board_info.gmac_block[1].baseaddr = XLR_IO_XGMAC_0_OFFSET;
xlr_board_info.gmac_block[1].baseirq = PIC_XGS_0_IRQ;
xlr_board_info.gmac_block[1].baseinst = 4;
/* XGMAC1 */
xlr_board_info.gmac_block[2].type = XLR_XGMAC;
xlr_board_info.gmac_block[2].enabled = 1;
xlr_board_info.gmac_block[2].credit_config = &cc_table_xgs_1;
xlr_board_info.gmac_block[2].station_txbase = MSGRNG_STNID_XGS1_TX;
xlr_board_info.gmac_block[2].station_rfr = MSGRNG_STNID_XGS1FR;
xlr_board_info.gmac_block[2].mode = -1;
xlr_board_info.gmac_block[2].baseaddr = XLR_IO_XGMAC_1_OFFSET;
xlr_board_info.gmac_block[2].baseirq = PIC_XGS_1_IRQ;
xlr_board_info.gmac_block[2].baseinst = 5;
}
return 0;
}

282
sys/mips/rmi/board.h Normal file
View File

@ -0,0 +1,282 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#ifndef _RMI_BOARD_H_
#define _RMI_BOARD_H_
#define RMI_XLR_BOARD_ARIZONA_I 1
#define RMI_XLR_BOARD_ARIZONA_II 2
#define RMI_XLR_BOARD_ARIZONA_III 3
#define RMI_XLR_BOARD_ARIZONA_IV 4
#define RMI_XLR_BOARD_ARIZONA_V 5
#define RMI_XLR_BOARD_ARIZONA_VI 6
#define RMI_XLR_BOARD_ARIZONA_VII 7
#define RMI_XLR_BOARD_ARIZONA_VIII 8
#define RMI_CHIP_XLR308_A0 0x0c0600
#define RMI_CHIP_XLR508_A0 0x0c0700
#define RMI_CHIP_XLR516_A0 0x0c0800
#define RMI_CHIP_XLR532_A0 0x0c0900
#define RMI_CHIP_XLR716_A0 0x0c0a00
#define RMI_CHIP_XLR732_A0 0x0c0b00
#define RMI_CHIP_XLR308_A1 0x0c0601
#define RMI_CHIP_XLR508_A1 0x0c0701
#define RMI_CHIP_XLR516_A1 0x0c0801
#define RMI_CHIP_XLR532_A1 0x0c0901
#define RMI_CHIP_XLR716_A1 0x0c0a01
#define RMI_CHIP_XLR732_A1 0x0c0b01
#define RMI_CHIP_XLR308_B0 0x0c0602
#define RMI_CHIP_XLR508_B0 0x0c0702
#define RMI_CHIP_XLR516_B0 0x0c0802
#define RMI_CHIP_XLR532_B0 0x0c0902
#define RMI_CHIP_XLR716_B0 0x0c0a02
#define RMI_CHIP_XLR732_B0 0x0c0b02
#define RMI_CHIP_XLR308_B1 0x0c0603
#define RMI_CHIP_XLR508_B1 0x0c0703
#define RMI_CHIP_XLR516_B1 0x0c0803
#define RMI_CHIP_XLR532_B1 0x0c0903
#define RMI_CHIP_XLR716_B1 0x0c0a03
#define RMI_CHIP_XLR732_B1 0x0c0b03
#define RMI_CHIP_XLR308_B2 0x0c0604
#define RMI_CHIP_XLR508_B2 0x0c0704
#define RMI_CHIP_XLR516_B2 0x0c0804
#define RMI_CHIP_XLR532_B2 0x0c0904
#define RMI_CHIP_XLR716_B2 0x0c0a04
#define RMI_CHIP_XLR732_B2 0x0c0b04
#define RMI_CHIP_XLR308_C0 0x0c0705
#define RMI_CHIP_XLR508_C0 0x0c0b05
#define RMI_CHIP_XLR516_C0 0x0c0a05
#define RMI_CHIP_XLR532_C0 0x0c0805
#define RMI_CHIP_XLR716_C0 0x0c0205
#define RMI_CHIP_XLR732_C0 0x0c0005
#define RMI_CHIP_XLR308_C1 0x0c0706
#define RMI_CHIP_XLR508_C1 0x0c0b06
#define RMI_CHIP_XLR516_C1 0x0c0a06
#define RMI_CHIP_XLR532_C1 0x0c0806
#define RMI_CHIP_XLR716_C1 0x0c0206
#define RMI_CHIP_XLR732_C1 0x0c0006
#define RMI_CHIP_XLR308_C2 0x0c0707
#define RMI_CHIP_XLR508_C2 0x0c0b07
#define RMI_CHIP_XLR516_C2 0x0c0a07
#define RMI_CHIP_XLR532_C2 0x0c0807
#define RMI_CHIP_XLR716_C2 0x0c0207
#define RMI_CHIP_XLR732_C2 0x0c0007
#define RMI_CHIP_XLR308_C3 0x0c0708
#define RMI_CHIP_XLR508_C3 0x0c0b08
#define RMI_CHIP_XLR516_C3 0x0c0a08
#define RMI_CHIP_XLR532_C3 0x0c0808
#define RMI_CHIP_XLR716_C3 0x0c0208
#define RMI_CHIP_XLR732_C3 0x0c0008
#define RMI_CHIP_XLR308_C4 0x0c0709
#define RMI_CHIP_XLR508_C4 0x0c0b09
#define RMI_CHIP_XLR516_C4 0x0c0a09
#define RMI_CHIP_XLR532_C4 0x0c0809
#define RMI_CHIP_XLR716_C4 0x0c0209
#define RMI_CHIP_XLR732_C4 0x0c0009
#define RMI_CHIP_XLS608_A0 0x0c8000
#define RMI_CHIP_XLS408_A0 0x0c8800
#define RMI_CHIP_XLS404_A0 0x0c8c00
#define RMI_CHIP_XLS208_A0 0x0c8e00
#define RMI_CHIP_XLS204_A0 0x0c8f00
#define RMI_CHIP_XLS608_A1 0x0c8001
#define RMI_CHIP_XLS408_A1 0x0c8801
#define RMI_CHIP_XLS404_A1 0x0c8c01
#define RMI_CHIP_XLS208_A1 0x0c8e01
#define RMI_CHIP_XLS204_A1 0x0c8f01
static __inline__ unsigned int
xlr_revision(void)
{
return mips_rd_prid() & 0xff00ff;
}
static __inline__ unsigned int
xlr_is_xls(void)
{
uint32_t prid = mips_rd_prid();
return (prid & 0xf000) == 0x8000 || (prid & 0xf000) == 0x4000;
}
static __inline__ int
xlr_revision_a0(void)
{
return xlr_revision() == 0x0c0000;
}
static __inline__ int
xlr_revision_b0(void)
{
return xlr_revision() == 0x0c0002;
}
static __inline__ int
xlr_revision_b1(void)
{
return xlr_revision() == 0x0c0003;
}
static __inline__ int
xlr_board_atx_i(void)
{
return xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_I;
}
static __inline__ int
xlr_board_atx_ii(void)
{
return xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_II;
}
static __inline__ int
xlr_board_atx_ii_b(void)
{
return (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_II)
&& (xlr_boot1_info.board_minor_version == 1);
}
static __inline__ int
xlr_board_atx_iii(void)
{
return xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_III;
}
static __inline__ int
xlr_board_atx_iv(void)
{
return (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_IV)
&& (xlr_boot1_info.board_minor_version == 0);
}
static __inline__ int
xlr_board_atx_iv_b(void)
{
return (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_IV)
&& (xlr_boot1_info.board_minor_version == 1);
}
static __inline__ int
xlr_board_atx_v(void)
{
return xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_V;
}
static __inline__ int
xlr_board_atx_vi(void)
{
return xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_VI;
}
static __inline__ int
xlr_board_atx_iii_256(void)
{
return (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_III)
&& (xlr_boot1_info.board_minor_version == 0);
}
static __inline__ int
xlr_board_atx_iii_512(void)
{
return (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_III)
&& (xlr_boot1_info.board_minor_version == 1);
}
static __inline__ int
xlr_board_atx_v_512(void)
{
return (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_V)
&& (xlr_boot1_info.board_minor_version == 1);
}
static __inline__ int
xlr_board_pci(void)
{
return (xlr_board_atx_iii_256() || xlr_board_atx_iii_512()
|| xlr_board_atx_v_512());
}
static __inline__ int
xlr_is_xls2xx(void)
{
uint32_t chipid = mips_rd_prid() & 0xffffff00U;
return chipid == 0x0c8e00 || chipid == 0x0c8f00;
}
static __inline__ int
xlr_is_xls4xx(void)
{
uint32_t chipid = mips_rd_prid() & 0xffffff00U;
return chipid == 0x0c8800 || chipid == 0x0c8c00;
}
/* all our knowledge of chip and board that cannot be detected run-time goes here */
enum gmac_block_types {
XLR_GMAC, XLR_XGMAC, XLR_SPI4
};
enum gmac_block_modes {
XLR_RGMII, XLR_SGMII, XLR_PORT0_RGMII
};
struct xlr_board_info {
int is_xls;
int nr_cpus;
int usb; /* usb enabled ? */
int cfi; /* compact flash driver for NOR? */
int pci_irq;
struct stn_cc **credit_configs; /* pointer to Core station credits */
struct bucket_size *bucket_sizes; /* pointer to Core station
* bucket */
int *msgmap; /* mapping of message station to devices */
int gmacports; /* number of gmac ports on the board */
struct xlr_gmac_block_t {
int type; /* see enum gmac_block_types */
unsigned int enabled; /* mask of ports enabled */
struct stn_cc *credit_config; /* credit configuration */
int station_txbase; /* station id for tx */
int station_rfr;/* free desc bucket */
int mode; /* see gmac_block_modes */
uint32_t baseaddr; /* IO base */
int baseirq; /* first irq for this block, the rest are in
* sequence */
int baseinst; /* the first rge unit for this block */
} gmac_block[3];
};
extern struct xlr_board_info xlr_board_info;
int xlr_board_info_setup(void);
#endif

View File

@ -0,0 +1,831 @@
/*-
* Copyright (c) 2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/ktr.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_kern.h>
#include <vm/vm_extern.h>
#include <machine/bus.h>
#include <machine/cache.h>
void xlr_print_int(uint32_t);
static int
rmi_bus_space_map(void *t, bus_addr_t addr,
bus_size_t size, int flags,
bus_space_handle_t * bshp);
static void
rmi_bus_space_unmap(void *t, bus_space_handle_t bsh,
bus_size_t size);
static int
rmi_bus_space_subregion(void *t,
bus_space_handle_t bsh,
bus_size_t offset, bus_size_t size,
bus_space_handle_t * nbshp);
static u_int8_t
rmi_bus_space_read_1(void *t,
bus_space_handle_t handle,
bus_size_t offset);
static u_int16_t
rmi_bus_space_read_2(void *t,
bus_space_handle_t handle,
bus_size_t offset);
static u_int32_t
rmi_bus_space_read_4(void *t,
bus_space_handle_t handle,
bus_size_t offset);
static void
rmi_bus_space_read_multi_1(void *t,
bus_space_handle_t handle,
bus_size_t offset, u_int8_t * addr,
size_t count);
static void
rmi_bus_space_read_multi_2(void *t,
bus_space_handle_t handle,
bus_size_t offset, u_int16_t * addr,
size_t count);
static void
rmi_bus_space_read_multi_4(void *t,
bus_space_handle_t handle,
bus_size_t offset, u_int32_t * addr,
size_t count);
static void
rmi_bus_space_read_region_1(void *t,
bus_space_handle_t bsh,
bus_size_t offset, u_int8_t * addr,
size_t count);
static void
rmi_bus_space_read_region_2(void *t,
bus_space_handle_t bsh,
bus_size_t offset, u_int16_t * addr,
size_t count);
static void
rmi_bus_space_read_region_4(void *t,
bus_space_handle_t bsh,
bus_size_t offset, u_int32_t * addr,
size_t count);
static void
rmi_bus_space_write_1(void *t,
bus_space_handle_t handle,
bus_size_t offset, u_int8_t value);
static void
rmi_bus_space_write_2(void *t,
bus_space_handle_t handle,
bus_size_t offset, u_int16_t value);
static void
rmi_bus_space_write_4(void *t,
bus_space_handle_t handle,
bus_size_t offset, u_int32_t value);
static void
rmi_bus_space_write_multi_1(void *t,
bus_space_handle_t handle,
bus_size_t offset,
const u_int8_t * addr,
size_t count);
static void
rmi_bus_space_write_multi_2(void *t,
bus_space_handle_t handle,
bus_size_t offset,
const u_int16_t * addr,
size_t count);
static void
rmi_bus_space_write_multi_4(void *t,
bus_space_handle_t handle,
bus_size_t offset,
const u_int32_t * addr,
size_t count);
static void
rmi_bus_space_write_region_2(void *t,
bus_space_handle_t bsh,
bus_size_t offset,
const u_int16_t * addr,
size_t count);
static void
rmi_bus_space_write_region_4(void *t,
bus_space_handle_t bsh,
bus_size_t offset,
const u_int32_t * addr,
size_t count);
static void
rmi_bus_space_set_region_2(void *t,
bus_space_handle_t bsh,
bus_size_t offset, u_int16_t value,
size_t count);
static void
rmi_bus_space_set_region_4(void *t,
bus_space_handle_t bsh,
bus_size_t offset, u_int32_t value,
size_t count);
static void
rmi_bus_space_barrier(void *tag __unused, bus_space_handle_t bsh __unused,
bus_size_t offset __unused, bus_size_t len __unused, int flags);
static void
rmi_bus_space_copy_region_2(void *t,
bus_space_handle_t bsh1,
bus_size_t off1,
bus_space_handle_t bsh2,
bus_size_t off2, size_t count);
u_int8_t
rmi_bus_space_read_stream_1(void *t, bus_space_handle_t handle,
bus_size_t offset);
static u_int16_t
rmi_bus_space_read_stream_2(void *t, bus_space_handle_t handle,
bus_size_t offset);
static u_int32_t
rmi_bus_space_read_stream_4(void *t, bus_space_handle_t handle,
bus_size_t offset);
static void
rmi_bus_space_read_multi_stream_1(void *t,
bus_space_handle_t handle,
bus_size_t offset, u_int8_t * addr,
size_t count);
static void
rmi_bus_space_read_multi_stream_2(void *t,
bus_space_handle_t handle,
bus_size_t offset, u_int16_t * addr,
size_t count);
static void
rmi_bus_space_read_multi_stream_4(void *t,
bus_space_handle_t handle,
bus_size_t offset, u_int32_t * addr,
size_t count);
void
rmi_bus_space_write_stream_1(void *t, bus_space_handle_t bsh,
bus_size_t offset, u_int8_t value);
static void
rmi_bus_space_write_stream_2(void *t, bus_space_handle_t handle,
bus_size_t offset, u_int16_t value);
static void
rmi_bus_space_write_stream_4(void *t, bus_space_handle_t handle,
bus_size_t offset, u_int32_t value);
static void
rmi_bus_space_write_multi_stream_1(void *t,
bus_space_handle_t handle,
bus_size_t offset,
const u_int8_t * addr,
size_t count);
static void
rmi_bus_space_write_multi_stream_2(void *t,
bus_space_handle_t handle,
bus_size_t offset,
const u_int16_t * addr,
size_t count);
static void
rmi_bus_space_write_multi_stream_4(void *t,
bus_space_handle_t handle,
bus_size_t offset,
const u_int32_t * addr,
size_t count);
static struct bus_space local_rmi_bus_space = {
/* cookie */
(void *)0,
/* mapping/unmapping */
rmi_bus_space_map,
rmi_bus_space_unmap,
rmi_bus_space_subregion,
/* allocation/deallocation */
NULL,
NULL,
/* barrier */
rmi_bus_space_barrier,
/* read (single) */
rmi_bus_space_read_1,
rmi_bus_space_read_2,
rmi_bus_space_read_4,
NULL,
/* read multiple */
rmi_bus_space_read_multi_1,
rmi_bus_space_read_multi_2,
rmi_bus_space_read_multi_4,
NULL,
/* read region */
rmi_bus_space_read_region_1,
rmi_bus_space_read_region_2,
rmi_bus_space_read_region_4,
NULL,
/* write (single) */
rmi_bus_space_write_1,
rmi_bus_space_write_2,
rmi_bus_space_write_4,
NULL,
/* write multiple */
rmi_bus_space_write_multi_1,
rmi_bus_space_write_multi_2,
rmi_bus_space_write_multi_4,
NULL,
/* write region */
NULL,
rmi_bus_space_write_region_2,
rmi_bus_space_write_region_4,
NULL,
/* set multiple */
NULL,
NULL,
NULL,
NULL,
/* set region */
NULL,
rmi_bus_space_set_region_2,
rmi_bus_space_set_region_4,
NULL,
/* copy */
NULL,
rmi_bus_space_copy_region_2,
NULL,
NULL,
/* read (single) stream */
rmi_bus_space_read_stream_1,
rmi_bus_space_read_stream_2,
rmi_bus_space_read_stream_4,
NULL,
/* read multiple stream */
rmi_bus_space_read_multi_stream_1,
rmi_bus_space_read_multi_stream_2,
rmi_bus_space_read_multi_stream_4,
NULL,
/* read region stream */
rmi_bus_space_read_region_1,
rmi_bus_space_read_region_2,
rmi_bus_space_read_region_4,
NULL,
/* write (single) stream */
rmi_bus_space_write_stream_1,
rmi_bus_space_write_stream_2,
rmi_bus_space_write_stream_4,
NULL,
/* write multiple stream */
rmi_bus_space_write_multi_stream_1,
rmi_bus_space_write_multi_stream_2,
rmi_bus_space_write_multi_stream_4,
NULL,
/* write region stream */
NULL,
rmi_bus_space_write_region_2,
rmi_bus_space_write_region_4,
NULL,
};
/* generic bus_space tag */
bus_space_tag_t rmi_bus_space = &local_rmi_bus_space;
#define MIPS_BUS_SPACE_IO 0 /* space is i/o space */
#define MIPS_BUS_SPACE_MEM 1 /* space is mem space */
#define MIPS_BUS_SPACE_PCI 10 /* avoid conflict with other spaces */
#define BUS_SPACE_UNRESTRICTED (~0)
#define SWAP32(x)\
(((x) & 0xff000000) >> 24) | \
(((x) & 0x000000ff) << 24) | \
(((x) & 0x0000ff00) << 8) | \
(((x) & 0x00ff0000) >> 8)
#define SWAP16(x)\
(((x) & 0xff00) >> 8) | \
(((x) & 0x00ff) << 8)
/*
* Map a region of device bus space into CPU virtual address space.
*/
static int
rmi_bus_space_map(void *t __unused, bus_addr_t addr,
bus_size_t size __unused, int flags __unused,
bus_space_handle_t * bshp)
{
*bshp = addr;
return (0);
}
/*
* Unmap a region of device bus space.
*/
static void
rmi_bus_space_unmap(void *t __unused, bus_space_handle_t bsh __unused,
bus_size_t size __unused)
{
}
/*
* Get a new handle for a subregion of an already-mapped area of bus space.
*/
static int
rmi_bus_space_subregion(void *t __unused, bus_space_handle_t bsh,
bus_size_t offset, bus_size_t size __unused,
bus_space_handle_t * nbshp)
{
*nbshp = bsh + offset;
return (0);
}
/*
* Read a 1, 2, 4, or 8 byte quantity from bus space
* described by tag/handle/offset.
*/
static u_int8_t
rmi_bus_space_read_1(void *tag, bus_space_handle_t handle,
bus_size_t offset)
{
if ((int)tag == MIPS_BUS_SPACE_PCI)
return (u_int8_t) (*(volatile u_int8_t *)(handle + offset));
else
return (u_int8_t) (*(volatile u_int32_t *)(handle + offset));
}
static u_int16_t
rmi_bus_space_read_2(void *tag, bus_space_handle_t handle,
bus_size_t offset)
{
if ((int)tag == MIPS_BUS_SPACE_PCI)
return SWAP16((u_int16_t) (*(volatile u_int16_t *)(handle + offset)));
else
return *(volatile u_int16_t *)(handle + offset);
}
static u_int32_t
rmi_bus_space_read_4(void *tag, bus_space_handle_t handle,
bus_size_t offset)
{
if ((int)tag == MIPS_BUS_SPACE_PCI)
return SWAP32((*(volatile u_int32_t *)(handle + offset)));
else
return (*(volatile u_int32_t *)(handle + offset));
}
/*
* Read `count' 1, 2, 4, or 8 byte quantities from bus space
* described by tag/handle/offset and copy into buffer provided.
*/
static void
rmi_bus_space_read_multi_1(void *tag, bus_space_handle_t handle,
bus_size_t offset, u_int8_t * addr, size_t count)
{
if ((int)tag != MIPS_BUS_SPACE_PCI)
return;
while (count--) {
*addr = (*(volatile u_int8_t *)(handle + offset));
addr++;
}
}
static void
rmi_bus_space_read_multi_2(void *tag, bus_space_handle_t handle,
bus_size_t offset, u_int16_t * addr, size_t count)
{
if ((int)tag != MIPS_BUS_SPACE_PCI)
return;
while (count--) {
*addr = *(volatile u_int16_t *)(handle + offset);
*addr = SWAP16(*addr);
addr++;
}
}
static void
rmi_bus_space_read_multi_4(void *tag, bus_space_handle_t handle,
bus_size_t offset, u_int32_t * addr, size_t count)
{
if ((int)tag != MIPS_BUS_SPACE_PCI)
return;
while (count--) {
*addr = *(volatile u_int32_t *)(handle + offset);
*addr = SWAP32(*addr);
addr++;
}
}
/*
* Write the 1, 2, 4, or 8 byte value `value' to bus space
* described by tag/handle/offset.
*/
static void
rmi_bus_space_write_1(void *tag, bus_space_handle_t handle,
bus_size_t offset, u_int8_t value)
{
mips_sync();
if ((int)tag == MIPS_BUS_SPACE_PCI)
*(volatile u_int8_t *)(handle + offset) = value;
else
*(volatile u_int32_t *)(handle + offset) = (u_int32_t) value;
}
static void
rmi_bus_space_write_2(void *tag, bus_space_handle_t handle,
bus_size_t offset, u_int16_t value)
{
mips_sync();
if ((int)tag == MIPS_BUS_SPACE_PCI) {
*(volatile u_int16_t *)(handle + offset) = SWAP16(value);
} else
*(volatile u_int16_t *)(handle + offset) = value;
}
static void
rmi_bus_space_write_4(void *tag, bus_space_handle_t handle,
bus_size_t offset, u_int32_t value)
{
mips_sync();
if ((int)tag == MIPS_BUS_SPACE_PCI) {
*(volatile u_int32_t *)(handle + offset) = SWAP32(value);
} else
*(volatile u_int32_t *)(handle + offset) = value;
}
/*
* Write `count' 1, 2, 4, or 8 byte quantities from the buffer
* provided to bus space described by tag/handle/offset.
*/
static void
rmi_bus_space_write_multi_1(void *tag, bus_space_handle_t handle,
bus_size_t offset, const u_int8_t * addr, size_t count)
{
mips_sync();
if ((int)tag != MIPS_BUS_SPACE_PCI)
return;
while (count--) {
(*(volatile u_int8_t *)(handle + offset)) = *addr;
addr++;
}
}
static void
rmi_bus_space_write_multi_2(void *tag, bus_space_handle_t handle,
bus_size_t offset, const u_int16_t * addr, size_t count)
{
mips_sync();
if ((int)tag != MIPS_BUS_SPACE_PCI)
return;
while (count--) {
(*(volatile u_int16_t *)(handle + offset)) = SWAP16(*addr);
addr++;
}
}
static void
rmi_bus_space_write_multi_4(void *tag, bus_space_handle_t handle,
bus_size_t offset, const u_int32_t * addr, size_t count)
{
mips_sync();
if ((int)tag != MIPS_BUS_SPACE_PCI)
return;
while (count--) {
(*(volatile u_int32_t *)(handle + offset)) = SWAP32(*addr);
addr++;
}
}
/*
* Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
* by tag/handle starting at `offset'.
*/
static void
rmi_bus_space_set_region_2(void *t, bus_space_handle_t bsh,
bus_size_t offset, u_int16_t value, size_t count)
{
bus_addr_t addr = bsh + offset;
for (; count != 0; count--, addr += 2)
(*(volatile u_int16_t *)(addr)) = value;
}
static void
rmi_bus_space_set_region_4(void *t, bus_space_handle_t bsh,
bus_size_t offset, u_int32_t value, size_t count)
{
bus_addr_t addr = bsh + offset;
for (; count != 0; count--, addr += 4)
(*(volatile u_int32_t *)(addr)) = value;
}
/*
* Copy `count' 1, 2, 4, or 8 byte values from bus space starting
* at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
*/
static void
rmi_bus_space_copy_region_2(void *t, bus_space_handle_t bsh1,
bus_size_t off1, bus_space_handle_t bsh2,
bus_size_t off2, size_t count)
{
printf("bus_space_copy_region_2 - unimplemented\n");
}
/*
* Read `count' 1, 2, 4, or 8 byte quantities from bus space
* described by tag/handle/offset and copy into buffer provided.
*/
u_int8_t
rmi_bus_space_read_stream_1(void *t, bus_space_handle_t handle,
bus_size_t offset)
{
return *((volatile u_int8_t *)(handle + offset));
}
static u_int16_t
rmi_bus_space_read_stream_2(void *t, bus_space_handle_t handle,
bus_size_t offset)
{
return *(volatile u_int16_t *)(handle + offset);
}
static u_int32_t
rmi_bus_space_read_stream_4(void *t, bus_space_handle_t handle,
bus_size_t offset)
{
return (*(volatile u_int32_t *)(handle + offset));
}
static void
rmi_bus_space_read_multi_stream_1(void *tag, bus_space_handle_t handle,
bus_size_t offset, u_int8_t * addr, size_t count)
{
if ((int)tag != MIPS_BUS_SPACE_PCI)
return;
while (count--) {
*addr = (*(volatile u_int8_t *)(handle + offset));
addr++;
}
}
static void
rmi_bus_space_read_multi_stream_2(void *tag, bus_space_handle_t handle,
bus_size_t offset, u_int16_t * addr, size_t count)
{
if ((int)tag != MIPS_BUS_SPACE_PCI)
return;
while (count--) {
*addr = (*(volatile u_int16_t *)(handle + offset));
addr++;
}
}
static void
rmi_bus_space_read_multi_stream_4(void *tag, bus_space_handle_t handle,
bus_size_t offset, u_int32_t * addr, size_t count)
{
if ((int)tag != MIPS_BUS_SPACE_PCI)
return;
while (count--) {
*addr = (*(volatile u_int32_t *)(handle + offset));
addr++;
}
}
/*
* Read `count' 1, 2, 4, or 8 byte quantities from bus space
* described by tag/handle and starting at `offset' and copy into
* buffer provided.
*/
void
rmi_bus_space_read_region_1(void *t, bus_space_handle_t bsh,
bus_size_t offset, u_int8_t * addr, size_t count)
{
bus_addr_t baddr = bsh + offset;
while (count--) {
*addr++ = (*(volatile u_int8_t *)(baddr));
baddr += 1;
}
}
void
rmi_bus_space_read_region_2(void *t, bus_space_handle_t bsh,
bus_size_t offset, u_int16_t * addr, size_t count)
{
bus_addr_t baddr = bsh + offset;
while (count--) {
*addr++ = (*(volatile u_int16_t *)(baddr));
baddr += 2;
}
}
void
rmi_bus_space_read_region_4(void *t, bus_space_handle_t bsh,
bus_size_t offset, u_int32_t * addr, size_t count)
{
bus_addr_t baddr = bsh + offset;
while (count--) {
*addr++ = (*(volatile u_int32_t *)(baddr));
baddr += 4;
}
}
void
rmi_bus_space_write_stream_1(void *t, bus_space_handle_t handle,
bus_size_t offset, u_int8_t value)
{
mips_sync();
*(volatile u_int8_t *)(handle + offset) = value;
}
static void
rmi_bus_space_write_stream_2(void *t, bus_space_handle_t handle,
bus_size_t offset, u_int16_t value)
{
mips_sync();
*(volatile u_int16_t *)(handle + offset) = value;
}
static void
rmi_bus_space_write_stream_4(void *t, bus_space_handle_t handle,
bus_size_t offset, u_int32_t value)
{
mips_sync();
*(volatile u_int32_t *)(handle + offset) = value;
}
static void
rmi_bus_space_write_multi_stream_1(void *tag, bus_space_handle_t handle,
bus_size_t offset, const u_int8_t * addr, size_t count)
{
mips_sync();
if ((int)tag != MIPS_BUS_SPACE_PCI)
return;
while (count--) {
(*(volatile u_int8_t *)(handle + offset)) = *addr;
addr++;
}
}
static void
rmi_bus_space_write_multi_stream_2(void *tag, bus_space_handle_t handle,
bus_size_t offset, const u_int16_t * addr, size_t count)
{
mips_sync();
if ((int)tag != MIPS_BUS_SPACE_PCI)
return;
while (count--) {
(*(volatile u_int16_t *)(handle + offset)) = *addr;
addr++;
}
}
static void
rmi_bus_space_write_multi_stream_4(void *tag, bus_space_handle_t handle,
bus_size_t offset, const u_int32_t * addr, size_t count)
{
mips_sync();
if ((int)tag != MIPS_BUS_SPACE_PCI)
return;
while (count--) {
(*(volatile u_int32_t *)(handle + offset)) = *addr;
addr++;
}
}
void
rmi_bus_space_write_region_2(void *t,
bus_space_handle_t bsh,
bus_size_t offset,
const u_int16_t * addr,
size_t count)
{
bus_addr_t baddr = (bus_addr_t) bsh + offset;
while (count--) {
(*(volatile u_int16_t *)(baddr)) = *addr;
addr++;
baddr += 2;
}
}
void
rmi_bus_space_write_region_4(void *t, bus_space_handle_t bsh,
bus_size_t offset, const u_int32_t * addr, size_t count)
{
bus_addr_t baddr = bsh + offset;
while (count--) {
(*(volatile u_int32_t *)(baddr)) = *addr;
addr++;
baddr += 4;
}
}
static void
rmi_bus_space_barrier(void *tag __unused, bus_space_handle_t bsh __unused,
bus_size_t offset __unused, bus_size_t len __unused, int flags)
{
}

346
sys/mips/rmi/clock.c Normal file
View File

@ -0,0 +1,346 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/queue.h>
#include <sys/smp.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/timetc.h>
#include <sys/module.h>
#include <sys/stdint.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <sys/systm.h>
#include <sys/clock.h>
#include <machine/clock.h>
#include <machine/md_var.h>
#include <machine/hwfunc.h>
#include <machine/intr_machdep.h>
#include <mips/rmi/iomap.h>
#include <mips/rmi/clock.h>
#include <mips/rmi/interrupt.h>
#include <mips/rmi/pic.h>
#include <mips/rmi/shared_structs.h>
#ifdef XLR_PERFMON
#include <mips/rmi/perfmon.h>
#endif
uint64_t counter_freq;
uint64_t cycles_per_tick;
uint64_t cycles_per_usec;
uint64_t cycles_per_sec;
uint64_t cycles_per_hz;
u_int32_t counter_upper = 0;
u_int32_t counter_lower_last = 0;
#define STAT_PROF_CLOCK_SCALE_FACTOR 8
static int scale_factor;
static int count_scale_factor[32];
uint64_t
platform_get_frequency()
{
return XLR_PIC_HZ;
}
void
mips_timer_early_init(uint64_t clock_hz)
{
/* Initialize clock early so that we can use DELAY sooner */
counter_freq = clock_hz;
cycles_per_usec = (clock_hz / (1000 * 1000));
}
/*
* count_compare_clockhandler:
*
* Handle the clock interrupt when count becomes equal to
* compare.
*/
int
count_compare_clockhandler(struct trapframe *tf)
{
int cpu = PCPU_GET(cpuid);
uint32_t cycles;
critical_enter();
if (cpu == 0) {
mips_wr_compare(0);
} else {
count_scale_factor[cpu]++;
cycles = mips_rd_count();
cycles += XLR_CPU_HZ / hz;
mips_wr_compare(cycles);
hardclock_cpu(USERMODE(tf->sr));
if (count_scale_factor[cpu] == STAT_PROF_CLOCK_SCALE_FACTOR) {
statclock(USERMODE(tf->sr));
if (profprocs != 0) {
profclock(USERMODE(tf->sr), tf->pc);
}
count_scale_factor[cpu] = 0;
}
/* If needed , handle count compare tick skew here */
}
critical_exit();
return (FILTER_HANDLED);
}
int
pic_hardclockhandler(struct trapframe *tf)
{
int cpu = PCPU_GET(cpuid);
critical_enter();
if (cpu == 0) {
scale_factor++;
hardclock(USERMODE(tf->sr), tf->pc);
if (scale_factor == STAT_PROF_CLOCK_SCALE_FACTOR) {
statclock(USERMODE(tf->sr));
if (profprocs != 0) {
profclock(USERMODE(tf->sr), tf->pc);
}
scale_factor = 0;
}
#ifdef XLR_PERFMON
if (xlr_perfmon_started)
xlr_perfmon_clockhandler();
#endif
} else {
/* If needed , handle count compare tick skew here */
}
critical_exit();
return (FILTER_HANDLED);
}
int
pic_timecounthandler(struct trapframe *tf)
{
return (FILTER_HANDLED);
}
void
rmi_early_counter_init()
{
int cpu = PCPU_GET(cpuid);
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
/*
* We do this to get the PIC time counter running right after system
* start. Otherwise the DELAY() function will not be able to work
* since it won't have a TC to read.
*/
xlr_write_reg(mmio, PIC_TIMER_6_MAXVAL_0, (0xffffffff & 0xffffffff));
xlr_write_reg(mmio, PIC_TIMER_6_MAXVAL_1, (0xffffffff & 0xffffffff));
xlr_write_reg(mmio, PIC_IRT_0_TIMER_6, (1 << cpu));
xlr_write_reg(mmio, PIC_IRT_1_TIMER_6, (1 << 31) | (0 << 30) | (1 << 6) | (PIC_TIMER_6_IRQ));
pic_update_control(1 << (8 + 6));
}
void tick_init(void);
void
platform_initclocks(void)
{
int cpu = PCPU_GET(cpuid);
void *cookie;
/*
* Note: Passing #3 as NULL ensures that clockhandler gets called
* with trapframe
*/
/* profiling/process accounting timer interrupt for non-zero cpus */
cpu_establish_hardintr("compare",
(driver_filter_t *) count_compare_clockhandler,
NULL,
NULL,
IRQ_TIMER,
INTR_TYPE_CLK | INTR_FAST, &cookie);
/* timekeeping timer interrupt for cpu 0 */
cpu_establish_hardintr("hardclk",
(driver_filter_t *) pic_hardclockhandler,
NULL,
NULL,
PIC_TIMER_7_IRQ,
INTR_TYPE_CLK | INTR_FAST,
&cookie);
/* this is used by timecounter */
cpu_establish_hardintr("timecount",
(driver_filter_t *) pic_timecounthandler, NULL,
NULL, PIC_TIMER_6_IRQ, INTR_TYPE_CLK | INTR_FAST,
&cookie);
if (cpu == 0) {
__uint64_t maxval = XLR_PIC_HZ / hz;
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
stathz = hz / STAT_PROF_CLOCK_SCALE_FACTOR;
profhz = stathz;
/* Setup PIC Interrupt */
if (rmi_spin_mutex_safe)
mtx_lock_spin(&xlr_pic_lock);
xlr_write_reg(mmio, PIC_TIMER_7_MAXVAL_0, (maxval & 0xffffffff)); /* 0x100 + 7 */
xlr_write_reg(mmio, PIC_TIMER_7_MAXVAL_1, (maxval >> 32) & 0xffffffff); /* 0x110 + 7 */
/* 0x40 + 8 */
/* reg 40 is lower bits 31-0 and holds CPU mask */
xlr_write_reg(mmio, PIC_IRT_0_TIMER_7, (1 << cpu));
/* 0x80 + 8 */
/* Reg 80 is upper bits 63-32 and holds */
/* Valid Edge Local IRQ */
xlr_write_reg(mmio, PIC_IRT_1_TIMER_7, (1 << 31) | (0 << 30) | (1 << 6) | (PIC_TIMER_7_IRQ));
pic_update_control(1 << (8 + 7));
xlr_write_reg(mmio, PIC_TIMER_6_MAXVAL_0, (0xffffffff & 0xffffffff));
xlr_write_reg(mmio, PIC_TIMER_6_MAXVAL_1, (0x0 & 0xffffffff));
xlr_write_reg(mmio, PIC_IRT_0_TIMER_6, (1 << cpu));
xlr_write_reg(mmio, PIC_IRT_1_TIMER_6, (1 << 31) | (0 << 30) | (1 << 6) | (PIC_TIMER_6_IRQ));
pic_update_control(1 << (8 + 6));
if (rmi_spin_mutex_safe)
mtx_unlock_spin(&xlr_pic_lock);
} else {
/* Setup count-compare interrupt for vcpu[1-31] */
mips_wr_compare((xlr_boot1_info.cpu_frequency) / hz);
}
tick_init();
}
unsigned
__attribute__((no_instrument_function))
platform_get_timecount(struct timecounter *tc __unused)
{
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
return 0xffffffffU - xlr_read_reg(mmio, PIC_TIMER_6_COUNTER_0);
}
void
DELAY(int n)
{
uint32_t cur, last, delta, usecs;
/*
* This works by polling the timer and counting the number of
* microseconds that go by.
*/
last = platform_get_timecount(NULL);
delta = usecs = 0;
while (n > usecs) {
cur = platform_get_timecount(NULL);
/* Check to see if the timer has wrapped around. */
if (cur < last)
delta += (cur + (cycles_per_hz - last));
else
delta += (cur - last);
last = cur;
if (delta >= cycles_per_usec) {
usecs += delta / cycles_per_usec;
delta %= cycles_per_usec;
}
}
}
static
uint64_t
read_pic_counter(void)
{
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
uint32_t lower, upper;
uint64_t tc;
/*
* Pull the value of the 64 bit counter which is stored in PIC
* register 120+N and 130+N
*/
upper = 0xffffffffU - xlr_read_reg(mmio, PIC_TIMER_6_COUNTER_1);
lower = 0xffffffffU - xlr_read_reg(mmio, PIC_TIMER_6_COUNTER_0);
tc = (((uint64_t) upper << 32) | (uint64_t) lower);
return (tc);
}
extern struct timecounter counter_timecounter;
void
mips_timer_init_params(uint64_t platform_counter_freq, int double_count)
{
/*
* XXX: Do not use printf here: uart code 8250 may use DELAY so this
* function should be called before cninit.
*/
counter_freq = platform_counter_freq;
/*
* XXX: Some MIPS32 cores update the Count register only every two
* pipeline cycles.
*/
if (double_count != 0)
counter_freq /= 2;
cycles_per_tick = counter_freq / 1000;
cycles_per_hz = counter_freq / hz;
cycles_per_usec = counter_freq / (1 * 1000 * 1000);
cycles_per_sec = counter_freq;
counter_timecounter.tc_frequency = counter_freq;
printf("hz=%d cyl_per_hz:%jd cyl_per_usec:%jd freq:%jd cyl_per_hz:%jd cyl_per_sec:%jd\n",
hz,
cycles_per_tick,
cycles_per_usec,
counter_freq,
cycles_per_hz,
cycles_per_sec
);
set_cputicker(read_pic_counter, counter_freq, 1);
}

41
sys/mips/rmi/clock.h Normal file
View File

@ -0,0 +1,41 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#ifndef _RMI_CLOCK_H_
#define _RMI_CLOCK_H_
#define XLR_PIC_HZ 66000000U
#define XLR_CPU_HZ (xlr_boot1_info.cpu_frequency)
int count_compare_clockhandler(struct trapframe *);
int pic_hardclockhandler(struct trapframe *);
int pic_timecounthandler(struct trapframe *);
void rmi_early_counter_init(void);
#endif /* _RMI_CLOCK_H_ */

103
sys/mips/rmi/debug.h Executable file
View File

@ -0,0 +1,103 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#ifndef _RMI_DEBUG_H_
#define _RMI_DEBUG_H_
#include <machine/atomic.h>
enum {
//cacheline 0
MSGRNG_INT,
MSGRNG_PIC_INT,
MSGRNG_MSG,
MSGRNG_EXIT_STATUS,
MSGRNG_MSG_CYCLES,
//cacheline 1
NETIF_TX = 8,
NETIF_RX,
NETIF_TX_COMPLETE,
NETIF_TX_COMPLETE_TX,
NETIF_RX_CYCLES,
NETIF_TX_COMPLETE_CYCLES,
NETIF_TX_CYCLES,
NETIF_TIMER_START_Q,
//NETIF_REG_FRIN,
//NETIF_INT_REG,
//cacheline 2
REPLENISH_ENTER = 16,
REPLENISH_ENTER_COUNT,
REPLENISH_CPU,
REPLENISH_FRIN,
REPLENISH_CYCLES,
NETIF_STACK_TX,
NETIF_START_Q,
NETIF_STOP_Q,
//cacheline 3
USER_MAC_START = 24,
USER_MAC_INT = 24,
USER_MAC_TX_COMPLETE,
USER_MAC_RX,
USER_MAC_POLL,
USER_MAC_TX,
USER_MAC_TX_FAIL,
USER_MAC_TX_COUNT,
USER_MAC_FRIN,
//cacheline 4
USER_MAC_TX_FAIL_GMAC_CREDITS = 32,
USER_MAC_DO_PAGE_FAULT,
USER_MAC_UPDATE_TLB,
USER_MAC_UPDATE_BIGTLB,
USER_MAC_UPDATE_TLB_PFN0,
USER_MAC_UPDATE_TLB_PFN1,
XLR_MAX_COUNTERS = 40
};
extern int xlr_counters[MAXCPU][XLR_MAX_COUNTERS];
extern __uint32_t msgrng_msg_cycles;
#ifdef ENABLE_DEBUG
#define xlr_inc_counter(x) atomic_add_int(&xlr_counters[PCPU_GET(cpuid)][(x)], 1)
#define xlr_dec_counter(x) atomic_subtract_int(&xlr_counters[PCPU_GET(cpuid)][(x)], 1)
#define xlr_set_counter(x, value) atomic_set_int(&xlr_counters[PCPU_GET(cpuid)][(x)], (value))
#define xlr_get_counter(x) (&xlr_counters[0][(x)])
#else /* default mode */
#define xlr_inc_counter(x)
#define xlr_dec_counter(x)
#define xlr_set_counter(x, value)
#define xlr_get_counter(x)
#endif
#define dbg_msg(fmt, args...) printf(fmt, ##args)
#define dbg_panic(fmt, args...) panic(fmt, ##args)
#endif

309
sys/mips/rmi/ehcireg.h Normal file
View File

@ -0,0 +1,309 @@
/* $NetBSD: ehcireg.h,v 1.18 2004/10/22 10:38:17 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/ehcireg.h,v 1.7.2.2.2.1 2008/10/02 02:57:24 kensmith Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Lennart Augustsson (lennart@augustsson.net).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* The EHCI 0.96 spec can be found at
* http://developer.intel.com/technology/usb/download/ehci-r096.pdf
* and the USB 2.0 spec at
* http://www.usb.org/developers/data/usb_20.zip
*/
#ifndef _DEV_PCI_EHCIREG_H_
#define _DEV_PCI_EHCIREG_H_
/*** PCI config registers ***/
#define PCI_CBMEM 0x10 /* configuration base MEM */
#define PCI_INTERFACE_EHCI 0x20
#define PCI_USBREV 0x60 /* RO USB protocol revision */
#define PCI_USBREV_MASK 0xff
#define PCI_USBREV_PRE_1_0 0x00
#define PCI_USBREV_1_0 0x10
#define PCI_USBREV_1_1 0x11
#define PCI_USBREV_2_0 0x20
#define PCI_EHCI_FLADJ 0x61 /* RW Frame len adj, SOF=59488+6*fladj */
#define PCI_EHCI_PORTWAKECAP 0x62 /* RW Port wake caps (opt) */
/* EHCI Extended Capabilities */
#define EHCI_EC_LEGSUP 0x01
#define EHCI_EECP_NEXT(x) (((x) >> 8) & 0xff)
#define EHCI_EECP_ID(x) ((x) & 0xff)
/* Legacy support extended capability */
#define EHCI_LEGSUP_OS_SEM 0x03 /* OS owned semaphore */
#define EHCI_LEGSUP_BIOS_SEM 0x02 /* BIOS owned semaphore */
#define EHCI_LEGSUP_USBLEGCTLSTS 0x04
/*** EHCI capability registers ***/
#define EHCI_CAPLENGTH 0x00 /* RO Capability register length field */
/* reserved 0x01 */
#define EHCI_HCIVERSION 0x02 /* RO Interface version number */
#define EHCI_HCSPARAMS 0x04 /* RO Structural parameters */
#define EHCI_HCS_DEBUGPORT(x) (((x) >> 20) & 0xf)
#define EHCI_HCS_P_INDICATOR(x) ((x) & 0x10000)
#define EHCI_HCS_N_CC(x) (((x) >> 12) & 0xf) /* # of companion ctlrs */
#define EHCI_HCS_N_PCC(x) (((x) >> 8) & 0xf) /* # of ports per comp. */
#define EHCI_HCS_PPC(x) ((x) & 0x10) /* port power control */
#define EHCI_HCS_N_PORTS(x) ((x) & 0xf) /* # of ports */
#define EHCI_HCCPARAMS 0x08 /* RO Capability parameters */
#define EHCI_HCC_EECP(x) (((x) >> 8) & 0xff) /* extended ports caps */
#define EHCI_HCC_IST(x) (((x) >> 4) & 0xf) /* isoc sched threshold */
#define EHCI_HCC_ASPC(x) ((x) & 0x4) /* async sched park cap */
#define EHCI_HCC_PFLF(x) ((x) & 0x2) /* prog frame list flag */
#define EHCI_HCC_64BIT(x) ((x) & 0x1) /* 64 bit address cap */
#define EHCI_HCSP_PORTROUTE 0x0c /* RO Companion port route description */
/* EHCI operational registers. Offset given by EHCI_CAPLENGTH register */
#define EHCI_USBCMD 0x00 /* RO, RW, WO Command register */
#define EHCI_CMD_ITC_M 0x00ff0000 /* RW interrupt threshold ctrl */
#define EHCI_CMD_ITC_1 0x00010000
#define EHCI_CMD_ITC_2 0x00020000
#define EHCI_CMD_ITC_4 0x00040000
#define EHCI_CMD_ITC_8 0x00080000
#define EHCI_CMD_ITC_16 0x00100000
#define EHCI_CMD_ITC_32 0x00200000
#define EHCI_CMD_ITC_64 0x00400000
#define EHCI_CMD_ASPME 0x00000800 /* RW/RO async park enable */
#define EHCI_CMD_ASPMC 0x00000300 /* RW/RO async park count */
#define EHCI_CMD_LHCR 0x00000080 /* RW light host ctrl reset */
#define EHCI_CMD_IAAD 0x00000040 /* RW intr on async adv door
* bell */
#define EHCI_CMD_ASE 0x00000020 /* RW async sched enable */
#define EHCI_CMD_PSE 0x00000010 /* RW periodic sched enable */
#define EHCI_CMD_FLS_M 0x0000000c /* RW/RO frame list size */
#define EHCI_CMD_FLS(x) (((x) >> 2) & 3) /* RW/RO frame list size */
#define EHCI_CMD_HCRESET 0x00000002 /* RW reset */
#define EHCI_CMD_RS 0x00000001 /* RW run/stop */
#define EHCI_USBSTS 0x04 /* RO, RW, RWC Status register */
#define EHCI_STS_ASS 0x00008000 /* RO async sched status */
#define EHCI_STS_PSS 0x00004000 /* RO periodic sched status */
#define EHCI_STS_REC 0x00002000 /* RO reclamation */
#define EHCI_STS_HCH 0x00001000 /* RO host controller halted */
#define EHCI_STS_IAA 0x00000020 /* RWC interrupt on async adv */
#define EHCI_STS_HSE 0x00000010 /* RWC host system error */
#define EHCI_STS_FLR 0x00000008 /* RWC frame list rollover */
#define EHCI_STS_PCD 0x00000004 /* RWC port change detect */
#define EHCI_STS_ERRINT 0x00000002 /* RWC error interrupt */
#define EHCI_STS_INT 0x00000001 /* RWC interrupt */
#define EHCI_STS_INTRS(x) ((x) & 0x3f)
#define EHCI_NORMAL_INTRS (EHCI_STS_IAA | EHCI_STS_HSE | EHCI_STS_PCD | EHCI_STS_ERRINT | EHCI_STS_INT)
#define EHCI_USBINTR 0x08 /* RW Interrupt register */
#define EHCI_INTR_IAAE 0x00000020 /* interrupt on async advance
* ena */
#define EHCI_INTR_HSEE 0x00000010 /* host system error ena */
#define EHCI_INTR_FLRE 0x00000008 /* frame list rollover ena */
#define EHCI_INTR_PCIE 0x00000004 /* port change ena */
#define EHCI_INTR_UEIE 0x00000002 /* USB error intr ena */
#define EHCI_INTR_UIE 0x00000001 /* USB intr ena */
#define EHCI_FRINDEX 0x0c /* RW Frame Index register */
#define EHCI_CTRLDSSEGMENT 0x10 /* RW Control Data Structure Segment */
#define EHCI_PERIODICLISTBASE 0x14 /* RW Periodic List Base */
#define EHCI_ASYNCLISTADDR 0x18 /* RW Async List Base */
#define EHCI_CONFIGFLAG 0x40 /* RW Configure Flag register */
#define EHCI_CONF_CF 0x00000001 /* RW configure flag */
#define EHCI_PORTSC(n) (0x40+4*(n)) /* RO, RW, RWC Port Status reg */
#define EHCI_PS_WKOC_E 0x00400000 /* RW wake on over current ena */
#define EHCI_PS_WKDSCNNT_E 0x00200000 /* RW wake on disconnect ena */
#define EHCI_PS_WKCNNT_E 0x00100000 /* RW wake on connect ena */
#define EHCI_PS_PTC 0x000f0000 /* RW port test control */
#define EHCI_PS_PIC 0x0000c000 /* RW port indicator control */
#define EHCI_PS_PO 0x00002000 /* RW port owner */
#define EHCI_PS_PP 0x00001000 /* RW,RO port power */
#define EHCI_PS_LS 0x00000c00 /* RO line status */
#define EHCI_PS_IS_LOWSPEED(x) (((x) & EHCI_PS_LS) == 0x00000400)
#define EHCI_PS_PR 0x00000100 /* RW port reset */
#define EHCI_PS_SUSP 0x00000080 /* RW suspend */
#define EHCI_PS_FPR 0x00000040 /* RW force port resume */
#define EHCI_PS_OCC 0x00000020 /* RWC over current change */
#define EHCI_PS_OCA 0x00000010 /* RO over current active */
#define EHCI_PS_PEC 0x00000008 /* RWC port enable change */
#define EHCI_PS_PE 0x00000004 /* RW port enable */
#define EHCI_PS_CSC 0x00000002 /* RWC connect status change */
#define EHCI_PS_CS 0x00000001 /* RO connect status */
#define EHCI_PS_CLEAR (EHCI_PS_OCC|EHCI_PS_PEC|EHCI_PS_CSC)
#define EHCI_PORT_RESET_COMPLETE 2 /* ms */
#define EHCI_FLALIGN_ALIGN 0x1000
/* No data structure may cross a page boundary. */
#define EHCI_PAGE_SIZE 0x1000
#define EHCI_PAGE(x) ((x) &~ 0xfff)
#define EHCI_PAGE_OFFSET(x) ((x) & 0xfff)
#if defined(__FreeBSD__)
#define EHCI_PAGE_MASK(x) ((x) & 0xfff)
#endif
typedef u_int32_t ehci_link_t;
#define EHCI_LINK_TERMINATE 0x00000001
#define EHCI_LINK_TYPE(x) ((x) & 0x00000006)
#define EHCI_LINK_ITD 0x0
#define EHCI_LINK_QH 0x2
#define EHCI_LINK_SITD 0x4
#define EHCI_LINK_FSTN 0x6
#define EHCI_LINK_ADDR(x) ((x) &~ 0x1f)
typedef u_int32_t ehci_physaddr_t;
/* Isochronous Transfer Descriptor */
typedef struct {
ehci_link_t itd_next;
/* XXX many more */
} ehci_itd_t;
#define EHCI_ITD_ALIGN 32
/* Split Transaction Isochronous Transfer Descriptor */
typedef struct {
ehci_link_t sitd_next;
/* XXX many more */
} ehci_sitd_t;
#define EHCI_SITD_ALIGN 32
/* Queue Element Transfer Descriptor */
#define EHCI_QTD_NBUFFERS 5
typedef struct {
ehci_link_t qtd_next;
ehci_link_t qtd_altnext;
u_int32_t qtd_status;
#define EHCI_QTD_GET_STATUS(x) (((x) >> 0) & 0xff)
#define EHCI_QTD_SET_STATUS(x) ((x) << 0)
#define EHCI_QTD_ACTIVE 0x80
#define EHCI_QTD_HALTED 0x40
#define EHCI_QTD_BUFERR 0x20
#define EHCI_QTD_BABBLE 0x10
#define EHCI_QTD_XACTERR 0x08
#define EHCI_QTD_MISSEDMICRO 0x04
#define EHCI_QTD_SPLITXSTATE 0x02
#define EHCI_QTD_PINGSTATE 0x01
#define EHCI_QTD_STATERRS 0x7c
#define EHCI_QTD_GET_PID(x) (((x) >> 8) & 0x3)
#define EHCI_QTD_SET_PID(x) ((x) << 8)
#define EHCI_QTD_PID_OUT 0x0
#define EHCI_QTD_PID_IN 0x1
#define EHCI_QTD_PID_SETUP 0x2
#define EHCI_QTD_GET_CERR(x) (((x) >> 10) & 0x3)
#define EHCI_QTD_SET_CERR(x) ((x) << 10)
#define EHCI_QTD_GET_C_PAGE(x) (((x) >> 12) & 0x7)
#define EHCI_QTD_SET_C_PAGE(x) ((x) << 12)
#define EHCI_QTD_GET_IOC(x) (((x) >> 15) & 0x1)
#define EHCI_QTD_IOC 0x00008000
#define EHCI_QTD_GET_BYTES(x) (((x) >> 16) & 0x7fff)
#define EHCI_QTD_SET_BYTES(x) ((x) << 16)
#define EHCI_QTD_GET_TOGGLE(x) (((x) >> 31) & 0x1)
#define EHCI_QTD_SET_TOGGLE(x) ((x) << 31)
#define EHCI_QTD_TOGGLE_MASK 0x80000000
ehci_physaddr_t qtd_buffer[EHCI_QTD_NBUFFERS];
ehci_physaddr_t qtd_buffer_hi[EHCI_QTD_NBUFFERS];
} ehci_qtd_t;
#define EHCI_QTD_ALIGN 32
/* Queue Head */
typedef struct {
ehci_link_t qh_link;
u_int32_t qh_endp;
#define EHCI_QH_GET_ADDR(x) (((x) >> 0) & 0x7f) /* endpoint addr */
#define EHCI_QH_SET_ADDR(x) (x)
#define EHCI_QH_ADDRMASK 0x0000007f
#define EHCI_QH_GET_INACT(x) (((x) >> 7) & 0x01) /* inactivate on next */
#define EHCI_QH_INACT 0x00000080
#define EHCI_QH_GET_ENDPT(x) (((x) >> 8) & 0x0f) /* endpoint no */
#define EHCI_QH_SET_ENDPT(x) ((x) << 8)
#define EHCI_QH_GET_EPS(x) (((x) >> 12) & 0x03) /* endpoint speed */
#define EHCI_QH_SET_EPS(x) ((x) << 12)
#define EHCI_QH_SPEED_FULL 0x0
#define EHCI_QH_SPEED_LOW 0x1
#define EHCI_QH_SPEED_HIGH 0x2
#define EHCI_QH_GET_DTC(x) (((x) >> 14) & 0x01) /* data toggle control */
#define EHCI_QH_DTC 0x00004000
#define EHCI_QH_GET_HRECL(x) (((x) >> 15) & 0x01) /* head of reclamation */
#define EHCI_QH_HRECL 0x00008000
#define EHCI_QH_GET_MPL(x) (((x) >> 16) & 0x7ff) /* max packet len */
#define EHCI_QH_SET_MPL(x) ((x) << 16)
#define EHCI_QH_MPLMASK 0x07ff0000
#define EHCI_QH_GET_CTL(x) (((x) >> 27) & 0x01) /* control endpoint */
#define EHCI_QH_CTL 0x08000000
#define EHCI_QH_GET_NRL(x) (((x) >> 28) & 0x0f) /* NAK reload */
#define EHCI_QH_SET_NRL(x) ((x) << 28)
u_int32_t qh_endphub;
#define EHCI_QH_GET_SMASK(x) (((x) >> 0) & 0xff) /* intr sched mask */
#define EHCI_QH_SET_SMASK(x) ((x) << 0)
#define EHCI_QH_GET_CMASK(x) (((x) >> 8) & 0xff) /* split completion mask */
#define EHCI_QH_SET_CMASK(x) ((x) << 8)
#define EHCI_QH_GET_HUBA(x) (((x) >> 16) & 0x7f) /* hub address */
#define EHCI_QH_SET_HUBA(x) ((x) << 16)
#define EHCI_QH_GET_PORT(x) (((x) >> 23) & 0x7f) /* hub port */
#define EHCI_QH_SET_PORT(x) ((x) << 23)
#define EHCI_QH_GET_MULT(x) (((x) >> 30) & 0x03) /* pipe multiplier */
#define EHCI_QH_SET_MULT(x) ((x) << 30)
ehci_link_t qh_curqtd;
ehci_qtd_t qh_qtd;
} ehci_qh_t;
#define EHCI_QH_ALIGN 32
/* Periodic Frame Span Traversal Node */
typedef struct {
ehci_link_t fstn_link;
ehci_link_t fstn_back;
} ehci_fstn_t;
#define EHCI_FSTN_ALIGN 32
#endif /* _DEV_PCI_EHCIREG_H_ */

195
sys/mips/rmi/ehcivar.h Normal file
View File

@ -0,0 +1,195 @@
/* $NetBSD: ehcivar.h,v 1.19 2005/04/29 15:04:29 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/ehcivar.h,v 1.9.2.1.8.1 2008/10/02 02:57:24 kensmith Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Lennart Augustsson (lennart@augustsson.net).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
typedef struct ehci_soft_qtd {
ehci_qtd_t qtd;
struct ehci_soft_qtd *nextqtd; /* mirrors nextqtd in TD */
ehci_physaddr_t physaddr;
usbd_xfer_handle xfer;
LIST_ENTRY(ehci_soft_qtd) hnext;
u_int16_t len;
} ehci_soft_qtd_t;
#define EHCI_SQTD_SIZE ((sizeof (struct ehci_soft_qtd) + EHCI_QTD_ALIGN - 1) / EHCI_QTD_ALIGN * EHCI_QTD_ALIGN)
#define EHCI_SQTD_CHUNK (EHCI_PAGE_SIZE / EHCI_SQTD_SIZE)
typedef struct ehci_soft_qh {
ehci_qh_t qh;
struct ehci_soft_qh *next;
struct ehci_soft_qh *prev;
struct ehci_soft_qtd *sqtd;
ehci_physaddr_t physaddr;
int islot; /* Interrupt list slot. */
} ehci_soft_qh_t;
#define EHCI_SQH_SIZE ((sizeof (struct ehci_soft_qh) + EHCI_QH_ALIGN - 1) / EHCI_QH_ALIGN * EHCI_QH_ALIGN)
#define EHCI_SQH_CHUNK (EHCI_PAGE_SIZE / EHCI_SQH_SIZE)
struct ehci_xfer {
struct usbd_xfer xfer;
struct usb_task abort_task;
LIST_ENTRY(ehci_xfer) inext; /* list of active xfers */
ehci_soft_qtd_t *sqtdstart;
ehci_soft_qtd_t *sqtdend;
u_int32_t ehci_xfer_flags;
#ifdef DIAGNOSTIC
int isdone;
#endif
};
#define EHCI_XFER_ABORTING 0x0001 /* xfer is aborting. */
#define EHCI_XFER_ABORTWAIT 0x0002 /* abort completion is being awaited. */
#define EXFER(xfer) ((struct ehci_xfer *)(xfer))
/*
* Information about an entry in the interrupt list.
*/
struct ehci_soft_islot {
ehci_soft_qh_t *sqh; /* Queue Head. */
};
#define EHCI_FRAMELIST_MAXCOUNT 1024
#define EHCI_IPOLLRATES 8 /* Poll rates (1ms, 2, 4, 8 ... 128) */
#define EHCI_INTRQHS ((1 << EHCI_IPOLLRATES) - 1)
#define EHCI_MAX_POLLRATE (1 << (EHCI_IPOLLRATES - 1))
#define EHCI_IQHIDX(lev, pos) \
((((pos) & ((1 << (lev)) - 1)) | (1 << (lev))) - 1)
#define EHCI_ILEV_IVAL(lev) (1 << (lev))
#define EHCI_HASH_SIZE 128
#define EHCI_COMPANION_MAX 8
#define EHCI_SCFLG_DONEINIT 0x0001 /* ehci_init() has been called. */
#define EHCI_SCFLG_LOSTINTRBUG 0x0002 /* workaround for VIA / ATI chipsets */
typedef struct ehci_softc {
struct usbd_bus sc_bus; /* base device */
int sc_flags;
bus_space_tag_t iot;
bus_space_handle_t ioh;
bus_size_t sc_size;
#if defined(__FreeBSD__)
void *ih;
struct resource *io_res;
struct resource *irq_res;
#endif
u_int sc_offs; /* offset to operational regs */
char sc_vendor[32]; /* vendor string for root hub */
int sc_id_vendor; /* vendor ID for root hub */
u_int32_t sc_cmd; /* shadow of cmd reg during suspend */
#if defined(__NetBSD__) || defined(__OpenBSD__)
void *sc_powerhook; /* cookie from power hook */
void *sc_shutdownhook; /* cookie from shutdown hook */
#endif
u_int sc_ncomp;
u_int sc_npcomp;
struct usbd_bus *sc_comps[EHCI_COMPANION_MAX];
usb_dma_t sc_fldma;
ehci_link_t *sc_flist;
u_int sc_flsize;
#ifndef __FreeBSD__
u_int sc_rand; /* XXX need proper intr scheduling */
#endif
struct ehci_soft_islot sc_islots[EHCI_INTRQHS];
LIST_HEAD(, ehci_xfer) sc_intrhead;
ehci_soft_qh_t *sc_freeqhs;
ehci_soft_qtd_t *sc_freeqtds;
int sc_noport;
u_int8_t sc_addr; /* device address */
u_int8_t sc_conf; /* device configuration */
usbd_xfer_handle sc_intrxfer;
char sc_isreset;
#ifdef USB_USE_SOFTINTR
char sc_softwake;
#endif /* USB_USE_SOFTINTR */
u_int32_t sc_eintrs;
ehci_soft_qh_t *sc_async_head;
SIMPLEQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */
struct lock sc_doorbell_lock;
usb_callout_t sc_tmo_pcd;
usb_callout_t sc_tmo_intrlist;
#if defined(__NetBSD__) || defined(__OpenBSD__)
device_ptr_t sc_child; /* /dev/usb# device */
#endif
char sc_dying;
#if defined(__NetBSD__)
struct usb_dma_reserve sc_dma_reserve;
#endif
} ehci_softc_t;
#define EREAD1(sc, a) bus_space_read_1((sc)->iot, (sc)->ioh, (a))
#define EREAD2(sc, a) bus_space_read_2((sc)->iot, (sc)->ioh, (a))
#define EREAD4(sc, a) bus_space_read_4((sc)->iot, (sc)->ioh, (a))
#define EWRITE1(sc, a, x) bus_space_write_1((sc)->iot, (sc)->ioh, (a), (x))
#define EWRITE2(sc, a, x) bus_space_write_2((sc)->iot, (sc)->ioh, (a), (x))
#define EWRITE4(sc, a, x) bus_space_write_4((sc)->iot, (sc)->ioh, (a), (x))
#define EOREAD1(sc, a) bus_space_read_1((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a))
#define EOREAD2(sc, a) bus_space_read_2((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a))
#define EOREAD4(sc, a) bus_space_read_4((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a))
#define EOWRITE1(sc, a, x) bus_space_write_1((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a), (x))
#define EOWRITE2(sc, a, x) bus_space_write_2((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a), (x))
#define EOWRITE4(sc, a, x) bus_space_write_4((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a), (x))
usbd_status ehci_init(ehci_softc_t *);
int ehci_intr(void *);
int ehci_detach(ehci_softc_t *, int);
#if defined(__NetBSD__) || defined(__OpenBSD__)
int ehci_activate(device_ptr_t, enum devact);
#endif
void ehci_power(int state, void *priv);
void ehci_shutdown(void *v);
#define MS_TO_TICKS(ms) ((ms) * hz / 1000)

26
sys/mips/rmi/files.xlr Normal file
View File

@ -0,0 +1,26 @@
# $FreeBSD$
#mips/rmi/xlr_boot1_console.c standard
mips/rmi/xlr_machdep.c standard
mips/rmi/clock.c standard
mips/rmi/tick.c standard
mips/rmi/iodi.c standard
mips/rmi/msgring.c standard
mips/rmi/msgring_xls.c standard
mips/rmi/board.c standard
mips/rmi/on_chip.c standard
mips/rmi/intr_machdep.c standard
mips/rmi/xlr_i2c.c optional iic
mips/rmi/uart_bus_xlr_iodi.c optional uart
mips/rmi/uart_cpu_mips_xlr.c optional uart
mips/rmi/perfmon_kern.c optional xlr_perfmon
mips/rmi/perfmon_percpu.c optional xlr_perfmon
#mips/rmi/pcibus.c optional pci
#mips/rmi/xlr_pci.c optional pci
#mips/rmi/xls_ehci.c optional usb ehci
dev/rmi/xlr/rge.c optional rge
mips/rmi/bus_space_rmi.c standard
dev/iicbus/xlr_rtc.c optional xlr_rtc
dev/iicbus/xlr_temperature.c optional xlr_temperature
dev/iicbus/xlr_eeprom.c optional xlr_eeprom
dev/rmi/sec/rmisec.c optional rmisec
dev/rmi/sec/rmilib.c optional rmisec

42
sys/mips/rmi/interrupt.h Normal file
View File

@ -0,0 +1,42 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#ifndef _RMI_INTERRUPT_H_
#define _RMI_INTERRUPT_H_
/* Defines for the IRQ numbers */
#define IRQ_DUMMY_UART 2
#define IRQ_IPI_SMP_FUNCTION 3
#define IRQ_IPI_SMP_RESCHEDULE 4
#define IRQ_REMOTE_DEBUG 5
#define IRQ_MSGRING 6
#define IRQ_TIMER 7
#endif /* _RMI_INTERRUPT_H_ */

217
sys/mips/rmi/intr_machdep.c Normal file
View File

@ -0,0 +1,217 @@
/*-
* Copyright (c) 2006-2009 RMI Corporation
* Copyright (c) 2002-2004 Juli Mallett <jmallett@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification, immediately at the beginning of the file.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/kernel.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/cpuinfo.h>
#include <machine/cpuregs.h>
#include <machine/frame.h>
#include <machine/intr_machdep.h>
#include <machine/md_var.h>
#include <machine/trap.h>
#include <machine/hwfunc.h>
#include <mips/rmi/xlrconfig.h>
#include <mips/rmi/interrupt.h>
#include <mips/rmi/clock.h>
#include <mips/rmi/pic.h>
/*#include <machine/intrcnt.h>*/
static mips_intrcnt_t mips_intr_counters[XLR_MAX_INTR];
struct mips_intrhand mips_intr_handlers[XLR_MAX_INTR];
static int intrcnt_index;
static void
mips_mask_hard_irq(void *source)
{
uintptr_t irq = (uintptr_t) source;
write_c0_eimr64(read_c0_eimr64() & ~(1ULL << irq));
}
static void
mips_unmask_hard_irq(void *source)
{
uintptr_t irq = (uintptr_t) source;
write_c0_eimr64(read_c0_eimr64() | (1ULL << irq));
}
void
cpu_establish_hardintr(const char *name, driver_filter_t * filt,
void (*handler) (void *), void *arg, int irq, int flags, void **cookiep)
{
struct mips_intrhand *mih; /* descriptor for the IRQ */
struct intr_event *ie; /* descriptor for the IRQ */
int errcode;
if (irq < 0 || irq > XLR_MAX_INTR)
panic("%s called for unknown hard intr %d", __func__, irq);
/*
* FIXME locking - not needed now, because we do this only on
* startup from CPU0
*/
mih = &mips_intr_handlers[irq];
/* mih->cntp = &intrcnt[irq]; */
ie = mih->mih_event;
if (ie == NULL) {
errcode = intr_event_create(&ie, (void *)(uintptr_t) irq, 0,
irq, mips_mask_hard_irq, mips_unmask_hard_irq,
NULL, NULL, "hard intr%d:", irq);
if (errcode) {
printf("Could not create event for intr %d\n", irq);
return;
}
}
intr_event_add_handler(ie, name, filt, handler, arg,
intr_priority(flags), flags, cookiep);
mih->mih_event = ie;
mips_unmask_hard_irq((void *)(uintptr_t) irq);
}
void
cpu_establish_softintr(const char *name, driver_filter_t * filt,
void (*handler) (void *), void *arg, int irq, int flags,
void **cookiep)
{
/* we don't separate them into soft/hard like other mips */
cpu_establish_hardintr(name, filt, handler, arg, irq, flags, cookiep);
}
void
cpu_intr(struct trapframe *tf)
{
struct mips_intrhand *mih;
struct intr_event *ie;
register_t eirr;
int i;
critical_enter();
eirr = read_c0_eirr64();
if (eirr == 0) {
critical_exit();
return;
}
/*
* No need to clear the EIRR here. the handler is gonna write to
* compare which clears eirr also
*/
if (eirr & (1 << IRQ_TIMER)) {
count_compare_clockhandler(tf);
critical_exit();
return;
}
/* FIXME sched pin >? LOCK>? */
for (i = sizeof(eirr) * 8 - 1; i >= 0; i--) {
if ((eirr & (1ULL << i)) == 0)
continue;
#ifdef SMP
/* These are reserved interrupts */
if ((i == IPI_AST) || (i == IPI_RENDEZVOUS) || (i == IPI_STOP)
|| (i == IPI_SMP_CALL_FUNCTION)) {
write_c0_eirr64(1ULL << i);
pic_ack(i);
smp_handle_ipi(tf, i);
pic_delayed_ack(i);
continue;
}
#ifdef XLR_PERFMON
if (i == IPI_PERFMON) {
write_c0_eirr64(1ULL << i);
pic_ack(i);
xlr_perfmon_sampler(NULL);
pic_delayed_ack(i);
continue;
}
#endif
#endif
mih = &mips_intr_handlers[i];
/* atomic_add_long(mih->cntp, 1); */
ie = mih->mih_event;
write_c0_eirr64(1ULL << i);
pic_ack(i);
if (!ie || TAILQ_EMPTY(&ie->ie_handlers)) {
printf("stray interrupt %d\n", i);
continue;
}
if (intr_event_handle(ie, tf) != 0) {
printf("stray interrupt %d\n", i);
}
pic_delayed_ack(i);
}
critical_exit();
}
void
mips_intrcnt_setname(mips_intrcnt_t counter, const char *name)
{
int idx = counter - intrcnt;
KASSERT(counter != NULL, ("mips_intrcnt_setname: NULL counter"));
snprintf(intrnames + (MAXCOMLEN + 1) * idx,
MAXCOMLEN + 1, "%-*s", MAXCOMLEN, name);
}
mips_intrcnt_t
mips_intrcnt_create(const char* name)
{
mips_intrcnt_t counter = &intrcnt[intrcnt_index++];
mips_intrcnt_setname(counter, name);
return counter;
}
void
cpu_init_interrupts()
{
int i;
char name[MAXCOMLEN + 1];
/*
* Initialize all available vectors so spare IRQ
* would show up in systat output
*/
for (i = 0; i < XLR_MAX_INTR; i++) {
snprintf(name, MAXCOMLEN + 1, "int%d:", i);
mips_intr_counters[i] = mips_intrcnt_create(name);
}
}

308
sys/mips/rmi/iodi.c Normal file
View File

@ -0,0 +1,308 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#define __RMAN_RESOURCE_VISIBLE
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/reboot.h>
#include <sys/types.h>
#include <sys/malloc.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/module.h>
#include <machine/cpu.h>
#include <machine/bus.h>
#include <machine/bus.h>
#include <machine/intr_machdep.h>
#include <mips/rmi/iomap.h>
#include <mips/rmi/pic.h>
#include <mips/rmi/shared_structs.h>
#include <mips/rmi/board.h>
#include <sys/rman.h>
#include <machine/param.h>
#include <machine/intr_machdep.h>
#include <machine/clock.h> /* for DELAY */
#include <machine/bus.h>
#include <machine/resource.h>
#include <mips/rmi/interrupt.h>
#include <mips/rmi/msgring.h>
#include <mips/rmi/iomap.h>
#include <mips/rmi/debug.h>
#include <mips/rmi/pic.h>
#include <mips/rmi/xlrconfig.h>
#include <mips/rmi/shared_structs.h>
#include <mips/rmi/board.h>
#include <dev/rmi/xlr/atx_cpld.h>
#include <dev/rmi/xlr/xgmac_mdio.h>
extern void iodi_activateirqs(void);
extern bus_space_tag_t uart_bus_space_mem;
static struct resource *
iodi_alloc_resource(device_t, device_t, int, int *,
u_long, u_long, u_long, u_int);
static int
iodi_activate_resource(device_t, device_t, int, int,
struct resource *);
static int
iodi_setup_intr(device_t, device_t, struct resource *, int,
driver_filter_t *, driver_intr_t *, void *, void **);
struct iodi_softc *iodi_softc; /* There can be only one. */
/*
static void pic_usb_ack(void *arg)
{
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
int irq = PIC_USB_IRQ ;
mtx_lock_spin(&xlr_pic_lock);
xlr_write_reg(mmio, PIC_INT_ACK, (1 << (irq - PIC_IRQ_BASE)));
mtx_unlock_spin(&xlr_pic_lock);
}
*/
static int
iodi_setup_intr(device_t dev, device_t child,
struct resource *ires, int flags, driver_filter_t * filt, driver_intr_t * intr, void *arg,
void **cookiep)
{
int level;
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
xlr_reg_t reg;
/* FIXME is this the right place to fiddle with PIC? */
if (strcmp(device_get_name(child), "uart") == 0) {
/* FIXME uart 1? */
if (rmi_spin_mutex_safe)
mtx_lock_spin(&xlr_pic_lock);
level = PIC_IRQ_IS_EDGE_TRIGGERED(PIC_IRT_UART_0_INDEX);
xlr_write_reg(mmio, PIC_IRT_0_UART_0, 0x01);
xlr_write_reg(mmio, PIC_IRT_1_UART_0, ((1 << 31) | (level << 30) | (1 << 6) | (PIC_UART_0_IRQ)));
if (rmi_spin_mutex_safe)
mtx_unlock_spin(&xlr_pic_lock);
cpu_establish_hardintr("uart", filt,
(driver_intr_t *) intr, (void *)arg, PIC_UART_0_IRQ, flags, cookiep);
} else if (strcmp(device_get_name(child), "rge") == 0) {
int irq;
/* This is a hack to pass in the irq */
irq = (int)ires->__r_i;
if (rmi_spin_mutex_safe)
mtx_lock_spin(&xlr_pic_lock);
reg = xlr_read_reg(mmio, PIC_IRT_1_BASE + irq - PIC_IRQ_BASE);
xlr_write_reg(mmio, PIC_IRT_1_BASE + irq - PIC_IRQ_BASE, reg | (1 << 6) | (1 << 30) | (1 << 31));
if (rmi_spin_mutex_safe)
mtx_unlock_spin(&xlr_pic_lock);
cpu_establish_hardintr("rge", filt, (driver_intr_t *) intr, (void *)arg, irq, flags, cookiep);
} else if (strcmp(device_get_name(child), "ehci") == 0) {
if (rmi_spin_mutex_safe)
mtx_lock_spin(&xlr_pic_lock);
reg = xlr_read_reg(mmio, PIC_IRT_1_BASE + PIC_USB_IRQ - PIC_IRQ_BASE);
xlr_write_reg(mmio, PIC_IRT_1_BASE + PIC_USB_IRQ - PIC_IRQ_BASE, reg | (1 << 6) | (1 << 30) | (1 << 31));
if (rmi_spin_mutex_safe)
mtx_unlock_spin(&xlr_pic_lock);
cpu_establish_hardintr("ehci", filt, (driver_intr_t *) intr, (void *)arg, PIC_USB_IRQ, flags, cookiep);
}
/*
* This causes a panic and looks recursive to me (RRS).
* BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, filt,
* intr, arg, cookiep);
*/
return (0);
}
/* Strange hook found in mips/include/bus.h */
#ifndef MIPS_BUS_SPACE_PCI
#define MIPS_BUS_SPACE_PCI 10
#endif
static struct resource *
iodi_alloc_resource(device_t bus, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct resource *res = malloc(sizeof(*res), M_DEVBUF, M_WAITOK);
int unit;
#ifdef DEBUG
switch (type) {
case SYS_RES_IRQ:
device_printf(bus, "IRQ resource - for %s %lx-%lx\n",
device_get_nameunit(child), start, end);
break;
case SYS_RES_IOPORT:
device_printf(bus, "IOPORT resource - for %s %lx-%lx\n",
device_get_nameunit(child), start, end);
break;
case SYS_RES_MEMORY:
device_printf(bus, "MEMORY resource - for %s %lx-%lx\n",
device_get_nameunit(child), start, end);
break;
}
#endif
if (strcmp(device_get_name(child), "uart") == 0) {
if ((unit = device_get_unit(child)) == 0) { /* uart 0 */
res->r_bushandle = (xlr_io_base + XLR_IO_UART_0_OFFSET);
} else if (unit == 1) {
res->r_bushandle = (xlr_io_base + XLR_IO_UART_1_OFFSET);
} else
printf("%s: Unknown uart unit\n", __FUNCTION__);
res->r_bustag = uart_bus_space_mem;
} else if (strcmp(device_get_name(child), "ehci") == 0) {
res->r_bushandle = 0xbef24000;
res->r_bustag = (bus_space_tag_t) MIPS_BUS_SPACE_PCI;
} else if (strcmp(device_get_name(child), "cfi") == 0) {
res->r_bushandle = 0xbc000000;
res->r_bustag = 0;
}
/* res->r_start = *rid; */
return (res);
}
static int
iodi_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
return (0);
}
/* prototypes */
static int iodi_probe(device_t);
static int iodi_attach(device_t);
static void iodi_identify(driver_t *, device_t);
int
iodi_probe(device_t dev)
{
return 0;
}
void
iodi_identify(driver_t * driver, device_t parent)
{
BUS_ADD_CHILD(parent, 0, "iodi", 0);
}
int
iodi_attach(device_t dev)
{
device_t tmpd;
/*
* Attach each devices
*/
device_add_child(dev, "uart", 0);
device_add_child(dev, "xlr_i2c", 0);
if (xlr_board_info.usb)
device_add_child(dev, "ehci", 0);
if (xlr_board_info.cfi)
device_add_child(dev, "cfi", 0);
if (xlr_board_info.gmac_block[0].enabled) {
tmpd = device_add_child(dev, "rge", 0);
device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);
tmpd = device_add_child(dev, "rge", 1);
device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);
tmpd = device_add_child(dev, "rge", 2);
device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);
tmpd = device_add_child(dev, "rge", 3);
device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);
}
if (xlr_board_info.gmac_block[1].enabled) {
if (xlr_board_info.gmac_block[1].type == XLR_GMAC) {
tmpd = device_add_child(dev, "rge", 4);
device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
tmpd = device_add_child(dev, "rge", 5);
device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
tmpd = device_add_child(dev, "rge", 6);
device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
tmpd = device_add_child(dev, "rge", 7);
device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
} else if (xlr_board_info.gmac_block[1].type == XLR_XGMAC) {
#if 0 /* XGMAC not yet */
tmpd = device_add_child(dev, "rge", 4);
device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
tmpd = device_add_child(dev, "rge", 5);
device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
#endif
} else
device_printf(dev, "Unknown type of gmac 1\n");
}
bus_generic_probe(dev);
bus_generic_attach(dev);
return 0;
}
static device_method_t iodi_methods[] = {
DEVMETHOD(device_probe, iodi_probe),
DEVMETHOD(device_attach, iodi_attach),
DEVMETHOD(device_identify, iodi_identify),
DEVMETHOD(bus_alloc_resource, iodi_alloc_resource),
DEVMETHOD(bus_activate_resource, iodi_activate_resource),
DEVMETHOD(bus_setup_intr, iodi_setup_intr),
{0, 0},
};
static driver_t iodi_driver = {
"iodi",
iodi_methods,
1 /* no softc */
};
static devclass_t iodi_devclass;
DRIVER_MODULE(iodi, nexus, iodi_driver, iodi_devclass, 0, 0);

113
sys/mips/rmi/iomap.h Normal file
View File

@ -0,0 +1,113 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#ifndef _RMI_IOMAP_H_
#define _RMI_IOMAP_H_
#include <machine/endian.h>
#define XLR_DEVICE_REGISTER_BASE 0x1EF00000
#define DEFAULT_XLR_IO_BASE 0xffffffffbef00000ULL
#define XLR_IO_SIZE 0x1000
#define XLR_IO_BRIDGE_OFFSET 0x00000
#define XLR_IO_DDR2_CHN0_OFFSET 0x01000
#define XLR_IO_DDR2_CHN1_OFFSET 0x02000
#define XLR_IO_DDR2_CHN2_OFFSET 0x03000
#define XLR_IO_DDR2_CHN3_OFFSET 0x04000
#define XLR_IO_RLD2_CHN0_OFFSET 0x05000
#define XLR_IO_RLD2_CHN1_OFFSET 0x06000
#define XLR_IO_SRAM_OFFSET 0x07000
#define XLR_IO_PIC_OFFSET 0x08000
#define XLR_IO_PCIX_OFFSET 0x09000
#define XLR_IO_HT_OFFSET 0x0A000
#define XLR_IO_SECURITY_OFFSET 0x0B000
#define XLR_IO_GMAC_0_OFFSET 0x0C000
#define XLR_IO_GMAC_1_OFFSET 0x0D000
#define XLR_IO_GMAC_2_OFFSET 0x0E000
#define XLR_IO_GMAC_3_OFFSET 0x0F000
#define XLR_IO_SPI4_0_OFFSET 0x10000
#define XLR_IO_XGMAC_0_OFFSET 0x11000
#define XLR_IO_SPI4_1_OFFSET 0x12000
#define XLR_IO_XGMAC_1_OFFSET 0x13000
#define XLR_IO_UART_0_OFFSET 0x14000
#define XLR_IO_UART_1_OFFSET 0x15000
#define XLR_UART0ADDR (XLR_IO_UART_0_OFFSET+XLR_DEVICE_REGISTER_BASE)
#define XLR_IO_I2C_0_OFFSET 0x16000
#define XLR_IO_I2C_1_OFFSET 0x17000
#define XLR_IO_GPIO_OFFSET 0x18000
#define XLR_IO_FLASH_OFFSET 0x19000
#define XLR_IO_TB_OFFSET 0x1C000
#define XLR_IO_GMAC_4_OFFSET 0x20000
#define XLR_IO_GMAC_5_OFFSET 0x21000
#define XLR_IO_GMAC_6_OFFSET 0x22000
#define XLR_IO_GMAC_7_OFFSET 0x23000
#define XLR_IO_PCIE_0_OFFSET 0x1E000
#define XLR_IO_PCIE_1_OFFSET 0x1F000
#define XLR_IO_USB_0_OFFSET 0x24000
#define XLR_IO_USB_1_OFFSET 0x25000
#define XLR_IO_COMP_OFFSET 0x1d000
/* Base Address (Virtual) of the PCI Config address space
* For now, choose 256M phys in kseg1 = 0xA0000000 + (1<<28)
* Config space spans 256 (num of buses) * 256 (num functions) * 256 bytes
* ie 1<<24 = 16M
*/
#define DEFAULT_PCI_CONFIG_BASE 0x18000000
#define DEFAULT_HT_TYPE0_CFG_BASE 0x16000000
#define DEFAULT_HT_TYPE1_CFG_BASE 0x17000000
typedef volatile __uint32_t xlr_reg_t;
extern unsigned long xlr_io_base;
#define xlr_io_mmio(offset) ((xlr_reg_t *)(xlr_io_base+(offset)))
#define xlr_read_reg(base, offset) (__ntohl((base)[(offset)]))
#define xlr_write_reg(base, offset, value) ((base)[(offset)] = __htonl((value)))
extern void on_chip_init(void);
#endif /* _RMI_IOMAP_H_ */

317
sys/mips/rmi/msgring.c Normal file
View File

@ -0,0 +1,317 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
/**********************************************************
* -----------------DO NOT EDIT THIS FILE------------------
* This file has been autogenerated by the build process
* from "msgring.cfg"
**********************************************************/
#include <mips/rmi/msgring.h>
struct bucket_size bucket_sizes = {
{
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 0,
32, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 0,
0, 32, 32, 32, 32, 32, 0, 32,
0, 0, 0, 0, 0, 0, 0, 0,
0, 32, 0, 32, 0, 0, 0, 0,
128, 0, 0, 0, 128, 0, 0, 0,
}
};
struct stn_cc cc_table_cpu_0 = {{
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 4, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{4, 2, 2, 2, 2, 2, 2, 2},
{2, 2, 2, 2, 2, 2, 2, 0},
{4, 2, 2, 2, 2, 2, 2, 2},
{2, 2, 2, 2, 2, 2, 2, 0},
{0, 2, 4, 4, 4, 4, 0, 2},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 2, 0, 2, 0, 0, 0, 0},
{16, 0, 0, 0, 16, 0, 0, 0},
}};
struct stn_cc cc_table_cpu_1 = {{
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{4, 2, 2, 2, 2, 2, 2, 2},
{2, 2, 2, 2, 2, 2, 2, 0},
{4, 2, 2, 2, 2, 2, 2, 2},
{2, 2, 2, 2, 2, 2, 2, 0},
{0, 2, 4, 4, 4, 4, 0, 2},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 2, 0, 2, 0, 0, 0, 0},
{16, 0, 0, 0, 16, 0, 0, 0},
}};
struct stn_cc cc_table_cpu_2 = {{
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{4, 2, 2, 2, 2, 2, 2, 2},
{2, 2, 2, 2, 2, 2, 2, 0},
{4, 2, 2, 2, 2, 2, 2, 2},
{2, 2, 2, 2, 2, 2, 2, 0},
{0, 4, 4, 4, 4, 4, 0, 4},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 0, 4, 0, 0, 0, 0},
{16, 0, 0, 0, 16, 0, 0, 0},
}};
struct stn_cc cc_table_cpu_3 = {{
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{4, 2, 2, 2, 2, 2, 2, 2},
{2, 2, 2, 2, 2, 2, 2, 0},
{4, 2, 2, 2, 2, 2, 2, 2},
{2, 2, 2, 2, 2, 2, 2, 0},
{0, 4, 4, 4, 4, 4, 0, 4},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 0, 4, 0, 0, 0, 0},
{16, 0, 0, 0, 16, 0, 0, 0},
}};
struct stn_cc cc_table_cpu_4 = {{
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{4, 2, 2, 2, 2, 2, 2, 2},
{2, 2, 2, 2, 2, 2, 2, 0},
{4, 2, 2, 2, 2, 2, 2, 2},
{2, 2, 2, 2, 2, 2, 2, 0},
{0, 4, 4, 4, 4, 4, 0, 4},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 0, 4, 0, 0, 0, 0},
{16, 0, 0, 0, 16, 0, 0, 0},
}};
struct stn_cc cc_table_cpu_5 = {{
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{4, 2, 2, 2, 2, 2, 2, 2},
{2, 2, 2, 2, 2, 2, 2, 0},
{4, 2, 2, 2, 2, 2, 2, 2},
{2, 2, 2, 2, 2, 2, 2, 0},
{0, 4, 4, 4, 4, 4, 0, 4},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 0, 4, 0, 0, 0, 0},
{16, 0, 0, 0, 16, 0, 0, 0},
}};
struct stn_cc cc_table_cpu_6 = {{
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{4, 2, 2, 2, 2, 2, 2, 2},
{2, 2, 2, 2, 2, 2, 2, 0},
{4, 2, 2, 2, 2, 2, 2, 2},
{2, 2, 2, 2, 2, 2, 2, 0},
{0, 4, 4, 4, 4, 4, 0, 4},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 0, 4, 0, 0, 0, 0},
{16, 0, 0, 0, 16, 0, 0, 0},
}};
struct stn_cc cc_table_cpu_7 = {{
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{4, 2, 2, 2, 2, 2, 2, 2},
{2, 2, 2, 2, 2, 2, 2, 0},
{4, 2, 2, 2, 2, 2, 2, 2},
{2, 2, 2, 2, 2, 2, 2, 0},
{0, 4, 4, 4, 4, 4, 0, 4},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 0, 4, 0, 0, 0, 0},
{16, 0, 0, 0, 16, 0, 0, 0},
}};
struct stn_cc cc_table_xgs_0 = {{
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
}};
struct stn_cc cc_table_xgs_1 = {{
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 4, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
}};
struct stn_cc cc_table_gmac = {{
{8, 8, 8, 8, 16, 16, 16, 16},
{8, 8, 8, 8, 16, 16, 16, 16},
{8, 8, 8, 8, 16, 16, 16, 16},
{8, 8, 8, 8, 16, 16, 16, 16},
{8, 8, 8, 8, 16, 16, 16, 16},
{8, 8, 8, 8, 16, 16, 16, 16},
{8, 8, 8, 8, 16, 16, 16, 16},
{8, 8, 8, 8, 16, 16, 16, 16},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 0, 0, 0, 0, 0, 4},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
}};
struct stn_cc cc_table_dma = {{
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
}};
struct stn_cc cc_table_sec = {{
{8, 8, 8, 8, 0, 0, 0, 0},
{8, 8, 8, 4, 0, 0, 0, 0},
{8, 8, 8, 8, 0, 0, 0, 0},
{8, 8, 8, 8, 0, 0, 0, 0},
{8, 8, 8, 8, 0, 0, 0, 0},
{8, 8, 8, 8, 0, 0, 0, 0},
{8, 8, 8, 8, 0, 0, 0, 0},
{8, 8, 8, 8, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
}};

1182
sys/mips/rmi/msgring.cfg Normal file

File diff suppressed because it is too large Load Diff

529
sys/mips/rmi/msgring.h Executable file
View File

@ -0,0 +1,529 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#ifndef _RMI_MSGRING_H_
#define _RMI_MSGRING_H_
#include <mips/rmi/xlrconfig.h>
#define MSGRNG_TX_BUF_REG 0
#define MSGRNG_RX_BUF_REG 1
#define MSGRNG_MSG_STATUS_REG 2
#define MSGRNG_MSG_CONFIG_REG 3
#define MSGRNG_MSG_BUCKSIZE_REG 4
#define MSGRNG_CC_0_REG 16
#define MSGRNG_CC_1_REG 17
#define MSGRNG_CC_2_REG 18
#define MSGRNG_CC_3_REG 19
#define MSGRNG_CC_4_REG 20
#define MSGRNG_CC_5_REG 21
#define MSGRNG_CC_6_REG 22
#define MSGRNG_CC_7_REG 23
#define MSGRNG_CC_8_REG 24
#define MSGRNG_CC_9_REG 25
#define MSGRNG_CC_10_REG 26
#define MSGRNG_CC_11_REG 27
#define MSGRNG_CC_12_REG 28
#define MSGRNG_CC_13_REG 29
#define MSGRNG_CC_14_REG 30
#define MSGRNG_CC_15_REG 31
#define msgrng_read_status() read_c2_register32(MSGRNG_MSG_STATUS_REG, 0)
#define msgrng_read_config() read_c2_register32(MSGRNG_MSG_CONFIG_REG, 0)
#define msgrng_write_config(value) write_c2_register32(MSGRNG_MSG_CONFIG_REG, 0, value)
#define msgrng_read_bucksize(bucket) read_c2_register32(MSGRNG_MSG_BUCKSIZE_REG, bucket)
#define msgrng_write_bucksize(bucket, value) write_c2_register32(MSGRNG_MSG_BUCKSIZE_REG, bucket, value)
#define msgrng_read_cc(reg, pri) read_c2_register32(reg, pri)
#define msgrng_write_cc(reg, value, pri) write_c2_register32(reg, pri, value)
#define msgrng_load_rx_msg0() read_c2_register64(MSGRNG_RX_BUF_REG, 0)
#define msgrng_load_rx_msg1() read_c2_register64(MSGRNG_RX_BUF_REG, 1)
#define msgrng_load_rx_msg2() read_c2_register64(MSGRNG_RX_BUF_REG, 2)
#define msgrng_load_rx_msg3() read_c2_register64(MSGRNG_RX_BUF_REG, 3)
#define msgrng_load_tx_msg0(value) write_c2_register64(MSGRNG_TX_BUF_REG, 0, value)
#define msgrng_load_tx_msg1(value) write_c2_register64(MSGRNG_TX_BUF_REG, 1, value)
#define msgrng_load_tx_msg2(value) write_c2_register64(MSGRNG_TX_BUF_REG, 2, value)
#define msgrng_load_tx_msg3(value) write_c2_register64(MSGRNG_TX_BUF_REG, 3, value)
/* Station IDs */
#define MSGRNG_STNID_CPU0 0x00
#define MSGRNG_STNID_CPU1 0x08
#define MSGRNG_STNID_CPU2 0x10
#define MSGRNG_STNID_CPU3 0x18
#define MSGRNG_STNID_CPU4 0x20
#define MSGRNG_STNID_CPU5 0x28
#define MSGRNG_STNID_CPU6 0x30
#define MSGRNG_STNID_CPU7 0x38
#define MSGRNG_STNID_XGS0_TX 64
#define MSGRNG_STNID_XMAC0_00_TX 64
#define MSGRNG_STNID_XMAC0_01_TX 65
#define MSGRNG_STNID_XMAC0_02_TX 66
#define MSGRNG_STNID_XMAC0_03_TX 67
#define MSGRNG_STNID_XMAC0_04_TX 68
#define MSGRNG_STNID_XMAC0_05_TX 69
#define MSGRNG_STNID_XMAC0_06_TX 70
#define MSGRNG_STNID_XMAC0_07_TX 71
#define MSGRNG_STNID_XMAC0_08_TX 72
#define MSGRNG_STNID_XMAC0_09_TX 73
#define MSGRNG_STNID_XMAC0_10_TX 74
#define MSGRNG_STNID_XMAC0_11_TX 75
#define MSGRNG_STNID_XMAC0_12_TX 76
#define MSGRNG_STNID_XMAC0_13_TX 77
#define MSGRNG_STNID_XMAC0_14_TX 78
#define MSGRNG_STNID_XMAC0_15_TX 79
#define MSGRNG_STNID_XGS1_TX 80
#define MSGRNG_STNID_XMAC1_00_TX 80
#define MSGRNG_STNID_XMAC1_01_TX 81
#define MSGRNG_STNID_XMAC1_02_TX 82
#define MSGRNG_STNID_XMAC1_03_TX 83
#define MSGRNG_STNID_XMAC1_04_TX 84
#define MSGRNG_STNID_XMAC1_05_TX 85
#define MSGRNG_STNID_XMAC1_06_TX 86
#define MSGRNG_STNID_XMAC1_07_TX 87
#define MSGRNG_STNID_XMAC1_08_TX 88
#define MSGRNG_STNID_XMAC1_09_TX 89
#define MSGRNG_STNID_XMAC1_10_TX 90
#define MSGRNG_STNID_XMAC1_11_TX 91
#define MSGRNG_STNID_XMAC1_12_TX 92
#define MSGRNG_STNID_XMAC1_13_TX 93
#define MSGRNG_STNID_XMAC1_14_TX 94
#define MSGRNG_STNID_XMAC1_15_TX 95
#define MSGRNG_STNID_GMAC 96
#define MSGRNG_STNID_GMACJFR_0 96
#define MSGRNG_STNID_GMACRFR_0 97
#define MSGRNG_STNID_GMACTX0 98
#define MSGRNG_STNID_GMACTX1 99
#define MSGRNG_STNID_GMACTX2 100
#define MSGRNG_STNID_GMACTX3 101
#define MSGRNG_STNID_GMACJFR_1 102
#define MSGRNG_STNID_GMACRFR_1 103
#define MSGRNG_STNID_DMA 104
#define MSGRNG_STNID_DMA_0 104
#define MSGRNG_STNID_DMA_1 105
#define MSGRNG_STNID_DMA_2 106
#define MSGRNG_STNID_DMA_3 107
#define MSGRNG_STNID_XGS0FR 112
#define MSGRNG_STNID_XMAC0JFR 112
#define MSGRNG_STNID_XMAC0RFR 113
#define MSGRNG_STNID_XGS1FR 114
#define MSGRNG_STNID_XMAC1JFR 114
#define MSGRNG_STNID_XMAC1RFR 115
#define MSGRNG_STNID_SEC 120
#define MSGRNG_STNID_SEC0 120
#define MSGRNG_STNID_SEC1 121
#define MSGRNG_STNID_SEC2 122
#define MSGRNG_STNID_SEC3 123
#define MSGRNG_STNID_PK0 124
#define MSGRNG_STNID_SEC_RSA 124
#define MSGRNG_STNID_SEC_RSVD0 125
#define MSGRNG_STNID_SEC_RSVD1 126
#define MSGRNG_STNID_SEC_RSVD2 127
#define MSGRNG_STNID_GMAC1 80
#define MSGRNG_STNID_GMAC1_FR_0 81
#define MSGRNG_STNID_GMAC1_TX0 82
#define MSGRNG_STNID_GMAC1_TX1 83
#define MSGRNG_STNID_GMAC1_TX2 84
#define MSGRNG_STNID_GMAC1_TX3 85
#define MSGRNG_STNID_GMAC1_FR_1 87
#define MSGRNG_STNID_GMAC0 96
#define MSGRNG_STNID_GMAC0_FR_0 97
#define MSGRNG_STNID_GMAC0_TX0 98
#define MSGRNG_STNID_GMAC0_TX1 99
#define MSGRNG_STNID_GMAC0_TX2 100
#define MSGRNG_STNID_GMAC0_TX3 101
#define MSGRNG_STNID_GMAC0_FR_1 103
#define MSGRNG_STNID_CMP_0 108
#define MSGRNG_STNID_CMP_1 109
#define MSGRNG_STNID_CMP_2 110
#define MSGRNG_STNID_CMP_3 111
#define MSGRNG_STNID_PCIE_0 116
#define MSGRNG_STNID_PCIE_1 117
#define MSGRNG_STNID_PCIE_2 118
#define MSGRNG_STNID_PCIE_3 119
#define MSGRNG_STNID_XLS_PK0 121
#define MSGRNG_CODE_MAC 0
#define MSGRNG_CODE_XGMAC 2
#define MSGRNG_CODE_SEC 0
#define MSGRNG_CODE_BOOT_WAKEUP 200
#define MSGRNG_CODE_SPI4 3
static inline int
msgrng_xgmac_stid_rfr(int id)
{
return !id ? MSGRNG_STNID_XMAC0RFR : MSGRNG_STNID_XMAC1RFR;
}
static inline int
msgrng_xgmac_stid_jfr(int id)
{
return !id ? MSGRNG_STNID_XMAC0JFR : MSGRNG_STNID_XMAC1JFR;
}
static inline int
msgrng_xgmac_stid_tx(int id)
{
return !id ? MSGRNG_STNID_XMAC0_00_TX : MSGRNG_STNID_XMAC1_00_TX;
}
static inline int
msgrng_gmac_stid_rfr(int id)
{
return (MSGRNG_STNID_GMACRFR_0);
}
static inline int
msgrng_gmac_stid_rfr_split_mode(int id)
{
return ((id >> 1) ? MSGRNG_STNID_GMACRFR_1 : MSGRNG_STNID_GMACRFR_0);
}
static inline int
msgrng_gmac_stid_jfr(int id)
{
return MSGRNG_STNID_GMACJFR_0;
}
static inline int
msgrng_gmac_stid_jfr_split_mode(int id)
{
return ((id >> 1) ? MSGRNG_STNID_GMACJFR_1 : MSGRNG_STNID_GMACJFR_0);
}
static inline int
msgrng_gmac_stid_tx(int id)
{
return (MSGRNG_STNID_GMACTX0 + id);
}
static inline void
msgrng_send(unsigned int stid)
{
__asm__ volatile (
".set push\n"
".set noreorder\n"
"sync\n"
// "msgsnd %0\n"
"move $8, %0\n"
"c2 0x80001\n"
".set pop\n"
:: "r" (stid):"$8"
);
}
static inline void
msgrng_receive(unsigned int pri)
{
__asm__ volatile (
".set push\n"
".set noreorder\n"
// "msgld %0\n"
"move $8, %0\n"
"c2 0x80002\n"
".set pop\n"
:: "r" (pri):"$8"
);
}
static inline void
msgrng_wait(unsigned int mask)
{
__asm__ volatile (
".set push\n"
".set noreorder\n"
// "msgwait %0\n"
"move $8, %0\n"
"c2 0x80003\n"
".set pop\n"
:: "r" (mask):"$8"
);
}
#define msgrng_enable(flags) \
do { \
__asm__ volatile ( \
".set push\n\t" \
".set reorder\n\t" \
".set noat\n\t" \
"mfc0 %0, $12\n\t" \
"li $8, 0x40000001\n\t" \
"or $1, %0, $8\n\t" \
"xori $1, 1\n\t" \
".set noreorder\n\t" \
"mtc0 $1, $12\n\t" \
".set\tpop\n\t" \
: "=r" (flags) \
: \
: "$8" \
); \
} while (0)
#define msgrng_disable(flags) __asm__ volatile ( \
"mtc0 %0, $12" : : "r" (flags))
#define msgrng_flags_save(flags) msgrng_enable(flags)
#define msgrng_flags_restore(flags) msgrng_disable(flags)
struct msgrng_msg {
__uint64_t msg0;
__uint64_t msg1;
__uint64_t msg2;
__uint64_t msg3;
};
static inline void
message_send_block_fast(int size, unsigned int code, unsigned int stid,
unsigned long long msg0, unsigned long long msg1,
unsigned long long msg2, unsigned long long msg3)
{
__asm__ __volatile__(".set push\n"
".set noreorder\n"
".set mips64\n"
"dmtc2 %1, $0, 0\n"
"dmtc2 %2, $0, 1\n"
"dmtc2 %3, $0, 2\n"
"dmtc2 %4, $0, 3\n"
"move $8, %0\n"
"1: c2 0x80001\n"
"mfc2 $8, $2\n"
"andi $8, $8, 0x6\n"
"bnez $8, 1b\n"
"move $8, %0\n"
".set pop\n"
:
: "r"(((size - 1) << 16) | (code << 8) | stid), "r"(msg0), "r"(msg1), "r"(msg2), "r"(msg3)
: "$8"
);
}
#define message_receive_fast(bucket, size, code, stid, msg0, msg1, msg2, msg3) \
( { unsigned int _status=0, _tmp=0; \
msgrng_receive(bucket); \
while ( (_status=msgrng_read_status()) & 0x08) ; \
_tmp = _status & 0x30; \
if (__builtin_expect((!_tmp), 1)) { \
(size)=((_status & 0xc0)>>6)+1; \
(code)=(_status & 0xff00)>>8; \
(stid)=(_status & 0x7f0000)>>16; \
(msg0)=msgrng_load_rx_msg0(); \
(msg1)=msgrng_load_rx_msg1(); \
(msg2)=msgrng_load_rx_msg2(); \
(msg3)=msgrng_load_rx_msg3(); \
_tmp=0; \
} \
_tmp; \
} )
static __inline__ int
message_send(unsigned int size, unsigned int code,
unsigned int stid, struct msgrng_msg *msg)
{
unsigned int dest = 0;
unsigned long long status = 0;
int i = 0;
msgrng_load_tx_msg0(msg->msg0);
msgrng_load_tx_msg1(msg->msg1);
msgrng_load_tx_msg2(msg->msg2);
msgrng_load_tx_msg3(msg->msg3);
dest = ((size - 1) << 16) | (code << 8) | (stid);
//dbg_msg("Sending msg<%Lx,%Lx,%Lx,%Lx> to dest = %x\n",
//msg->msg0, msg->msg1, msg->msg2, msg->msg3, dest);
msgrng_send(dest);
for (i = 0; i < 16; i++) {
status = msgrng_read_status();
//dbg_msg("status = %Lx\n", status);
if (status & 0x6) {
continue;
} else
break;
}
if (i == 16) {
if (dest == 0x61)
//dbg_msg("Processor %x: Unable to send msg to %llx\n", processor_id(), dest);
return status & 0x6;
}
return msgrng_read_status() & 0x06;
}
static __inline__ int
message_send_retry(unsigned int size, unsigned int code,
unsigned int stid, struct msgrng_msg *msg)
{
int res = 0;
int retry = 0;
for (;;) {
res = message_send(size, code, stid, msg);
/* retry a pending fail */
if (res & 0x02)
continue;
/* credit fail */
if (res & 0x04)
retry++;
else
break;
if (retry == 4)
return res & 0x06;
}
return 0;
}
static __inline__ int
message_receive(int pri, int *size, int *code, int *src_id,
struct msgrng_msg *msg)
{
int res = message_receive_fast(pri, *size, *code, *src_id, msg->msg0, msg->msg1, msg->msg2, msg->msg3);
#ifdef MSGRING_DUMP_MESSAGES
if (!res) {
dbg_msg("Received msg <%llx, %llx, %llx, %llx> <%d,%d,%d>\n",
msg->msg0, msg->msg1, msg->msg2, msg->msg3,
*size, *code, *src_id);
}
#endif
return res;
}
#define MSGRNG_STN_RX_QSIZE 256
struct stn_cc {
unsigned short counters[16][8];
};
struct bucket_size {
unsigned short bucket[128];
};
extern struct bucket_size bucket_sizes;
extern struct stn_cc cc_table_cpu_0;
extern struct stn_cc cc_table_cpu_1;
extern struct stn_cc cc_table_cpu_2;
extern struct stn_cc cc_table_cpu_3;
extern struct stn_cc cc_table_cpu_4;
extern struct stn_cc cc_table_cpu_5;
extern struct stn_cc cc_table_cpu_6;
extern struct stn_cc cc_table_cpu_7;
extern struct stn_cc cc_table_xgs_0;
extern struct stn_cc cc_table_xgs_1;
extern struct stn_cc cc_table_gmac;
extern struct stn_cc cc_table_dma;
extern struct stn_cc cc_table_sec;
extern struct bucket_size xls_bucket_sizes;
extern struct stn_cc xls_cc_table_cpu_0;
extern struct stn_cc xls_cc_table_cpu_1;
extern struct stn_cc xls_cc_table_cpu_2;
extern struct stn_cc xls_cc_table_cpu_3;
extern struct stn_cc xls_cc_table_gmac0;
extern struct stn_cc xls_cc_table_gmac1;
extern struct stn_cc xls_cc_table_cmp;
extern struct stn_cc xls_cc_table_pcie;
extern struct stn_cc xls_cc_table_dma;
extern struct stn_cc xls_cc_table_sec;
#define msgrng_access_save(lock, mflags) do { \
if (rmi_spin_mutex_safe) mtx_lock_spin(lock); \
msgrng_flags_save(mflags); \
}while(0)
#define msgrng_access_restore(lock, mflags) do { \
msgrng_flags_restore(mflags); \
if (rmi_spin_mutex_safe) mtx_unlock_spin(lock); \
}while(0)
#define msgrng_access_enable(mflags) do { \
critical_enter(); \
msgrng_flags_save(mflags); \
} while(0)
#define msgrng_access_disable(mflags) do { \
msgrng_flags_restore(mflags); \
critical_exit(); \
} while(0)
/*
* NOTE: this is not stationid/8, ie the station numbers below are just
* for internal use
*/
enum {
TX_STN_CPU_0,
TX_STN_CPU_1,
TX_STN_CPU_2,
TX_STN_CPU_3,
TX_STN_CPU_4,
TX_STN_CPU_5,
TX_STN_CPU_6,
TX_STN_CPU_7,
TX_STN_GMAC,
TX_STN_DMA,
TX_STN_XGS_0,
TX_STN_XGS_1,
TX_STN_SAE,
TX_STN_GMAC0,
TX_STN_GMAC1,
TX_STN_CDE,
TX_STN_PCIE,
TX_STN_INVALID,
MAX_TX_STNS
};
extern int
register_msgring_handler(int major,
void (*action) (int, int, int, int, struct msgrng_msg *, void *),
void *dev_id);
extern void xlr_msgring_cpu_init(void);
extern void xlr_msgring_config(void);
#define cpu_to_msgring_bucket(cpu) ((((cpu) >> 2)<<3)|((cpu) & 0x03))
#endif

217
sys/mips/rmi/msgring_xls.c Normal file
View File

@ -0,0 +1,217 @@
/**********************************************************
* -----------------DO NOT EDIT THIS FILE------------------
* This file has been autogenerated by the build process
* from "msgring_xls.cfg"
**********************************************************/
#include <mips/rmi/msgring.h>
struct bucket_size xls_bucket_sizes = {
{32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 32, 32, 32, 32, 32, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 32, 32, 32, 32, 32, 0, 0,
64, 64, 64, 64, 32, 32, 32, 32,
0, 0, 0, 0, 0, 0, 0, 0,
128, 128, 0, 0, 0, 0, 0, 0,
}
};
struct stn_cc xls_cc_table_cpu_0 = {{
{1, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 8, 0, 0, 0, 0},
{0, 0, 0, 8, 0, 0, 0, 0},
{0, 0, 0, 8, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 8, 8, 8, 8, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 8, 8, 8, 8, 0, 0},
{16, 16, 16, 16, 16, 16, 16, 16},
{0, 0, 0, 0, 0, 0, 0, 0},
{32, 32, 0, 0, 0, 0, 0, 0},
}};
struct stn_cc xls_cc_table_cpu_1 = {{
{1, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 8, 8, 8, 8, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 8, 8, 8, 8, 0, 0},
{16, 16, 16, 16, 16, 16, 16, 16},
{0, 0, 0, 0, 0, 0, 0, 0},
{32, 32, 0, 0, 0, 0, 0, 0},
}};
struct stn_cc xls_cc_table_cpu_2 = {{
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 8, 8, 8, 8, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 8, 8, 8, 8, 0, 0},
{16, 16, 16, 16, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{32, 32, 0, 0, 0, 0, 0, 0},
}};
struct stn_cc xls_cc_table_cpu_3 = {{
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 8, 8, 8, 8, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 8, 8, 8, 8, 0, 0},
{16, 16, 16, 16, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{32, 32, 0, 0, 0, 0, 0, 0},
}};
struct stn_cc xls_cc_table_gmac0 = {{
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 8, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 8, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
}};
struct stn_cc xls_cc_table_gmac1 = {{
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{8, 8, 8, 8, 8, 8, 8, 8},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 8, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 8, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
}};
struct stn_cc xls_cc_table_dma = {{
{4, 4, 4, 4, 4, 4, 4, 4},
{4, 4, 4, 2, 4, 4, 4, 4},
{4, 4, 4, 2, 4, 4, 4, 4},
{4, 4, 4, 2, 4, 4, 4, 4},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
}};
struct stn_cc xls_cc_table_cmp = {{
{4, 4, 4, 4, 4, 4, 4, 4},
{4, 4, 4, 2, 4, 4, 4, 4},
{4, 4, 4, 2, 4, 4, 4, 4},
{4, 4, 4, 2, 4, 4, 4, 4},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
}};
struct stn_cc xls_cc_table_pcie = {{
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
}};
struct stn_cc xls_cc_table_sec = {{
{6, 8, 8, 8, 0, 0, 0, 0},
{8, 8, 8, 4, 0, 0, 0, 0},
{8, 8, 8, 4, 0, 0, 0, 0},
{8, 8, 8, 4, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
}};

563
sys/mips/rmi/msgring_xls.cfg Executable file
View File

@ -0,0 +1,563 @@
/*********************************************************************
*
* Copyright 2003-2006 Raza Microelectronics, Inc. (RMI). All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY Raza Microelectronics, Inc. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RMI OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES, LOSS OF USE, DATA, OR PROFITS, OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* *****************************RMI_2**********************************/
/*
* This file defines the message ring configuration for XLS two core. It tries to allow
* many different point-point communications between the message stations on the message ring
* and as result is _not_ the best configuration for performance
*
* The message ring on phoenix family of processors connects the cpus, gmacs, xgmac/spi4,
* security engine and the general purpose DMA engines. It provides a high bandwidth,
* low latency communication links. On traditional processors, this communication goes through
* which inherently does not scale very well with increasing number of cpus.
*
* Message ring has an in-built flow control mechanism. Every agent/station on the ring has to
* have software configured credits to send messages to any agent. Every receiving agent on the
* ring has a 256 entry FIFO that can divided into "buckets". All addressing on the ring is
* in terms of buckets. There are a total 128 buckets on the ring. The total number of credits
* across all sending agents should not exceed the bucket size.
*
* Below are the receiving agents and the max number of buckets they can have
* CPU 0 : 8 buckets
* CPU 1 : 8 buckets
*
* GMAC : 8 buckets
*
* SEC : 8 buckets
*
* DMA : 8 buckets
*
* CMP : Currently disabled.
*
* The bucket size of a bucket should be aligned to the bucket's starting index in that
* receiving station's FIFO. For example, if sizes of bucket0 and bucket1 of a station
* are 32 and 32, bucket2's size has to be 64. bucket size 0 is valid.
*
* The format of the file is pretty straight forward. Each bucket definition has the size
* and the list of sending agents to that bucket with the number of credits to send.
*
* Undefined buckets have a size of 0 and Tx stations have 0 credits to send to that bucket.
*
* Following are the currently supported bucket names
* cpu_0_0
* cpu_0_1
* cpu_0_2
* cpu_0_3
* cpu_0_4
* cpu_0_5
* cpu_0_6
* cpu_0_7
*
* cpu_1_0
* cpu_1_1
* cpu_1_2
* cpu_1_3
* cpu_1_4
* cpu_1_5
* cpu_1_6
* cpu_1_7
*
* enabled only for xls-b0
* cpu_2_0
* cpu_2_1
* cpu_2_2
* cpu_2_3
* cpu_2_4
* cpu_2_5
* cpu_2_6
* cpu_2_7
*
* enabled only for xls-b0
* cpu_3_0
* cpu_3_1
* cpu_3_2
* cpu_3_3
* cpu_3_4
* cpu_3_5
* cpu_3_6
* cpu_3_7
*
* gmac0_rfr
* gmac0_tx_0
* gmac0_tx_1
* gmac0_tx_2
* gmac0_tx_3
*
* gmac1_rfr
* gmac1_tx_0
* gmac1_tx_1
* gmac1_tx_2
* gmac1_tx_3
*
* sec_pipe_0
* sec_rsa
*
* Following are the currently supported Tx Agent/Station names
*
* tx_stn_cpu_0
* tx_stn_cpu_1
*
* tx_stn_gmac0
* tx_stn_gmac1
*
* tx_stn_dma
*
* tx_stn_sec
*
*
*/
/*************************************************************/
// CPU_0 Message Station
bucket "cpu_0_0" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_sec" 6;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
"tx_stn_cpu_0" 1;
"tx_stn_cpu_1" 1; /* NEEDED BY RMIOS IPSEC */
}
bucket "cpu_0_1" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_sec" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_0_2" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_sec" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_0_3" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_sec" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_0_4" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_0_5" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_0_6" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_0_7" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
/*************************************************************/
// CPU_1 Message Station
bucket "cpu_1_0" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_sec" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_1_1" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_sec" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_1_2" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_sec" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_1_3" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_sec" 4;
"tx_stn_cpu_0" 8; /* NEEDED BY RMIOS IPSEC */
"tx_stn_dma" 2;
"tx_stn_cmp" 2;
}
bucket "cpu_1_4" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_1_5" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_1_6" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_1_7" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
/*************************************************************/
// CPU_2 Message Station
bucket "cpu_2_0" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_sec" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_2_1" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_sec" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_2_2" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_sec" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_2_3" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_sec" 4;
"tx_stn_cpu_0" 8; /* NEEDED BY RMIOS IPSEC */
"tx_stn_dma" 2;
"tx_stn_cmp" 2;
}
bucket "cpu_2_4" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_2_5" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_2_6" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_2_7" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
/*************************************************************/
// CPU_3 Message Station
bucket "cpu_3_0" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_sec" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_3_1" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_sec" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_3_2" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_sec" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_3_3" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_sec" 4;
"tx_stn_cpu_0" 8; /* NEEDED BY RMIOS IPSEC */
"tx_stn_dma" 2;
"tx_stn_cmp" 2;
}
bucket "cpu_3_4" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_3_5" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_3_6" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
bucket "cpu_3_7" {
size 32;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
"tx_stn_dma" 4;
"tx_stn_cmp" 4;
}
/*************************************************************/
// GMAC Message Station
bucket "gmac0_rfr" {
size 32;
"tx_stn_cpu_0" 4;
"tx_stn_cpu_1" 4;
"tx_stn_cpu_2" 4;
"tx_stn_cpu_3" 4;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
}
bucket "gmac0_tx_0" {
size 32;
"tx_stn_cpu_0" 8;
"tx_stn_cpu_1" 8;
"tx_stn_cpu_2" 8;
"tx_stn_cpu_3" 8;
}
bucket "gmac0_tx_1" {
size 32;
"tx_stn_cpu_0" 8;
"tx_stn_cpu_1" 8;
"tx_stn_cpu_2" 8;
"tx_stn_cpu_3" 8;
}
bucket "gmac0_tx_2" {
size 32;
"tx_stn_cpu_0" 8;
"tx_stn_cpu_1" 8;
"tx_stn_cpu_2" 8;
"tx_stn_cpu_3" 8;
}
bucket "gmac0_tx_3" {
size 32;
"tx_stn_cpu_0" 8;
"tx_stn_cpu_1" 8;
"tx_stn_cpu_2" 8;
"tx_stn_cpu_3" 8;
}
bucket "gmac1_rfr" {
size 32;
"tx_stn_cpu_0" 4;
"tx_stn_cpu_1" 4;
"tx_stn_cpu_2" 4;
"tx_stn_cpu_3" 4;
"tx_stn_gmac0" 8;
"tx_stn_gmac1" 8;
}
bucket "gmac1_tx_0" {
size 32;
"tx_stn_cpu_0" 8;
"tx_stn_cpu_1" 8;
"tx_stn_cpu_2" 8;
"tx_stn_cpu_3" 8;
}
bucket "gmac1_tx_1" {
size 32;
"tx_stn_cpu_0" 8;
"tx_stn_cpu_1" 8;
"tx_stn_cpu_2" 8;
"tx_stn_cpu_3" 8;
}
bucket "gmac1_tx_2" {
size 32;
"tx_stn_cpu_0" 8;
"tx_stn_cpu_1" 8;
"tx_stn_cpu_2" 8;
"tx_stn_cpu_3" 8;
}
bucket "gmac1_tx_3" {
size 32;
"tx_stn_cpu_0" 8;
"tx_stn_cpu_1" 8;
"tx_stn_cpu_2" 8;
"tx_stn_cpu_3" 8;
}
/*************************************************************/
// Security Message Station
bucket "sec_pipe_0" {
size 128;
"tx_stn_cpu_0" 32;
"tx_stn_cpu_1" 32;
"tx_stn_cpu_2" 32;
"tx_stn_cpu_3" 32;
}
bucket "sec_rsa_ecc" {
size 128;
"tx_stn_cpu_0" 32;
"tx_stn_cpu_1" 32;
"tx_stn_cpu_2" 32;
"tx_stn_cpu_3" 32;
}
bucket "dma_rsvd_0" {
size 64;
"tx_stn_cpu_0" 16;
"tx_stn_cpu_1" 16;
"tx_stn_cpu_2" 16;
"tx_stn_cpu_3" 16;
}
bucket "dma_rsvd_1" {
size 64;
"tx_stn_cpu_0" 16;
"tx_stn_cpu_1" 16;
"tx_stn_cpu_2" 16;
"tx_stn_cpu_3" 16;
}
bucket "dma_rsvd_2" {
size 64;
"tx_stn_cpu_0" 16;
"tx_stn_cpu_1" 16;
"tx_stn_cpu_2" 16;
"tx_stn_cpu_3" 16;
}
bucket "dma_rsvd_3" {
size 64;
"tx_stn_cpu_0" 16;
"tx_stn_cpu_1" 16;
"tx_stn_cpu_2" 16;
"tx_stn_cpu_3" 16;
}
/*************************************************************/
// Compression Message Station
bucket "cmp_0" {
size 32;
"tx_stn_cpu_0" 16;
"tx_stn_cpu_1" 16;
}
bucket "cmp_1" {
size 32;
"tx_stn_cpu_0" 16;
"tx_stn_cpu_1" 16;
}
bucket "cmp_2" {
size 32;
"tx_stn_cpu_0" 16;
"tx_stn_cpu_1" 16;
}
bucket "cmp_3" {
size 32;
"tx_stn_cpu_0" 16;
"tx_stn_cpu_1" 16;
}

330
sys/mips/rmi/on_chip.c Normal file
View File

@ -0,0 +1,330 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/limits.h>
#include <sys/bus.h>
#include <machine/reg.h>
#include <machine/cpu.h>
#include <machine/mips_opcode.h>
#include <machine/param.h>
#include <machine/intr_machdep.h>
#include <mips/rmi/interrupt.h>
#include <mips/rmi/msgring.h>
#include <mips/rmi/iomap.h>
#include <mips/rmi/debug.h>
#include <mips/rmi/pic.h>
#include <mips/rmi/board.h>
void
disable_msgring_int(void *arg);
void
enable_msgring_int(void *arg);
/* definitions */
struct tx_stn_handler {
void (*action) (int, int, int, int, struct msgrng_msg *, void *);
void *dev_id;
};
/* globals */
static struct tx_stn_handler tx_stn_handlers[MAX_TX_STNS];
#define MSGRNG_CC_INIT_CPU_DEST(dest, counter) \
do { \
msgrng_write_cc(MSGRNG_CC_##dest##_REG, counter[dest][0], 0 ); \
msgrng_write_cc(MSGRNG_CC_##dest##_REG, counter[dest][1], 1 ); \
msgrng_write_cc(MSGRNG_CC_##dest##_REG, counter[dest][2], 2 ); \
msgrng_write_cc(MSGRNG_CC_##dest##_REG, counter[dest][3], 3 ); \
msgrng_write_cc(MSGRNG_CC_##dest##_REG, counter[dest][4], 4 ); \
msgrng_write_cc(MSGRNG_CC_##dest##_REG, counter[dest][5], 5 ); \
msgrng_write_cc(MSGRNG_CC_##dest##_REG, counter[dest][6], 6 ); \
msgrng_write_cc(MSGRNG_CC_##dest##_REG, counter[dest][7], 7 ); \
} while(0)
/* make this a read/write spinlock */
static struct mtx msgrng_lock;
static int msgring_int_enabled;
struct mtx xlr_pic_lock;
static int msgring_pop_num_buckets;
static uint32_t msgring_pop_bucket_mask;
static int msgring_int_type;
static int msgring_watermark_count;
static uint32_t msgring_thread_mask;
uint32_t msgrng_msg_cycles = 0;
int xlr_counters[MAXCPU][XLR_MAX_COUNTERS] __aligned(XLR_CACHELINE_SIZE);
void xlr_msgring_handler(struct trapframe *);
void
xlr_msgring_cpu_init(void)
{
struct stn_cc *cc_config;
struct bucket_size *bucket_sizes;
int id;
unsigned long flags;
/* if not thread 0 */
if (xlr_thr_id() != 0)
return;
id = xlr_cpu_id();
bucket_sizes = xlr_board_info.bucket_sizes;
cc_config = xlr_board_info.credit_configs[id];
msgrng_flags_save(flags);
/*
* Message Stations are shared among all threads in a cpu core
* Assume, thread 0 on all cores are always active when more than 1
* thread is active in a core
*/
msgrng_write_bucksize(0, bucket_sizes->bucket[id * 8 + 0]);
msgrng_write_bucksize(1, bucket_sizes->bucket[id * 8 + 1]);
msgrng_write_bucksize(2, bucket_sizes->bucket[id * 8 + 2]);
msgrng_write_bucksize(3, bucket_sizes->bucket[id * 8 + 3]);
msgrng_write_bucksize(4, bucket_sizes->bucket[id * 8 + 4]);
msgrng_write_bucksize(5, bucket_sizes->bucket[id * 8 + 5]);
msgrng_write_bucksize(6, bucket_sizes->bucket[id * 8 + 6]);
msgrng_write_bucksize(7, bucket_sizes->bucket[id * 8 + 7]);
MSGRNG_CC_INIT_CPU_DEST(0, cc_config->counters);
MSGRNG_CC_INIT_CPU_DEST(1, cc_config->counters);
MSGRNG_CC_INIT_CPU_DEST(2, cc_config->counters);
MSGRNG_CC_INIT_CPU_DEST(3, cc_config->counters);
MSGRNG_CC_INIT_CPU_DEST(4, cc_config->counters);
MSGRNG_CC_INIT_CPU_DEST(5, cc_config->counters);
MSGRNG_CC_INIT_CPU_DEST(6, cc_config->counters);
MSGRNG_CC_INIT_CPU_DEST(7, cc_config->counters);
MSGRNG_CC_INIT_CPU_DEST(8, cc_config->counters);
MSGRNG_CC_INIT_CPU_DEST(9, cc_config->counters);
MSGRNG_CC_INIT_CPU_DEST(10, cc_config->counters);
MSGRNG_CC_INIT_CPU_DEST(11, cc_config->counters);
MSGRNG_CC_INIT_CPU_DEST(12, cc_config->counters);
MSGRNG_CC_INIT_CPU_DEST(13, cc_config->counters);
MSGRNG_CC_INIT_CPU_DEST(14, cc_config->counters);
MSGRNG_CC_INIT_CPU_DEST(15, cc_config->counters);
msgrng_flags_restore(flags);
}
void
xlr_msgring_config(void)
{
msgring_int_type = 0x02;
msgring_pop_num_buckets = 8;
msgring_pop_bucket_mask = 0xff;
msgring_watermark_count = 1;
msgring_thread_mask = 0x01;
/* printf("[%s]: int_type = 0x%x, pop_num_buckets=%d, pop_bucket_mask=%x" */
/* "watermark_count=%d, thread_mask=%x\n", __FUNCTION__, */
/* msgring_int_type, msgring_pop_num_buckets, msgring_pop_bucket_mask, */
/* msgring_watermark_count, msgring_thread_mask); */
}
void
xlr_msgring_handler(struct trapframe *tf)
{
unsigned long mflags;
int bucket = 0;
int size = 0, code = 0, rx_stid = 0, tx_stid = 0;
struct msgrng_msg msg;
unsigned int bucket_empty_bm = 0;
unsigned int status = 0;
xlr_inc_counter(MSGRNG_INT);
/* TODO: not necessary to disable preemption */
msgrng_flags_save(mflags);
/* First Drain all the high priority messages */
for (;;) {
bucket_empty_bm = (msgrng_read_status() >> 24) & msgring_pop_bucket_mask;
/* all buckets empty, break */
if (bucket_empty_bm == msgring_pop_bucket_mask)
break;
for (bucket = 0; bucket < msgring_pop_num_buckets; bucket++) {
uint32_t cycles = 0;
if ((bucket_empty_bm & (1 << bucket)) /* empty */ )
continue;
status = message_receive(bucket, &size, &code, &rx_stid, &msg);
if (status)
continue;
xlr_inc_counter(MSGRNG_MSG);
msgrng_msg_cycles = mips_rd_count();
cycles = msgrng_msg_cycles;
tx_stid = xlr_board_info.msgmap[rx_stid];
if (!tx_stn_handlers[tx_stid].action) {
printf("[%s]: No Handler for message from stn_id=%d, bucket=%d, "
"size=%d, msg0=%llx, dropping message\n",
__FUNCTION__, tx_stid, bucket, size, msg.msg0);
} else {
//printf("[%s]: rx_stid = %d\n", __FUNCTION__, rx_stid);
msgrng_flags_restore(mflags);
(*tx_stn_handlers[tx_stid].action) (bucket, size, code, rx_stid,
&msg, tx_stn_handlers[tx_stid].dev_id);
msgrng_flags_save(mflags);
}
xlr_set_counter(MSGRNG_MSG_CYCLES, (read_c0_count() - cycles));
}
}
xlr_set_counter(MSGRNG_EXIT_STATUS, msgrng_read_status());
msgrng_flags_restore(mflags);
//dbg_msg("OUT irq=%d\n", irq);
/* Call the msg callback */
}
void
enable_msgring_int(void *arg)
{
unsigned long mflags = 0;
msgrng_access_save(&msgrng_lock, mflags);
/* enable the message ring interrupts */
msgrng_write_config((msgring_watermark_count << 24) | (IRQ_MSGRING << 16)
| (msgring_thread_mask << 8) | msgring_int_type);
msgrng_access_restore(&msgrng_lock, mflags);
}
void
disable_msgring_int(void *arg)
{
unsigned long mflags = 0;
uint32_t config;
msgrng_access_save(&msgrng_lock, mflags);
config = msgrng_read_config();
config &= ~0x3;
msgrng_write_config(config);
msgrng_access_restore(&msgrng_lock, mflags);
}
extern void platform_prep_smp_launch(void);
extern void msgring_process_fast_intr(void *arg);
int
register_msgring_handler(int major,
void (*action) (int, int, int, int, struct msgrng_msg *, void *),
void *dev_id)
{
void *cookie; /* FIXME - use? */
if (major >= MAX_TX_STNS)
return 1;
//dbg_msg("major=%d, action=%p, dev_id=%p\n", major, action, dev_id);
if (rmi_spin_mutex_safe)
mtx_lock_spin(&msgrng_lock);
tx_stn_handlers[major].action = action;
tx_stn_handlers[major].dev_id = dev_id;
if (rmi_spin_mutex_safe)
mtx_unlock_spin(&msgrng_lock);
if (xlr_test_and_set(&msgring_int_enabled)) {
platform_prep_smp_launch();
cpu_establish_hardintr("msgring", (driver_filter_t *) NULL,
(driver_intr_t *) msgring_process_fast_intr,
NULL, IRQ_MSGRING, INTR_TYPE_NET | INTR_FAST, &cookie);
/* configure the msgring interrupt on cpu 0 */
enable_msgring_int(NULL);
}
return 0;
}
static void
pic_init(void)
{
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
int i = 0;
int level;
dbg_msg("Initializing PIC...\n");
for (i = 0; i < PIC_NUM_IRTS; i++) {
level = PIC_IRQ_IS_EDGE_TRIGGERED(i);
/* Bind all PIC irqs to cpu 0 */
xlr_write_reg(mmio, PIC_IRT_0_BASE + i, 0x01);
/*
* Use local scheduling and high polarity for all IRTs
* Invalidate all IRTs, by default
*/
xlr_write_reg(mmio, PIC_IRT_1_BASE + i, (level << 30) | (1 << 6) | (PIC_IRQ_BASE + i));
}
dbg_msg("PIC init now done\n");
}
void
on_chip_init(void)
{
int i = 0, j = 0;
/* Set xlr_io_base to the run time value */
mtx_init(&msgrng_lock, "msgring", NULL, MTX_SPIN | MTX_RECURSE);
mtx_init(&xlr_pic_lock, "pic", NULL, MTX_SPIN);
xlr_board_info_setup();
msgring_int_enabled = 0;
xlr_msgring_config();
pic_init();
xlr_msgring_cpu_init();
for (i = 0; i < MAXCPU; i++)
for (j = 0; j < XLR_MAX_COUNTERS; j++)
atomic_set_int(&xlr_counters[i][j], 0);
}

357
sys/mips/rmi/pcibus.c Normal file
View File

@ -0,0 +1,357 @@
/*-
* Copyright (c) 1997, Stefan Esser <se@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/alpha/pci/pcibus.c,v 1.36 2005/01/05 20:05:52 imp Exp $");
#include "opt_isa.h"
#define __RMAN_RESOURCE_VISIBLE
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/bus.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/pmap.h>
#include <machine/bus.h>
#include <machine/pmap.h>
#include <sys/interrupt.h>
#include <sys/sysctl.h>
#include <mips/rmi/iomap.h>
#include <mips/rmi/pic.h>
#include <mips/rmi/shared_structs.h>
#include <mips/rmi/board.h>
#include <sys/rman.h>
#include <dev/pci/pcivar.h>
#include <machine/resource.h>
#include <machine/md_var.h>
#include <machine/intr_machdep.h>
#include <mips/rmi/pcibus.h>
/*
static void bridge_pcix_ack(void *);
static void bridge_pcie_ack(void *);
static void pic_pcix_ack(void *);
static void pic_pcie_ack(void *);
*/
extern vm_map_t kernel_map;
vm_offset_t kmem_alloc_nofault(vm_map_t map, vm_size_t size);
int
mips_pci_route_interrupt(device_t bus, device_t dev, int pin)
{
/*
* Validate requested pin number.
*/
if ((pin < 1) || (pin > 4))
return (255);
if (xlr_board_info.is_xls) {
switch (pin) {
case 1:
return PIC_PCIE_LINK0_IRQ;
case 2:
return PIC_PCIE_LINK1_IRQ;
case 3:
return PIC_PCIE_LINK2_IRQ;
case 4:
return PIC_PCIE_LINK3_IRQ;
}
} else {
if (pin == 1) {
return (16);
}
}
return (255);
}
static struct rman irq_rman, port_rman, mem_rman;
/*
static void bridge_pcix_ack(void *arg)
{
xlr_read_reg(xlr_io_mmio(XLR_IO_PCIX_OFFSET), 0x140 >> 2);
}
*/
/*
static void bridge_pcie_ack(void *arg)
{
int irq = (int)arg;
uint32_t reg;
xlr_reg_t *pcie_mmio_le = xlr_io_mmio(XLR_IO_PCIE_1_OFFSET);
switch (irq) {
case PIC_PCIE_LINK0_IRQ : reg = PCIE_LINK0_MSI_STATUS; break;
case PIC_PCIE_LINK1_IRQ : reg = PCIE_LINK1_MSI_STATUS; break;
case PIC_PCIE_LINK2_IRQ : reg = PCIE_LINK2_MSI_STATUS; break;
case PIC_PCIE_LINK3_IRQ : reg = PCIE_LINK3_MSI_STATUS; break;
default:
return;
}
xlr_write_reg(pcie_mmio_le, reg>>2, 0xffffffff);
}
*/
/*
static void pic_pcix_ack(void *none)
{
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
mtx_lock_spin(&xlr_pic_lock);
xlr_write_reg(mmio, PIC_INT_ACK, (1 << PIC_IRT_PCIX_INDEX));
mtx_unlock_spin(&xlr_pic_lock);
}
*/
/*
static void pic_pcie_ack(void *arg)
{
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
int irq = (int) arg;
mtx_lock_spin(&xlr_pic_lock);
xlr_write_reg(mmio, PIC_INT_ACK, (1 << (irq - PIC_IRQ_BASE)));
mtx_unlock_spin(&xlr_pic_lock);
}
*/
int
mips_platform_pci_setup_intr(device_t dev, device_t child,
struct resource *irq, int flags,
driver_filter_t * filt,
driver_intr_t * intr, void *arg,
void **cookiep)
{
int level;
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
int error = 0;
int xlrirq;
error = rman_activate_resource(irq);
if (error)
return error;
if (rman_get_start(irq) != rman_get_end(irq)) {
device_printf(dev, "Interrupt allocation %lu != %lu\n",
rman_get_start(irq), rman_get_end(irq));
return EINVAL;
}
xlrirq = rman_get_start(irq);
if (strcmp(device_get_name(dev), "pcib") != 0)
return 0;
if (xlr_board_info.is_xls == 0) {
if (rmi_spin_mutex_safe) mtx_lock_spin(&xlr_pic_lock);
level = PIC_IRQ_IS_EDGE_TRIGGERED(PIC_IRT_PCIX_INDEX);
xlr_write_reg(mmio, PIC_IRT_0_PCIX, 0x01);
xlr_write_reg(mmio, PIC_IRT_1_PCIX, ((1 << 31) | (level << 30) |
(1 << 6) | (PIC_PCIX_IRQ)));
if (rmi_spin_mutex_safe) mtx_unlock_spin(&xlr_pic_lock);
cpu_establish_hardintr(device_get_name(child), filt,
(driver_intr_t *) intr, (void *)arg, PIC_PCIX_IRQ, flags, cookiep);
} else {
if (rmi_spin_mutex_safe) mtx_lock_spin(&xlr_pic_lock);
xlr_write_reg(mmio, PIC_IRT_0_BASE + xlrirq - PIC_IRQ_BASE, 0x01);
xlr_write_reg(mmio, PIC_IRT_1_BASE + xlrirq - PIC_IRQ_BASE,
((1 << 31) | (1 << 30) | (1 << 6) | xlrirq));
if (rmi_spin_mutex_safe) mtx_unlock_spin(&xlr_pic_lock);
if (flags & INTR_FAST)
cpu_establish_hardintr(device_get_name(child), filt,
(driver_intr_t *) intr, (void *)arg, xlrirq, flags, cookiep);
else
cpu_establish_hardintr(device_get_name(child), filt,
(driver_intr_t *) intr, (void *)arg, xlrirq, flags, cookiep);
}
return bus_generic_setup_intr(dev, child, irq, flags, filt, intr,
arg, cookiep);
}
int
mips_platform_pci_teardown_intr(device_t dev, device_t child,
struct resource *irq, void *cookie);
int
mips_platform_pci_teardown_intr(device_t dev, device_t child,
struct resource *irq, void *cookie)
{
if (strcmp(device_get_name(child), "pci") == 0) {
/* if needed reprogram the pic to clear pcix related entry */
}
return bus_generic_teardown_intr(dev, child, irq, cookie);
}
void
pci_init_resources(void)
{
irq_rman.rm_start = 0;
irq_rman.rm_end = 255;
irq_rman.rm_type = RMAN_ARRAY;
irq_rman.rm_descr = "PCI Mapped Interrupts";
if (rman_init(&irq_rman)
|| rman_manage_region(&irq_rman, 0, 255))
panic("pci_init_resources irq_rman");
port_rman.rm_start = 0;
port_rman.rm_end = ~0u;
port_rman.rm_type = RMAN_ARRAY;
port_rman.rm_descr = "I/O ports";
if (rman_init(&port_rman)
|| rman_manage_region(&port_rman, 0x10000000, 0x1fffffff))
panic("pci_init_resources port_rman");
mem_rman.rm_start = 0;
mem_rman.rm_end = ~0u;
mem_rman.rm_type = RMAN_ARRAY;
mem_rman.rm_descr = "I/O memory";
if (rman_init(&mem_rman)
|| rman_manage_region(&mem_rman, 0xd0000000, 0xdfffffff))
panic("pci_init_resources mem_rman");
}
/* hack from bus.h in mips/include/bus.h */
#ifndef MIPS_BUS_SPACE_PCI
#define MIPS_BUS_SPACE_PCI 10
#endif
struct resource *
xlr_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct rman *rm;
struct resource *rv;
vm_offset_t va;
int needactivate = flags & RF_ACTIVE;
#if 0
device_printf(bus, "xlr_pci_alloc_resource : child %s, type %d, start %lx end %lx, count %lx, flags %x\n",
device_get_nameunit(child), type, start, end, count, flags);
#endif
switch (type) {
case SYS_RES_IRQ:
rm = &irq_rman;
break;
case SYS_RES_IOPORT:
rm = &port_rman;
break;
case SYS_RES_MEMORY:
rm = &mem_rman;
break;
default:
return 0;
}
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == 0)
return 0;
rman_set_bustag(rv, (bus_space_tag_t) MIPS_BUS_SPACE_PCI);
rman_set_rid(rv, *rid);
if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
/*
* if ((start + count) > (2 << 28)) { va_start =
* kmem_alloc_nofault(kernel_map, count); }
*/
/*
* This called for pmap_map_uncached, but the pmap_map calls
* pmap_kenter which does a is_cacheable_mem() check and
* thus sets the PTE_UNCACHED bit. Hopefully this will work
* for this guy... RRS
*/
/* va = pmap_map(&va_start, start, start + count, 0); */
va = (vm_offset_t)pmap_mapdev(start, start + count);
rman_set_bushandle(rv, va);
/* bushandle is same as virtual addr */
rman_set_virtual(rv, (void *)va);
rman_set_bustag(rv, (bus_space_tag_t) MIPS_BUS_SPACE_PCI);
}
if (needactivate) {
if (bus_activate_resource(child, type, *rid, rv)) {
rman_release_resource(rv);
return (NULL);
}
}
return rv;
}
int
pci_deactivate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
return (rman_deactivate_resource(r));
}
/* now in pci.c
int
pci_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
return (rman_activate_resource(r));
}
int
pci_release_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
return (rman_release_resource(r));
}
*/
struct rman *
pci_get_rman(device_t dev, int type)
{
switch (type) {
case SYS_RES_IOPORT:
return &port_rman;
case SYS_RES_MEMORY:
return &mem_rman;
case SYS_RES_IRQ:
return &irq_rman;
}
return 0;
}

62
sys/mips/rmi/pcibus.h Normal file
View File

@ -0,0 +1,62 @@
/*-
* Copyright (c) 1998 Doug Rabson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/alpha/pci/pcibus.h,v 1.5 2002/02/28 18:18:41 gallatin Exp $
*/
#define DEFAULT_PCI_CONFIG_BASE 0x18000000
#define MSI_MIPS_ADDR_BASE 0xfee00000
#define PCIE_LINK0_MSI_STATUS 0x90
#define PCIE_LINK1_MSI_STATUS 0x94
#define PCIE_LINK2_MSI_STATUS 0x190
#define PCIE_LINK3_MSI_STATUS 0x194
void pci_init_resources(void);
struct resource *
xlr_pci_alloc_resource(device_t bus, device_t child,
int type, int *rid,
u_long start, u_long end, u_long count,
u_int flags);
int
pci_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r);
int
pci_deactivate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r);
int
pci_release_resource(device_t bus, device_t child, int type, int rid,
struct resource *r);
struct rman *pci_get_rman(device_t dev, int type);
int
mips_platform_pci_setup_intr(device_t dev, device_t child,
struct resource *irq, int flags,
driver_filter_t * filt,
driver_intr_t * intr, void *arg,
void **cookiep);
int
mips_pci_route_interrupt(device_t bus, device_t dev, int pin);

183
sys/mips/rmi/perfmon.h Normal file
View File

@ -0,0 +1,183 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#ifndef PERFMON_H
#define PERFMON_H
#include <mips/rmi/perfmon_xlrconfig.h>
/*
* category events reported by the perfmon library
*/
enum event_category_t {
PERF_CP0_COUNTER = 1, PERF_CP2_CREDITS, PERF_L2_COUNTER,
PERF_SBC_COUNTER, PERF_SBC_CREDITS, PERF_GMAC0_COUNTER, PERF_GMAC1_COUNTER,
PERF_GMAC2_COUNTER, PERF_GMAC_STAT_COM, PERF_GMAC_STAT_TX,
PERF_GMAC_STAT_RX, PERF_DRAM_COUNTER, PERF_PARAMETER_CONF = 127};
enum perf_param_t {
PERF_CPU_SAMPLING_INTERVAL, PERF_SYS_SAMPLING_INTERVAL, PERF_CC_SAMPLE_RATE, PERF_CP0_FLAGS
};
#define CPO_EVENTS_TEMPLATE 0x06 /* enable kernel and user events */
#define PERFMON_ACTIVE_MAGIC 0xc001
#define PERFMON_ENABLED_MAGIC 0xb007
#define PERFMON_INITIAL_GENERATION 0x0101
#define PERFMON_SERVER_PORT 7007
enum system_bridge_credits_t {
PCIX_CREDITS, HT_CREDITS, GIO_CREDITS, OTHER_CREDITS
};
struct perf_config_data {
uint16_t magic; /* monitor start when this is initialized */
uint16_t generation; /* incremented when the config changes */
uint16_t flags;
uint16_t cc_sample_rate;/* rate at which credit counters are sampled
* relative to sampling_rate */
uint32_t sampling_rate; /* rate at which events are sampled */
uint32_t cc_register_mask; /* credit counters registers to be
* sampled */
uint64_t events[NTHREADS]; /* events bitmap for each thread */
};
struct perf_sample {
uint32_t counter;
uint32_t timestamp;
uint32_t sample_tag;
uint32_t duration;
};
struct sample_q {
int32_t head, tail;
struct perf_sample samples[PERF_SAMPLE_BUFSZ];
uint32_t overflows;
};
struct perf_area {
struct perf_config_data perf_config;
struct sample_q sample_fifo;
};
/*
* We have a shared location to keep a global tick counter for all the
* CPUS - TODO is this optimal? effect on cache?
*/
extern uint32_t *xlr_perfmon_timer_loc;
#define PERFMON_TIMESTAMP_LOC (xlr_perfmon_timer_loc)
static __inline__ uint32_t
perfmon_timestamp_get(void)
{
return *PERFMON_TIMESTAMP_LOC;
}
static __inline__ void
perfmon_timestamp_set(uint32_t val)
{
*PERFMON_TIMESTAMP_LOC = val;
}
static __inline__ void
perfmon_timestamp_incr(int val)
{
(*PERFMON_TIMESTAMP_LOC) += val;
}
static __inline__ void
send_sample_gts(uint32_t tag, uint32_t value, uint32_t td)
{
xlr_send_sample(tag, value, perfmon_timestamp_get(), td);
}
/*
* Simple FIFO, one producer - one consumer - circlar queue - no locking
*/
static __inline__ void
init_fifo(struct sample_q *q)
{
q->head = q->tail = 0;
}
static __inline__ void
put_sample(struct sample_q *q, uint32_t sample_tag, uint32_t counter,
uint32_t duration)
{
uint32_t timestamp = perfmon_timestamp_get();
int new_tail = (q->tail + 1) % PERF_SAMPLE_BUFSZ;
if (q->head == new_tail) {
q->overflows++;
return;
}
q->samples[new_tail].sample_tag = sample_tag;
q->samples[new_tail].counter = counter;
q->samples[new_tail].timestamp = timestamp;
q->samples[new_tail].duration = duration;
q->tail = new_tail;
}
static __inline__ int
get_sample(struct sample_q *q, uint32_t * sample_tag, uint32_t * counter,
uint32_t * timestamp, uint32_t * duration)
{
int head = q->head;
if (head == q->tail)
return 0;
*sample_tag = q->samples[head].sample_tag;
*counter = q->samples[head].counter;
*timestamp = q->samples[head].timestamp;
*duration = q->samples[head].duration;
q->head = (head + 1) % PERF_SAMPLE_BUFSZ;
return 1;
}
static __inline__ void
clear_queue(struct sample_q *q)
{
q->head = q->tail;
}
void xlr_perfmon_init_cpu(void *);
void xlr_perfmon_sampler(void *);
void log_active_core(int core);
int get_start_generation(void);
void xlr_perfmon_clockhandler(void);
extern int xlr_perfmon_started;
#endif /* PERFMON_H */

163
sys/mips/rmi/perfmon_kern.c Normal file
View File

@ -0,0 +1,163 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
#include <sys/smp.h>
#include <sys/sysctl.h>
#include <machine/smp.h>
#include <mips/rmi/perfmon.h>
#include <mips/rmi/pic.h>
#include <sys/mutex.h>
#include <mips/rmi/clock.h>
int xlr_perfmon_started = 0;
struct perf_area *xlr_shared_config_area = NULL;
uint32_t *xlr_perfmon_timer_loc;
uint32_t *xlr_cpu_sampling_interval;
uint32_t xlr_perfmon_kernel_version = 1; /* Future use */
uint32_t xlr_perfmon_ticks;
extern int mips_cpu_online_mask;
extern uint32_t cpu_ltop_map[MAXCPU];
#ifdef SMP
static __inline__ void
pic_send_perfmon_ipi(int cpu)
{
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
int tid, pid;
uint32_t ipi;
tid = cpu & 0x3;
pid = (cpu >> 2) & 0x7;
ipi = (pid << 20) | (tid << 16) | IPI_PERFMON;
mtx_lock_spin(&xlr_pic_lock);
xlr_write_reg(mmio, PIC_IPI, ipi);
mtx_unlock_spin(&xlr_pic_lock);
}
#endif
void
xlr_perfmon_clockhandler(void)
{
#ifdef SMP
int cpu;
int i;
#endif
if (xlr_perfmon_ticks++ >= (*xlr_cpu_sampling_interval) / (XLR_PIC_HZ / (hz * 1024))) {
/* update timer */
*xlr_perfmon_timer_loc += *xlr_cpu_sampling_interval;
xlr_perfmon_ticks = 0;
xlr_perfmon_sampler(NULL);
#ifdef SMP
for (i = 0; i < NCPUS; i = i + NTHREADS) { /* oly thread 0 */
cpu = cpu_ltop_map[i];
if ((mips_cpu_online_mask & (1 << i)) &&
xlr_shared_config_area[cpu / NTHREADS].perf_config.magic ==
PERFMON_ACTIVE_MAGIC)
pic_send_perfmon_ipi(cpu);
}
#endif
}
}
static void
xlr_perfmon_start(void)
{
size_t size;
size = (NCORES * sizeof(*xlr_shared_config_area)) +
sizeof(*xlr_perfmon_timer_loc) +
sizeof(*xlr_cpu_sampling_interval);
xlr_shared_config_area = malloc(size, M_TEMP, M_WAITOK);
if (!xlr_shared_config_area) {
/* ERROR */
return;
}
xlr_perfmon_timer_loc = (uint32_t *) (xlr_shared_config_area + NCORES);
xlr_cpu_sampling_interval = (uint32_t *) (xlr_perfmon_timer_loc + 1);
*xlr_cpu_sampling_interval = DEFAULT_CPU_SAMPLING_INTERVAL;
*xlr_perfmon_timer_loc = 0;
xlr_perfmon_ticks = 0;
xlr_perfmon_init_cpu(NULL);
#ifdef SMP
smp_call_function(xlr_perfmon_init_cpu, NULL,
PCPU_GET(other_cpus) & 0x11111111);
#endif
xlr_perfmon_started = 1;
}
static void
xlr_perfmon_stop(void)
{
xlr_perfmon_started = 0;
free(xlr_shared_config_area, M_TEMP);
xlr_shared_config_area = NULL;
}
static int
sysctl_xlr_perfmon_start_stop(SYSCTL_HANDLER_ARGS)
{
int error, val = xlr_perfmon_started;
error = sysctl_handle_int(oidp, &val, 0, req);
if (error != 0 || req->newptr == NULL)
return (error);
if (!xlr_perfmon_started && val != 0)
xlr_perfmon_start();
else if (xlr_perfmon_started && val == 0)
xlr_perfmon_stop();
return (0);
}
SYSCTL_NODE(_debug, OID_AUTO, xlrperf, CTLFLAG_RW, NULL, "XLR PERF Nodes");
SYSCTL_PROC(_debug_xlrperf, OID_AUTO, start, CTLTYPE_INT | CTLFLAG_RW,
&xlr_perfmon_started, 0, sysctl_xlr_perfmon_start_stop, "I", "set/unset to start/stop "
"performance monitoring");

View File

@ -0,0 +1,342 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/smp.h>
#include <sys/pcpu.h>
#include <mips/rmi/xlrconfig.h>
#include <mips/rmi/perfmon_xlrconfig.h>
#include <mips/rmi/perfmon.h>
#include <mips/rmi/perfmon_utils.h>
#include <mips/rmi/pic.h>
#include <mips/rmi/msgring.h>
#define CC_SAMPLE (PERF_CP2_CREDITS <<24)
#define CC_REG0 16
#define CC_REG1 17
#define CC_REG2 18
#define CC_REG3 19
#define CC_REG4 20
#define CC_REG5 21
#define CC_REG6 22
#define CC_REG7 23
#define CC_REG8 24
#define CC_REG9 25
#define CC_REG10 26
#define CC_REG11 27
#define CC_REG12 28
#define CC_REG13 29
#define CC_REG14 30
#define CC_REG15 31
extern uint32_t cpu_ltop_map[MAXCPU];
extern struct perf_area *xlr_shared_config_area;
static __inline__ uint32_t
make_cpu_tag(uint32_t val)
{
return PERF_CP0_COUNTER << 24 | (val & 0xffff);
}
static __inline__ uint32_t
make_cp0_perf_control(uint32_t flags, uint32_t thread, uint32_t event)
{
return (flags & 0x1f) | (thread & 0x03) << 11 | (event & 0x3f) << 5 | 0x01;
}
static __inline__ uint32_t
cp0_perf_control_get_thread(uint32_t control_word)
{
return (control_word & 0x1800) >> 11;
}
static __inline__ uint32_t
cp0_perf_control_get_event(uint32_t control_word)
{
return (control_word & 0x7e0) >> 5;
}
static __inline__ uint32_t
read_pic_6_timer_count(void)
{
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
/* PIC counts down, convert it to count up */
return 0xffffffffU - xlr_read_reg(mmio, PIC_TIMER_6_COUNTER_0);
}
static uint32_t
get_num_events(const uint64_t * events)
{
int total = 0;
int thread;
for (thread = 0; thread < NTHREADS; thread++) {
if (events[thread] == 0)
continue;
total += get_set_bit_count64(events[thread]);
}
return total;
}
static uint32_t
get_first_control_word(uint32_t flags, const uint64_t * events)
{
int thread, event;
for (thread = 0; thread < NTHREADS; thread++) {
if (events[thread] != 0)
break;
}
if (thread == NTHREADS)
return -1;
event = find_first_set_bit64(events[thread]);
return make_cp0_perf_control(flags, thread, event);
}
static uint32_t
get_next_control_word(uint32_t current_control_word, const uint64_t * events)
{
int thread = cp0_perf_control_get_thread(current_control_word);
int event = cp0_perf_control_get_event(current_control_word);
int i;
event = find_next_set_bit64(events[thread], event);
for (i = 0; event == -1 && i < NTHREADS; i++) {
thread = (thread + 1) % NTHREADS;
if (events[thread] == 0)
continue;
event = find_first_set_bit64(events[thread]);
}
ASSERT(event != -1);
return make_cp0_perf_control(current_control_word, thread, event);
}
/* Global state per core */
#define MY_CORE_NUM (cpu_ltop_map[PCPU_GET(cpuid)]/NTHREADS)
#define my_perf_area (&(xlr_shared_config_area[MY_CORE_NUM]))
static int num_events_array[NCORES];
static uint32_t saved_timestamp_array[NCORES];
static struct perf_config_data saved_config_array[NCORES];
static int cc_sample_array[NCORES];
#define num_events (num_events_array[MY_CORE_NUM])
#define saved_timestamp (saved_timestamp_array[MY_CORE_NUM])
#define saved_config (saved_config_array[MY_CORE_NUM])
#define cc_sample (cc_sample_array[MY_CORE_NUM])
static void
do_sample_cc_registers(struct sample_q *q, uint32_t mask)
{
unsigned long flags;
DPRINT("Sample CC registers %x", mask);
msgrng_flags_save(flags);
if (mask & 0x00000001)
put_sample(q, CC_SAMPLE + 0, read_cc_registers_0123(CC_REG0), 0);
if (mask & 0x00000002)
put_sample(q, CC_SAMPLE + 1, read_cc_registers_4567(CC_REG0), 0);
if (mask & 0x00000004)
put_sample(q, CC_SAMPLE + 2, read_cc_registers_0123(CC_REG1), 0);
if (mask & 0x00000008)
put_sample(q, CC_SAMPLE + 3, read_cc_registers_4567(CC_REG1), 0);
if (mask & 0x00000010)
put_sample(q, CC_SAMPLE + 4, read_cc_registers_0123(CC_REG2), 0);
if (mask & 0x00000020)
put_sample(q, CC_SAMPLE + 5, read_cc_registers_4567(CC_REG2), 0);
if (mask & 0x00000040)
put_sample(q, CC_SAMPLE + 6, read_cc_registers_0123(CC_REG3), 0);
if (mask & 0x00000080)
put_sample(q, CC_SAMPLE + 7, read_cc_registers_4567(CC_REG3), 0);
if (mask & 0x00000100)
put_sample(q, CC_SAMPLE + 8, read_cc_registers_0123(CC_REG4), 0);
if (mask & 0x00000200)
put_sample(q, CC_SAMPLE + 9, read_cc_registers_4567(CC_REG4), 0);
if (mask & 0x00000400)
put_sample(q, CC_SAMPLE + 10, read_cc_registers_0123(CC_REG5), 0);
if (mask & 0x00000800)
put_sample(q, CC_SAMPLE + 11, read_cc_registers_4567(CC_REG5), 0);
if (mask & 0x00001000)
put_sample(q, CC_SAMPLE + 12, read_cc_registers_0123(CC_REG6), 0);
if (mask & 0x00002000)
put_sample(q, CC_SAMPLE + 13, read_cc_registers_4567(CC_REG6), 0);
if (mask & 0x00004000)
put_sample(q, CC_SAMPLE + 14, read_cc_registers_0123(CC_REG7), 0);
if (mask & 0x00008000)
put_sample(q, CC_SAMPLE + 15, read_cc_registers_4567(CC_REG7), 0);
if (mask & 0x00010000)
put_sample(q, CC_SAMPLE + 16, read_cc_registers_0123(CC_REG8), 0);
if (mask & 0x00020000)
put_sample(q, CC_SAMPLE + 17, read_cc_registers_4567(CC_REG8), 0);
if (mask & 0x00040000)
put_sample(q, CC_SAMPLE + 18, read_cc_registers_0123(CC_REG9), 0);
if (mask & 0x00080000)
put_sample(q, CC_SAMPLE + 19, read_cc_registers_4567(CC_REG9), 0);
if (mask & 0x00100000)
put_sample(q, CC_SAMPLE + 20, read_cc_registers_0123(CC_REG10), 0);
if (mask & 0x00200000)
put_sample(q, CC_SAMPLE + 21, read_cc_registers_4567(CC_REG10), 0);
if (mask & 0x00400000)
put_sample(q, CC_SAMPLE + 22, read_cc_registers_0123(CC_REG11), 0);
if (mask & 0x00800000)
put_sample(q, CC_SAMPLE + 23, read_cc_registers_4567(CC_REG11), 0);
if (mask & 0x01000000)
put_sample(q, CC_SAMPLE + 24, read_cc_registers_0123(CC_REG12), 0);
if (mask & 0x02000000)
put_sample(q, CC_SAMPLE + 24, read_cc_registers_4567(CC_REG12), 0);
if (mask & 0x04000000)
put_sample(q, CC_SAMPLE + 26, read_cc_registers_0123(CC_REG13), 0);
if (mask & 0x08000000)
put_sample(q, CC_SAMPLE + 27, read_cc_registers_4567(CC_REG13), 0);
if (mask & 0x10000000)
put_sample(q, CC_SAMPLE + 28, read_cc_registers_0123(CC_REG14), 0);
if (mask & 0x20000000)
put_sample(q, CC_SAMPLE + 29, read_cc_registers_4567(CC_REG14), 0);
if (mask & 0x40000000)
put_sample(q, CC_SAMPLE + 30, read_cc_registers_0123(CC_REG15), 0);
if (mask & 0x80000000)
put_sample(q, CC_SAMPLE + 31, read_cc_registers_4567(CC_REG15), 0);
msgrng_flags_restore(flags);
}
static void
reconfigure(void)
{
uint32_t cntr_cntrl;
saved_config = my_perf_area->perf_config;
num_events = get_num_events(saved_config.events);
cc_sample = saved_config.cc_sample_rate;
DPRINT("%d - reconfigure num_events = %d, events = %llx,%llx,%llx,%llx\n",
processor_id(), num_events, saved_config.events[0],
saved_config.events[1], saved_config.events[2], saved_config.events[3]);
if (num_events == 0)
return;
cntr_cntrl = get_first_control_word(saved_config.flags, saved_config.events);
write_c0_register(CP0_PERF_COUNTER, PERFCNTRCTL0, cntr_cntrl);
write_c0_register(CP0_PERF_COUNTER, PERFCNTR0, 0); /* reset count */
if (num_events > 1) {
cntr_cntrl = get_next_control_word(cntr_cntrl, saved_config.events);
write_c0_register(CP0_PERF_COUNTER, PERFCNTRCTL1, cntr_cntrl);
write_c0_register(CP0_PERF_COUNTER, PERFCNTR1, 0); /* reset count */
}
saved_timestamp = read_pic_6_timer_count();
}
int xlr_perfmon_no_event_count = 0;
int xlr_perfmon_sample_count;
/* timer callback routine */
void
xlr_perfmon_sampler(void *dummy)
{
uint32_t current_ts;
uint32_t cntr_cntrl = 0;
/* xlr_ack_interrupt(XLR_PERFMON_IPI_VECTOR); */
if (my_perf_area->perf_config.magic != PERFMON_ACTIVE_MAGIC)
return;
/*
* If there has been a change in configuation, update the
* configuration
*/
if (saved_config.generation != my_perf_area->perf_config.generation) {
reconfigure();
return;
}
/* credit counter samples if reqd */
if (saved_config.cc_register_mask && --cc_sample == 0) {
cc_sample = saved_config.cc_sample_rate;
do_sample_cc_registers(&my_perf_area->sample_fifo,
my_perf_area->perf_config.cc_register_mask);
}
if (num_events == 0) {
xlr_perfmon_no_event_count++;
return;
}
/* put samples in the queue */
current_ts = read_pic_6_timer_count();
cntr_cntrl = read_c0_register(CP0_PERF_COUNTER, PERFCNTRCTL0);
put_sample(&my_perf_area->sample_fifo, make_cpu_tag(cntr_cntrl),
read_c0_register(CP0_PERF_COUNTER, PERFCNTR0), current_ts - saved_timestamp);
xlr_perfmon_sample_count++;
write_c0_register(CP0_PERF_COUNTER, PERFCNTR0, 0); /* reset count */
if (num_events > 1) {
cntr_cntrl = read_c0_register(CP0_PERF_COUNTER, PERFCNTRCTL1);
put_sample(&my_perf_area->sample_fifo, make_cpu_tag(cntr_cntrl),
read_c0_register(CP0_PERF_COUNTER, PERFCNTR1), current_ts - saved_timestamp);
xlr_perfmon_sample_count++;
write_c0_register(CP0_PERF_COUNTER, PERFCNTR1, 0); /* reset count */
if (num_events > 2) {
/* multiplex events */
cntr_cntrl = get_next_control_word(cntr_cntrl, saved_config.events);
write_c0_register(CP0_PERF_COUNTER, PERFCNTRCTL0, cntr_cntrl);
cntr_cntrl = get_next_control_word(cntr_cntrl, saved_config.events);
write_c0_register(CP0_PERF_COUNTER, PERFCNTRCTL1, cntr_cntrl);
}
}
saved_timestamp = read_pic_6_timer_count();
}
/*
* Initializes time to gather CPU performance counters and credit counters
*/
void
xlr_perfmon_init_cpu(void *dummy)
{
int processor = cpu_ltop_map[PCPU_GET(cpuid)];
/* run on just one thread per core */
if (processor % 4)
return;
DPRINT("%d : configure with %p", processor, my_perf_area);
memset(my_perf_area, 0, sizeof(*my_perf_area));
init_fifo(&my_perf_area->sample_fifo);
my_perf_area->perf_config.magic = PERFMON_ENABLED_MAGIC;
my_perf_area->perf_config.generation = PERFMON_INITIAL_GENERATION;
DPRINT("%d : Initialize", processor);
return;
}

View File

@ -0,0 +1,126 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#ifndef UTILS_H
#define UTILS_H
#include <machine/stdarg.h> /* variable args */
/* TODO optimize of mips, even i & (i-1) is better */
static int __inline__
get_set_bit_count64(uint64_t value)
{
int i, result = 0;
for (i = 0; i < sizeof(value) * 8; i++)
if (value & (1ULL << i))
result++;
return result;
}
static int __inline__
find_first_set_bit64(uint64_t value)
{
int i;
for (i = 0; i < sizeof(value) * 8; i++)
if (value & (1ULL << i))
return i;
return -1;
}
static int __inline__
find_next_set_bit64(uint64_t value, int pos)
{
int i;
for (i = pos + 1; i < sizeof(value) * 8; i++)
if (value & (1ULL << i))
return i;
return -1;
}
/** --- **/
static int __inline__
get_set_bit_count(uint32_t value)
{
int i, result = 0;
for (i = 0; i < sizeof(value) * 8; i++)
if (value & (1U << i))
result++;
return result;
}
static int __inline__
find_first_set_bit(uint32_t value)
{
int i;
for (i = 0; i < sizeof(value) * 8; i++)
if (value & (1U << i))
return i;
return -1;
}
static int __inline__
find_next_set_bit(uint32_t value, int pos)
{
int i;
for (i = pos + 1; i < sizeof(value) * 8; i++)
if (value & (1U << i))
return i;
return -1;
}
#ifdef DEBUG
void abort();
#define DPUTC(c) (putchar(c) && fflush(stdout))
#define DPRINT(fmt, ...) printf(fmt "\n", __VA_ARGS__)
#define ASSERT(x) ((x) || ({ printf("%s failed at (%s:%d)", #x, __FILE__, __LINE__) ; abort(); 0; }) )
#else
#define DPUTC(c)
#define DPRINT(fmt, ...)
#define ASSERT(x)
#endif
void xlr_send_sample(uint32_t tag, uint32_t value, uint32_t ts, uint32_t td);
#endif

View File

@ -0,0 +1,156 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#ifdef XLR_PERFMON
#ifndef XLRCONFIG_PERFMON_H
#define XLRCONFIG_PERFMON_H
#include <mips/rmi/perfmon_utils.h> /* for DPRINT */
#define NCPUS 32
#define NCORES 8
#define NTHREADS 4
#define PERF_SAMPLE_BUFSZ 32
/*select timeout is 512*1024 microsecs */
#define DEFAULT_SYS_SAMPLING_INTERVAL (512*1024)
/* default timer value programmed to PIC is 10*1024*1024 */
#define DEFAULT_CPU_SAMPLING_INTERVAL (10*1024)
#define DEFAULT_CC_SAMPLE_RATE 16
#define DEFAULT_CP0_FLAGS 0x0A
#define NUM_L2_BANKS 8
#define NUM_DRAM_BANKS 4
/* CP0 register for timestamp */
#define CP0_COUNT 9
#define CP0_EIRR_REG 9
#define CP0_EIRR_SEL 6
#define CP0_EIMR_REG 9
#define CP0_EIMR_SEL 7
/* CP0 register for perf counters */
#define CP0_PERF_COUNTER 25
/* selector values */
#define PERFCNTRCTL0 0
#define PERFCNTR0 1
#define PERFCNTRCTL1 2
#define PERFCNTR1 3
#define XLR_IO_PIC_OFFSET 0x08000
#define PIC_SYS_TIMER_0_BASE 0x120
#define PIC_SYS_TIMER_NUM_6 6
/* CP2 registers for reading credit counters */
#define CC_REG0 16
#define read_c0_register(reg, sel) \
({ unsigned int __rv; \
__asm__ __volatile__( \
".set\tpush\n\t" \
".set mips32\n\t" \
"mfc0\t%0,$%1,%2\n\t" \
".set\tpop" \
: "=r" (__rv) : "i" (reg), "i" (sel) ); \
__rv;})
#define write_c0_register(reg, sel, value) \
__asm__ __volatile__( \
".set\tpush\n\t" \
".set mips32\n\t" \
"mtc0\t%0,$%1,%2\n\t" \
".set\tpop" \
: : "r" (value), "i" (reg), "i" (sel) );
#define read_c2_register(reg, sel) \
({ unsigned int __rv; \
__asm__ __volatile__( \
".set\tpush\n\t" \
".set mips32\n\t" \
"mfc0\t%0,$%1,%2\n\t" \
".set\tpop" \
: "=r" (__rv) : "i"(reg), "i" (sel) ); \
__rv;})
/*
* We have 128 registers in C2 credit counters, reading them one at
* a time using bitmap will take a lot of code, so we have two functions
* to read registers sel0-3 and sel 4-7 into one 32 bit word.
*/
#define read_cc_registers_0123(reg) \
({ \
unsigned int __rv; \
\
__asm__ __volatile__( \
".set push\n\t" \
".set mips32\n\t" \
".set noreorder\n\t" \
"mfc2 %0, $%1, 0\n\t" \
"mfc2 $8, $%1, 1\n\t" \
"sll %0, %0, 8\n\t" \
"or %0, %0, $8\n\t" \
"mfc2 $8, $%1, 2\n\t" \
"sll %0, %0, 8\n\t" \
"or %0, %0, $8\n\t" \
"mfc2 $8, $%1, 3\n\t" \
"sll %0, %0, 8\n\t" \
"or %0, %0, $8\n\t" \
".set pop" \
: "=r" (__rv) : "i"(reg) : "$8"); \
\
__rv; \
})
#define read_cc_registers_4567(reg) \
({ \
unsigned int __rv; \
\
__asm__ __volatile__( \
".set push\n\t" \
".set mips32\n\t" \
".set noreorder\n\t" \
"mfc2 %0, $%1, 4\n\t" \
"mfc2 $8, $%1, 5\n\t" \
"sll %0, %0, 8\n\t" \
"or %0, %0, $8\n\t" \
"mfc2 $8, $%1, 6\n\t" \
"sll %0, %0, 8\n\t" \
"or %0, %0, $8\n\t" \
"mfc2 $8, $%1, 7\n\t" \
"sll %0, %0, 8\n\t" \
"or %0, %0, $8\n\t" \
".set pop" \
: "=r" (__rv) :"i"(reg) : "$8"); \
\
__rv; \
})
#endif
#endif

279
sys/mips/rmi/pic.h Normal file
View File

@ -0,0 +1,279 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#ifndef _RMI_PIC_H_
#define _RMI_PIC_H_
extern int rmi_spin_mutex_safe;
#include <sys/lock.h>
#include <sys/mutex.h>
#include <mips/rmi/iomap.h>
#define PIC_IRT_WD_INDEX 0
#define PIC_IRT_TIMER_0_INDEX 1
#define PIC_IRT_TIMER_1_INDEX 2
#define PIC_IRT_TIMER_2_INDEX 3
#define PIC_IRT_TIMER_3_INDEX 4
#define PIC_IRT_TIMER_4_INDEX 5
#define PIC_IRT_TIMER_5_INDEX 6
#define PIC_IRT_TIMER_6_INDEX 7
#define PIC_IRT_TIMER_7_INDEX 8
#define PIC_IRT_CLOCK_INDEX PIC_IRT_TIMER_7_INDEX
#define PIC_IRT_UART_0_INDEX 9
#define PIC_IRT_UART_1_INDEX 10
#define PIC_IRT_I2C_0_INDEX 11
#define PIC_IRT_I2C_1_INDEX 12
#define PIC_IRT_PCMCIA_INDEX 13
#define PIC_IRT_GPIO_INDEX 14
#define PIC_IRT_HYPER_INDEX 15
#define PIC_IRT_PCIX_INDEX 16
#define PIC_IRT_GMAC0_INDEX 17
#define PIC_IRT_GMAC1_INDEX 18
#define PIC_IRT_GMAC2_INDEX 19
#define PIC_IRT_GMAC3_INDEX 20
#define PIC_IRT_XGS0_INDEX 21
#define PIC_IRT_XGS1_INDEX 22
#define PIC_IRT_HYPER_FATAL_INDEX 23
#define PIC_IRT_PCIX_FATAL_INDEX 24
#define PIC_IRT_BRIDGE_AERR_INDEX 25
#define PIC_IRT_BRIDGE_BERR_INDEX 26
#define PIC_IRT_BRIDGE_TB_INDEX 27
#define PIC_IRT_BRIDGE_AERR_NMI_INDEX 28
/* numbering for XLS */
#define PIC_IRT_BRIDGE_ERR_INDEX 25
#define PIC_IRT_PCIE_LINK0_INDEX 26
#define PIC_IRT_PCIE_LINK1_INDEX 27
#define PIC_IRT_PCIE_LINK2_INDEX 23
#define PIC_IRT_PCIE_LINK3_INDEX 24
#define PIC_IRT_PCIE_INT_INDEX 28
#define PIC_IRT_PCIE_FATAL_INDEX 29
#define PIC_IRT_GPIO_B_INDEX 30
#define PIC_IRT_USB_INDEX 31
#define PIC_NUM_IRTS 32
#define PIC_SYS_TIMER_MAXVAL_0_BASE 0x100
#define PIC_SYS_TIMER_MAXVAL_1_BASE 0x110
#define PIC_SYS_TIMER_0_BASE 0x120
#define PIC_SYS_TIMER_1_BASE 0x130
#define PIC_CLOCK_TIMER 7
#define PIC_CTRL 0x00
#define PIC_IPI 0x04
#define PIC_INT_ACK 0x06
#define WD_MAX_VAL_0 0x08
#define WD_MAX_VAL_1 0x09
#define WD_MASK_0 0x0a
#define WD_MASK_1 0x0b
#define WD_HEARBEAT_0 0x0c
#define WD_HEARBEAT_1 0x0d
#define PIC_IRT_0_BASE 0x40
#define PIC_IRT_1_BASE 0x80
#define PIC_IRT_0_WD (PIC_IRT_0_BASE + PIC_IRT_WD_INDEX)
#define PIC_IRT_1_WD (PIC_IRT_1_BASE + PIC_IRT_WD_INDEX)
#define PIC_IRT_0_TIMER_0 (PIC_IRT_0_BASE + PIC_IRT_TIMER_0_INDEX)
#define PIC_IRT_1_TIMER_0 (PIC_IRT_1_BASE + PIC_IRT_TIMER_0_INDEX)
#define PIC_IRT_0_TIMER_1 (PIC_IRT_0_BASE + PIC_IRT_TIMER_1_INDEX)
#define PIC_IRT_1_TIMER_1 (PIC_IRT_1_BASE + PIC_IRT_TIMER_1_INDEX)
#define PIC_IRT_0_TIMER_2 (PIC_IRT_0_BASE + PIC_IRT_TIMER_2_INDEX)
#define PIC_IRT_1_TIMER_2 (PIC_IRT_1_BASE + PIC_IRT_TIMER_2_INDEX)
#define PIC_IRT_0_TIMER_3 (PIC_IRT_0_BASE + PIC_IRT_TIMER_3_INDEX)
#define PIC_IRT_1_TIMER_3 (PIC_IRT_1_BASE + PIC_IRT_TIMER_3_INDEX)
#define PIC_IRT_0_TIMER_4 (PIC_IRT_0_BASE + PIC_IRT_TIMER_4_INDEX)
#define PIC_IRT_1_TIMER_4 (PIC_IRT_1_BASE + PIC_IRT_TIMER_4_INDEX)
#define PIC_IRT_0_TIMER_5 (PIC_IRT_0_BASE + PIC_IRT_TIMER_5_INDEX)
#define PIC_IRT_1_TIMER_5 (PIC_IRT_1_BASE + PIC_IRT_TIMER_5_INDEX)
#define PIC_IRT_0_TIMER_6 (PIC_IRT_0_BASE + PIC_IRT_TIMER_6_INDEX)
#define PIC_IRT_1_TIMER_6 (PIC_IRT_1_BASE + PIC_IRT_TIMER_6_INDEX)
#define PIC_IRT_0_TIMER_7 (PIC_IRT_0_BASE + PIC_IRT_TIMER_7_INDEX)
#define PIC_IRT_1_TIMER_7 (PIC_IRT_1_BASE + PIC_IRT_TIMER_7_INDEX)
#define PIC_IRT_0_CLOCK (PIC_IRT_0_TIMER_7)
#define PIC_IRT_1_CLOCK (PIC_IRT_1_TIMER_7)
#define PIC_IRT_0_UART_0 (PIC_IRT_0_BASE + PIC_IRT_UART_0_INDEX)
#define PIC_IRT_1_UART_0 (PIC_IRT_1_BASE + PIC_IRT_UART_0_INDEX)
#define PIC_IRT_0_UART_1 (PIC_IRT_0_BASE + PIC_IRT_UART_1_INDEX)
#define PIC_IRT_1_UART_1 (PIC_IRT_1_BASE + PIC_IRT_UART_1_INDEX)
#define PIC_IRT_0_I2C_0 (PIC_IRT_0_BASE + PIC_IRT_I2C_0_INDEX)
#define PIC_IRT_1_I2C_0 (PIC_IRT_1_BASE + PIC_IRT_I2C_0_INDEX)
#define PIC_IRT_0_I2C_1 (PIC_IRT_0_BASE + PIC_IRT_I2C_1_INDEX)
#define PIC_IRT_1_I2C_1 (PIC_IRT_1_BASE + PIC_IRT_I2C_1_INDEX)
#define PIC_IRT_0_HYPER (PIC_IRT_0_BASE + PIC_IRT_HYPER_INDEX)
#define PIC_IRT_1_HYPER (PIC_IRT_1_BASE + PIC_IRT_HYPER_INDEX)
#define PIC_IRT_0_PCIX (PIC_IRT_0_BASE + PIC_IRT_PCIX_INDEX)
#define PIC_IRT_1_PCIX (PIC_IRT_1_BASE + PIC_IRT_PCIX_INDEX)
#define PIC_TIMER_0_MAXVAL_0 (PIC_SYS_TIMER_MAXVAL_0_BASE + 0)
#define PIC_TIMER_0_MAXVAL_1 (PIC_SYS_TIMER_MAXVAL_1_BASE + 0)
#define PIC_TIMER_0_COUNTER_0 (PIC_SYS_TIMER_0_BASE + 0)
#define PIC_TIMER_0_COUNTER_1 (PIC_SYS_TIMER_1_BASE + 0)
#define PIC_TIMER_6_MAXVAL_0 (PIC_SYS_TIMER_MAXVAL_0_BASE + 6)
#define PIC_TIMER_6_MAXVAL_1 (PIC_SYS_TIMER_MAXVAL_1_BASE + 6)
#define PIC_TIMER_6_COUNTER_0 (PIC_SYS_TIMER_0_BASE + 6)
#define PIC_TIMER_6_COUNTER_1 (PIC_SYS_TIMER_1_BASE + 6)
#define PIC_TIMER_7_MAXVAL_0 (PIC_SYS_TIMER_MAXVAL_0_BASE + 7)
#define PIC_TIMER_7_MAXVAL_1 (PIC_SYS_TIMER_MAXVAL_1_BASE + 7)
#define PIC_TIMER_7_COUNTER_0 (PIC_SYS_TIMER_0_BASE + 7)
#define PIC_TIMER_7_COUNTER_1 (PIC_SYS_TIMER_1_BASE + 7)
#define PIC_IRQ_BASE 8
#define PIC_IRT_FIRST_IRQ PIC_IRQ_BASE
#define PIC_WD_IRQ (PIC_IRQ_BASE + PIC_IRT_WD_INDEX)
#define PIC_TIMER_0_IRQ (PIC_IRQ_BASE + PIC_IRT_TIMER_0_INDEX)
#define PIC_TIMER_1_IRQ (PIC_IRQ_BASE + PIC_IRT_TIMER_1_INDEX)
#define PIC_TIMER_2_IRQ (PIC_IRQ_BASE + PIC_IRT_TIMER_2_INDEX)
#define PIC_TIMER_3_IRQ (PIC_IRQ_BASE + PIC_IRT_TIMER_3_INDEX)
#define PIC_TIMER_4_IRQ (PIC_IRQ_BASE + PIC_IRT_TIMER_4_INDEX)
#define PIC_TIMER_5_IRQ (PIC_IRQ_BASE + PIC_IRT_TIMER_5_INDEX)
#define PIC_TIMER_6_IRQ (PIC_IRQ_BASE + PIC_IRT_TIMER_6_INDEX)
#define PIC_TIMER_7_IRQ (PIC_IRQ_BASE + PIC_IRT_TIMER_7_INDEX)
#define PIC_CLOCK_IRQ (PIC_TIMER_7_IRQ)
#define PIC_UART_0_IRQ (PIC_IRQ_BASE + PIC_IRT_UART_0_INDEX)
#define PIC_UART_1_IRQ (PIC_IRQ_BASE + PIC_IRT_UART_1_INDEX)
#define PIC_I2C_0_IRQ (PIC_IRQ_BASE + PIC_IRT_I2C_0_INDEX)
#define PIC_I2C_1_IRQ (PIC_IRQ_BASE + PIC_IRT_I2C_1_INDEX)
#define PIC_PCMCIA_IRQ (PIC_IRQ_BASE + PIC_IRT_PCMCIA_INDEX)
#define PIC_GPIO_IRQ (PIC_IRQ_BASE + PIC_IRT_GPIO_INDEX)
#define PIC_HYPER_IRQ (PIC_IRQ_BASE + PIC_IRT_HYPER_INDEX)
#define PIC_PCIX_IRQ (PIC_IRQ_BASE + PIC_IRT_PCIX_INDEX)
#define PIC_GMAC_0_IRQ (PIC_IRQ_BASE + PIC_IRT_GMAC0_INDEX)
#define PIC_GMAC_1_IRQ (PIC_IRQ_BASE + PIC_IRT_GMAC1_INDEX)
#define PIC_GMAC_2_IRQ (PIC_IRQ_BASE + PIC_IRT_GMAC2_INDEX)
#define PIC_GMAC_3_IRQ (PIC_IRQ_BASE + PIC_IRT_GMAC3_INDEX)
#define PIC_XGS_0_IRQ (PIC_IRQ_BASE + PIC_IRT_XGS0_INDEX)
#define PIC_XGS_1_IRQ (PIC_IRQ_BASE + PIC_IRT_XGS1_INDEX)
#define PIC_HYPER_FATAL_IRQ (PIC_IRQ_BASE + PIC_IRT_HYPER_FATAL_INDEX)
#define PIC_PCIX_FATAL_IRQ (PIC_IRQ_BASE + PIC_IRT_PCIX_FATAL_INDEX)
#define PIC_BRIDGE_AERR_IRQ (PIC_IRQ_BASE + PIC_IRT_BRIDGE_AERR_INDEX)
#define PIC_BRIDGE_BERR_IRQ (PIC_IRQ_BASE + PIC_IRT_BRIDGE_BERR_INDEX)
#define PIC_BRIDGE_TB_IRQ (PIC_IRQ_BASE + PIC_IRT_BRIDGE_TB_INDEX)
#define PIC_BRIDGE_AERR_NMI_IRQ (PIC_IRQ_BASE + PIC_IRT_BRIDGE_AERR_NMI_INDEX)
#define PIC_BRIDGE_ERR_IRQ (PIC_IRQ_BASE + PIC_IRT_BRIDGE_ERR_INDEX)
#define PIC_PCIE_LINK0_IRQ (PIC_IRQ_BASE + PIC_IRT_PCIE_LINK0_INDEX)
#define PIC_PCIE_LINK1_IRQ (PIC_IRQ_BASE + PIC_IRT_PCIE_LINK1_INDEX)
#define PIC_PCIE_LINK2_IRQ (PIC_IRQ_BASE + PIC_IRT_PCIE_LINK2_INDEX)
#define PIC_PCIE_LINK3_IRQ (PIC_IRQ_BASE + PIC_IRT_PCIE_LINK3_INDEX)
#define PIC_PCIE_INT_IRQ (PIC_IRQ_BASE + PIC_IRT_PCIE_INT__INDEX)
#define PIC_PCIE_FATAL_IRQ (PIC_IRQ_BASE + PIC_IRT_PCIE_FATAL_INDEX)
#define PIC_GPIO_B_IRQ (PIC_IRQ_BASE + PIC_IRT_GPIO_B_INDEX)
#define PIC_USB_IRQ (PIC_IRQ_BASE + PIC_IRT_USB_INDEX)
#define PIC_IRT_LAST_IRQ PIC_USB_IRQ
#define PIC_IRQ_IS_EDGE_TRIGGERED(irq) ( ((irq)>=PIC_TIMER_0_IRQ) && ((irq)<=PIC_TIMER_7_IRQ) )
#define PIC_IRQ_IS_IRT(irq) ( ((irq)>=PIC_IRT_FIRST_IRQ) && ((irq)<=PIC_IRT_LAST_IRQ) )
extern struct mtx xlr_pic_lock;
static __inline__ __uint32_t
pic_read_control(void)
{
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
__uint32_t reg;
if (rmi_spin_mutex_safe)
mtx_lock_spin(&xlr_pic_lock);
xlr_read_reg(mmio, PIC_CTRL);
if (rmi_spin_mutex_safe)
mtx_unlock_spin(&xlr_pic_lock);
return reg;
}
static __inline__ void
pic_write_control(__uint32_t control)
{
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
if (rmi_spin_mutex_safe)
mtx_lock_spin(&xlr_pic_lock);
xlr_write_reg(mmio, PIC_CTRL, control);
if (rmi_spin_mutex_safe)
mtx_unlock_spin(&xlr_pic_lock);
}
static __inline__ void
pic_update_control(__uint32_t control)
{
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
if (rmi_spin_mutex_safe)
mtx_lock_spin(&xlr_pic_lock);
xlr_write_reg(mmio, PIC_CTRL, (control | xlr_read_reg(mmio, PIC_CTRL)));
if (rmi_spin_mutex_safe)
mtx_unlock_spin(&xlr_pic_lock);
}
static __inline__ void
pic_ack(int irq)
{
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
/* ack the pic, if needed */
if (!PIC_IRQ_IS_IRT(irq))
return;
if (PIC_IRQ_IS_EDGE_TRIGGERED(irq)) {
if (rmi_spin_mutex_safe)
mtx_lock_spin(&xlr_pic_lock);
xlr_write_reg(mmio, PIC_INT_ACK, (1 << (irq - PIC_IRQ_BASE)));
if (rmi_spin_mutex_safe)
mtx_unlock_spin(&xlr_pic_lock);
return;
}
return;
}
static inline void
pic_delayed_ack(int irq)
{
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
if (!PIC_IRQ_IS_IRT(irq))
return;
if (!PIC_IRQ_IS_EDGE_TRIGGERED(irq)) {
if (rmi_spin_mutex_safe)
mtx_lock_spin(&xlr_pic_lock);
xlr_write_reg(mmio, PIC_INT_ACK, (1 << (irq - PIC_IRQ_BASE)));
if (rmi_spin_mutex_safe)
mtx_unlock_spin(&xlr_pic_lock);
return;
}
}
#endif /* _RMI_PIC_H_ */

View File

@ -0,0 +1,144 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#ifndef __MIPS_EXTS_H__
#define __MIPS_EXTS_H__
#define enable_KX(flags) __asm__ __volatile__ ( \
".set push\n" \
".set noat\n" \
".set noreorder\n" \
"mfc0 %0, $12\n\t" \
"ori $1, %0, 0x81\n\t" \
"xori $1, 1\n\t" \
"mtc0 $1, $12\n" \
".set pop\n" \
: "=r"(flags) )
#define disable_KX(flags) __asm__ __volatile__ ( \
".set push\n" \
"mtc0 %0, $12\n" \
".set pop\n" \
: : "r"(flags) )
#define CPU_BLOCKID_IFU 0
#define CPU_BLOCKID_ICU 1
#define CPU_BLOCKID_IEU 2
#define CPU_BLOCKID_LSU 3
#define CPU_BLOCKID_MMU 4
#define CPU_BLOCKID_PRF 5
#define LSU_CERRLOG_REGID 9
static __inline__ unsigned int read_32bit_phnx_ctrl_reg(int block, int reg)
{
unsigned int __res;
__asm__ __volatile__(
".set\tpush\n\t"
".set\tnoreorder\n\t"
"move $9, %1\n"
/* "mfcr\t$8, $9\n\t" */
".word 0x71280018\n"
"move %0, $8\n"
".set\tpop"
: "=r" (__res) : "r"((block<<8)|reg)
: "$8", "$9"
);
return __res;
}
static __inline__ void write_32bit_phnx_ctrl_reg(int block, int reg, unsigned int value)
{
__asm__ __volatile__(
".set\tpush\n\t"
".set\tnoreorder\n\t"
"move $8, %0\n"
"move $9, %1\n"
/* "mtcr\t$8, $9\n\t" */
".word 0x71280019\n"
".set\tpop"
:
: "r" (value), "r"((block<<8)|reg)
: "$8", "$9"
);
}
static __inline__ unsigned long long read_64bit_phnx_ctrl_reg(int block, int reg)
{
unsigned int high, low;
__asm__ __volatile__(
".set\tmips64\n\t"
"move $9, %2\n"
/* "mfcr $8, $9\n" */
".word 0x71280018\n"
"dsrl32 %0, $8, 0\n\t"
"dsll32 $8, $8, 0\n\t"
"dsrl32 %1, $8, 0\n\t"
".set mips0"
: "=r" (high), "=r"(low)
: "r"((block<<8)|reg)
: "$8", "$9"
);
return ( (((unsigned long long)high)<<32) | low);
}
static __inline__ void write_64bit_phnx_ctrl_reg(int block, int reg,unsigned long long value)
{
__uint32_t low, high;
high = value >> 32;
low = value & 0xffffffff;
__asm__ __volatile__(
".set push\n"
".set noreorder\n"
".set mips4\n\t"
/* Set up "rs" */
"move $9, %0\n"
/* Store 64 bit value in "rt" */
"dsll32 $10, %1, 0 \n\t"
"dsll32 $8, %2, 0 \n\t"
"dsrl32 $8, $8, 0 \n\t"
"or $10, $8, $8 \n\t"
".word 0x71280019\n" /* mtcr $8, $9 */
".set pop\n"
: /* No outputs */
: "r"((block<<8)|reg), "r" (high), "r" (low)
: "$8", "$9", "$10"
);
}
#endif

View File

@ -0,0 +1,676 @@
# This is the list of files that
# should be in your rootfs (copy it from
# the build world nfsmount dir. When the rge0
# driver gets fixed we should be able to start
# using nfs mount... for now we need to use MD_ROOT
./.cshrc
./.profile
./COPYRIGHT
./bin
./bin/cat
./bin/chflags
./bin/chio
./bin/chmod
./bin/cp
./bin/csh
./bin/tcsh
./bin/date
./bin/dd
./bin/df
./bin/domainname
./bin/echo
./bin/ed
./bin/red
./bin/expr
./bin/getfacl
./bin/hostname
./bin/kenv
./bin/kill
./bin/ln
./bin/link
./bin/ls
./bin/mkdir
./bin/mv
./bin/pax
./bin/pkill
./bin/pgrep
./bin/ps
./bin/pwd
./bin/rcp
./bin/realpath
./bin/rm
./bin/unlink
./bin/rmail
./bin/rmdir
./bin/setfacl
./bin/sh
./bin/sleep
./bin/stty
./bin/sync
./bin/test
./bin/[
./bin/uuidgen
./etc
./etc/bluetooth
./etc/bluetooth/hcsecd.conf
./etc/bluetooth/hosts
./etc/bluetooth/protocols
./etc/defaults
./etc/defaults/bluetooth.device.conf
./etc/defaults/devfs.rules
./etc/defaults/periodic.conf
./etc/defaults/rc.conf
./etc/devd
./etc/devd/asus.conf
./etc/gnats
./etc/gnats/freefall
./etc/gss
./etc/gss/mech
./etc/gss/qop
./etc/mail
./etc/mail/mailer.conf
./etc/mail/freebsd.mc
./etc/mail/freebsd.cf
./etc/mail/freebsd.submit.mc
./etc/mail/freebsd.submit.cf
./etc/mail/helpfile
./etc/mail/sendmail.cf
./etc/mail/submit.cf
./etc/mail/Makefile
./etc/mail/README
./etc/mail/access.sample
./etc/mail/virtusertable.sample
./etc/mail/mailertable.sample
./etc/mail/aliases
./etc/mtree
./etc/mtree/BSD.include.dist
./etc/mtree/BSD.root.dist
./etc/mtree/BSD.usr.dist
./etc/mtree/BSD.var.dist
./etc/mtree/BSD.sendmail.dist
./etc/mtree/BIND.chroot.dist
./etc/pam.d
./etc/pam.d/README
./etc/pam.d/atrun
./etc/pam.d/cron
./etc/pam.d/ftpd
./etc/pam.d/imap
./etc/pam.d/kde
./etc/pam.d/login
./etc/pam.d/other
./etc/pam.d/passwd
./etc/pam.d/pop3
./etc/pam.d/rsh
./etc/pam.d/sshd
./etc/pam.d/su
./etc/pam.d/system
./etc/pam.d/telnetd
./etc/pam.d/xdm
./etc/pam.d/ftp
./etc/periodic
./etc/periodic/daily
./etc/periodic/daily/100.clean-disks
./etc/periodic/daily/110.clean-tmps
./etc/periodic/daily/120.clean-preserve
./etc/periodic/daily/200.backup-passwd
./etc/periodic/daily/330.news
./etc/periodic/daily/400.status-disks
./etc/periodic/daily/404.status-zfs
./etc/periodic/daily/405.status-ata-raid
./etc/periodic/daily/406.status-gmirror
./etc/periodic/daily/407.status-graid3
./etc/periodic/daily/408.status-gstripe
./etc/periodic/daily/409.status-gconcat
./etc/periodic/daily/420.status-network
./etc/periodic/daily/450.status-security
./etc/periodic/daily/999.local
./etc/periodic/daily/310.accounting
./etc/periodic/daily/470.status-named
./etc/periodic/daily/300.calendar
./etc/periodic/daily/130.clean-msgs
./etc/periodic/daily/480.status-ntpd
./etc/periodic/daily/140.clean-rwho
./etc/periodic/daily/430.status-rwho
./etc/periodic/daily/150.clean-hoststat
./etc/periodic/daily/210.backup-aliases
./etc/periodic/daily/440.status-mailq
./etc/periodic/daily/460.status-mail-rejects
./etc/periodic/daily/500.queuerun
./etc/periodic/monthly
./etc/periodic/monthly/999.local
./etc/periodic/monthly/200.accounting
./etc/periodic/security
./etc/periodic/security/100.chksetuid
./etc/periodic/security/200.chkmounts
./etc/periodic/security/300.chkuid0
./etc/periodic/security/400.passwdless
./etc/periodic/security/410.logincheck
./etc/periodic/security/700.kernelmsg
./etc/periodic/security/800.loginfail
./etc/periodic/security/900.tcpwrap
./etc/periodic/security/security.functions
./etc/periodic/security/510.ipfdenied
./etc/periodic/security/500.ipfwdenied
./etc/periodic/security/550.ipfwlimit
./etc/periodic/security/520.pfdenied
./etc/periodic/weekly
./etc/periodic/weekly/340.noid
./etc/periodic/weekly/999.local
./etc/periodic/weekly/310.locate
./etc/periodic/weekly/320.whatis
./etc/periodic/weekly/330.catman
./etc/periodic/weekly/400.status-pkg
./etc/ppp
./etc/ppp/ppp.conf
./etc/rc.d
./etc/rc.d/DAEMON
./etc/rc.d/FILESYSTEMS
./etc/rc.d/LOGIN
./etc/rc.d/NETWORKING
./etc/rc.d/SERVERS
./etc/rc.d/abi
./etc/rc.d/accounting
./etc/rc.d/addswap
./etc/rc.d/adjkerntz
./etc/rc.d/amd
./etc/rc.d/apm
./etc/rc.d/apmd
./etc/rc.d/archdep
./etc/rc.d/atm1
./etc/rc.d/atm2
./etc/rc.d/atm3
./etc/rc.d/auditd
./etc/rc.d/bgfsck
./etc/rc.d/bluetooth
./etc/rc.d/bootparams
./etc/rc.d/bridge
./etc/rc.d/bthidd
./etc/rc.d/ccd
./etc/rc.d/cleanvar
./etc/rc.d/cleartmp
./etc/rc.d/cron
./etc/rc.d/ddb
./etc/rc.d/defaultroute
./etc/rc.d/devd
./etc/rc.d/devfs
./etc/rc.d/dhclient
./etc/rc.d/dmesg
./etc/rc.d/dumpon
./etc/rc.d/encswap
./etc/rc.d/faith
./etc/rc.d/fsck
./etc/rc.d/ftp-proxy
./etc/rc.d/ftpd
./etc/rc.d/gbde
./etc/rc.d/geli
./etc/rc.d/geli2
./etc/rc.d/gssd
./etc/rc.d/hcsecd
./etc/rc.d/hostapd
./etc/rc.d/hostid
./etc/rc.d/hostid_save
./etc/rc.d/hostname
./etc/rc.d/inetd
./etc/rc.d/initrandom
./etc/rc.d/ip6addrctl
./etc/rc.d/ip6fw
./etc/rc.d/ipfilter
./etc/rc.d/ipfs
./etc/rc.d/ipfw
./etc/rc.d/ipmon
./etc/rc.d/ipnat
./etc/rc.d/ipsec
./etc/rc.d/ipxrouted
./etc/rc.d/jail
./etc/rc.d/kadmind
./etc/rc.d/kerberos
./etc/rc.d/keyserv
./etc/rc.d/kldxref
./etc/rc.d/kpasswdd
./etc/rc.d/ldconfig
./etc/rc.d/local
./etc/rc.d/localpkg
./etc/rc.d/lockd
./etc/rc.d/lpd
./etc/rc.d/mixer
./etc/rc.d/motd
./etc/rc.d/mountcritlocal
./etc/rc.d/mountcritremote
./etc/rc.d/mountlate
./etc/rc.d/mdconfig
./etc/rc.d/mdconfig2
./etc/rc.d/mountd
./etc/rc.d/moused
./etc/rc.d/mroute6d
./etc/rc.d/mrouted
./etc/rc.d/msgs
./etc/rc.d/named
./etc/rc.d/natd
./etc/rc.d/netif
./etc/rc.d/netoptions
./etc/rc.d/newsyslog
./etc/rc.d/pf
./etc/rc.d/nfscbd
./etc/rc.d/nfsclient
./etc/rc.d/nfsd
./etc/rc.d/nfsserver
./etc/rc.d/nfsuserd
./etc/rc.d/nisdomain
./etc/rc.d/nsswitch
./etc/rc.d/ntpd
./etc/rc.d/ntpdate
./etc/rc.d/othermta
./etc/rc.d/pflog
./etc/rc.d/pfsync
./etc/rc.d/powerd
./etc/rc.d/power_profile
./etc/rc.d/ppp
./etc/rc.d/pppoed
./etc/rc.d/pwcheck
./etc/rc.d/quota
./etc/rc.d/random
./etc/rc.d/rarpd
./etc/rc.d/resolv
./etc/rc.d/rfcomm_pppd_server
./etc/rc.d/root
./etc/rc.d/route6d
./etc/rc.d/routed
./etc/rc.d/routing
./etc/rc.d/rpcbind
./etc/rc.d/rtadvd
./etc/rc.d/rwho
./etc/rc.d/savecore
./etc/rc.d/sdpd
./etc/rc.d/securelevel
./etc/rc.d/sendmail
./etc/rc.d/serial
./etc/rc.d/sppp
./etc/rc.d/statd
./etc/rc.d/static_arp
./etc/rc.d/stf
./etc/rc.d/swap1
./etc/rc.d/syscons
./etc/rc.d/sysctl
./etc/rc.d/syslogd
./etc/rc.d/timed
./etc/rc.d/tmp
./etc/rc.d/ugidfw
./etc/rc.d/var
./etc/rc.d/virecover
./etc/rc.d/watchdogd
./etc/rc.d/wpa_supplicant
./etc/rc.d/ypbind
./etc/rc.d/yppasswdd
./etc/rc.d/ypserv
./etc/rc.d/ypset
./etc/rc.d/ypupdated
./etc/rc.d/ypxfrd
./etc/rc.d/zfs
./etc/rc.d/zvol
./etc/rc.d/sshd
./etc/rc.d/nscd
./etc/security
./etc/security/audit_class
./etc/security/audit_event
./etc/security/audit_control
./etc/security/audit_user
./etc/security/audit_warn
./etc/ssh
./etc/ssh/ssh_config
./etc/ssh/sshd_config
./etc/ssh/moduli
./etc/ssl
./etc/ssl/openssl.cnf
./etc/auth.conf
./etc/crontab
./etc/devd.conf
./etc/devfs.conf
./etc/ddb.conf
./etc/dhclient.conf
./etc/disktab
./etc/fbtab
./etc/ftpusers
./etc/gettytab
./etc/group
./etc/hosts
./etc/hosts.allow
./etc/hosts.equiv
./etc/inetd.conf
./etc/libalias.conf
./etc/login.access
./etc/login.conf
./etc/mac.conf
./etc/motd
./etc/netconfig
./etc/network.subr
./etc/networks
./etc/newsyslog.conf
./etc/nsswitch.conf
./etc/phones
./etc/profile
./etc/protocols
./etc/rc
./etc/rc.bsdextended
./etc/rc.firewall
./etc/rc.firewall6
./etc/rc.initdiskless
./etc/rc.sendmail
./etc/rc.shutdown
./etc/rc.subr
./etc/remote
./etc/rpc
./etc/services
./etc/shells
./etc/sysctl.conf
./etc/syslog.conf
./etc/ttys
./etc/amd.map
./etc/apmd.conf
./etc/freebsd-update.conf
./etc/locate.rc
./etc/hosts.lpd
./etc/printcap
./etc/mail.rc
./etc/manpath.config
./etc/ntp.conf
./etc/nscd.conf
./etc/portsnap.conf
./etc/pf.os
./etc/csh.cshrc
./etc/csh.login
./etc/csh.logout
./etc/regdomain.xml
./etc/login.conf.db
./etc/pwd.db
./etc/netstart
./etc/pccard_ether
./etc/rc.suspend
./etc/rc.resume
./etc/master.passwd
./etc/nsmb.conf
./etc/opieaccess
./etc/spwd.db
./etc/passwd
./etc/dumpdates
./etc/fstab
./etc/rc.conf
./etc/resolv.conf
./etc/termcap
./lib
./lib/geom
./lib/geom/geom_cache.so
./lib/geom/geom_concat.so
./lib/geom/geom_eli.so
./lib/geom/geom_journal.so
./lib/geom/geom_label.so
./lib/geom/geom_mirror.so
./lib/geom/geom_multipath.so
./lib/geom/geom_nop.so
./lib/geom/geom_part.so
./lib/geom/geom_raid3.so
./lib/geom/geom_shsec.so
./lib/geom/geom_stripe.so
./lib/geom/geom_virstor.so
./lib/libc.so.7
./lib/libcrypt.so.5
./lib/libkvm.so.5
./lib/libm.so.5
./lib/libmd.so.5
./lib/libncurses.so.8
./lib/libncursesw.so.8
./lib/libsbuf.so.5
./lib/libutil.so.8
./lib/libalias.so.7
./lib/libalias_cuseeme.so
./lib/libalias_dummy.so
./lib/libalias_ftp.so
./lib/libalias_irc.so
./lib/libalias_nbt.so
./lib/libalias_pptp.so
./lib/libalias_skinny.so
./lib/libalias_smedia.so
./lib/libbegemot.so.4
./lib/libcam.so.5
./lib/libdevstat.so.7
./lib/libedit.so.7
./lib/libbsdxml.so.4
./lib/libgeom.so.5
./lib/libipsec.so.4
./lib/libipx.so.5
./lib/libjail.so.1
./lib/libkiconv.so.4
./lib/libpcap.so.7
./lib/libthr.so.3
./lib/libufs.so.5
./lib/libz.so.5
./lib/libgcc_s.so.1
./lib/libreadline.so.8
./lib/libssp.so.0
./lib/libcrypto.so.6
./libexec
./libexec/ld-elf.so.1
./libexec/ld-elf.so.1.old
./sbin
./sbin/adjkerntz
./sbin/atacontrol
./sbin/badsect
./sbin/bsdlabel
./sbin/camcontrol
./sbin/ccdconfig
./sbin/clri
./sbin/comcontrol
./sbin/conscontrol
./sbin/devd
./sbin/devfs
./sbin/dhclient
./sbin/dhclient-script
./sbin/dmesg
./sbin/dump
./sbin/rdump
./sbin/dumpfs
./sbin/dumpon
./sbin/fdisk
./sbin/ffsinfo
./sbin/fsck
./sbin/fsck_ffs
./sbin/fsck_ufs
./sbin/fsck_4.2bsd
./sbin/fsdb
./sbin/fsirand
./sbin/gbde
./sbin/fsck_msdosfs
./sbin/geom
./sbin/gcache
./sbin/gconcat
./sbin/geli
./sbin/gjournal
./sbin/glabel
./sbin/gmirror
./sbin/gmultipath
./sbin/gnop
./sbin/gpart
./sbin/graid3
./sbin/gshsec
./sbin/gstripe
./sbin/gvirstor
./sbin/ggatec
./sbin/ggated
./sbin/ggatel
./sbin/growfs
./sbin/gvinum
./sbin/ifconfig
./sbin/init
./sbin/ipf
./sbin/ipfs
./sbin/ipfstat
./sbin/ipftest
./sbin/ipmon
./sbin/ipnat
./sbin/ippool
./sbin/md5
./sbin/ipfw
./sbin/ipresend
./sbin/iscontrol
./sbin/kldconfig
./sbin/kldload
./sbin/kldstat
./sbin/kldunload
./sbin/ldconfig
./sbin/rmd160
./sbin/sha1
./sbin/sha256
./sbin/mdconfig
./sbin/mdmfs
./sbin/mount_mfs
./sbin/mknod
./sbin/mksnap_ffs
./sbin/mount
./sbin/mount_cd9660
./sbin/mount_msdosfs
./sbin/mount_nfs
./sbin/mount_newnfs
./sbin/mount_ntfs
./sbin/mount_nullfs
./sbin/mount_udf
./sbin/mount_unionfs
./sbin/natd
./sbin/ddb
./sbin/newfs
./sbin/newfs_msdos
./sbin/nfsiod
./sbin/nos-tun
./sbin/pfctl
./sbin/pflogd
./sbin/ping
./sbin/ping6
./sbin/quotacheck
./sbin/rcorder
./sbin/reboot
./sbin/nextboot
./sbin/halt
./sbin/fastboot
./sbin/fasthalt
./sbin/recoverdisk
./sbin/restore
./sbin/rrestore
./sbin/route
./sbin/routed
./sbin/rtquery
./sbin/rtsol
./sbin/savecore
./sbin/setkey
./sbin/shutdown
./sbin/spppcontrol
./sbin/swapon
./sbin/swapoff
./sbin/swapctl
./sbin/sysctl
./sbin/tunefs
./sbin/umount
./sbin/init.bak
./var
./var/crash
./var/crash/minfree
./var/db
./var/db/locate.database
./var/log
./var/log/sendmail.st
./var/named
./var/named/etc
./var/named/etc/namedb
./var/named/etc/namedb/master
./var/named/etc/namedb/master/empty.db
./var/named/etc/namedb/master/localhost-forward.db
./var/named/etc/namedb/master/localhost-reverse.db
./var/named/etc/namedb/named.conf
./var/named/etc/namedb/named.root
./var/yp
./var/yp/Makefile.dist
./var/run
./var/cron
./var/cron/tabs
./root
./root/.k5login
./root/.profile
./root/.cshrc
./root/.login
./list
./dev
./usr
./usr/sbin
./usr/sbin/newsyslog
./usr/sbin/syslogd
./usr/sbin/ip6addrctl
./usr/sbin/sendmail
./usr/sbin/cron
./usr/lib
./usr/lib/libpam.so.5
./usr/lib/libpam.so
./usr/lib/pam_opie.so.5
./usr/lib/libbsm.so.3
./usr/lib/libbsm.so
./usr/lib/pam_chroot.so.5
./usr/lib/pam_tacplus.so.5
./usr/lib/pam_ssh.so.5
./usr/lib/pam_self.so.5
./usr/lib/pam_securetty.so.5
./usr/lib/pam_rootok.so.5
./usr/lib/pam_rhosts.so.5
./usr/lib/pam_radius.so.5
./usr/lib/pam_permit.so.5
./usr/lib/pam_passwdqc.so.5
./usr/lib/libcom_err.so.5
./usr/lib/libcom_err.so
./usr/lib/pam_opieaccess.so.5
./usr/lib/pam_nologin.so.5
./usr/lib/libc.so.7
./usr/lib/pam_login_access.so.5
./usr/lib/pam_lastlog.so.5
./usr/lib/pam_ksu.so.5
./usr/lib/pam_krb5.so.5
./usr/lib/pam_guest.so.5
./usr/lib/pam_group.so.5
./usr/lib/pam_ftpusers.so.5
./usr/lib/pam_exec.so.5
./usr/lib/pam_echo.so.5
./usr/lib/pam_deny.so.5
./usr/lib/pam_unix.so.5
./usr/lib/pam_chroot.so
./usr/lib/libopie.so
./usr/lib/pam_deny.so
./usr/lib/pam_echo.so
./usr/lib/pam_exec.so
./usr/lib/pam_ftpusers.so
./usr/lib/pam_group.so
./usr/lib/pam_guest.so
./usr/lib/pam_krb5.so
./usr/lib/pam_ksu.so
./usr/lib/pam_lastlog.so
./usr/lib/pam_login_access.so
./usr/lib/pam_nologin.so
./usr/lib/pam_opie.so
./usr/lib/pam_opieaccess.so
./usr/lib/pam_passwdqc.so
./usr/lib/pam_permit.so
./usr/lib/pam_radius.so
./usr/lib/pam_rhosts.so
./usr/lib/pam_rootok.so
./usr/lib/pam_securetty.so
./usr/lib/pam_self.so
./usr/lib/pam_ssh.so
./usr/lib/pam_tacplus.so
./usr/lib/pam_unix.so
./usr/lib/libmd.so.5
./usr/lib/libbz2.so.4
./usr/lib/libgnuregex.so.5
./usr/lib/libypclnt.so.4
./usr/bin
./usr/bin/mktemp
./usr/bin/login
./usr/bin/uname
./usr/bin/awk
./usr/bin/logger
./usr/bin/grep
./usr/bin/ftp
./usr/libexec
./usr/libexec/getty

110
sys/mips/rmi/shared_structs.h Executable file
View File

@ -0,0 +1,110 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#ifndef _SHARED_STRUCTS_H
#define _SHARED_STRUCTS_H
/* If you make any changes to the below structs, shared_structs_offsets.h
* should be regenerated
*/
#define BOOT1_INFO_VERSION 0x0001
struct boot1_info {
uint64_t boot_level;
uint64_t io_base;
uint64_t output_device;
uint64_t uart_print;
uint64_t led_output;
uint64_t init;
uint64_t exit;
uint64_t warm_reset;
uint64_t wakeup;
uint64_t cpu_online_map;
uint64_t master_reentry_sp;
uint64_t master_reentry_gp;
uint64_t master_reentry_fn;
uint64_t slave_reentry_fn;
uint64_t magic_dword;
uint64_t uart_putchar;
uint64_t size;
uint64_t uart_getchar;
uint64_t nmi_handler;
uint64_t psb_version;
uint64_t mac_addr;
uint64_t cpu_frequency;
uint64_t board_version;
uint64_t malloc;
uint64_t free;
uint64_t alloc_pbuf;
uint64_t free_pbuf;
uint64_t psb_os_cpu_map;
uint64_t userapp_cpu_map;
uint64_t wakeup_os;
uint64_t psb_mem_map;
uint64_t board_major_version;
uint64_t board_minor_version;
uint64_t board_manf_revision;
uint64_t board_serial_number;
uint64_t psb_physaddr_map;
};
extern struct boot1_info xlr_boot1_info;
/* This structure is passed to all applications launched from the linux
loader through K0 register
*/
#define XLR_LOADER_INFO_MAGIC 0x600ddeed
struct xlr_loader_info {
uint32_t magic;
/* xlr_loader_shared_struct_t for CPU 0 will start here */
unsigned long sh_mem_start;
/* Size of the shared memory b/w linux apps and rmios apps */
uint32_t app_sh_mem_size;
};
/* Boot loader uses the linux mips convention */
#define BOOT1_MEMMAP_MAX 32
enum xlr_phys_memmap_t {
BOOT1_MEM_RAM = 1, BOOT1_MEM_ROM_DATA, BOOT1_MEM_RESERVED
};
struct xlr_boot1_mem_map {
uint32_t num_entries;
struct {
uint64_t addr;
uint64_t size;
uint32_t type;
uint32_t pad;
} physmem_map[BOOT1_MEMMAP_MAX];
};
#endif

View File

@ -0,0 +1,54 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
/* DO NOT EDIT THIS FILE
* This file has been autogenerated by ./gen_struct_offsets
*/
#ifndef _SHARED_STRUCTS_FUNC_H
#define _SHARED_STRUCTS_FUNC_H
/* struct boot1_info function prototypes */
#define boot1_info_uart_print_func(info_ptr, ...) ((void (*)(const char *, ...))(unsigned long)(info_ptr->uart_print))( __VA_ARGS__ )
#define boot1_info_led_output_func(info_ptr, ...) ((void (*)(int))(unsigned long)(info_ptr->led_output))( __VA_ARGS__ )
#define boot1_info_init_func(info_ptr, ...) ((void (*)(void))(unsigned long)(info_ptr->init))( __VA_ARGS__ )
#define boot1_info_exit_func(info_ptr, ...) ((void (*)(void))(unsigned long)(info_ptr->exit))( __VA_ARGS__ )
#define boot1_info_warm_reset_func(info_ptr, ...) ((void (*)(void))(unsigned long)(info_ptr->warm_reset))( __VA_ARGS__ )
#define boot1_info_wakeup_func(info_ptr, ...) ((int (*)(void *, void *, unsigned int))(unsigned long)(info_ptr->wakeup))( __VA_ARGS__ )
#define boot1_info_master_reentry_fn_func(info_ptr, ...) ((void (*)(void *))(unsigned long)(info_ptr->master_reentry_fn))( __VA_ARGS__ )
#define boot1_info_slave_reentry_fn_func(info_ptr, ...) ((void (*)(void *))(unsigned long)(info_ptr->slave_reentry_fn))( __VA_ARGS__ )
#define boot1_info_uart_putchar_func(info_ptr, ...) ((void (*)(char))(unsigned long)(info_ptr->uart_putchar))( __VA_ARGS__ )
#define boot1_info_uart_getchar_func(info_ptr, ...) ((char (*)(void))(unsigned long)(info_ptr->uart_getchar))( __VA_ARGS__ )
#define boot1_info_malloc_func(info_ptr, ...) ((void *(*)(size_t))(unsigned long)(info_ptr->malloc))( __VA_ARGS__ )
#define boot1_info_free_func(info_ptr, ...) ((void (*)(void *))(unsigned long)(info_ptr->free))( __VA_ARGS__ )
#define boot1_info_alloc_pbuf_func(info_ptr, ...) ((struct packet *(*)(void))(unsigned long)(info_ptr->alloc_pbuf))( __VA_ARGS__ )
#define boot1_info_free_pbuf_func(info_ptr, ...) ((void (*)(struct packet *))(unsigned long)(info_ptr->free_pbuf))( __VA_ARGS__ )
#define boot1_info_wakeup_os_func(info_ptr, ...) ((int (*)(void *, void *, unsigned int))(unsigned long)(info_ptr->wakeup_os))( __VA_ARGS__ )
#endif

View File

@ -0,0 +1,76 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
/* DO NOT EDIT THIS FILE
* This file has been autogenerated by ./gen_struct_offsets
*/
#ifndef _SHARED_STRUCTS_OFFSETS_H
#define _SHARED_STRUCTS_OFFSETS_H
/* struct boot1_info offsets */
#define boot1_info_boot_level_off 0
#define boot1_info_io_base_off 8
#define boot1_info_output_device_off 16
#define boot1_info_uart_print_off 24
#define boot1_info_led_output_off 32
#define boot1_info_init_off 40
#define boot1_info_exit_off 48
#define boot1_info_warm_reset_off 56
#define boot1_info_wakeup_off 64
#define boot1_info_cpu_online_map_off 72
#define boot1_info_master_reentry_sp_off 80
#define boot1_info_master_reentry_gp_off 88
#define boot1_info_master_reentry_fn_off 96
#define boot1_info_slave_reentry_fn_off 104
#define boot1_info_magic_dword_off 112
#define boot1_info_uart_putchar_off 120
#define boot1_info_size_off 128
#define boot1_info_uart_getchar_off 136
#define boot1_info_nmi_handler_off 144
#define boot1_info_psb_version_off 152
#define boot1_info_mac_addr_off 160
#define boot1_info_cpu_frequency_off 168
#define boot1_info_board_version_off 176
#define boot1_info_malloc_off 184
#define boot1_info_free_off 192
#define boot1_info_alloc_pbuf_off 200
#define boot1_info_free_pbuf_off 208
#define boot1_info_psb_os_cpu_map_off 216
#define boot1_info_userapp_cpu_map_off 224
#define boot1_info_wakeup_os_off 232
#define boot1_info_psb_mem_map_off 240
/* struct boot1_info size */
#define boot1_info_size 248
/* boot1_info version */
#define boot1_info_version 1
#endif

10
sys/mips/rmi/std.xlr Normal file
View File

@ -0,0 +1,10 @@
# $FreeBSD$
files "../rmi/files.xlr"
#
# XXXMIPS: It's a stub, isn't it?
#
cpu CPU_MIPS4KC
option NOFPU
# Kludge for now
options TARGET_XLR_XLS

113
sys/mips/rmi/tick.c Normal file
View File

@ -0,0 +1,113 @@
/*-
* Copyright (c) 2006-2009 RMI Corporation
* Copyright (c) 2006 Bruce M. Simpson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Simple driver for the 32-bit interval counter built in to all
* MIPS32 CPUs.
* XXX: For calibration this either needs an external clock, or
* to be explicitly told what the frequency is.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <sys/timetc.h>
#include <sys/kernel.h>
#include <sys/power.h>
#include <sys/smp.h>
#include <machine/clock.h>
#include <machine/locore.h>
#include <machine/md_var.h>
#include <machine/hwfunc.h>
struct timecounter counter_timecounter = {
platform_get_timecount, /* get_timecount */
0, /* no poll_pps */
~0u, /* counter_mask */
0, /* frequency */
"MIPS32", /* name */
800, /* quality (adjusted in code) */
};
void tick_init(void);
void
tick_init(void)
{
counter_freq = platform_get_frequency();
if (bootverbose)
printf("MIPS32 clock: %u MHz", cpu_clock);
counter_timecounter.tc_frequency = counter_freq;
tc_init(&counter_timecounter);
}
void
cpu_startprofclock(void)
{
/* nothing to do */
}
void
cpu_stopprofclock(void)
{
/* nothing to do */
}
static int
sysctl_machdep_counter_freq(SYSCTL_HANDLER_ARGS)
{
int error;
uint64_t freq;
/*
* RRS wonders if this will really work. You don't change the req of
* the system here, it would require changes to the RMI PIC in order
* to get the TC to run at a differrent frequency.
*/
if (counter_timecounter.tc_frequency == 0)
return (EOPNOTSUPP);
freq = counter_freq;
error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
if (error == 0 && req->newptr != NULL) {
counter_freq = freq;
counter_timecounter.tc_frequency = counter_freq;
}
return (error);
}
SYSCTL_PROC(_machdep, OID_AUTO, counter_freq, CTLTYPE_QUAD | CTLFLAG_RW,
0, sizeof(u_int), sysctl_machdep_counter_freq, "IU", "");

View File

@ -0,0 +1,80 @@
/*-
* Copyright (c) 2006 Raza Microelectronics
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/dev/uart/uart_bus_iodi.c,v 1.6.2.5 2006/02/15 09:16:01 marius Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <machine/resource.h>
#include <mips/rmi/iomap.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_cpu.h>
static int uart_iodi_probe(device_t dev);
static device_method_t uart_iodi_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, uart_iodi_probe),
DEVMETHOD(device_attach, uart_bus_attach),
DEVMETHOD(device_detach, uart_bus_detach),
{0, 0}
};
static driver_t uart_iodi_driver = {
uart_driver_name,
uart_iodi_methods,
sizeof(struct uart_softc),
};
extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
static int
uart_iodi_probe(device_t dev)
{
struct uart_softc *sc;
sc = device_get_softc(dev);
sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs);
sc->sc_class = &uart_ns8250_class;
bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
sc->sc_sysdev->bas.bst = rmi_bus_space;
sc->sc_sysdev->bas.bsh = MIPS_PHYS_TO_KSEG1(XLR_UART0ADDR);
sc->sc_bas.bst = rmi_bus_space;
sc->sc_bas.bsh = MIPS_PHYS_TO_KSEG1(XLR_UART0ADDR);
/* regshft = 2, rclk = 66000000, rid = 0, chan = 0 */
return (uart_bus_probe(dev, 2, 66000000, 0, 0));
}
DRIVER_MODULE(uart, iodi, uart_iodi_driver, uart_devclass, 0, 0);

View File

@ -0,0 +1,84 @@
/*-
* Copyright (c) 2006 Wojciech A. Koszek <wkoszek@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: uart_cpu_mips_xlr.c,v 1.5 2008-07-16 20:22:39 jayachandranc Exp $
*/
/*
* Skeleton of this file was based on respective code for ARM
* code written by Olivier Houchard.
*/
/*
* XLRMIPS: This file is hacked from arm/...
*/
#include "opt_uart.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <mips/rmi/iomap.h>
bus_space_tag_t uart_bus_space_io;
bus_space_tag_t uart_bus_space_mem;
int
uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
{
return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
}
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
di->ops = uart_getops(&uart_ns8250_class);
di->bas.chan = 0;
di->bas.bst = rmi_bus_space;
di->bas.bsh = MIPS_PHYS_TO_KSEG1(XLR_UART0ADDR);
di->bas.regshft = 2;
/* divisor = rclk / (baudrate * 16); */
di->bas.rclk = 66000000;
di->baudrate = 0;
di->databits = 8;
di->stopbits = 1;
di->parity = UART_PARITY_NONE;
uart_bus_space_io = NULL;
uart_bus_space_mem = rmi_bus_space;
return (0);
}

View File

@ -0,0 +1,113 @@
/*-
* Copyright (c) 2006 Wojciech A. Koszek <wkoszek@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: xlr_boot1_console.c,v 1.6 2008-07-16 20:22:49 jayachandranc Exp $
*/
/*
* Adapted for XLR bootloader
* RMi
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_comconsole.h"
#include <sys/param.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/types.h>
#include <sys/conf.h>
#include <sys/cons.h>
#include <sys/consio.h>
#include <sys/tty.h>
#include <mips/rmi/xlrconfig.h>
#include <mips/rmi/shared_structs.h>
#include <mips/rmi/shared_structs_func.h>
#include <ddb/ddb.h>
#if 0
static cn_probe_t xlr_boot1_cnprobe;
static cn_init_t xlr_boot1_cninit;
static cn_term_t xlr_boot1_cnterm;
static cn_getc_t xlr_boot1_cngetc;
static cn_checkc_t xlr_boot1_cncheckc;
static cn_putc_t xlr_boot1_cnputc;
CONS_DRIVER(xlrboot, xlr_boot1_cnprobe, xlr_boot1_cninit, xlr_boot1_cnterm, xlr_boot1_cngetc,
xlr_boot1_cncheckc, xlr_boot1_cnputc, NULL);
/*
* Device gets probed. Firmwire should be checked here probably.
*/
static void
xlr_boot1_cnprobe(struct consdev *cp)
{
cp->cn_pri = CN_NORMAL;
cp->cn_tp = NULL;
cp->cn_arg = NULL; /* softc */
cp->cn_unit = -1; /* ? */
cp->cn_flags = 0;
}
/*
* Initialization.
*/
static void
xlr_boot1_cninit(struct consdev *cp)
{
sprintf(cp->cn_name, "boot1");
}
static void
xlr_boot1_cnterm(struct consdev *cp)
{
cp->cn_pri = CN_DEAD;
cp->cn_flags = 0;
return;
}
static int
xlr_boot1_cngetc(struct consdev *cp)
{
return boot1_info_uart_getchar_func(&xlr_boot1_info);
}
static void
xlr_boot1_cnputc(struct consdev *cp, int c)
{
boot1_info_uart_putchar_func(&xlr_boot1_info, c);
}
static int
xlr_boot1_cncheckc(struct consdev *cp)
{
return 0;
}
#endif

View File

@ -0,0 +1,217 @@
#include <machine/asm.h>
/*
* a0: source address
* a1: length of the area to checksum
* a2: partial checksum
* a3: dst
*/
#define src a0
#define dst a3
#define sum v0
.text
.set noreorder
.macro CSUM_BIGCHUNK_AND_COPY offset
pref 0, (\offset+0x0)(a0)
ld t0, (\offset+0x00)(a0)
ld t1, (\offset+0x08)(a0)
.word 0x70481038 /*daddwc v0, v0, t0 */
.word 0x70491038 /*daddwc v0, v0, t1 */
ld t0, (\offset + 0x10)(a0)
ld t1, (\offset + 0x18)(a0)
.word 0x70481038 /* daddwc v0, v0, t0 */
.word 0x70491038 /*daddwc v0, v0, t1 */
.endm
small_csumcpy: /* unknown src alignment and < 8 bytes to go */
move a1, t2
andi t0, a1, 4
beqz t0, 1f
andi t0, a1, 2
ulw t1, (src) /* Still a full word to go */
daddiu src, 4
.word 0x70491038 /*daddwc v0, v0, t1 */
1: move t1, zero
beqz t0, 1f
andi t0, a1, 1
ulhu t1, (src) /* Still a halfword to go */
daddiu src, 2
1: beqz t0, 1f
sll t1, t1, 16
lbu t2, (src)
nop
#ifdef __MIPSEB__
sll t2, t2, 8
#endif
or t1, t2
1: .word 0x70491038 /*daddwc v0, v0, t1 */
.word 0x70461038 /*daddwc v0, v0, a2 */
.word 0x70401038 /*daddwc v0, v0, $0 */
/* Ideally at this point of time the status flag must be cleared */
dsll32 v1, sum, 0
.word 0x70431038 /*daddwc v0, v0, v1 */
dsrl32 sum, sum, 0
.word 0x70401038 /*daddwc v0, v0, zero */
/* fold the checksum */
sll v1, sum, 16
addu sum, v1
sltu v1, sum, v1
srl sum, sum, 16
addu sum, v1
1:
.set reorder
jr ra
.set noreorder
/* ------------------------------------------------------------------ */
.align 5
LEAF(xlr_csum_partial_nocopy)
move sum, zero
move t7, zero
sltiu t8, a1, 0x8
bnez t8, small_csumcpy /* < 8 bytes to copy */
move t2, a1
beqz a1, out
andi t7, src, 0x1 /* odd buffer? */
hword_align:
beqz t7, word_align
andi t8, src, 0x2
lbu t0, (src)
dsubu a1, a1, 0x1
.word 0x70481038 /*daddwc v0, v0, t0 */
daddu src, src, 0x1
andi t8, src, 0x2
word_align:
beqz t8, dword_align
sltiu t8, a1, 56
lhu t0, (src)
dsubu a1, a1, 0x2
.word 0x70481038 /*daddwc v0, v0, t0 */
sltiu t8, a1, 56
daddu src, src, 0x2
dword_align:
bnez t8, do_end_words
move t8, a1
andi t8, src, 0x4
beqz t8, qword_align
andi t8, src, 0x8
lw t0, 0x00(src)
dsubu a1, a1, 0x4
.word 0x70481038 /*daddwc v0, v0, t0 */
daddu src, src, 0x4
andi t8, src, 0x8
qword_align:
beqz t8, oword_align
andi t8, src, 0x10
ld t0, 0x00(src)
dsubu a1, a1, 0x8
.word 0x70481038 /*daddwc v0, v0, t0 */
daddu src, src, 0x8
andi t8, src, 0x10
oword_align:
beqz t8, begin_movement
dsrl t8, a1, 0x7
ld t3, 0x08(src)
ld t0, 0x00(src)
.word 0x704b1038 /*daddwc v0, v0, t3 */
.word 0x70481038 /*daddwc v0, v0, t0 */
dsubu a1, a1, 0x10
daddu src, src, 0x10
dsrl t8, a1, 0x7
begin_movement:
beqz t8, 1f
andi t2, a1, 0x40
move_128bytes:
pref 0, 0x20(a0)
pref 0, 0x40(a0)
pref 0, 0x60(a0)
CSUM_BIGCHUNK_AND_COPY(0x00)
CSUM_BIGCHUNK_AND_COPY(0x20)
CSUM_BIGCHUNK_AND_COPY(0x40)
CSUM_BIGCHUNK_AND_COPY(0x60)
dsubu t8, t8, 0x01
bnez t8, move_128bytes /* flag */
daddu src, src, 0x80
1:
beqz t2, 1f
andi t2, a1, 0x20
move_64bytes:
pref 0, 0x20(a0)
pref 0, 0x40(a0)
CSUM_BIGCHUNK_AND_COPY(0x00)
CSUM_BIGCHUNK_AND_COPY(0x20)
daddu src, src, 0x40
1:
beqz t2, do_end_words
andi t8, a1, 0x1c
move_32bytes:
pref 0, 0x20(a0)
CSUM_BIGCHUNK_AND_COPY(0x00)
andi t8, a1, 0x1c
daddu src, src, 0x20
do_end_words:
beqz t8, maybe_end_cruft
dsrl t8, t8, 0x2
end_words:
lw t0, (src)
dsubu t8, t8, 0x1
.word 0x70481038 /*daddwc v0, v0, t0 */
bnez t8, end_words
daddu src, src, 0x4
maybe_end_cruft:
andi t2, a1, 0x3
small_memcpy:
j small_csumcpy; move a1, t2
beqz t2, out
move a1, t2
end_bytes:
lb t0, (src)
dsubu a1, a1, 0x1
bnez a2, end_bytes
daddu src, src, 0x1
out:
jr ra
move v0, sum
END(xlr_csum_partial_nocopy)

455
sys/mips/rmi/xlr_i2c.c Normal file
View File

@ -0,0 +1,455 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/mips/xlr/xlr_i2c.c,v 1.20.8.1 2008/08/25 23:17:51 cognet Exp $");
/*
* I2C driver for the Palm-BK3220 I2C Host adapter on the RMI XLR.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <dev/iicbus/iiconf.h>
#include <dev/iicbus/iicbus.h>
#include <mips/rmi/iomap.h>
#include <mips/include/resource.h>
#include "iicbus_if.h"
#define DEVTOIICBUS(dev) ((struct iicbus_device*)device_get_ivars(dev))
#define I2C_PALM_CFG 0x00
#define I2C_PALM_CLKDIV 0x01
#define I2C_PALM_DEVADDR 0x02
#define I2C_PALM_ADDR 0x03
#define I2C_PALM_DATAOUT 0x04
#define I2C_PALM_DATAIN 0x05
#define I2C_PALM_STATUS 0x06
#define I2C_PALM_STARTXFR 0x07
#define I2C_PALM_BYTECNT 0x08
#define I2C_PALM_HDSTATIM 0x09
/* TEST Values!! Change as required */
#define I2C_PALM_CFG_DEF 0x000000F8 /* 8-Bit Addr + POR Values */
#define I2C_PALM_CLKDIV_DEF 0x14A //0x00000052
#define I2C_PALM_HDSTATIM_DEF 0x107 //0x00000000
#define I2C_PALM_STARTXFR_RD 0x00000001
#define I2C_PALM_STARTXFR_WR 0x00000000
#define PHOENIX_IO_I2C_0_OFFSET 0x16000
#define PHOENIX_IO_I2C_1_OFFSET 0x17000
#define ARIZONA_I2c_BUS 1
int bus = 1;
uint8_t current_slave;
uint8_t read_address;
static xlr_reg_t *iobase_i2c_regs;
static devclass_t xlr_i2c_devclass;
/*
* Device methods
*/
static int xlr_i2c_probe(device_t);
static int xlr_i2c_attach(device_t);
static int xlr_i2c_detach(device_t);
static int xlr_i2c_start(device_t dev, u_char slave, int timeout);
static int xlr_i2c_stop(device_t dev);
static int xlr_i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay);
static int xlr_i2c_write(device_t dev, char *buf, int len, int *sent, int timeout);
struct xlr_i2c_softc {
device_t dev; /* Myself */
struct resource *mem_res; /* Memory resource */
volatile int flags;
#define RXRDY 4
#define TXRDY 0x10
int sc_started;
int twi_addr;
device_t iicbus;
};
#define MDELAY(a){ \
unsigned long local_loop = 0xfffff; \
while(local_loop--); \
}\
static void
get_i2c_base(void)
{
if (bus == 0)
iobase_i2c_regs = xlr_io_mmio(PHOENIX_IO_I2C_0_OFFSET);
else
iobase_i2c_regs = xlr_io_mmio(PHOENIX_IO_I2C_1_OFFSET);
return;
}
static void
palm_write(int reg, int value)
{
get_i2c_base();
xlr_write_reg(iobase_i2c_regs, reg, value);
return;
}
static int
palm_read(int reg)
{
uint32_t val;
get_i2c_base();
val = xlr_read_reg(iobase_i2c_regs, reg);
return ((int)val);
}
static int
palm_addr_only(uint8_t addr, uint8_t offset)
{
volatile uint32_t regVal = 0x00;
palm_write(I2C_PALM_ADDR, offset);
palm_write(I2C_PALM_DEVADDR, addr);
palm_write(I2C_PALM_CFG, 0xfa);
palm_write(I2C_PALM_STARTXFR, 0x02);
regVal = palm_read(I2C_PALM_STATUS);
if (regVal & 0x0008) {
printf("palm_addr_only: ACKERR. Aborting...\n");
return -1;
}
return 0;
}
static int
palm_rx(uint8_t addr, uint8_t offset, uint8_t len,
uint8_t * buf)
{
volatile uint32_t regVal = 0x00, ctr = 0x00;
int timeOut, numBytes = 0x00;
palm_write(I2C_PALM_CFG, 0xfa);
palm_write(I2C_PALM_BYTECNT, len);
palm_write(I2C_PALM_DEVADDR, addr);
//DEVADDR = 0x4c, 0x68
MDELAY(1);
for (numBytes = 0x00; numBytes < len; numBytes++) {
palm_write(I2C_PALM_ADDR, offset + numBytes);
//I2C_PALM_ADDR:offset
MDELAY(1);
if (!ctr) {
/* Trigger a READ Transaction */
palm_write(I2C_PALM_STARTXFR, I2C_PALM_STARTXFR_RD);
ctr++;
}
/* Error Conditions [Begin] */
regVal = palm_read(I2C_PALM_STATUS);
MDELAY(1);
if (regVal & 0x0008) {
printf("palm_rx: ACKERR. Aborting...\n");
return -1;
}
timeOut = 10;
while ((regVal & 0x0030) && timeOut--) {
palm_write(I2C_PALM_STARTXFR, I2C_PALM_STARTXFR_RD);
regVal = palm_read(I2C_PALM_STATUS);
}
if (timeOut == 0x00) {
printf("palm_rx: TimedOut on Valid STARTXFR/Arbitration\n");
return -1;
}
timeOut = 10;
/* Do we have valid data from the device yet..? */
regVal &= 0x0004;
while (!regVal && timeOut--) {
regVal = palm_read(I2C_PALM_STATUS) & 0x0004;
}
if (timeOut == 0x00) {
printf("palm_rx: TimedOut Waiting for Valid Data\n");
return -1;
}
/* Error Conditions [End] */
/* Read the data */
buf[numBytes] = (uint8_t) palm_read(I2C_PALM_DATAIN);
}
return 0;
}
static int
wait_for_idle(void)
{
int timeOut = 0x1000;
volatile uint32_t regVal = 0x00;
regVal = palm_read(I2C_PALM_STATUS) & 0x0001;
while (regVal && timeOut--) {
regVal = palm_read(I2C_PALM_STATUS) & 0x0001;
}
if (timeOut == 0x00)
return -1; /* Timed Out */
else
return 0;
}
static int
palm_tx(uint8_t addr, uint8_t offset, uint8_t * buf, uint8_t len)
{
volatile uint32_t regVal = 0x00;
int timeOut, ctr = 0x00, numBytes = len;
for (ctr = 0x00; ctr < len; ctr++) {
if (wait_for_idle() < 0) {
printf("TimedOut on Waiting for I2C Bus Idle.\n");
return -EIO;
}
palm_write(I2C_PALM_CFG, 0xF8);
palm_write(I2C_PALM_BYTECNT, 0x00);
palm_write(I2C_PALM_DEVADDR, addr);
//0x4c, 0x68
palm_write(I2C_PALM_ADDR, offset + numBytes - 1);
//offset
palm_write(I2C_PALM_DATAOUT, buf[ctr]);
palm_write(I2C_PALM_STARTXFR, I2C_PALM_STARTXFR_WR);
MDELAY(1);
regVal = palm_read(I2C_PALM_STATUS);
MDELAY(1);
if (regVal & 0x0008) {
printf("palm_tx: ACKERR. Aborting...\n");
return -1;
}
timeOut = 0x1000;
while (!(regVal & 0x0002) && timeOut) {
regVal = palm_read(I2C_PALM_STATUS);
timeOut--;
}
if (timeOut == 0x00) {
printf("palm_tx: [TimeOut] SDOEMPTY Not Set\n");
return -1;
}
timeOut = 1000;
while ((regVal & 0x0030) && timeOut) {
palm_write(I2C_PALM_STARTXFR, I2C_PALM_STARTXFR_WR);
regVal = palm_read(I2C_PALM_STATUS);
timeOut--;
}
if (timeOut == 0x00) {
printf("palm_rx: TimedOut on Valid STARTXFR/Arbitration\n");
return -1;
}
numBytes--;
}
return 0;
}
static int
xlr_i2c_probe(device_t dev)
{
device_set_desc(dev, "I2C bus controller");
return (0);
}
/*
* We add all the devices which we know about.
* The generic attach routine will attach them if they are alive.
*/
static int
xlr_i2c_attach(device_t dev)
{
struct xlr_i2c_softc *sc;
int rid;
sc = device_get_softc(dev);
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
RF_ACTIVE);
if (sc->mem_res == NULL) {
printf("not able to allocate the bus resource\n");
}
if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL)
printf("could not allocate iicbus instance\n");
bus_generic_attach(dev);
return (0);
}
static int
xlr_i2c_detach(device_t dev)
{
bus_generic_detach(dev);
return (0);
}
/*
static int
xlr_i2c_add_child(device_t dev, int order, const char *name, int unit)
{
printf("********* %s ******** \n", __FUNCTION__);
device_add_child_ordered(dev, order, name, unit);
bus_generic_attach(dev);
return (0);
}
*/
static int
xlr_i2c_start(device_t dev, u_char slave, int timeout)
{
int error = 0;
struct xlr_i2c_softc *sc;
sc = device_get_softc(dev);
sc->sc_started = 1;
current_slave = (slave >> 1);
return error;
}
static int
xlr_i2c_stop(device_t dev)
{
int error = 0;
return error;
}
static int
xlr_i2c_read(device_t dev, char *buf, int len, int *read, int last,
int delay)
{
int error = 0;
if (palm_addr_only(current_slave, read_address) == -1) {
printf("I2C ADDRONLY Phase Fail.\n");
return -1;
}
if (palm_rx(current_slave, read_address, len, buf) == -1) {
printf("I2C Read Fail.\n");
return -1;
}
*read = len;
return error;
}
static int
xlr_i2c_write(device_t dev, char *buf, int len, int *sent, int timeout /* us */ )
{
int error = 0;
uint8_t write_address;
if (len == 1) {
/* address for the next read */
read_address = buf[0];
return error;
}
if (len < 2)
return (-1);
write_address = buf[0];
/*
* for write operation, buf[0] contains the register offset and
* buf[1] onwards contains the value
*/
palm_tx(current_slave, write_address, &buf[1], len - 1);
return error;
}
static int
xlr_i2c_callback(device_t dev, int index, caddr_t *data)
{
return 0;
}
static int
xlr_i2c_repeated_start(device_t dev, u_char slave, int timeout)
{
return 0;
}
static device_method_t xlr_i2c_methods[] = {
/* device interface */
DEVMETHOD(device_probe, xlr_i2c_probe),
DEVMETHOD(device_attach, xlr_i2c_attach),
DEVMETHOD(device_detach, xlr_i2c_detach),
/* iicbus interface */
DEVMETHOD(iicbus_callback, xlr_i2c_callback),
DEVMETHOD(iicbus_repeated_start, xlr_i2c_repeated_start),
DEVMETHOD(iicbus_start, xlr_i2c_start),
DEVMETHOD(iicbus_stop, xlr_i2c_stop),
DEVMETHOD(iicbus_write, xlr_i2c_write),
DEVMETHOD(iicbus_read, xlr_i2c_read),
{0, 0}
};
static driver_t xlr_i2c_driver = {
"xlr_i2c",
xlr_i2c_methods,
sizeof(struct xlr_i2c_softc),
};
DRIVER_MODULE(xlr_i2c, iodi, xlr_i2c_driver, xlr_i2c_devclass, 0, 0);

726
sys/mips/rmi/xlr_machdep.c Normal file
View File

@ -0,0 +1,726 @@
/*-
* Copyright (c) 2006-2009 RMI Corporation
* Copyright (c) 2002-2004 Juli Mallett <jmallett@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/rtprio.h>
#include <sys/systm.h>
#include <sys/interrupt.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
#include <sys/ktr.h>
#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/random.h>
#include <sys/resourcevar.h>
#include <sys/sched.h>
#include <sys/sysctl.h>
#include <sys/unistd.h>
#include <sys/cons.h> /* cinit() */
#include <sys/kdb.h>
#include <sys/reboot.h>
#include <sys/queue.h>
#include <sys/smp.h>
#include <sys/timetc.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/cpuinfo.h>
#include <machine/cpuregs.h>
#include <machine/frame.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/asm.h>
#include <machine/pmap.h>
#include <machine/trap.h>
#include <machine/clock.h>
#include <machine/fls64.h>
#include <machine/intr_machdep.h>
#include <machine/smp.h>
#include <mips/rmi/rmi_mips_exts.h>
#include <mips/rmi/iomap.h>
#include <mips/rmi/clock.h>
#include <mips/rmi/msgring.h>
#include <mips/rmi/xlrconfig.h>
#include <mips/rmi/interrupt.h>
#include <mips/rmi/pic.h>
#ifdef XLR_PERFMON
#include <mips/rmi/perfmon.h>
#endif
void platform_prep_smp_launch(void);
unsigned long xlr_io_base = (unsigned long)(DEFAULT_XLR_IO_BASE);
/* 4KB static data aread to keep a copy of the bootload env until
the dynamic kenv is setup */
char boot1_env[4096];
extern unsigned long _gp;
int rmi_spin_mutex_safe=0;
/*
* Parameters from boot loader
*/
struct boot1_info xlr_boot1_info;
struct xlr_loader_info xlr_loader_info; /* FIXME : Unused */
int xlr_run_mode;
int xlr_argc;
char **xlr_argv, **xlr_envp;
uint64_t cpu_mask_info;
uint32_t xlr_online_cpumask;
#ifdef SMP
static unsigned long xlr_secondary_gp[MAXCPU];
static unsigned long xlr_secondary_sp[MAXCPU];
#endif
extern int mips_cpu_online_mask;
extern int mips_cpu_logical_mask;
uint32_t cpu_ltop_map[MAXCPU];
uint32_t cpu_ptol_map[MAXCPU];
uint32_t xlr_core_cpu_mask = 0x1; /* Core 0 thread 0 is always there */
void
platform_reset(void)
{
/* FIXME : use proper define */
u_int32_t *mmio = (u_int32_t *) 0xbef18000;
printf("Rebooting the system now\n");
mmio[8] = 0x1;
}
void
platform_secondary_init(void)
{
#ifdef SMP
xlr_msgring_cpu_init();
/* Setup interrupts for secondary CPUs here */
mips_mask_hard_irq(IPI_SMP_CALL_FUNCTION);
mips_mask_hard_irq(IPI_STOP);
mips_mask_hard_irq(IPI_RENDEZVOUS);
mips_mask_hard_irq(IPI_AST);
mips_mask_hard_irq(IRQ_TIMER);
#ifdef XLR_PERFMON
mips_mask_hard_irq(IPI_PERFMON);
#endif
return;
#endif
}
int xlr_asid_pcpu = 256; /* This the default */
int xlr_shtlb_enabled = 0;
/* This function sets up the number of tlb entries available
to the kernel based on the number of threads brought up.
The ASID range also gets divided similarly.
THE NUMBER OF THREADS BROUGHT UP IN EACH CORE MUST BE THE SAME
NOTE: This function will mark all 64TLB entries as available
to the threads brought up in the core. If kernel is brought with say mask
0x33333333, no TLBs will be available to the threads in each core.
*/
static void
setup_tlb_resource(void)
{
int mmu_setup;
int value = 0;
uint32_t cpu_map = xlr_boot1_info.cpu_online_map;
uint32_t thr_mask = cpu_map >> (xlr_cpu_id() << 2);
uint8_t core0 = xlr_boot1_info.cpu_online_map & 0xf;
uint8_t core_thr_mask;
int i = 0, count = 0;
/* If CPU0 did not enable shared TLB, other cores need to follow */
if ((xlr_cpu_id() != 0) && (xlr_shtlb_enabled == 0))
return;
/* First check if each core is brought up with the same mask */
for (i = 1; i < 8; i++) {
core_thr_mask = cpu_map >> (i << 2);
core_thr_mask &= 0xf;
if (core_thr_mask && core_thr_mask != core0) {
printf
("Each core must be brought with same cpu mask\n");
printf("Cannot enabled shared TLB. ");
printf("Falling back to split TLB mode\n");
return;
}
}
xlr_shtlb_enabled = 1;
for (i = 0; i < 4; i++)
if (thr_mask & (1 << i))
count++;
switch (count) {
case 1:
xlr_asid_pcpu = 256;
break;
case 2:
xlr_asid_pcpu = 128;
value = 0x2;
break;
default:
xlr_asid_pcpu = 64;
value = 0x3;
break;
}
mmu_setup = read_32bit_phnx_ctrl_reg(4, 0);
mmu_setup = mmu_setup & ~0x06;
mmu_setup |= (value << 1);
/* turn on global mode */
mmu_setup |= 0x01;
write_32bit_phnx_ctrl_reg(4, 0, mmu_setup);
}
/*
* Platform specific register setup for CPUs
* XLR has control registers accessible with MFCR/MTCR instructions, this
* code initialized them from the environment variable xlr.cr of form:
* xlr.cr=reg:val[,reg:val]*, all values in hex.
* To enable shared TLB option use xlr.shtlb=1
*/
void
platform_cpu_init()
{
char *hw_env;
char *start, *end;
uint32_t reg, val;
int thr_id = xlr_thr_id();
if (thr_id == 0) {
if ((hw_env = getenv("xlr.shtlb")) != NULL) {
start = hw_env;
reg = strtoul(start, &end, 16);
if (start != end && reg != 0)
setup_tlb_resource();
} else {
/* By default TLB entries are shared in a core */
setup_tlb_resource();
}
}
if ((hw_env = getenv("xlr.cr")) == NULL)
return;
start = hw_env;
while (*start != '\0') {
reg = strtoul(start, &end, 16);
if (start == end) {
printf("Invalid value in xlr.cr %s, cannot read a hex value at %d\n",
hw_env, start - hw_env);
goto err_return;
}
if (*end != ':') {
printf("Invalid format in xlr.cr %s, ':' expected at pos %d\n",
hw_env, end - hw_env);
goto err_return;
}
start = end + 1;/* step over ':' */
val = strtoul(start, &end, 16);
if (start == end) {
printf("Invalid value in xlr.cr %s, cannot read a hex value at pos %d\n",
hw_env, start - hw_env);
goto err_return;
}
if (*end != ',' && *end != '\0') {
printf("Invalid format in xlr.cr %s, ',' expected at pos %d\n",
hw_env, end - hw_env);
goto err_return;
}
xlr_mtcr(reg, val);
if (*end == ',')
start = end + 1; /* skip over ',' */
else
start = end;
}
freeenv(hw_env);
return;
err_return:
panic("Invalid xlr.cr setting!");
return;
}
#ifdef SMP
extern void xlr_secondary_start(unsigned long, unsigned long, unsigned long);
static void
xlr_secondary_entry(void *data)
{
unsigned long sp, gp;
unsigned int cpu = (xlr_cpu_id() << 2) + xlr_thr_id();
sp = xlr_secondary_sp[cpu];
gp = xlr_secondary_gp[cpu];
xlr_secondary_start((unsigned long)mips_secondary_wait, sp, gp);
}
#endif
static void
xlr_set_boot_flags(void)
{
char *p;
for (p = getenv("boot_flags"); p && *p != '\0'; p++) {
switch (*p) {
case 'd':
case 'D':
boothowto |= RB_KDB;
break;
case 'g':
case 'G':
boothowto |= RB_GDB;
break;
case 'v':
case 'V':
boothowto |= RB_VERBOSE;
break;
case 's': /* single-user (default, supported for sanity) */
case 'S':
boothowto |= RB_SINGLE;
break;
default:
printf("Unrecognized boot flag '%c'.\n", *p);
break;
}
}
if (p)
freeenv(p);
return;
}
extern uint32_t _end;
static void
mips_init(void)
{
init_param1();
init_param2(physmem);
/* XXX: Catch 22. Something touches the tlb. */
mips_cpu_init();
pmap_bootstrap();
mips_proc0_init();
write_c0_register32(MIPS_COP_0_OSSCRATCH, 7, pcpup->pc_curthread);
mutex_init();
PMAP_LOCK_INIT(kernel_pmap);
#ifdef DDB
#ifdef SMP
setup_nmi();
#endif /* SMP */
kdb_init();
if (boothowto & RB_KDB) {
kdb_enter("Boot flags requested debugger", NULL);
}
#endif
}
void
platform_start(__register_t a0 __unused,
__register_t a1 __unused,
__register_t a2 __unused,
__register_t a3 __unused)
{
vm_size_t physsz = 0;
int i, j;
struct xlr_boot1_mem_map *boot_map;
#ifdef SMP
uint32_t tmp;
void (*wakeup) (void *, void *, unsigned int);
#endif
/* XXX no zeroing of BSS? */
/* Initialize pcpu stuff */
mips_pcpu0_init();
/* XXX FIXME the code below is not 64 bit clean */
/* Save boot loader and other stuff from scratch regs */
xlr_boot1_info = *(struct boot1_info *)read_c0_register32(MIPS_COP_0_OSSCRATCH, 0);
cpu_mask_info = read_c0_register64(MIPS_COP_0_OSSCRATCH, 1);
xlr_online_cpumask = read_c0_register32(MIPS_COP_0_OSSCRATCH, 2);
xlr_run_mode = read_c0_register32(MIPS_COP_0_OSSCRATCH, 3);
xlr_argc = read_c0_register32(MIPS_COP_0_OSSCRATCH, 4);
xlr_argv = (char **)read_c0_register32(MIPS_COP_0_OSSCRATCH, 5);
xlr_envp = (char **)read_c0_register32(MIPS_COP_0_OSSCRATCH, 6);
/* TODO: Verify the magic number here */
/* FIXMELATER: xlr_boot1_info.magic_number */
/* initialize console so that we have printf */
boothowto |= (RB_SERIAL | RB_MULTIPLE); /* Use multiple consoles */
/* clockrate used by delay, so initialize it here */
cpu_clock = xlr_boot1_info.cpu_frequency / 1000000;
/*
* Note the time counter on CPU0 runs not at system clock speed, but
* at PIC time counter speed (which is returned by
* platform_get_frequency(). Thus we do not use
* xlr_boot1_info.cpu_frequency here.
*/
mips_timer_early_init(platform_get_frequency());
/* Init the time counter in the PIC and local putc routine*/
rmi_early_counter_init();
/* Init console please */
cninit();
init_static_kenv(boot1_env, sizeof(boot1_env));
printf("Environment (from %d args):\n", xlr_argc - 1);
if (xlr_argc == 1)
printf("\tNone\n");
for (i = 1; i < xlr_argc; i++) {
char *n;
printf("\t%s\n", xlr_argv[i]);
n = strsep(&xlr_argv[i], "=");
if (xlr_argv[i] == NULL)
setenv(n, "1");
else
setenv(n, xlr_argv[i]);
}
xlr_set_boot_flags();
/* get physical memory info from boot loader */
boot_map = (struct xlr_boot1_mem_map *)
(unsigned long)xlr_boot1_info.psb_mem_map;
for (i = 0, j = 0; i < boot_map->num_entries; i++, j += 2) {
if (boot_map->physmem_map[i].type == BOOT1_MEM_RAM) {
if (j == 14) {
printf("*** ERROR *** memory map too large ***\n");
break;
}
if (j == 0) {
/* TODO FIXME */
/* start after kernel end */
phys_avail[0] = (vm_paddr_t)
MIPS_KSEG0_TO_PHYS(&_end) + 0x20000;
/* boot loader start */
/* HACK to Use bootloaders memory region */
/* TODO FIXME */
if (boot_map->physmem_map[0].size == 0x0c000000) {
boot_map->physmem_map[0].size = 0x0ff00000;
}
phys_avail[1] = boot_map->physmem_map[0].addr +
boot_map->physmem_map[0].size;
} else {
/*
* Can't use this code yet, because most of the fixed allocations happen from
* the biggest physical area. If we have more than 512M memory the kernel will try
* to map from the second are which is not in KSEG0 and not mapped
*/
phys_avail[j] = (vm_paddr_t)
boot_map->physmem_map[i].addr;
phys_avail[j + 1] = phys_avail[j] +
boot_map->physmem_map[i].size;
#if 0 /* FIXME TOD0 */
phys_avail[j] = phys_avail[j + 1] = 0;
#endif
}
physsz += boot_map->physmem_map[i].size;
}
}
/* FIXME XLR TODO */
phys_avail[j] = phys_avail[j + 1] = 0;
realmem = physmem = btoc(physsz);
/* Store pcpu in scratch 5 */
write_c0_register32(MIPS_COP_0_OSSCRATCH, 5, pcpup);
/* Set up hz, among others. */
mips_init();
#ifdef SMP
/*
* If thread 0 of any core is not available then mark whole core as
* not available
*/
tmp = xlr_boot1_info.cpu_online_map;
for (i = 4; i < MAXCPU; i += 4) {
if ((tmp & (0xf << i)) && !(tmp & (0x1 << i))) {
/*
* Oopps.. thread 0 is not available. Disable whole
* core
*/
tmp = tmp & ~(0xf << i);
printf("WARNING: Core %d is disabled because thread 0"
" of this core is not enabled.\n", i / 4);
}
}
xlr_boot1_info.cpu_online_map = tmp;
/* Wakeup Other cpus, and put them in bsd park code. */
for (i = 1, j = 1; i < 32; i++) {
/* Allocate stack for all other cpus from fbsd kseg0 memory. */
if ((1U << i) & xlr_boot1_info.cpu_online_map) {
xlr_secondary_gp[i] =
pmap_steal_memory(PAGE_SIZE);
if (!xlr_secondary_gp[i])
panic("Allocation failed for secondary cpu stacks");
xlr_secondary_sp[i] =
xlr_secondary_gp[i] + PAGE_SIZE - CALLFRAME_SIZ;
xlr_secondary_gp[i] = (unsigned long)&_gp;
/* Build ltop and ptol cpu map. */
cpu_ltop_map[j] = i;
cpu_ptol_map[i] = j;
if ((i & 0x3) == 0) /* store thread0 of each core */
xlr_core_cpu_mask |= (1 << j);
mips_cpu_logical_mask |= (1 << j);
j++;
}
}
mips_cpu_online_mask |= xlr_boot1_info.cpu_online_map;
wakeup = ((void (*) (void *, void *, unsigned int))
(unsigned long)(xlr_boot1_info.wakeup));
printf("Waking up CPUs 0x%llx.\n", xlr_boot1_info.cpu_online_map & ~(0x1U));
if (xlr_boot1_info.cpu_online_map & ~(0x1U))
wakeup(xlr_secondary_entry, 0,
(unsigned int)xlr_boot1_info.cpu_online_map);
#endif
/* xlr specific post initialization */
/*
* The expectation is that mutex_init() is already done in
* mips_init() XXX NOTE: We may need to move this to SMP based init
* code for each CPU, later.
*/
rmi_spin_mutex_safe = 1;
on_chip_init();
mips_timer_init_params(platform_get_frequency(), 0);
printf("Platform specific startup now completes\n");
}
void
platform_identify(void)
{
printf("Board [%d:%d], processor 0x%08x\n", (int)xlr_boot1_info.board_major_version,
(int)xlr_boot1_info.board_minor_version, mips_rd_prid());
}
/*
* XXX Maybe return the state of the watchdog in enter, and pass it to
* exit? Like spl().
*/
void
platform_trap_enter(void)
{
}
void
platform_trap_exit(void)
{
}
/*
void
platform_update_intrmask(int intr)
{
write_c0_eimr64(read_c0_eimr64() | (1ULL<<intr));
}
*/
void
disable_msgring_int(void *arg);
void
enable_msgring_int(void *arg);
void xlr_msgring_handler(struct trapframe *tf);
void msgring_process_fast_intr(void *arg);
struct msgring_ithread {
struct thread *i_thread;
u_int i_pending;
u_int i_flags;
int i_cpu;
};
struct msgring_ithread msgring_ithreads[MAXCPU];
char ithd_name[MAXCPU][32];
void
msgring_process_fast_intr(void *arg)
{
int cpu = PCPU_GET(cpuid);
volatile struct msgring_ithread *it;
struct proc *p;
struct thread *td;
/* wakeup an appropriate intr_thread for processing this interrupt */
it = (volatile struct msgring_ithread *)&msgring_ithreads[cpu];
td = it->i_thread;
p = td->td_proc;
/*
* Interrupt thread will enable the interrupts after processing all
* messages
*/
disable_msgring_int(NULL);
it->i_pending = 1;
if (TD_AWAITING_INTR(td)) {
thread_lock(td);
CTR3(KTR_INTR, "%s: schedule pid %d (%s)", __func__, p->p_pid,
p->p_comm);
TD_CLR_IWAIT(td);
sched_add(td, SRQ_INTR);
thread_unlock(td);
} else {
CTR4(KTR_INTR, "%s: pid %d (%s): state %d",
__func__, p->p_pid, p->p_comm, td->td_state);
}
}
#define MIT_DEAD 4
static void
msgring_process(void *arg)
{
volatile struct msgring_ithread *ithd;
struct thread *td;
struct proc *p;
td = curthread;
p = td->td_proc;
ithd = (volatile struct msgring_ithread *)arg;
KASSERT(ithd->i_thread == td,
("%s:msg_ithread and proc linkage out of sync", __func__));
/* First bind this thread to the right CPU */
thread_lock(td);
sched_bind(td, ithd->i_cpu);
thread_unlock(td);
//printf("Started %s on CPU %d\n", __FUNCTION__, ithd->i_cpu);
while (1) {
if (ithd->i_flags & MIT_DEAD) {
CTR3(KTR_INTR, "%s: pid %d (%s) exiting", __func__,
p->p_pid, p->p_comm);
kthread_exit();
}
while (ithd->i_pending) {
/*
* This might need a full read and write barrier to
* make sure that this write posts before any of the
* memory or device accesses in the handlers.
*/
atomic_store_rel_int(&ithd->i_pending, 0);
xlr_msgring_handler(NULL);
}
if (!ithd->i_pending && !(ithd->i_flags & MIT_DEAD)) {
thread_lock(td);
sched_class(td, PRI_ITHD);
TD_SET_IWAIT(td);
thread_unlock(td);
enable_msgring_int(NULL);
mi_switch(SW_VOL, NULL);
}
}
}
void
platform_prep_smp_launch(void)
{
int cpu;
uint32_t cpu_mask;
struct msgring_ithread *ithd;
struct thread *td;
struct proc *p;
int error;
cpu_mask = PCPU_GET(cpumask) | PCPU_GET(other_cpus);
/* Create kernel threads for message ring interrupt processing */
/* Currently create one task for thread 0 of each core */
for (cpu = 0; cpu < MAXCPU; cpu += 1) {
if (!((1 << cpu) & cpu_mask))
continue;
if ((cpu_ltop_map[cpu] % 4) != 0)
continue;
ithd = &msgring_ithreads[cpu];
sprintf(ithd_name[cpu], "msg_intr%d", cpu);
error = kproc_create(msgring_process,
(void *)ithd,
&p,
(RFSTOPPED | RFHIGHPID),
2,
ithd_name[cpu]);
if (error)
panic("kproc_create() failed with %d", error);
td = FIRST_THREAD_IN_PROC(p); /* XXXKSE */
thread_lock(td);
sched_class(td, PRI_ITHD);
TD_SET_IWAIT(td);
thread_unlock(td);
ithd->i_thread = td;
ithd->i_pending = 0;
ithd->i_cpu = cpu;
CTR2(KTR_INTR, "%s: created %s", __func__, ithd_name[cpu]);
}
}

426
sys/mips/rmi/xlr_pci.c Normal file
View File

@ -0,0 +1,426 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <machine/md_var.h>
#include <mips/rmi/rmi_mips_exts.h>
#include <machine/cpuregs.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/pmap.h>
#include <sys/rman.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcib_private.h>
#include <mips/rmi/iomap.h>
#include <mips/rmi/pic.h>
#include <mips/rmi/shared_structs.h>
#include <mips/rmi/board.h>
#include <mips/rmi/pcibus.h>
#include "pcib_if.h"
#define LSU_CFG0_REGID 0
#define LSU_CERRLOG_REGID 9
#define LSU_CERROVF_REGID 10
#define LSU_CERRINT_REGID 11
#define SWAP32(x)\
(((x) & 0xff000000) >> 24) | \
(((x) & 0x000000ff) << 24) | \
(((x) & 0x0000ff00) << 8) | \
(((x) & 0x00ff0000) >> 8)
/* MSI support */
#define MSI_MIPS_ADDR_DEST 0x000ff000
#define MSI_MIPS_ADDR_RH 0x00000008
#define MSI_MIPS_ADDR_RH_OFF 0x00000000
#define MSI_MIPS_ADDR_RH_ON 0x00000008
#define MSI_MIPS_ADDR_DM 0x00000004
#define MSI_MIPS_ADDR_DM_PHYSICAL 0x00000000
#define MSI_MIPS_ADDR_DM_LOGICAL 0x00000004
/* Fields in data for Intel MSI messages. */
#define MSI_MIPS_DATA_TRGRMOD 0x00008000 /* Trigger mode */
#define MSI_MIPS_DATA_TRGREDG 0x00000000 /* edge */
#define MSI_MIPS_DATA_TRGRLVL 0x00008000 /* level */
#define MSI_MIPS_DATA_LEVEL 0x00004000 /* Polarity. */
#define MSI_MIPS_DATA_DEASSERT 0x00000000
#define MSI_MIPS_DATA_ASSERT 0x00004000
#define MSI_MIPS_DATA_DELMOD 0x00000700 /* Delivery Mode */
#define MSI_MIPS_DATA_DELFIXED 0x00000000 /* fixed */
#define MSI_MIPS_DATA_DELLOPRI 0x00000100 /* lowest priority */
#define MSI_MIPS_DATA_INTVEC 0x000000ff
/*
* Build Intel MSI message and data values from a source. AMD64 systems
* seem to be compatible, so we use the same function for both.
*/
#define MIPS_MSI_ADDR(cpu) \
(MSI_MIPS_ADDR_BASE | (cpu) << 12 | \
MSI_MIPS_ADDR_RH_OFF | MSI_MIPS_ADDR_DM_PHYSICAL)
#define MIPS_MSI_DATA(irq) \
(MSI_MIPS_DATA_TRGRLVL | MSI_MIPS_DATA_DELFIXED | \
MSI_MIPS_DATA_ASSERT | (irq))
struct xlr_hose_softc {
int junk; /* no softc */
};
static devclass_t pcib_devclass;
static int pci_bus_status = 0;
static void *pci_config_base;
static uint32_t pci_cfg_read_32bit(uint32_t addr);
static void pci_cfg_write_32bit(uint32_t addr, uint32_t data);
static int
xlr_pcib_probe(device_t dev)
{
device_set_desc(dev, "xlr system bridge controller");
pci_init_resources();
pci_config_base = (void *)MIPS_PHYS_TO_KSEG1(DEFAULT_PCI_CONFIG_BASE);
pci_bus_status = 1;
return 0;
}
static int
xlr_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t * result)
{
#if 0
device_printf(dev, "xlr_pcib_read_ivar : read ivar %d for child %s\n", which, device_get_nameunit(child));
#endif
switch (which) {
case PCIB_IVAR_BUS:
*result = 0;
return 0;
}
return ENOENT;
}
static int
xlr_pcib_maxslots(device_t dev)
{
if (xlr_board_info.is_xls)
return 4;
else
return 32;
}
#define pci_cfg_offset(bus,slot,devfn,where) (((bus)<<16) + ((slot) << 11)+((devfn)<<8)+(where))
static __inline__ void
disable_and_clear_cache_error(void)
{
uint64_t lsu_cfg0 = read_64bit_phnx_ctrl_reg(CPU_BLOCKID_LSU, LSU_CFG0_REGID);
lsu_cfg0 = lsu_cfg0 & ~0x2e;
write_64bit_phnx_ctrl_reg(CPU_BLOCKID_LSU, LSU_CFG0_REGID, lsu_cfg0);
/* Clear cache error log */
write_64bit_phnx_ctrl_reg(CPU_BLOCKID_LSU, LSU_CERRLOG_REGID, 0);
}
static __inline__ void
clear_and_enable_cache_error(void)
{
uint64_t lsu_cfg0 = 0;
/* first clear the cache error logging register */
write_64bit_phnx_ctrl_reg(CPU_BLOCKID_LSU, LSU_CERRLOG_REGID, 0);
write_64bit_phnx_ctrl_reg(CPU_BLOCKID_LSU, LSU_CERROVF_REGID, 0);
write_64bit_phnx_ctrl_reg(CPU_BLOCKID_LSU, LSU_CERRINT_REGID, 0);
lsu_cfg0 = read_64bit_phnx_ctrl_reg(CPU_BLOCKID_LSU, LSU_CFG0_REGID);
lsu_cfg0 = lsu_cfg0 | 0x2e;
write_64bit_phnx_ctrl_reg(CPU_BLOCKID_LSU, LSU_CFG0_REGID, lsu_cfg0);
}
static uint32_t
phoenix_pciread(u_int b, u_int s, u_int f,
u_int reg, int width)
{
uint32_t data = 0;
if ((width == 2) && (reg & 1))
return 0xFFFFFFFF;
else if ((width == 4) && (reg & 3))
return 0xFFFFFFFF;
if (pci_bus_status)
data = pci_cfg_read_32bit(pci_cfg_offset(b, s, f, reg));
else
data = 0xFFFFFFFF;
if (width == 1)
return ((data >> ((reg & 3) << 3)) & 0xff);
else if (width == 2)
return ((data >> ((reg & 3) << 3)) & 0xffff);
else
return data;
}
static void
phoenix_pciwrite(u_int b, u_int s, u_int f,
u_int reg, u_int val, int width)
{
uint32_t cfgaddr = pci_cfg_offset(b, s, f, reg);
uint32_t data = 0;
if ((width == 2) && (reg & 1))
return;
else if ((width == 4) && (reg & 3))
return;
if (!pci_bus_status)
return;
if (width == 1) {
data = pci_cfg_read_32bit(cfgaddr);
data = (data & ~(0xff << ((reg & 3) << 3))) |
(val << ((reg & 3) << 3));
} else if (width == 2) {
data = pci_cfg_read_32bit(cfgaddr);
data = (data & ~(0xffff << ((reg & 3) << 3))) |
(val << ((reg & 3) << 3));
} else {
data = val;
}
pci_cfg_write_32bit(cfgaddr, data);
return;
}
static uint32_t
pci_cfg_read_32bit(uint32_t addr)
{
uint32_t temp = 0;
uint32_t *p = (uint32_t *) ((uint32_t) pci_config_base + (addr & ~3));
uint64_t cerr_cpu_log = 0;
disable_and_clear_cache_error();
temp = SWAP32(*p);
/* Read cache err log */
cerr_cpu_log = read_64bit_phnx_ctrl_reg(CPU_BLOCKID_LSU, LSU_CERRLOG_REGID);
if (cerr_cpu_log) {
/* Device don't exist. */
temp = ~0x0;
}
clear_and_enable_cache_error();
return temp;
}
static void
pci_cfg_write_32bit(uint32_t addr, uint32_t data)
{
unsigned int *p = (unsigned int *)((uint32_t) pci_config_base + (addr & ~3));
*p = SWAP32(data);
}
static u_int32_t
xlr_pcib_read_config(device_t dev, u_int b, u_int s, u_int f,
u_int reg, int width)
{
return phoenix_pciread(b, s, f, reg, width);
}
static void
xlr_pcib_write_config(device_t dev, u_int b, u_int s, u_int f,
u_int reg, u_int32_t val, int width)
{
phoenix_pciwrite(b, s, f, reg, val, width);
}
static int
xlr_pcib_attach(device_t dev)
{
device_add_child(dev, "pci", 0);
bus_generic_attach(dev);
return 0;
}
#define PCIE_LINK_STATE 0x4000
static void
xlr_pcib_identify(driver_t * driver, device_t parent)
{
xlr_reg_t *pcie_mmio_le = xlr_io_mmio(XLR_IO_PCIE_1_OFFSET);
xlr_reg_t reg_link0 = xlr_read_reg(pcie_mmio_le, (0x80 >> 2));
xlr_reg_t reg_link1 = xlr_read_reg(pcie_mmio_le, (0x84 >> 2));
if ((uint16_t) reg_link0 & PCIE_LINK_STATE) {
device_printf(parent, "Link 0 up\n");
}
if ((uint16_t) reg_link1 & PCIE_LINK_STATE) {
device_printf(parent, "Link 1 up\n");
}
BUS_ADD_CHILD(parent, 0, "pcib", 0);
}
static int
xlr_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs);
static int
xlr_release_msi(device_t pcib, device_t dev, int count, int *irqs);
static int
xlr_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs)
{
int pciirq;
int i;
device_t parent, tmp;
/* find the lane on which the slot is connected to */
tmp = dev;
while (1) {
parent = device_get_parent(tmp);
if (parent == NULL || parent == pcib) {
device_printf(dev, "Cannot find parent bus\n");
return ENXIO;
}
if (strcmp(device_get_nameunit(parent), "pci0") == 0)
break;
tmp = parent;
}
switch (pci_get_slot(tmp)) {
case 0:
pciirq = PIC_PCIE_LINK0_IRQ;
break;
case 1:
pciirq = PIC_PCIE_LINK1_IRQ;
break;
case 2:
pciirq = PIC_PCIE_LINK2_IRQ;
break;
case 3:
pciirq = PIC_PCIE_LINK3_IRQ;
break;
default:
return ENXIO;
}
irqs[0] = pciirq;
/*
* For now put in some fixed values for the other requested MSI,
* TODO handle multiple messages
*/
for (i = 1; i < count; i++)
irqs[i] = pciirq + 64 * i;
return 0;
}
static int
xlr_release_msi(device_t pcib, device_t dev, int count, int *irqs)
{
device_printf(dev, "%s: msi release %d\n", device_get_nameunit(pcib), count);
return 0;
}
static int
xlr_map_msi(device_t pcib, device_t dev, int irq, uint64_t * addr, uint32_t * data);
static int
xlr_map_msi(device_t pcib, device_t dev, int irq, uint64_t * addr, uint32_t * data)
{
switch (irq) {
case PIC_PCIE_LINK0_IRQ:
case PIC_PCIE_LINK1_IRQ:
case PIC_PCIE_LINK2_IRQ:
case PIC_PCIE_LINK3_IRQ:
*addr = MIPS_MSI_ADDR(0);
*data = MIPS_MSI_DATA(irq);
return 0;
default:
device_printf(dev, "%s: map_msi for irq %d - ignored", device_get_nameunit(pcib),
irq);
return (ENXIO);
}
}
static device_method_t xlr_pcib_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, xlr_pcib_identify),
DEVMETHOD(device_probe, xlr_pcib_probe),
DEVMETHOD(device_attach, xlr_pcib_attach),
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, xlr_pcib_read_ivar),
DEVMETHOD(bus_alloc_resource, xlr_pci_alloc_resource),
DEVMETHOD(bus_release_resource, pci_release_resource),
DEVMETHOD(bus_activate_resource, pci_activate_resource),
DEVMETHOD(bus_deactivate_resource, pci_deactivate_resource),
DEVMETHOD(bus_setup_intr, mips_platform_pci_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
/* pcib interface */
DEVMETHOD(pcib_maxslots, xlr_pcib_maxslots),
DEVMETHOD(pcib_read_config, xlr_pcib_read_config),
DEVMETHOD(pcib_write_config, xlr_pcib_write_config),
DEVMETHOD(pcib_route_interrupt, mips_pci_route_interrupt),
DEVMETHOD(pcib_alloc_msi, xlr_alloc_msi),
DEVMETHOD(pcib_release_msi, xlr_release_msi),
DEVMETHOD(pcib_map_msi, xlr_map_msi),
{0, 0}
};
static driver_t xlr_pcib_driver = {
"pcib",
xlr_pcib_methods,
sizeof(struct xlr_hose_softc),
};
DRIVER_MODULE(pcib, nexus, xlr_pcib_driver, pcib_devclass, 0, 0);

336
sys/mips/rmi/xlrconfig.h Normal file
View File

@ -0,0 +1,336 @@
/*-
* Copyright (c) 2003-2009 RMI Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of RMI Corporation, nor the names of its contributors,
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RMI_BSD */
#ifndef XLRCONFIG_H
#define XLRCONFIG_H
#include <sys/types.h>
#include <mips/rmi/shared_structs.h>
#include <mips/rmi/shared_structs_func.h>
#define read_c0_register32(reg, sel) \
({ unsigned int __rv; \
__asm__ __volatile__( \
".set\tpush\n\t" \
".set mips32\n\t" \
"mfc0\t%0,$%1,%2\n\t" \
".set\tpop" \
: "=r" (__rv) : "i" (reg), "i" (sel) ); \
__rv;})
#define write_c0_register32(reg, sel, value) \
__asm__ __volatile__( \
".set\tpush\n\t" \
".set mips32\n\t" \
"mtc0\t%0,$%1,%2\n\t" \
".set\tpop" \
: : "r" (value), "i" (reg), "i" (sel) );
#define read_c0_register64(reg, sel) \
({ unsigned int __high, __low; \
__asm__ __volatile__( \
".set\tpush\n\t" \
".set mips64\n\t" \
"dmfc0\t $8, $%2, %3\n\t" \
"dsrl32\t%0, $8, 0\n\t" \
"dsll32\t$8, $8, 0\n\t" \
"dsrl32\t%1, $8, 0\n\t" \
".set\tpop" \
: "=r"(__high), "=r"(__low): "i"(reg), "i"(sel): "$8" );\
(((unsigned long long)__high << 32) | __low);})
#define write_c0_register64(reg, sel, value) \
do{ \
unsigned int __high = val>>32; \
unsigned int __low = val & 0xffffffff; \
__asm__ __volatile__( \
".set\tpush\n\t" \
".set mips64\n\t" \
"dsll32\t$8, %1, 0\n\t" \
"dsll32\t$9, %0, 0\n\t" \
"or\t $8, $8, $9\n\t" \
"dmtc0\t $8, $%2, %3\n\t" \
".set\tpop" \
:: "r"(high), "r"(low), "i"(reg), "i"(sel):"$8", "$9");\
} while(0)
#define read_c2_register32(reg, sel) \
({ unsigned int __rv; \
__asm__ __volatile__( \
".set\tpush\n\t" \
".set mips32\n\t" \
"mfc2\t%0,$%1,%2\n\t" \
".set\tpop" \
: "=r" (__rv) : "i" (reg), "i" (sel) ); \
__rv;})
#define write_c2_register32(reg, sel, value) \
__asm__ __volatile__( \
".set\tpush\n\t" \
".set mips32\n\t" \
"mtc2\t%0,$%1,%2\n\t" \
".set\tpop" \
: : "r" (value), "i" (reg), "i" (sel) );
#define read_c2_register64(reg, sel) \
({ unsigned int __high, __low; \
__asm__ __volatile__( \
".set mips64\n\t" \
"dmfc2\t $8, $%2, %3\n\t" \
"dsrl32\t%0, $8, 0\n\t" \
"dsll32\t$8, $8, 0\n\t" \
"dsrl32\t%1, $8, 0\n\t" \
".set\tmips0" \
: "=r"(__high), "=r"(__low): "i"(reg), "i"(sel): "$8" );\
(((unsigned long long)__high << 32) | __low);})
#define write_c2_register64(reg, sel, value) \
do{ \
unsigned int __high = value>>32; \
unsigned int __low = value & 0xffffffff; \
__asm__ __volatile__( \
".set mips64\n\t" \
"dsll32\t$8, %1, 0\n\t" \
"dsll32\t$9, %0, 0\n\t" \
"dsrl32\t$8, $8, 0\n\t" \
"or\t $8, $8, $9\n\t" \
"dmtc2\t $8, $%2, %3\n\t" \
".set\tmips0" \
:: "r"(__high), "r"(__low), \
"i"(reg), "i"(sel) \
:"$8", "$9"); \
} while(0)
#if 0
#define xlr_processor_id() \
({int __id; \
__asm__ __volatile__ ( \
".set push\n" \
".set noreorder\n" \
".word 0x40088007\n" \
"srl $8, $8, 10\n" \
"andi %0, $8, 0x3f\n" \
".set pop\n" \
: "=r" (__id) : : "$8"); \
__id;})
#endif
#define xlr_cpu_id() \
({int __id; \
__asm__ __volatile__ ( \
".set push\n" \
".set noreorder\n" \
".word 0x40088007\n" \
"srl $8, $8, 4\n" \
"andi %0, $8, 0x7\n" \
".set pop\n" \
: "=r" (__id) : : "$8"); \
__id;})
#define xlr_thr_id() \
({int __id; \
__asm__ __volatile__ ( \
".set push\n" \
".set noreorder\n" \
".word 0x40088007\n" \
"andi %0, $8, 0x03\n" \
".set pop\n" \
: "=r" (__id) : : "$8"); \
__id;})
/* Additional registers on the XLR */
#define MIPS_COP_0_OSSCRATCH 22
#define XLR_CACHELINE_SIZE 32
#define XLR_MAX_CORES 8
/* functions to write to and read from the extended
* cp0 registers.
* EIRR : Extended Interrupt Request Register
* cp0 register 9 sel 6
* bits 0...7 are same as cause register 8...15
* EIMR : Extended Interrupt Mask Register
* cp0 register 9 sel 7
* bits 0...7 are same as status register 8...15
*/
static inline uint64_t
read_c0_eirr64(void)
{
__uint32_t high, low;
__asm__ __volatile__(
".set push\n"
".set noreorder\n"
".set noat\n"
".set mips4\n"
".word 0x40214806 \n\t"
"nop \n\t"
"dsra32 %0, $1, 0 \n\t"
"sll %1, $1, 0 \n\t"
".set pop\n"
: "=r"(high), "=r"(low)
);
return (((__uint64_t) high) << 32) | low;
}
static inline __uint64_t
read_c0_eimr64(void)
{
__uint32_t high, low;
__asm__ __volatile__(
".set push\n"
".set noreorder\n"
".set noat\n"
".set mips4\n"
".word 0x40214807 \n\t"
"nop \n\t"
"dsra32 %0, $1, 0 \n\t"
"sll %1, $1, 0 \n\t"
".set pop\n"
: "=r"(high), "=r"(low)
);
return (((__uint64_t) high) << 32) | low;
}
static inline void
write_c0_eirr64(__uint64_t value)
{
__uint32_t low, high;
high = value >> 32;
low = value & 0xffffffff;
__asm__ __volatile__(
".set push\n"
".set noreorder\n"
".set noat\n"
".set mips4\n\t"
"dsll32 $2, %1, 0 \n\t"
"dsll32 $1, %0, 0 \n\t"
"dsrl32 $2, $2, 0 \n\t"
"or $1, $1, $2 \n\t"
".word 0x40a14806 \n\t"
"nop \n\t"
".set pop\n"
:
: "r"(high), "r"(low)
: "$1", "$2");
}
static inline void
write_c0_eimr64(__uint64_t value)
{
__uint32_t low, high;
high = value >> 32;
low = value & 0xffffffff;
__asm__ __volatile__(
".set push\n"
".set noreorder\n"
".set noat\n"
".set mips4\n\t"
"dsll32 $2, %1, 0 \n\t"
"dsll32 $1, %0, 0 \n\t"
"dsrl32 $2, $2, 0 \n\t"
"or $1, $1, $2 \n\t"
".word 0x40a14807 \n\t"
"nop \n\t"
".set pop\n"
:
: "r"(high), "r"(low)
: "$1", "$2");
}
static __inline__ int
xlr_test_and_set(int *lock)
{
int oldval = 0;
__asm__ __volatile__(".set push\n"
".set noreorder\n"
"move $9, %2\n"
"li $8, 1\n"
// "swapw $8, $9\n"
".word 0x71280014\n"
"move %1, $8\n"
".set pop\n"
: "+m"(*lock), "=r"(oldval)
: "r"((unsigned long)lock)
: "$8", "$9"
);
return (oldval == 0 ? 1 /* success */ : 0 /* failure */ );
}
static __inline__ uint32_t
xlr_mfcr(uint32_t reg)
{
uint32_t val;
__asm__ __volatile__(
"move $8, %1\n"
".word 0x71090018\n"
"move %0, $9\n"
: "=r"(val)
: "r"(reg):"$8", "$9");
return val;
}
static __inline__ void
xlr_mtcr(uint32_t reg, uint32_t val)
{
__asm__ __volatile__(
"move $8, %1\n"
"move $9, %0\n"
".word 0x71090019\n"
:: "r"(val), "r"(reg)
: "$8", "$9");
}
#endif

303
sys/mips/rmi/xls_ehci.c Normal file
View File

@ -0,0 +1,303 @@
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Lennart Augustsson (augustss@carlstedt.se) at
* Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/dev/usb/ehci_pci.c,v 1.18.2.4 2008/04/23 18:54:51 jhb Exp $");
/*
* USB Enhanced Host Controller Driver, a.k.a. USB 2.0 controller.
*
* The EHCI 1.0 spec can be found at
* http://developer.intel.com/technology/usb/download/ehci-r10.pdf
* and the USB 2.0 spec at
* http://www.usb.org/developers/docs/usb_20.zip
*/
/* The low level controller code for EHCI has been split into
* PCI probes and EHCI specific code. This was done to facilitate the
* sharing of code between *BSD's
*/
#include "opt_bus.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/queue.h>
#include <sys/lock.h>
#include <sys/lockmgr.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <machine/resource.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
/*#include <dev/usb/usbdivar.h> */
/*#include <dev/usb/usb_mem.h> */
#include <mips/rmi/ehcireg.h>
#include <mips/rmi/ehcivar.h>
#ifdef USB_DEBUG
#define EHCI_DEBUG USB_DEBUG
#define DPRINTF(x) do { if (ehcidebug) logprintf x; } while (0)
extern int ehcidebug;
#else
#define DPRINTF(x)
#endif
static int ehci_xls_attach(device_t self);
static int ehci_xls_detach(device_t self);
static int ehci_xls_shutdown(device_t self);
static int ehci_xls_suspend(device_t self);
static int ehci_xls_resume(device_t self);
static void ehci_xls_givecontroller(device_t self);
static void ehci_xls_takecontroller(device_t self);
static int
ehci_xls_suspend(device_t self)
{
ehci_softc_t *sc = device_get_softc(self);
int err;
err = bus_generic_suspend(self);
if (err)
return (err);
ehci_power(PWR_SUSPEND, sc);
return 0;
}
static int
ehci_xls_resume(device_t self)
{
ehci_softc_t *sc = device_get_softc(self);
ehci_xls_takecontroller(self);
ehci_power(PWR_RESUME, sc);
bus_generic_resume(self);
return 0;
}
static int
ehci_xls_shutdown(device_t self)
{
ehci_softc_t *sc = device_get_softc(self);
int err;
err = bus_generic_shutdown(self);
if (err)
return (err);
ehci_shutdown(sc);
ehci_xls_givecontroller(self);
return 0;
}
static const char *xlr_usb_dev_desc = "RMI XLR USB 2.0 controller";
static const char *xlr_vendor_desc = "RMI Corp";
static int
ehci_xls_probe(device_t self)
{
/* TODO see if usb is enabled on the board */
device_set_desc(self, xlr_usb_dev_desc);
return BUS_PROBE_DEFAULT;
}
static int
ehci_xls_attach(device_t self)
{
ehci_softc_t *sc = device_get_softc(self);
device_t parent;
device_t *neighbors;
int err;
int rid;
int count;
int res;
sc->sc_bus.usbrev = USBREV_2_0;
rid = 0;
sc->io_res = bus_alloc_resource(self, SYS_RES_MEMORY, &rid,
0ul, ~0ul, 0x400, RF_ACTIVE);
if (!sc->io_res) {
device_printf(self, "Could not map memory\n");
return ENXIO;
}
sc->iot = rman_get_bustag(sc->io_res);
sc->ioh = rman_get_bushandle(sc->io_res);
rid = 0;
sc->irq_res = bus_alloc_resource(self, SYS_RES_IRQ, &rid,
39, 39, 1, RF_SHAREABLE | RF_ACTIVE);
if (sc->irq_res == NULL) {
device_printf(self, "Could not allocate irq\n");
ehci_xls_detach(self);
return ENXIO;
}
sc->sc_bus.bdev = device_add_child(self, "usb", -1);
if (!sc->sc_bus.bdev) {
device_printf(self, "Could not add USB device\n");
ehci_xls_detach(self);
return ENOMEM;
}
device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
/* ehci_pci_match will never return NULL if ehci_pci_probe succeeded */
device_set_desc(sc->sc_bus.bdev, xlr_usb_dev_desc);
sprintf(sc->sc_vendor, xlr_vendor_desc);
err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO,
(driver_intr_t *) ehci_intr, sc, &sc->ih);
if (err) {
device_printf(self, "Could not setup irq, %d\n", err);
sc->ih = NULL;
ehci_xls_detach(self);
return ENXIO;
}
/*
* Find companion controllers. According to the spec they always
* have lower function numbers so they should be enumerated already.
*/
parent = device_get_parent(self);
res = device_get_children(parent, &neighbors, &count);
if (res != 0) {
device_printf(self, "Error finding companion busses\n");
ehci_xls_detach(self);
return ENXIO;
}
sc->sc_ncomp = 0;
ehci_xls_takecontroller(self);
err = ehci_init(sc);
if (!err) {
sc->sc_flags |= EHCI_SCFLG_DONEINIT;
err = device_probe_and_attach(sc->sc_bus.bdev);
}
if (err) {
device_printf(self, "USB init failed err=%d\n", err);
ehci_xls_detach(self);
return EIO;
}
return 0;
}
static int
ehci_xls_detach(device_t self)
{
ehci_softc_t *sc = device_get_softc(self);
if (sc->sc_flags & EHCI_SCFLG_DONEINIT) {
ehci_detach(sc, 0);
sc->sc_flags &= ~EHCI_SCFLG_DONEINIT;
}
/*
* disable interrupts that might have been switched on in ehci_init
*/
if (sc->iot && sc->ioh)
bus_space_write_4(sc->iot, sc->ioh, EHCI_USBINTR, 0);
if (sc->irq_res && sc->ih) {
int err = bus_teardown_intr(self, sc->irq_res, sc->ih);
if (err)
/* XXX or should we panic? */
device_printf(self, "Could not tear down irq, %d\n",
err);
sc->ih = NULL;
}
if (sc->sc_bus.bdev) {
device_delete_child(self, sc->sc_bus.bdev);
sc->sc_bus.bdev = NULL;
}
if (sc->irq_res) {
bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res);
sc->irq_res = NULL;
}
if (sc->io_res) {
bus_release_resource(self, SYS_RES_MEMORY, PCI_CBMEM, sc->io_res);
sc->io_res = NULL;
sc->iot = 0;
sc->ioh = 0;
}
return 0;
}
static void
ehci_xls_takecontroller(device_t self)
{
//device_printf(self, "In func %s\n", __func__);
}
static void
ehci_xls_givecontroller(device_t self)
{
//device_printf(self, "In func %s\n", __func__);
}
static device_method_t ehci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ehci_xls_probe),
DEVMETHOD(device_attach, ehci_xls_attach),
DEVMETHOD(device_detach, ehci_xls_detach),
DEVMETHOD(device_suspend, ehci_xls_suspend),
DEVMETHOD(device_resume, ehci_xls_resume),
DEVMETHOD(device_shutdown, ehci_xls_shutdown),
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
{0, 0}
};
static driver_t ehci_driver = {
"ehci",
ehci_methods,
sizeof(ehci_softc_t),
};
static devclass_t ehci_devclass;
DRIVER_MODULE(ehci, iodi, ehci_driver, ehci_devclass, 0, 0);
/* DRIVER_MODULE(ehci, cardbus, ehci_driver, ehci_devclass, 0, 0); */