/***********************license start*************** * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights * reserved. * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * 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. * * * Neither the name of Cavium Networks nor the names of * its contributors may be used to endorse or promote products * derived from this software without specific prior written * permission. * * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. * * * For any questions regarding licensing please contact marketing@caviumnetworks.com * ***********************license end**************************************/ /* $FreeBSD$ */ /*------------------------------------------------------------------ * octeon_pko.h Packet Output Block * *------------------------------------------------------------------ */ #ifndef ___OCTEON_PKO__H___ #define ___OCTEON_PKO__H___ /* * PKO Command Buffer Register. * Specify Pool-# and Size of each entry in Pool. For Output Cmd Buffers. */ typedef union { uint64_t word64; struct { uint64_t unused_mbz : 41; /* Must be zero */ uint64_t pool : 3; /* FPA Pool to use */ uint64_t unused_mbz2 : 7; /* Must be zero */ uint64_t size : 13; /* Size of the pool blocks */ } bits; } octeon_pko_pool_cfg_t; /* * PKO GMX Mode Register * Specify the # of GMX1 ports and GMX0 ports */ typedef union { uint64_t word64; struct { uint64_t unused_mbz : 58; /* MBZ */ uint64_t mode1 : 3; /* # GMX1 ports; */ /* 16 >> MODE1, 0 <= MODE1 <=4 */ uint64_t mode0 : 3; /* # GMX0 ports; */ /* 16 >> MODE0, 0 <= MODE0 <=4 */ } bits; } octeon_pko_reg_gmx_port_mode_t; typedef union { uint64_t word64; struct { uint64_t unused_mbz : 62; /* MBZ */ uint64_t mode : 2; /* Queues Mode */ } bits; } octeon_pko_queue_mode_t; typedef union { uint64_t word64; struct { uint64_t unused_mbz : 32; /* MBZ */ uint64_t crc_ports_mask : 32; /* CRC Ports Enable mask */ } bits; } octeon_pko_crc_ports_enable_t; #define OCTEON_PKO_QUEUES_MAX 128 #define OCTEON_PKO_PORTS_MAX 36 #define OCTEON_PKO_PORT_ILLEGAL 63 /* Defines how the PKO command buffer FAU register is used */ #define OCTEON_PKO_INDEX_BITS 12 #define OCTEON_PKO_INDEX_MASK ((1ull << OCTEON_PKO_INDEX_BITS) - 1) typedef enum { OCTEON_PKO_SUCCESS, OCTEON_PKO_INVALID_PORT, OCTEON_PKO_INVALID_QUEUE, OCTEON_PKO_INVALID_PRIORITY, OCTEON_PKO_NO_MEMORY } octeon_pko_status_t; typedef struct { long packets; uint64_t octets; uint64_t doorbell; } octeon_pko_port_status_t; typedef union { uint64_t word64; struct { octeon_mips_space_t mem_space : 2; /* Octeon IO_SEG */ uint64_t unused_mbz :13; /* Must be zero */ uint64_t is_io : 1; /* Must be one */ uint64_t did : 8; /* device-ID on non-coherent bus*/ uint64_t unused_mbz2 : 4; /* Must be zero */ uint64_t unused_mbz3 :18; /* Must be zero */ uint64_t port : 6; /* output port */ uint64_t queue : 9; /* output queue to send */ uint64_t unused_mbz4 : 3; /* Must be zero */ } bits; } octeon_pko_doorbell_address_t; /* * Structure of the first packet output command word. */ typedef union { uint64_t word64; struct { octeon_fau_op_size_t size1 : 2; /* The size of reg1 operation */ /* - could be 8, 16, 32, or 64 bits */ octeon_fau_op_size_t size0 : 2; /* The size of the reg0 operation */ /* - could be 8, 16, 32, or 64 bits */ uint64_t subone1 : 1; /* Subtract 1, else sub pkt size */ uint64_t reg1 :11; /* The register, subtract will be */ /* done if reg1 is non-zero */ uint64_t subone0 : 1; /* Subtract 1, else sub pkt size */ uint64_t reg0 :11; /* The register, subtract will be */ /* done if reg0 is non-zero */ uint64_t unused : 2; /* Must be zero */ uint64_t wqp : 1; /* If rsp, then word3 contains a */ /* ptr to a work queue entry */ uint64_t rsp : 1; /* HW will respond when done */ uint64_t gather : 1; /* If set, the supplied pkt_ptr is */ /* a ptr to a list of pkt_ptr's */ uint64_t ipoffp1 : 7; /* Off to IP hdr. For HW checksum */ uint64_t ignore_i : 1; /* Ignore I bit in all pointers */ uint64_t dontfree : 1; /* Don't free buffs containing pkt */ uint64_t segs : 6; /* Number of segs. If gather set, */ /* also gather list length */ uint64_t total_bytes :16; /* Includes L2, w/o trailing CRC */ } bits; } octeon_pko_command_word0_t; typedef union { void* ptr; uint64_t word64; struct { uint64_t i : 1; /* Invert the "free" pick of the overall pkt. */ /* For inbound pkts, HW always sets this to 0 */ uint64_t back : 4; /* Amount to back up to get to buffer start */ /* in cache lines. This is mostly less than 1 */ /* complete cache line; so the value is zero */ uint64_t pool : 3; /* FPA pool that the buffer belongs to */ uint64_t size :16; /* segment size (bytes) pointed at by addr */ uint64_t addr :40; /* Ptr to 1st data byte. NOT buffer */ } bits; } octeon_pko_packet_ptr_t; /* * Definition of the hardware structure used to configure an * output queue. */ typedef union { uint64_t word64; struct { uint64_t unused_mbz : 3; /* Must be zero */ uint64_t qos_mask : 8; /* Control Mask priority */ /* across 8 QOS levels */ uint64_t buf_ptr : 36; /* Command buffer pointer, */ /* 8 byte-aligned */ uint64_t tail : 1; /* Set if this queue is the tail */ /* of the port queue array */ uint64_t index : 3; /* Index (distance from head) in */ /* the port queue array */ uint64_t port : 6; /* Port ID for this queue mapping */ uint64_t queue : 7; /* Hardware queue number */ } bits; } octeon_pko_queue_cfg_t; typedef union { uint64_t word64; struct { uint64_t unused_mbz : 48; uint64_t inc : 8; uint64_t idx : 8; } bits; } octeon_pko_read_idx_t; typedef struct octeon_pko_sw_queue_info_t_ { uint64_t xmit_command_state; octeon_spinlock_t lock; uint32_t pad[29]; } octeon_pko_sw_queue_info_t; #define OCTEON_DID_PKT 10ULL #define OCTEON_DID_PKT_SEND OCTEON_ADDR_FULL_DID(OCTEON_DID_PKT,2ULL) /* * Ring the packet output doorbell. This tells the packet * output hardware that "len" command words have been added * to its pending list. This command includes the required * SYNCW before the doorbell ring. * * @param port Port the packet is for * @param queue Queue the packet is for * @param len Length of the command in 64 bit words */ extern void octeon_pko_doorbell_data(u_int port); //#define CORE_0_ONLY 1 static inline void octeon_pko_ring_doorbell (u_int port, u_int queue, u_int len) { octeon_pko_doorbell_address_t ptr; ptr.word64 = 0; ptr.bits.mem_space = OCTEON_IO_SEG; ptr.bits.did = OCTEON_DID_PKT_SEND; ptr.bits.is_io = 1; ptr.bits.port = port; ptr.bits.queue = queue; OCTEON_SYNCWS; oct_write64(ptr.word64, len); } #define OCTEON_PKO_QUEUES_PER_PORT_INTERFACE0 1 #define OCTEON_PKO_QUEUES_PER_PORT_INTERFACE1 1 #define OCTEON_PKO_QUEUES_PER_PORT_PCI 1 /* * octeon_pko_get_base_queue * * For a given port number, return the base pko output queue * for the port. */ static inline u_int octeon_pko_get_base_queue (u_int port) { if (port < 16) { return (port * OCTEON_PKO_QUEUES_PER_PORT_INTERFACE0); } if (port < 32) { return (16 * OCTEON_PKO_QUEUES_PER_PORT_INTERFACE0 + (port - 16) * OCTEON_PKO_QUEUES_PER_PORT_INTERFACE1); } return (16 * OCTEON_PKO_QUEUES_PER_PORT_INTERFACE0 + 16 * OCTEON_PKO_QUEUES_PER_PORT_INTERFACE1 + (port - 32) * OCTEON_PKO_QUEUES_PER_PORT_PCI); } /* * For a given port number, return the number of pko output queues. * * @param port Port number * @return Number of output queues */ static inline u_int octeon_pko_get_num_queues(u_int port) { if (port < 16) { return (OCTEON_PKO_QUEUES_PER_PORT_INTERFACE0); } else if (port<32) { return (OCTEON_PKO_QUEUES_PER_PORT_INTERFACE1); } return (OCTEON_PKO_QUEUES_PER_PORT_PCI); } /* * Externs */ extern void octeon_pko_init(void); extern void octeon_pko_enable(void); extern void octeon_pko_disable(void); extern void octeon_pko_show(u_int start_port, u_int end_port); extern void octeon_pko_config(void); extern void octeon_pko_config_cmdbuf_global_defaults(u_int cmdbuf_pool, u_int elem_size); extern void octeon_pko_config_rgmx_ports(void); extern void octeon_pko_get_port_status(u_int, u_int, octeon_pko_port_status_t *status); extern octeon_pko_status_t octeon_pko_config_port(u_int port, u_int base_queue, u_int num_queues, const u_int priority[], u_int pko_output_cmdbuf_fpa_pool, octeon_pko_sw_queue_info_t sw_queues[]); #endif /* ___OCTEON_PKO__H___ */