diff options
Diffstat (limited to 'gpxe/src/drivers/infiniband')
-rw-r--r-- | gpxe/src/drivers/infiniband/arbel.c | 160 | ||||
-rw-r--r-- | gpxe/src/drivers/infiniband/hermon.c | 160 | ||||
-rw-r--r-- | gpxe/src/drivers/infiniband/ib_packet.c | 234 | ||||
-rw-r--r-- | gpxe/src/drivers/infiniband/ib_sma.c | 553 | ||||
-rw-r--r-- | gpxe/src/drivers/infiniband/ib_smc.c | 166 | ||||
-rw-r--r-- | gpxe/src/drivers/infiniband/linda.c | 2396 | ||||
-rw-r--r-- | gpxe/src/drivers/infiniband/linda.h | 271 | ||||
-rw-r--r-- | gpxe/src/drivers/infiniband/linda_fw.c | 1067 | ||||
-rw-r--r-- | gpxe/src/drivers/infiniband/qib_7220_regs.h | 1763 | ||||
-rw-r--r-- | gpxe/src/drivers/infiniband/qib_genbits.pl | 95 |
10 files changed, 6707 insertions, 158 deletions
diff --git a/gpxe/src/drivers/infiniband/arbel.c b/gpxe/src/drivers/infiniband/arbel.c index 1b55131b..e516031b 100644 --- a/gpxe/src/drivers/infiniband/arbel.c +++ b/gpxe/src/drivers/infiniband/arbel.c @@ -33,6 +33,7 @@ #include <gpxe/iobuf.h> #include <gpxe/netdevice.h> #include <gpxe/infiniband.h> +#include <gpxe/ib_smc.h> #include "arbel.h" /** @@ -484,6 +485,50 @@ arbel_cmd_map_fa ( struct arbel *arbel, /*************************************************************************** * + * MAD operations + * + *************************************************************************** + */ + +/** + * Issue management datagram + * + * @v ibdev Infiniband device + * @v mad Management datagram + * @ret rc Return status code + */ +static int arbel_mad ( struct ib_device *ibdev, union ib_mad *mad ) { + struct arbel *arbel = ib_get_drvdata ( ibdev ); + union arbelprm_mad mad_ifc; + int rc; + + linker_assert ( sizeof ( *mad ) == sizeof ( mad_ifc.mad ), + mad_size_mismatch ); + + /* Copy in request packet */ + memcpy ( &mad_ifc.mad, mad, sizeof ( mad_ifc.mad ) ); + + /* Issue MAD */ + if ( ( rc = arbel_cmd_mad_ifc ( arbel, ibdev->port, + &mad_ifc ) ) != 0 ) { + DBGC ( arbel, "Arbel %p could not issue MAD IFC: %s\n", + arbel, strerror ( rc ) ); + return rc; + } + + /* Copy out reply packet */ + memcpy ( mad, &mad_ifc.mad, sizeof ( *mad ) ); + + if ( mad->hdr.status != 0 ) { + DBGC ( arbel, "Arbel %p MAD IFC status %04x\n", + arbel, ntohs ( mad->hdr.status ) ); + return -EIO; + } + return 0; +} + +/*************************************************************************** + * * Completion queue operations * *************************************************************************** @@ -1006,7 +1051,7 @@ static int arbel_post_send ( struct ib_device *ibdev, ud_address_vector.pd, ARBEL_GLOBAL_PD, ud_address_vector.port_number, ibdev->port ); MLX_FILL_2 ( &wqe->ud, 1, - ud_address_vector.rlid, av->dlid, + ud_address_vector.rlid, av->lid, ud_address_vector.g, av->gid_present ); MLX_FILL_2 ( &wqe->ud, 2, ud_address_vector.max_stat_rate, @@ -1015,7 +1060,7 @@ static int arbel_post_send ( struct ib_device *ibdev, MLX_FILL_1 ( &wqe->ud, 3, ud_address_vector.sl, av->sl ); gid = ( av->gid_present ? &av->gid : &arbel_no_gid ); memcpy ( &wqe->ud.u.dwords[4], gid, sizeof ( *gid ) ); - MLX_FILL_1 ( &wqe->ud, 8, destination_qp, av->dest_qp ); + MLX_FILL_1 ( &wqe->ud, 8, destination_qp, av->qpn ); MLX_FILL_1 ( &wqe->ud, 9, q_key, av->qkey ); MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_len ( iobuf ) ); MLX_FILL_1 ( &wqe->data[0], 1, l_key, arbel->reserved_lkey ); @@ -1106,17 +1151,12 @@ static int arbel_post_recv ( struct ib_device *ibdev, * @v ibdev Infiniband device * @v cq Completion queue * @v cqe Hardware completion queue entry - * @v complete_send Send completion handler - * @v complete_recv Receive completion handler * @ret rc Return status code */ static int arbel_complete ( struct ib_device *ibdev, struct ib_completion_queue *cq, - union arbelprm_completion_entry *cqe, - ib_completer_t complete_send, - ib_completer_t complete_recv ) { + union arbelprm_completion_entry *cqe ) { struct arbel *arbel = ib_get_drvdata ( ibdev ); - struct ib_completion completion; struct ib_work_queue *wq; struct ib_queue_pair *qp; struct arbel_queue_pair *arbel_qp; @@ -1124,16 +1164,17 @@ static int arbel_complete ( struct ib_device *ibdev, struct arbel_recv_work_queue *arbel_recv_wq; struct arbelprm_recv_wqe *recv_wqe; struct io_buffer *iobuf; - ib_completer_t complete; + struct ib_address_vector av; + struct ib_global_route_header *grh; unsigned int opcode; unsigned long qpn; int is_send; unsigned long wqe_adr; unsigned int wqe_idx; + size_t len; int rc = 0; /* Parse completion */ - memset ( &completion, 0, sizeof ( completion ) ); qpn = MLX_GET ( &cqe->normal, my_qpn ); is_send = MLX_GET ( &cqe->normal, s ); wqe_adr = ( MLX_GET ( &cqe->normal, wqe_adr ) << 6 ); @@ -1141,9 +1182,8 @@ static int arbel_complete ( struct ib_device *ibdev, if ( opcode >= ARBEL_OPCODE_RECV_ERROR ) { /* "s" field is not valid for error opcodes */ is_send = ( opcode == ARBEL_OPCODE_SEND_ERROR ); - completion.syndrome = MLX_GET ( &cqe->error, syndrome ); - DBGC ( arbel, "Arbel %p CPN %lx syndrome %x vendor %lx\n", - arbel, cq->cqn, completion.syndrome, + DBGC ( arbel, "Arbel %p CPN %lx syndrome %lx vendor %lx\n", + arbel, cq->cqn, MLX_GET ( &cqe->error, syndrome ), MLX_GET ( &cqe->error, vendor_code ) ); rc = -EIO; /* Don't return immediately; propagate error to completer */ @@ -1181,9 +1221,12 @@ static int arbel_complete ( struct ib_device *ibdev, } wq->iobufs[wqe_idx] = NULL; - /* Fill in length for received packets */ - if ( ! is_send ) { - completion.len = MLX_GET ( &cqe->normal, byte_cnt ); + if ( is_send ) { + /* Hand off to completion handler */ + ib_complete_send ( ibdev, qp, iobuf, rc ); + } else { + /* Set received length */ + len = MLX_GET ( &cqe->normal, byte_cnt ); recv_wqe = &arbel_recv_wq->wqe[wqe_idx].recv; assert ( MLX_GET ( &recv_wqe->data[0], local_address_l ) == virt_to_bus ( iobuf->data ) ); @@ -1192,18 +1235,22 @@ static int arbel_complete ( struct ib_device *ibdev, MLX_FILL_1 ( &recv_wqe->data[0], 0, byte_count, 0 ); MLX_FILL_1 ( &recv_wqe->data[0], 1, l_key, ARBEL_INVALID_LKEY ); - if ( completion.len > iob_tailroom ( iobuf ) ) { - DBGC ( arbel, "Arbel %p CQN %lx QPN %lx IDX %x " - "overlength received packet length %zd\n", - arbel, cq->cqn, qpn, wqe_idx, completion.len ); - return -EIO; - } + assert ( len <= iob_tailroom ( iobuf ) ); + iob_put ( iobuf, len ); + assert ( iob_len ( iobuf ) >= sizeof ( *grh ) ); + grh = iobuf->data; + iob_pull ( iobuf, sizeof ( *grh ) ); + /* Construct address vector */ + memset ( &av, 0, sizeof ( av ) ); + av.qpn = MLX_GET ( &cqe->normal, rqpn ); + av.lid = MLX_GET ( &cqe->normal, rlid ); + av.sl = MLX_GET ( &cqe->normal, sl ); + av.gid_present = MLX_GET ( &cqe->normal, g ); + memcpy ( &av.gid, &grh->sgid, sizeof ( av.gid ) ); + /* Hand off to completion handler */ + ib_complete_recv ( ibdev, qp, &av, iobuf, rc ); } - /* Pass off to caller's completion handler */ - complete = ( is_send ? complete_send : complete_recv ); - complete ( ibdev, qp, &completion, iobuf ); - return rc; } @@ -1212,13 +1259,9 @@ static int arbel_complete ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v cq Completion queue - * @v complete_send Send completion handler - * @v complete_recv Receive completion handler */ static void arbel_poll_cq ( struct ib_device *ibdev, - struct ib_completion_queue *cq, - ib_completer_t complete_send, - ib_completer_t complete_recv ) { + struct ib_completion_queue *cq ) { struct arbel *arbel = ib_get_drvdata ( ibdev ); struct arbel_completion_queue *arbel_cq = ib_cq_get_drvdata ( cq ); struct arbelprm_cq_ci_db_record *ci_db_rec; @@ -1236,8 +1279,7 @@ static void arbel_poll_cq ( struct ib_device *ibdev, } /* Handle completion */ - if ( ( rc = arbel_complete ( ibdev, cq, cqe, complete_send, - complete_recv ) ) != 0 ) { + if ( ( rc = arbel_complete ( ibdev, cq, cqe ) ) != 0 ) { DBGC ( arbel, "Arbel %p failed to complete: %s\n", arbel, strerror ( rc ) ); DBGC_HD ( arbel, cqe, sizeof ( *cqe ) ); @@ -1397,6 +1439,9 @@ static void arbel_event_port_state_change ( struct arbel *arbel, return; } + /* Update MAD parameters */ + ib_smc_update ( arbel->ibdev[port], arbel_mad ); + /* Notify Infiniband core of link state change */ ib_link_state_changed ( arbel->ibdev[port] ); } @@ -1486,6 +1531,9 @@ static int arbel_open ( struct ib_device *ibdev ) { return rc; } + /* Update MAD parameters */ + ib_smc_update ( ibdev, arbel_mad ); + return 0; } @@ -1601,51 +1649,6 @@ static void arbel_mcast_detach ( struct ib_device *ibdev, } } -/*************************************************************************** - * - * MAD operations - * - *************************************************************************** - */ - -/** - * Issue management datagram - * - * @v ibdev Infiniband device - * @v mad Management datagram - * @v len Length of management datagram - * @ret rc Return status code - */ -static int arbel_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad, - size_t len ) { - struct arbel *arbel = ib_get_drvdata ( ibdev ); - union arbelprm_mad mad_ifc; - int rc; - - /* Copy in request packet */ - memset ( &mad_ifc, 0, sizeof ( mad_ifc ) ); - assert ( len <= sizeof ( mad_ifc.mad ) ); - memcpy ( &mad_ifc.mad, mad, len ); - - /* Issue MAD */ - if ( ( rc = arbel_cmd_mad_ifc ( arbel, ibdev->port, - &mad_ifc ) ) != 0 ) { - DBGC ( arbel, "Arbel %p could not issue MAD IFC: %s\n", - arbel, strerror ( rc ) ); - return rc; - } - - /* Copy out reply packet */ - memcpy ( mad, &mad_ifc.mad, len ); - - if ( mad->status != 0 ) { - DBGC ( arbel, "Arbel %p MAD IFC status %04x\n", - arbel, ntohs ( mad->status ) ); - return -EIO; - } - return 0; -} - /** Arbel Infiniband operations */ static struct ib_device_operations arbel_ib_operations = { .create_cq = arbel_create_cq, @@ -1661,7 +1664,6 @@ static struct ib_device_operations arbel_ib_operations = { .close = arbel_close, .mcast_attach = arbel_mcast_attach, .mcast_detach = arbel_mcast_detach, - .mad = arbel_mad, }; /*************************************************************************** diff --git a/gpxe/src/drivers/infiniband/hermon.c b/gpxe/src/drivers/infiniband/hermon.c index 3ca60033..01eab396 100644 --- a/gpxe/src/drivers/infiniband/hermon.c +++ b/gpxe/src/drivers/infiniband/hermon.c @@ -31,6 +31,7 @@ #include <gpxe/iobuf.h> #include <gpxe/netdevice.h> #include <gpxe/infiniband.h> +#include <gpxe/ib_smc.h> #include "hermon.h" /** @@ -610,6 +611,50 @@ static void hermon_free_mtt ( struct hermon *hermon, /*************************************************************************** * + * MAD operations + * + *************************************************************************** + */ + +/** + * Issue management datagram + * + * @v ibdev Infiniband device + * @v mad Management datagram + * @ret rc Return status code + */ +static int hermon_mad ( struct ib_device *ibdev, union ib_mad *mad ) { + struct hermon *hermon = ib_get_drvdata ( ibdev ); + union hermonprm_mad mad_ifc; + int rc; + + linker_assert ( sizeof ( *mad ) == sizeof ( mad_ifc.mad ), + mad_size_mismatch ); + + /* Copy in request packet */ + memcpy ( &mad_ifc.mad, mad, sizeof ( mad_ifc.mad ) ); + + /* Issue MAD */ + if ( ( rc = hermon_cmd_mad_ifc ( hermon, ibdev->port, + &mad_ifc ) ) != 0 ) { + DBGC ( hermon, "Hermon %p could not issue MAD IFC: %s\n", + hermon, strerror ( rc ) ); + return rc; + } + + /* Copy out reply packet */ + memcpy ( mad, &mad_ifc.mad, sizeof ( *mad ) ); + + if ( mad->hdr.status != 0 ) { + DBGC ( hermon, "Hermon %p MAD IFC status %04x\n", + hermon, ntohs ( mad->hdr.status ) ); + return -EIO; + } + return 0; +} + +/*************************************************************************** + * * Completion queue operations * *************************************************************************** @@ -1015,7 +1060,7 @@ static int hermon_post_send ( struct ib_device *ibdev, ud_address_vector.pd, HERMON_GLOBAL_PD, ud_address_vector.port_number, ibdev->port ); MLX_FILL_2 ( &wqe->ud, 1, - ud_address_vector.rlid, av->dlid, + ud_address_vector.rlid, av->lid, ud_address_vector.g, av->gid_present ); MLX_FILL_1 ( &wqe->ud, 2, ud_address_vector.max_stat_rate, @@ -1024,7 +1069,7 @@ static int hermon_post_send ( struct ib_device *ibdev, MLX_FILL_1 ( &wqe->ud, 3, ud_address_vector.sl, av->sl ); gid = ( av->gid_present ? &av->gid : &hermon_no_gid ); memcpy ( &wqe->ud.u.dwords[4], gid, sizeof ( *gid ) ); - MLX_FILL_1 ( &wqe->ud, 8, destination_qp, av->dest_qp ); + MLX_FILL_1 ( &wqe->ud, 8, destination_qp, av->qpn ); MLX_FILL_1 ( &wqe->ud, 9, q_key, av->qkey ); MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_len ( iobuf ) ); MLX_FILL_1 ( &wqe->data[0], 1, l_key, hermon->reserved_lkey ); @@ -1101,39 +1146,34 @@ static int hermon_post_recv ( struct ib_device *ibdev, * @v ibdev Infiniband device * @v cq Completion queue * @v cqe Hardware completion queue entry - * @v complete_send Send completion handler - * @v complete_recv Receive completion handler * @ret rc Return status code */ static int hermon_complete ( struct ib_device *ibdev, struct ib_completion_queue *cq, - union hermonprm_completion_entry *cqe, - ib_completer_t complete_send, - ib_completer_t complete_recv ) { + union hermonprm_completion_entry *cqe ) { struct hermon *hermon = ib_get_drvdata ( ibdev ); - struct ib_completion completion; struct ib_work_queue *wq; struct ib_queue_pair *qp; struct hermon_queue_pair *hermon_qp; struct io_buffer *iobuf; - ib_completer_t complete; + struct ib_address_vector av; + struct ib_global_route_header *grh; unsigned int opcode; unsigned long qpn; int is_send; unsigned int wqe_idx; + size_t len; int rc = 0; /* Parse completion */ - memset ( &completion, 0, sizeof ( completion ) ); qpn = MLX_GET ( &cqe->normal, qpn ); is_send = MLX_GET ( &cqe->normal, s_r ); opcode = MLX_GET ( &cqe->normal, opcode ); if ( opcode >= HERMON_OPCODE_RECV_ERROR ) { /* "s" field is not valid for error opcodes */ is_send = ( opcode == HERMON_OPCODE_SEND_ERROR ); - completion.syndrome = MLX_GET ( &cqe->error, syndrome ); - DBGC ( hermon, "Hermon %p CQN %lx syndrome %x vendor %lx\n", - hermon, cq->cqn, completion.syndrome, + DBGC ( hermon, "Hermon %p CQN %lx syndrome %lx vendor %lx\n", + hermon, cq->cqn, MLX_GET ( &cqe->error, syndrome ), MLX_GET ( &cqe->error, vendor_error_syndrome ) ); rc = -EIO; /* Don't return immediately; propagate error to completer */ @@ -1160,21 +1200,28 @@ static int hermon_complete ( struct ib_device *ibdev, } wq->iobufs[wqe_idx] = NULL; - /* Fill in length for received packets */ - if ( ! is_send ) { - completion.len = MLX_GET ( &cqe->normal, byte_cnt ); - if ( completion.len > iob_tailroom ( iobuf ) ) { - DBGC ( hermon, "Hermon %p CQN %lx QPN %lx IDX %x " - "overlength received packet length %zd\n", - hermon, cq->cqn, qpn, wqe_idx, completion.len ); - return -EIO; - } + if ( is_send ) { + /* Hand off to completion handler */ + ib_complete_send ( ibdev, qp, iobuf, rc ); + } else { + /* Set received length */ + len = MLX_GET ( &cqe->normal, byte_cnt ); + assert ( len <= iob_tailroom ( iobuf ) ); + iob_put ( iobuf, len ); + assert ( iob_len ( iobuf ) >= sizeof ( *grh ) ); + grh = iobuf->data; + iob_pull ( iobuf, sizeof ( *grh ) ); + /* Construct address vector */ + memset ( &av, 0, sizeof ( av ) ); + av.qpn = MLX_GET ( &cqe->normal, srq_rqpn ); + av.lid = MLX_GET ( &cqe->normal, slid_smac47_32 ); + av.sl = MLX_GET ( &cqe->normal, sl ); + av.gid_present = MLX_GET ( &cqe->normal, g ); + memcpy ( &av.gid, &grh->sgid, sizeof ( av.gid ) ); + /* Hand off to completion handler */ + ib_complete_recv ( ibdev, qp, &av, iobuf, rc ); } - /* Pass off to caller's completion handler */ - complete = ( is_send ? complete_send : complete_recv ); - complete ( ibdev, qp, &completion, iobuf ); - return rc; } @@ -1183,13 +1230,9 @@ static int hermon_complete ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v cq Completion queue - * @v complete_send Send completion handler - * @v complete_recv Receive completion handler */ static void hermon_poll_cq ( struct ib_device *ibdev, - struct ib_completion_queue *cq, - ib_completer_t complete_send, - ib_completer_t complete_recv ) { + struct ib_completion_queue *cq ) { struct hermon *hermon = ib_get_drvdata ( ibdev ); struct hermon_completion_queue *hermon_cq = ib_cq_get_drvdata ( cq ); union hermonprm_completion_entry *cqe; @@ -1209,8 +1252,7 @@ static void hermon_poll_cq ( struct ib_device *ibdev, DBGCP_HD ( hermon, cqe, sizeof ( *cqe ) ); /* Handle completion */ - if ( ( rc = hermon_complete ( ibdev, cq, cqe, complete_send, - complete_recv ) ) != 0 ) { + if ( ( rc = hermon_complete ( ibdev, cq, cqe ) ) != 0 ) { DBGC ( hermon, "Hermon %p failed to complete: %s\n", hermon, strerror ( rc ) ); DBGC_HD ( hermon, cqe, sizeof ( *cqe ) ); @@ -1380,6 +1422,9 @@ static void hermon_event_port_state_change ( struct hermon *hermon, return; } + /* Update MAD parameters */ + ib_smc_update ( hermon->ibdev[port], hermon_mad ); + /* Notify Infiniband core of link state change */ ib_link_state_changed ( hermon->ibdev[port] ); } @@ -1468,6 +1513,9 @@ static int hermon_open ( struct ib_device *ibdev ) { return rc; } + /* Update MAD parameters */ + ib_smc_update ( ibdev, hermon_mad ); + return 0; } @@ -1582,51 +1630,6 @@ static void hermon_mcast_detach ( struct ib_device *ibdev, } } -/*************************************************************************** - * - * MAD operations - * - *************************************************************************** - */ - -/** - * Issue management datagram - * - * @v ibdev Infiniband device - * @v mad Management datagram - * @v len Length of management datagram - * @ret rc Return status code - */ -static int hermon_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad, - size_t len ) { - struct hermon *hermon = ib_get_drvdata ( ibdev ); - union hermonprm_mad mad_ifc; - int rc; - - /* Copy in request packet */ - memset ( &mad_ifc, 0, sizeof ( mad_ifc ) ); - assert ( len <= sizeof ( mad_ifc.mad ) ); - memcpy ( &mad_ifc.mad, mad, len ); - - /* Issue MAD */ - if ( ( rc = hermon_cmd_mad_ifc ( hermon, ibdev->port, - &mad_ifc ) ) != 0 ) { - DBGC ( hermon, "Hermon %p could not issue MAD IFC: %s\n", - hermon, strerror ( rc ) ); - return rc; - } - - /* Copy out reply packet */ - memcpy ( mad, &mad_ifc.mad, len ); - - if ( mad->status != 0 ) { - DBGC ( hermon, "Hermon %p MAD IFC status %04x\n", - hermon, ntohs ( mad->status ) ); - return -EIO; - } - return 0; -} - /** Hermon Infiniband operations */ static struct ib_device_operations hermon_ib_operations = { .create_cq = hermon_create_cq, @@ -1642,7 +1645,6 @@ static struct ib_device_operations hermon_ib_operations = { .close = hermon_close, .mcast_attach = hermon_mcast_attach, .mcast_detach = hermon_mcast_detach, - .mad = hermon_mad, }; /*************************************************************************** diff --git a/gpxe/src/drivers/infiniband/ib_packet.c b/gpxe/src/drivers/infiniband/ib_packet.c new file mode 100644 index 00000000..74721337 --- /dev/null +++ b/gpxe/src/drivers/infiniband/ib_packet.c @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <byteswap.h> +#include <gpxe/iobuf.h> +#include <gpxe/infiniband.h> +#include <gpxe/ib_packet.h> + +/** + * @file + * + * Infiniband Packet Formats + * + */ + +/** + * Add IB headers + * + * @v ibdev Infiniband device + * @v iobuf I/O buffer to contain headers + * @v qp Queue pair + * @v payload_len Payload length + * @v av Address vector + */ +int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf, + struct ib_queue_pair *qp, size_t payload_len, + const struct ib_address_vector *av ) { + struct ib_local_route_header *lrh; + struct ib_global_route_header *grh; + struct ib_base_transport_header *bth; + struct ib_datagram_extended_transport_header *deth; + size_t orig_iob_len = iob_len ( iobuf ); + size_t pad_len; + size_t lrh_len; + size_t grh_len; + unsigned int vl; + unsigned int lnh; + + DBGC2 ( ibdev, "IBDEV %p TX %04x:%08lx => %04x:%08lx (key %08lx)\n", + ibdev, ibdev->lid, qp->qpn, av->lid, av->qpn, av->qkey ); + + /* Calculate packet length */ + pad_len = ( (-payload_len) & 0x3 ); + payload_len += pad_len; + payload_len += 4; /* ICRC */ + + /* Reserve space for headers */ + orig_iob_len = iob_len ( iobuf ); + deth = iob_push ( iobuf, sizeof ( *deth ) ); + bth = iob_push ( iobuf, sizeof ( *bth ) ); + grh_len = ( payload_len + iob_len ( iobuf ) - orig_iob_len ); + grh = ( av->gid_present ? + iob_push ( iobuf, sizeof ( *grh ) ) : NULL ); + lrh = iob_push ( iobuf, sizeof ( *lrh ) ); + lrh_len = ( payload_len + iob_len ( iobuf ) - orig_iob_len ); + + /* Construct LRH */ + vl = ( ( av->qpn == IB_QPN_SMP ) ? IB_VL_SMP : IB_VL_DEFAULT ); + lrh->vl__lver = ( vl << 4 ); + lnh = ( grh ? IB_LNH_GRH : IB_LNH_BTH ); + lrh->sl__lnh = ( ( av->sl << 4 ) | lnh ); + lrh->dlid = htons ( av->lid ); + lrh->length = htons ( lrh_len >> 2 ); + lrh->slid = htons ( ibdev->lid ); + + /* Construct GRH, if required */ + if ( grh ) { + grh->ipver__tclass__flowlabel = + htonl ( IB_GRH_IPVER_IPv6 << 28 ); + grh->paylen = htons ( grh_len ); + grh->nxthdr = IB_GRH_NXTHDR_IBA; + grh->hoplmt = 0; + memcpy ( &grh->sgid, &ibdev->gid, sizeof ( grh->sgid ) ); + memcpy ( &grh->dgid, &av->gid, sizeof ( grh->dgid ) ); + } + + /* Construct BTH */ + bth->opcode = BTH_OPCODE_UD_SEND; + bth->se__m__padcnt__tver = ( pad_len << 4 ); + bth->pkey = htons ( ibdev->pkey ); + bth->dest_qp = htonl ( av->qpn ); + bth->ack__psn = htonl ( ( ibdev->psn++ ) & 0xffffffUL ); + + /* Construct DETH */ + deth->qkey = htonl ( av->qkey ); + deth->src_qp = htonl ( qp->qpn ); + + DBGCP_HDA ( ibdev, 0, iobuf->data, + ( iob_len ( iobuf ) - orig_iob_len ) ); + + return 0; +} + +/** + * Remove IB headers + * + * @v ibdev Infiniband device + * @v iobuf I/O buffer containing headers + * @v qp Queue pair to fill in, or NULL + * @v payload_len Payload length to fill in, or NULL + * @v av Address vector to fill in + */ +int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, + struct ib_queue_pair **qp, size_t *payload_len, + struct ib_address_vector *av ) { + struct ib_local_route_header *lrh; + struct ib_global_route_header *grh; + struct ib_base_transport_header *bth; + struct ib_datagram_extended_transport_header *deth; + size_t orig_iob_len = iob_len ( iobuf ); + unsigned int lnh; + size_t pad_len; + unsigned long qpn; + unsigned int lid; + + /* Clear return values */ + if ( qp ) + *qp = NULL; + if ( payload_len ) + *payload_len = 0; + memset ( av, 0, sizeof ( *av ) ); + + /* Extract LRH */ + if ( iob_len ( iobuf ) < sizeof ( *lrh ) ) { + DBGC ( ibdev, "IBDEV %p RX too short (%zd bytes) for LRH\n", + ibdev, iob_len ( iobuf ) ); + return -EINVAL; + } + lrh = iobuf->data; + iob_pull ( iobuf, sizeof ( *lrh ) ); + av->lid = ntohs ( lrh->slid ); + av->sl = ( lrh->sl__lnh >> 4 ); + lnh = ( lrh->sl__lnh & 0x3 ); + lid = ntohs ( lrh->dlid ); + + /* Reject unsupported packets */ + if ( ! ( ( lnh == IB_LNH_BTH ) || ( lnh == IB_LNH_GRH ) ) ) { + DBGC ( ibdev, "IBDEV %p RX unsupported LNH %x\n", + ibdev, lnh ); + return -ENOTSUP; + } + + /* Extract GRH, if present */ + if ( lnh == IB_LNH_GRH ) { + if ( iob_len ( iobuf ) < sizeof ( *grh ) ) { + DBGC ( ibdev, "IBDEV %p RX too short (%zd bytes) " + "for GRH\n", ibdev, iob_len ( iobuf ) ); + return -EINVAL; + } + grh = iobuf->data; + iob_pull ( iobuf, sizeof ( *grh ) ); + av->gid_present = 1; + memcpy ( &av->gid, &grh->sgid, sizeof ( av->gid ) ); + } else { + grh = NULL; + } + + /* Extract BTH */ + if ( iob_len ( iobuf ) < sizeof ( *bth ) ) { + DBGC ( ibdev, "IBDEV %p RX too short (%zd bytes) for BTH\n", + ibdev, iob_len ( iobuf ) ); + return -EINVAL; + } + bth = iobuf->data; + iob_pull ( iobuf, sizeof ( *bth ) ); + if ( bth->opcode != BTH_OPCODE_UD_SEND ) { + DBGC ( ibdev, "IBDEV %p unsupported BTH opcode %x\n", + ibdev, bth->opcode ); + return -ENOTSUP; + } + qpn = ntohl ( bth->dest_qp ); + + /* Extract DETH */ + if ( iob_len ( iobuf ) < sizeof ( *deth ) ) { + DBGC ( ibdev, "IBDEV %p RX too short (%zd bytes) for DETH\n", + ibdev, iob_len ( iobuf ) ); + return -EINVAL; + } + deth = iobuf->data; + iob_pull ( iobuf, sizeof ( *deth ) ); + av->qpn = ntohl ( deth->src_qp ); + av->qkey = ntohl ( deth->qkey ); + + /* Calculate payload length, if applicable */ + if ( payload_len ) { + pad_len = ( ( bth->se__m__padcnt__tver >> 4 ) & 0x3 ); + *payload_len = ( ( ntohs ( lrh->length ) << 2 ) + - ( orig_iob_len - iob_len ( iobuf ) ) + - pad_len - 4 /* ICRC */ ); + } + + /* Determine destination QP, if applicable */ + if ( qp ) { + if ( IB_LID_MULTICAST ( lid ) && grh ) { + *qp = ib_find_qp_mgid ( ibdev, &grh->dgid ); + } else { + *qp = ib_find_qp_qpn ( ibdev, qpn ); + } + if ( ! *qp ) { + DBGC ( ibdev, "IBDEV %p RX for nonexistent QP\n", + ibdev ); + return -ENODEV; + } + } + + DBGC2 ( ibdev, "IBDEV %p RX %04x:%08lx <= %04x:%08lx (key %08lx)\n", + ibdev, lid, + ( IB_LID_MULTICAST( lid ) ? ( qp ? (*qp)->qpn : -1UL ) : qpn ), + av->lid, av->qpn, ntohl ( deth->qkey ) ); + DBGCP_HDA ( ibdev, 0, + ( iobuf->data - ( orig_iob_len - iob_len ( iobuf ) ) ), + ( orig_iob_len - iob_len ( iobuf ) ) ); + + return 0; +} diff --git a/gpxe/src/drivers/infiniband/ib_sma.c b/gpxe/src/drivers/infiniband/ib_sma.c new file mode 100644 index 00000000..9426c8f1 --- /dev/null +++ b/gpxe/src/drivers/infiniband/ib_sma.c @@ -0,0 +1,553 @@ +/* + * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> +#include <unistd.h> +#include <byteswap.h> +#include <gpxe/infiniband.h> +#include <gpxe/iobuf.h> +#include <gpxe/process.h> +#include <gpxe/ib_sma.h> + +/** + * @file + * + * Infiniband Subnet Management Agent + * + */ + +/** + * Get node information + * + * @v sma Subnet management agent + * @v get Attribute to get + */ +static void ib_sma_get_node_info ( struct ib_sma *sma, + union ib_smp_data *get ) { + struct ib_device *ibdev = sma->ibdev; + struct ib_node_info *node_info = &get->node_info; + struct ib_device *tmp; + + memset ( node_info, 0, sizeof ( *node_info ) ); + node_info->base_version = IB_MGMT_BASE_VERSION; + node_info->class_version = IB_SMP_CLASS_VERSION; + node_info->node_type = IB_NODE_TYPE_HCA; + /* Search for IB devices with the same physical device to + * identify port count and a suitable Node GUID. + */ + for_each_ibdev ( tmp ) { + if ( tmp->dev != ibdev->dev ) + continue; + if ( node_info->num_ports == 0 ) { + memcpy ( node_info->sys_guid, &tmp->gid.u.half[1], + sizeof ( node_info->sys_guid ) ); + memcpy ( node_info->node_guid, &tmp->gid.u.half[1], + sizeof ( node_info->node_guid ) ); + } + node_info->num_ports++; + } + memcpy ( node_info->port_guid, &ibdev->gid.u.half[1], + sizeof ( node_info->port_guid ) ); + node_info->partition_cap = htons ( 1 ); + node_info->local_port_num = ibdev->port; +} + +/** + * Get node description + * + * @v sma Subnet management agent + * @v get Attribute to get + */ +static void ib_sma_get_node_desc ( struct ib_sma *sma, + union ib_smp_data *get ) { + struct ib_device *ibdev = sma->ibdev; + struct ib_node_desc *node_desc = &get->node_desc; + struct ib_gid_half *guid = &ibdev->gid.u.half[1]; + + memset ( node_desc, 0, sizeof ( *node_desc ) ); + snprintf ( node_desc->node_string, sizeof ( node_desc->node_string ), + "gPXE %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)", + guid->bytes[0], guid->bytes[1], guid->bytes[2], + guid->bytes[3], guid->bytes[4], guid->bytes[5], + guid->bytes[6], guid->bytes[7], ibdev->dev->name ); +} + +/** + * Get GUID information + * + * @v sma Subnet management agent + * @v get Attribute to get + */ +static void ib_sma_get_guid_info ( struct ib_sma *sma, + union ib_smp_data *get ) { + struct ib_device *ibdev = sma->ibdev; + struct ib_guid_info *guid_info = &get->guid_info; + + memset ( guid_info, 0, sizeof ( *guid_info ) ); + memcpy ( guid_info->guid[0], &ibdev->gid.u.half[1], + sizeof ( guid_info->guid[0] ) ); +} + +/** + * Get port information + * + * @v sma Subnet management agent + * @v get Attribute to get + */ +static void ib_sma_get_port_info ( struct ib_sma *sma, + union ib_smp_data *get ) { + struct ib_device *ibdev = sma->ibdev; + struct ib_port_info *port_info = &get->port_info; + + memset ( port_info, 0, sizeof ( *port_info ) ); + memcpy ( port_info->gid_prefix, &ibdev->gid.u.half[0], + sizeof ( port_info->gid_prefix ) ); + port_info->lid = ntohs ( ibdev->lid ); + port_info->mastersm_lid = ntohs ( ibdev->sm_lid ); + port_info->local_port_num = ibdev->port; + port_info->link_width_enabled = ibdev->link_width; + port_info->link_width_supported = ibdev->link_width; + port_info->link_width_active = ibdev->link_width; + port_info->link_speed_supported__port_state = + ( ( ibdev->link_speed << 4 ) | ibdev->port_state ); + port_info->port_phys_state__link_down_def_state = + ( ( IB_PORT_PHYS_STATE_POLLING << 4 ) | + IB_PORT_PHYS_STATE_POLLING ); + port_info->link_speed_active__link_speed_enabled = + ( ( ibdev->link_speed << 4 ) | ibdev->link_speed ); + port_info->neighbour_mtu__mastersm_sl = + ( ( IB_MTU_2048 << 4 ) | ibdev->sm_sl ); + port_info->vl_cap__init_type = ( IB_VL_0 << 4 ); + port_info->init_type_reply__mtu_cap = IB_MTU_2048; + port_info->operational_vls__enforcement = ( IB_VL_0 << 4 ); + port_info->guid_cap = 1; +} + +/** + * Set port information + * + * @v sma Subnet management agent + * @v set Attribute to set + * @ret rc Return status code + */ +static int ib_sma_set_port_info ( struct ib_sma *sma, + const union ib_smp_data *set ) { + struct ib_device *ibdev = sma->ibdev; + const struct ib_port_info *port_info = &set->port_info; + + memcpy ( &ibdev->gid.u.half[0], port_info->gid_prefix, + sizeof ( ibdev->gid.u.half[0] ) ); + ibdev->lid = ntohs ( port_info->lid ); + ibdev->sm_lid = ntohs ( port_info->mastersm_lid ); + ibdev->sm_sl = ( port_info->neighbour_mtu__mastersm_sl & 0xf ); + + if ( ! sma->op->set_port_info ) { + /* Not an error; we just ignore all other settings */ + return 0; + } + + return sma->op->set_port_info ( ibdev, port_info ); +} + +/** + * Get partition key table + * + * @v sma Subnet management agent + * @v get Attribute to get + */ +static void ib_sma_get_pkey_table ( struct ib_sma *sma, + union ib_smp_data *get ) { + struct ib_device *ibdev = sma->ibdev; + struct ib_pkey_table *pkey_table = &get->pkey_table; + + memset ( pkey_table, 0, sizeof ( *pkey_table ) ); + pkey_table->pkey[0] = htons ( ibdev->pkey ); +} + +/** + * Set partition key table + * + * @v sma Subnet management agent + * @v set Attribute to set + */ +static int ib_sma_set_pkey_table ( struct ib_sma *sma, + const union ib_smp_data *get ) { + struct ib_device *ibdev = sma->ibdev; + const struct ib_pkey_table *pkey_table = &get->pkey_table; + + ibdev->pkey = ntohs ( pkey_table->pkey[0] ); + return 0; +} + +/** An attribute handler */ +struct ib_sma_handler { + /** Attribute (in network byte order) */ + uint16_t attr_id; + /** Get attribute + * + * @v sma Subnet management agent + * @v get Attribute to get + * @ret rc Return status code + */ + void ( * get ) ( struct ib_sma *sma, union ib_smp_data *get ); + /** Set attribute + * + * @v sma Subnet management agent + * @v set Attribute to set + * @ret rc Return status code + */ + int ( * set ) ( struct ib_sma *sma, const union ib_smp_data *set ); +}; + +/** List of attribute handlers */ +static struct ib_sma_handler ib_sma_handlers[] = { + { htons ( IB_SMP_ATTR_NODE_DESC ), + ib_sma_get_node_desc, NULL }, + { htons ( IB_SMP_ATTR_NODE_INFO ), + ib_sma_get_node_info, NULL }, + { htons ( IB_SMP_ATTR_GUID_INFO ), + ib_sma_get_guid_info, NULL }, + { htons ( IB_SMP_ATTR_PORT_INFO ), + ib_sma_get_port_info, ib_sma_set_port_info }, + { htons ( IB_SMP_ATTR_PKEY_TABLE ), + ib_sma_get_pkey_table, ib_sma_set_pkey_table }, +}; + +/** + * Identify attribute handler + * + * @v attr_id Attribute ID (in network byte order) + * @ret handler Attribute handler (or NULL) + */ +static struct ib_sma_handler * ib_sma_handler ( uint16_t attr_id ) { + struct ib_sma_handler *handler; + unsigned int i; + + for ( i = 0 ; i < ( sizeof ( ib_sma_handlers ) / + sizeof ( ib_sma_handlers[0] ) ) ; i++ ) { + handler = &ib_sma_handlers[i]; + if ( handler->attr_id == attr_id ) + return handler; + } + + return NULL; +} + +/** + * Respond to management datagram + * + * @v sma Subnet management agent + * @v mad Management datagram + * @ret rc Return status code + */ +static int ib_sma_mad ( struct ib_sma *sma, union ib_mad *mad ) { + struct ib_device *ibdev = sma->ibdev; + struct ib_mad_hdr *hdr = &mad->hdr; + struct ib_mad_smp *smp = &mad->smp; + struct ib_sma_handler *handler = NULL; + unsigned int hop_pointer; + unsigned int hop_count; + int rc; + + DBGC ( sma, "SMA %p received SMP with bv=%02x mc=%02x cv=%02x " + "meth=%02x attr=%04x mod=%08lx\n", sma, hdr->base_version, + hdr->mgmt_class, hdr->class_version, hdr->method, + ntohs ( hdr->attr_id ), ntohl ( hdr->attr_mod ) ); + DBGC2_HDA ( sma, 0, mad, sizeof ( *mad ) ); + + /* Sanity checks */ + if ( hdr->base_version != IB_MGMT_BASE_VERSION ) { + DBGC ( sma, "SMA %p unsupported base version %x\n", + sma, hdr->base_version ); + return -ENOTSUP; + } + if ( ( hdr->mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE ) && + ( hdr->mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED ) ) { + DBGC ( sma, "SMA %p unsupported management class %x\n", + sma, hdr->mgmt_class ); + return -ENOTSUP; + } + if ( hdr->class_version != IB_SMP_CLASS_VERSION ) { + DBGC ( sma, "SMA %p unsupported class version %x\n", + sma, hdr->class_version ); + return -ENOTSUP; + } + if ( ( hdr->method != IB_MGMT_METHOD_GET ) && + ( hdr->method != IB_MGMT_METHOD_SET ) ) { + DBGC ( sma, "SMA %p unsupported method %x\n", + sma, hdr->method ); + return -ENOTSUP; + } + + /* Identify handler */ + if ( ! ( handler = ib_sma_handler ( hdr->attr_id ) ) ) { + DBGC ( sma, "SMA %p unsupported attribute %x\n", + sma, ntohs ( hdr->attr_id ) ); + hdr->status = htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR ); + goto respond_without_data; + } + + /* Set attribute (if applicable) */ + if ( hdr->method != IB_MGMT_METHOD_SET ) { + hdr->status = htons ( IB_MGMT_STATUS_OK ); + goto respond; + } + if ( ! handler->set ) { + DBGC ( sma, "SMA %p attribute %x is unsettable\n", + sma, ntohs ( hdr->attr_id ) ); + hdr->status = htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR ); + goto respond; + } + if ( ( rc = handler->set ( sma, &smp->smp_data ) ) != 0 ) { + DBGC ( sma, "SMA %p could not set attribute %x: %s\n", + sma, ntohs ( hdr->attr_id ), strerror ( rc ) ); + hdr->status = htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR ); + goto respond; + } + + hdr->status = htons ( IB_MGMT_STATUS_OK ); + + respond: + /* Get attribute */ + handler->get ( sma, &smp->smp_data ); + + respond_without_data: + + /* Set method to "Get Response" */ + hdr->method = IB_MGMT_METHOD_GET_RESP; + + /* Set response fields for directed route SMPs */ + if ( hdr->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE ) { + hdr->status |= htons ( IB_SMP_STATUS_D_INBOUND ); + hop_pointer = smp->mad_hdr.class_specific.smp.hop_pointer; + hop_count = smp->mad_hdr.class_specific.smp.hop_count; + assert ( hop_count == hop_pointer ); + if ( hop_pointer < ( sizeof ( smp->return_path.hops ) / + sizeof ( smp->return_path.hops[0] ) ) ) { + smp->return_path.hops[hop_pointer] = ibdev->port; + } else { + DBGC ( sma, "SMA %p invalid hop pointer %d\n", + sma, hop_pointer ); + return -EINVAL; + } + } + + DBGC ( sma, "SMA %p responding with status=%04x\n", + sma, ntohs ( hdr->status ) ); + DBGC2_HDA ( sma, 0, mad, sizeof ( *mad ) ); + + return 0; +} + +/** + * Refill SMA receive ring + * + * @v sma Subnet management agent + */ +static void ib_sma_refill_recv ( struct ib_sma *sma ) { + struct ib_device *ibdev = sma->ibdev; + struct io_buffer *iobuf; + int rc; + + while ( sma->qp->recv.fill < IB_SMA_NUM_RECV_WQES ) { + + /* Allocate I/O buffer */ + iobuf = alloc_iob ( IB_SMA_PAYLOAD_LEN ); + if ( ! iobuf ) { + /* Non-fatal; we will refill on next attempt */ + return; + } + + /* Post I/O buffer */ + if ( ( rc = ib_post_recv ( ibdev, sma->qp, iobuf ) ) != 0 ) { + DBGC ( sma, "SMA %p could not refill: %s\n", + sma, strerror ( rc ) ); + free_iob ( iobuf ); + /* Give up */ + return; + } + } +} + +/** + * Complete SMA send + * + * + * @v ibdev Infiniband device + * @v qp Queue pair + * @v iobuf I/O buffer + * @v rc Completion status code + */ +static void ib_sma_complete_send ( struct ib_device *ibdev __unused, + struct ib_queue_pair *qp, + struct io_buffer *iobuf, int rc ) { + struct ib_sma *sma = ib_qp_get_ownerdata ( qp ); + + if ( rc != 0 ) { + DBGC ( sma, "SMA %p send completion error: %s\n", + sma, strerror ( rc ) ); + } + free_iob ( iobuf ); +} + +/** + * Complete SMA receive + * + * + * @v ibdev Infiniband device + * @v qp Queue pair + * @v av Address vector + * @v iobuf I/O buffer + * @v rc Completion status code + */ +static void ib_sma_complete_recv ( struct ib_device *ibdev, + struct ib_queue_pair *qp, + struct ib_address_vector *av, + struct io_buffer *iobuf, int rc ) { + struct ib_sma *sma = ib_qp_get_ownerdata ( qp ); + union ib_mad *mad; + + /* Ignore errors */ + if ( rc != 0 ) { + DBGC ( sma, "SMA %p RX error: %s\n", sma, strerror ( rc ) ); + goto err; + } + + /* Sanity check */ + if ( iob_len ( iobuf ) != sizeof ( *mad ) ) { + DBGC ( sma, "SMA %p RX bad size (%zd bytes)\n", + sma, iob_len ( iobuf ) ); + goto err; + } + mad = iobuf->data; + + /* Construct MAD response */ + if ( ( rc = ib_sma_mad ( sma, mad ) ) != 0 ) { + DBGC ( sma, "SMA %p could not construct MAD response: %s\n", + sma, strerror ( rc ) ); + goto err; + } + + /* Send MAD response */ + if ( ( rc = ib_post_send ( ibdev, qp, av, iobuf ) ) != 0 ) { + DBGC ( sma, "SMA %p could not send MAD response: %s\n", + sma, strerror ( rc ) ); + goto err; + } + + return; + + err: + free_iob ( iobuf ); +} + +/** SMA completion operations */ +static struct ib_completion_queue_operations ib_sma_completion_ops = { + .complete_send = ib_sma_complete_send, + .complete_recv = ib_sma_complete_recv, +}; + +/** + * Poll SMA + * + * @v process Process + */ +static void ib_sma_step ( struct process *process ) { + struct ib_sma *sma = + container_of ( process, struct ib_sma, poll ); + struct ib_device *ibdev = sma->ibdev; + + /* Poll the kernel completion queue */ + ib_poll_cq ( ibdev, sma->cq ); + + /* Refill the receive ring */ + ib_sma_refill_recv ( sma ); +} + +/** + * Create SMA + * + * @v sma Subnet management agent + * @v ibdev Infiniband device + * @v op Subnet management operations + * @ret rc Return status code + */ +int ib_create_sma ( struct ib_sma *sma, struct ib_device *ibdev, + struct ib_sma_operations *op ) { + int rc; + + /* Initialise fields */ + memset ( sma, 0, sizeof ( *sma ) ); + sma->ibdev = ibdev; + sma->op = op; + process_init ( &sma->poll, ib_sma_step, &ibdev->refcnt ); + + /* Create completion queue */ + sma->cq = ib_create_cq ( ibdev, IB_SMA_NUM_CQES, + &ib_sma_completion_ops ); + if ( ! sma->cq ) { + rc = -ENOMEM; + goto err_create_cq; + } + + /* Create queue pair */ + sma->qp = ib_create_qp ( ibdev, IB_SMA_NUM_SEND_WQES, sma->cq, + IB_SMA_NUM_RECV_WQES, sma->cq, 0 ); + if ( ! sma->qp ) { + rc = -ENOMEM; + goto err_create_qp; + } + ib_qp_set_ownerdata ( sma->qp, sma ); + + /* If we don't get QP0, we can't function */ + if ( sma->qp->qpn != IB_QPN_SMP ) { + DBGC ( sma, "SMA %p on QPN %lx, needs to be on QPN 0\n", + sma, sma->qp->qpn ); + rc = -ENOTSUP; + goto err_not_qp0; + } + + /* Fill receive ring */ + ib_sma_refill_recv ( sma ); + return 0; + + err_not_qp0: + ib_destroy_qp ( ibdev, sma->qp ); + err_create_qp: + ib_destroy_cq ( ibdev, sma->cq ); + err_create_cq: + process_del ( &sma->poll ); + return rc; +} + +/** + * Destroy SMA + * + * @v sma Subnet management agent + */ +void ib_destroy_sma ( struct ib_sma *sma ) { + struct ib_device *ibdev = sma->ibdev; + + ib_destroy_qp ( ibdev, sma->qp ); + ib_destroy_cq ( ibdev, sma->cq ); + process_del ( &sma->poll ); +} diff --git a/gpxe/src/drivers/infiniband/ib_smc.c b/gpxe/src/drivers/infiniband/ib_smc.c new file mode 100644 index 00000000..c07a4fef --- /dev/null +++ b/gpxe/src/drivers/infiniband/ib_smc.c @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <byteswap.h> +#include <gpxe/infiniband.h> +#include <gpxe/ib_smc.h> + +/** + * @file + * + * Infiniband Subnet Management Client + * + */ + +/** + * Get port information + * + * @v ibdev Infiniband device + * @v local_mad Method for issuing local MADs + * @v mad Management datagram to fill in + * @ret rc Return status code + */ +static int ib_smc_get_port_info ( struct ib_device *ibdev, + ib_local_mad_t local_mad, + union ib_mad *mad ) { + int rc; + + /* Construct MAD */ + memset ( mad, 0, sizeof ( *mad ) ); + mad->hdr.base_version = IB_MGMT_BASE_VERSION; + mad->hdr.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; + mad->hdr.class_version = 1; + mad->hdr.method = IB_MGMT_METHOD_GET; + mad->hdr.attr_id = htons ( IB_SMP_ATTR_PORT_INFO ); + mad->hdr.attr_mod = htonl ( ibdev->port ); + + if ( ( rc = local_mad ( ibdev, mad ) ) != 0 ) { + DBGC ( ibdev, "IBDEV %p could not get port info: %s\n", + ibdev, strerror ( rc ) ); + return rc; + } + return 0; +} + +/** + * Get GUID information + * + * @v ibdev Infiniband device + * @v local_mad Method for issuing local MADs + * @v mad Management datagram to fill in + * @ret rc Return status code + */ +static int ib_smc_get_guid_info ( struct ib_device *ibdev, + ib_local_mad_t local_mad, + union ib_mad *mad ) { + int rc; + + /* Construct MAD */ + memset ( mad, 0, sizeof ( *mad ) ); + mad->hdr.base_version = IB_MGMT_BASE_VERSION; + mad->hdr.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; + mad->hdr.class_version = 1; + mad->hdr.method = IB_MGMT_METHOD_GET; + mad->hdr.attr_id = htons ( IB_SMP_ATTR_GUID_INFO ); + + if ( ( rc = local_mad ( ibdev, mad ) ) != 0 ) { + DBGC ( ibdev, "IBDEV %p could not get GUID info: %s\n", + ibdev, strerror ( rc ) ); + return rc; + } + return 0; +} + +/** + * Get partition key table + * + * @v ibdev Infiniband device + * @v local_mad Method for issuing local MADs + * @v mad Management datagram to fill in + * @ret rc Return status code + */ +static int ib_smc_get_pkey_table ( struct ib_device *ibdev, + ib_local_mad_t local_mad, + union ib_mad *mad ) { + int rc; + + /* Construct MAD */ + memset ( mad, 0, sizeof ( *mad ) ); + mad->hdr.base_version = IB_MGMT_BASE_VERSION; + mad->hdr.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; + mad->hdr.class_version = 1; + mad->hdr.method = IB_MGMT_METHOD_GET; + mad->hdr.attr_id = htons ( IB_SMP_ATTR_PKEY_TABLE ); + + if ( ( rc = local_mad ( ibdev, mad ) ) != 0 ) { + DBGC ( ibdev, "IBDEV %p could not get pkey table: %s\n", + ibdev, strerror ( rc ) ); + return rc; + } + return 0; +} + +/** + * Get MAD parameters + * + * @v ibdev Infiniband device + * @v local_mad Method for issuing local MADs + * @ret rc Return status code + */ +int ib_smc_update ( struct ib_device *ibdev, ib_local_mad_t local_mad ) { + union ib_mad mad; + union ib_smp_data *smp = &mad.smp.smp_data; + int rc; + + /* Port info gives us the link state, the first half of the + * port GID and the SM LID. + */ + if ( ( rc = ib_smc_get_port_info ( ibdev, local_mad, &mad ) ) != 0 ) + return rc; + ibdev->port_state = + ( smp->port_info.link_speed_supported__port_state & 0x0f ); + memcpy ( &ibdev->gid.u.half[0], smp->port_info.gid_prefix, + sizeof ( ibdev->gid.u.half[0] ) ); + ibdev->lid = ntohs ( smp->port_info.lid ); + ibdev->sm_lid = ntohs ( smp->port_info.mastersm_lid ); + ibdev->sm_sl = ( smp->port_info.neighbour_mtu__mastersm_sl & 0xf ); + + /* GUID info gives us the second half of the port GID */ + if ( ( rc = ib_smc_get_guid_info ( ibdev, local_mad, &mad ) ) != 0 ) + return rc; + memcpy ( &ibdev->gid.u.half[1], smp->guid_info.guid[0], + sizeof ( ibdev->gid.u.half[1] ) ); + + /* Get partition key */ + if ( ( rc = ib_smc_get_pkey_table ( ibdev, local_mad, &mad ) ) != 0 ) + return rc; + ibdev->pkey = ntohs ( smp->pkey_table.pkey[0] ); + + DBGC ( ibdev, "IBDEV %p port GID is %08lx:%08lx:%08lx:%08lx\n", ibdev, + htonl ( ibdev->gid.u.dwords[0] ), + htonl ( ibdev->gid.u.dwords[1] ), + htonl ( ibdev->gid.u.dwords[2] ), + htonl ( ibdev->gid.u.dwords[3] ) ); + + return 0; +} diff --git a/gpxe/src/drivers/infiniband/linda.c b/gpxe/src/drivers/infiniband/linda.c new file mode 100644 index 00000000..170eec47 --- /dev/null +++ b/gpxe/src/drivers/infiniband/linda.c @@ -0,0 +1,2396 @@ +/* + * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdint.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <assert.h> +#include <gpxe/pci.h> +#include <gpxe/infiniband.h> +#include <gpxe/i2c.h> +#include <gpxe/bitbash.h> +#include <gpxe/malloc.h> +#include <gpxe/iobuf.h> +#include <gpxe/ib_sma.h> +#include "linda.h" + +/** + * @file + * + * QLogic Linda Infiniband HCA + * + */ + +/** A Linda send work queue */ +struct linda_send_work_queue { + /** Send buffer usage */ + uint8_t *send_buf; + /** Producer index */ + unsigned int prod; + /** Consumer index */ + unsigned int cons; +}; + +/** A Linda receive work queue */ +struct linda_recv_work_queue { + /** Receive header ring */ + void *header; + /** Receive header producer offset (written by hardware) */ + struct QIB_7220_scalar header_prod; + /** Receive header consumer offset */ + unsigned int header_cons; + /** Offset within register space of the eager array */ + unsigned long eager_array; + /** Number of entries in eager array */ + unsigned int eager_entries; + /** Eager array producer index */ + unsigned int eager_prod; + /** Eager array consumer index */ + unsigned int eager_cons; +}; + +/** A Linda HCA */ +struct linda { + /** Registers */ + void *regs; + + /** In-use contexts */ + uint8_t used_ctx[LINDA_NUM_CONTEXTS]; + /** Send work queues */ + struct linda_send_work_queue send_wq[LINDA_NUM_CONTEXTS]; + /** Receive work queues */ + struct linda_recv_work_queue recv_wq[LINDA_NUM_CONTEXTS]; + + /** Offset within register space of the first send buffer */ + unsigned long send_buffer_base; + /** Send buffer availability (reported by hardware) */ + struct QIB_7220_SendBufAvail *sendbufavail; + /** Send buffer availability (maintained by software) */ + uint8_t send_buf[LINDA_MAX_SEND_BUFS]; + /** Send buffer availability producer counter */ + unsigned int send_buf_prod; + /** Send buffer availability consumer counter */ + unsigned int send_buf_cons; + /** Number of reserved send buffers (across all QPs) */ + unsigned int reserved_send_bufs; + + /** I2C bit-bashing interface */ + struct i2c_bit_basher i2c; + /** I2C serial EEPROM */ + struct i2c_device eeprom; + + /** Subnet management agent */ + struct ib_sma sma; +}; + +/*************************************************************************** + * + * Linda register access + * + *************************************************************************** + * + * This card requires atomic 64-bit accesses. Strange things happen + * if you try to use 32-bit accesses; sometimes they work, sometimes + * they don't, sometimes you get random data. + * + * These accessors use the "movq" MMX instruction, and so won't work + * on really old Pentiums (which won't have PCIe anyway, so this is + * something of a moot point). + */ + +/** + * Read Linda qword register + * + * @v linda Linda device + * @v dwords Register buffer to read into + * @v offset Register offset + */ +static void linda_readq ( struct linda *linda, uint32_t *dwords, + unsigned long offset ) { + void *addr = ( linda->regs + offset ); + + __asm__ __volatile__ ( "movq (%1), %%mm0\n\t" + "movq %%mm0, (%0)\n\t" + : : "r" ( dwords ), "r" ( addr ) : "memory" ); + + DBGIO ( "[%08lx] => %08lx%08lx\n", + virt_to_phys ( addr ), dwords[1], dwords[0] ); +} +#define linda_readq( _linda, _ptr, _offset ) \ + linda_readq ( (_linda), (_ptr)->u.dwords, (_offset) ) +#define linda_readq_array8b( _linda, _ptr, _offset, _idx ) \ + linda_readq ( (_linda), (_ptr), ( (_offset) + ( (_idx) * 8 ) ) ) +#define linda_readq_array64k( _linda, _ptr, _offset, _idx ) \ + linda_readq ( (_linda), (_ptr), ( (_offset) + ( (_idx) * 65536 ) ) ) + +/** + * Write Linda qword register + * + * @v linda Linda device + * @v dwords Register buffer to write + * @v offset Register offset + */ +static void linda_writeq ( struct linda *linda, const uint32_t *dwords, + unsigned long offset ) { + void *addr = ( linda->regs + offset ); + + DBGIO ( "[%08lx] <= %08lx%08lx\n", + virt_to_phys ( addr ), dwords[1], dwords[0] ); + + __asm__ __volatile__ ( "movq (%0), %%mm0\n\t" + "movq %%mm0, (%1)\n\t" + : : "r" ( dwords ), "r" ( addr ) : "memory" ); +} +#define linda_writeq( _linda, _ptr, _offset ) \ + linda_writeq ( (_linda), (_ptr)->u.dwords, (_offset) ) +#define linda_writeq_array8b( _linda, _ptr, _offset, _idx ) \ + linda_writeq ( (_linda), (_ptr), ( (_offset) + ( (_idx) * 8 ) ) ) +#define linda_writeq_array64k( _linda, _ptr, _offset, _idx ) \ + linda_writeq ( (_linda), (_ptr), ( (_offset) + ( (_idx) * 65536 ) ) ) + +/** + * Write Linda dword register + * + * @v linda Linda device + * @v dword Value to write + * @v offset Register offset + */ +static void linda_writel ( struct linda *linda, uint32_t dword, + unsigned long offset ) { + writel ( dword, ( linda->regs + offset ) ); +} + +/*************************************************************************** + * + * Link state management + * + *************************************************************************** + */ + +/** + * Textual representation of link state + * + * @v link_state Link state + * @ret link_text Link state text + */ +static const char * linda_link_state_text ( unsigned int link_state ) { + switch ( link_state ) { + case LINDA_LINK_STATE_DOWN: return "DOWN"; + case LINDA_LINK_STATE_INIT: return "INIT"; + case LINDA_LINK_STATE_ARM: return "ARM"; + case LINDA_LINK_STATE_ACTIVE: return "ACTIVE"; + case LINDA_LINK_STATE_ACT_DEFER:return "ACT_DEFER"; + default: return "UNKNOWN"; + } +} + +/** + * Handle link state change + * + * @v linda Linda device + */ +static void linda_link_state_changed ( struct ib_device *ibdev ) { + struct linda *linda = ib_get_drvdata ( ibdev ); + struct QIB_7220_IBCStatus ibcstatus; + struct QIB_7220_EXTCtrl extctrl; + unsigned int link_state; + unsigned int link_width; + unsigned int link_speed; + + /* Read link state */ + linda_readq ( linda, &ibcstatus, QIB_7220_IBCStatus_offset ); + link_state = BIT_GET ( &ibcstatus, LinkState ); + link_width = BIT_GET ( &ibcstatus, LinkWidthActive ); + link_speed = BIT_GET ( &ibcstatus, LinkSpeedActive ); + DBGC ( linda, "Linda %p link state %s (%s %s)\n", linda, + linda_link_state_text ( link_state ), + ( link_speed ? "DDR" : "SDR" ), ( link_width ? "x4" : "x1" ) ); + + /* Set LEDs according to link state */ + linda_readq ( linda, &extctrl, QIB_7220_EXTCtrl_offset ); + BIT_SET ( &extctrl, LEDPriPortGreenOn, + ( ( link_state >= LINDA_LINK_STATE_INIT ) ? 1 : 0 ) ); + BIT_SET ( &extctrl, LEDPriPortYellowOn, + ( ( link_state >= LINDA_LINK_STATE_ACTIVE ) ? 1 : 0 ) ); + linda_writeq ( linda, &extctrl, QIB_7220_EXTCtrl_offset ); + + /* Notify Infiniband core of link state change */ + ibdev->port_state = ( link_state + 1 ); + ibdev->link_width = + ( link_width ? IB_LINK_WIDTH_4X : IB_LINK_WIDTH_1X ); + ibdev->link_speed = + ( link_speed ? IB_LINK_SPEED_DDR : IB_LINK_SPEED_SDR ); + ib_link_state_changed ( ibdev ); +} + +/** + * Set port information + * + * @v ibdev Infiniband device + * @v port_info New port information + */ +static int linda_set_port_info ( struct ib_device *ibdev, + const struct ib_port_info *port_info ) { + struct linda *linda = ib_get_drvdata ( ibdev ); + struct QIB_7220_IBCCtrl ibcctrl; + unsigned int port_state; + unsigned int link_state; + + /* Set new link state */ + port_state = ( port_info->link_speed_supported__port_state & 0xf ); + if ( port_state ) { + link_state = ( port_state - 1 ); + DBGC ( linda, "Linda %p set link state to %s (%x)\n", linda, + linda_link_state_text ( link_state ), link_state ); + linda_readq ( linda, &ibcctrl, QIB_7220_IBCCtrl_offset ); + BIT_SET ( &ibcctrl, LinkCmd, link_state ); + linda_writeq ( linda, &ibcctrl, QIB_7220_IBCCtrl_offset ); + } + + /* Detect and report link state change */ + linda_link_state_changed ( ibdev ); + + return 0; +} + +/** Linda subnet management operations */ +static struct ib_sma_operations linda_sma_operations = { + .set_port_info = linda_set_port_info, +}; + +/*************************************************************************** + * + * Context allocation + * + *************************************************************************** + */ + +/** + * Map context number to QPN + * + * @v ctx Context index + * @ret qpn Queue pair number + */ +static int linda_ctx_to_qpn ( unsigned int ctx ) { + /* This mapping is fixed by hardware */ + return ( ctx * 2 ); +} + +/** + * Map QPN to context number + * + * @v qpn Queue pair number + * @ret ctx Context index + */ +static int linda_qpn_to_ctx ( unsigned int qpn ) { + /* This mapping is fixed by hardware */ + return ( qpn / 2 ); +} + +/** + * Allocate a context + * + * @v linda Linda device + * @ret ctx Context index, or negative error + */ +static int linda_alloc_ctx ( struct linda *linda ) { + unsigned int ctx; + + for ( ctx = 0 ; ctx < LINDA_NUM_CONTEXTS ; ctx++ ) { + + if ( ! linda->used_ctx[ctx] ) { + linda->used_ctx[ctx ] = 1; + DBGC2 ( linda, "Linda %p CTX %d allocated\n", + linda, ctx ); + return ctx; + } + } + + DBGC ( linda, "Linda %p out of available contexts\n", linda ); + return -ENOENT; +} + +/** + * Free a context + * + * @v linda Linda device + * @v ctx Context index + */ +static void linda_free_ctx ( struct linda *linda, unsigned int ctx ) { + + linda->used_ctx[ctx] = 0; + DBGC2 ( linda, "Linda %p CTX %d freed\n", linda, ctx ); +} + +/*************************************************************************** + * + * Send datapath + * + *************************************************************************** + */ + +/** Send buffer toggle bit + * + * We encode send buffers as 7 bits of send buffer index plus a single + * bit which should match the "check" bit in the SendBufAvail array. + */ +#define LINDA_SEND_BUF_TOGGLE 0x80 + +/** + * Allocate a send buffer + * + * @v linda Linda device + * @ret send_buf Send buffer + * + * You must guarantee that a send buffer is available. This is done + * by refusing to allocate more TX WQEs in total than the number of + * available send buffers. + */ +static unsigned int linda_alloc_send_buf ( struct linda *linda ) { + unsigned int send_buf; + + send_buf = linda->send_buf[linda->send_buf_cons]; + send_buf ^= LINDA_SEND_BUF_TOGGLE; + linda->send_buf_cons = ( ( linda->send_buf_cons + 1 ) % + LINDA_MAX_SEND_BUFS ); + return send_buf; +} + +/** + * Free a send buffer + * + * @v linda Linda device + * @v send_buf Send buffer + */ +static void linda_free_send_buf ( struct linda *linda, + unsigned int send_buf ) { + linda->send_buf[linda->send_buf_prod] = send_buf; + linda->send_buf_prod = ( ( linda->send_buf_prod + 1 ) % + LINDA_MAX_SEND_BUFS ); +} + +/** + * Check to see if send buffer is in use + * + * @v linda Linda device + * @v send_buf Send buffer + * @ret in_use Send buffer is in use + */ +static int linda_send_buf_in_use ( struct linda *linda, + unsigned int send_buf ) { + unsigned int send_idx; + unsigned int send_check; + unsigned int inusecheck; + unsigned int inuse; + unsigned int check; + + send_idx = ( send_buf & ~LINDA_SEND_BUF_TOGGLE ); + send_check = ( !! ( send_buf & LINDA_SEND_BUF_TOGGLE ) ); + inusecheck = BIT_GET ( linda->sendbufavail, InUseCheck[send_idx] ); + inuse = ( !! ( inusecheck & 0x02 ) ); + check = ( !! ( inusecheck & 0x01 ) ); + return ( inuse || ( check != send_check ) ); +} + +/** + * Calculate starting offset for send buffer + * + * @v linda Linda device + * @v send_buf Send buffer + * @ret offset Starting offset + */ +static unsigned long linda_send_buffer_offset ( struct linda *linda, + unsigned int send_buf ) { + return ( linda->send_buffer_base + + ( ( send_buf & ~LINDA_SEND_BUF_TOGGLE ) * + LINDA_SEND_BUF_SIZE ) ); +} + +/** + * Create send work queue + * + * @v linda Linda device + * @v qp Queue pair + */ +static int linda_create_send_wq ( struct linda *linda, + struct ib_queue_pair *qp ) { + struct ib_work_queue *wq = &qp->send; + struct linda_send_work_queue *linda_wq = ib_wq_get_drvdata ( wq ); + int rc; + + /* Reserve send buffers */ + if ( ( linda->reserved_send_bufs + qp->send.num_wqes ) > + LINDA_MAX_SEND_BUFS ) { + DBGC ( linda, "Linda %p out of send buffers (have %d, used " + "%d, need %d)\n", linda, LINDA_MAX_SEND_BUFS, + linda->reserved_send_bufs, qp->send.num_wqes ); + rc = -ENOBUFS; + goto err_reserve_bufs; + } + linda->reserved_send_bufs += qp->send.num_wqes; + + /* Reset work queue */ + linda_wq->prod = 0; + linda_wq->cons = 0; + + /* Allocate space for send buffer uasge list */ + linda_wq->send_buf = zalloc ( qp->send.num_wqes * + sizeof ( linda_wq->send_buf[0] ) ); + if ( ! linda_wq->send_buf ) { + rc = -ENOBUFS; + goto err_alloc_send_buf; + } + + return 0; + + free ( linda_wq->send_buf ); + err_alloc_send_buf: + linda->reserved_send_bufs -= qp->send.num_wqes; + err_reserve_bufs: + return rc; +} + +/** + * Destroy send work queue + * + * @v linda Linda device + * @v qp Queue pair + */ +static void linda_destroy_send_wq ( struct linda *linda, + struct ib_queue_pair *qp ) { + struct ib_work_queue *wq = &qp->send; + struct linda_send_work_queue *linda_wq = ib_wq_get_drvdata ( wq ); + + free ( linda_wq->send_buf ); + linda->reserved_send_bufs -= qp->send.num_wqes; +} + +/** + * Initialise send datapath + * + * @v linda Linda device + * @ret rc Return status code + */ +static int linda_init_send ( struct linda *linda ) { + struct QIB_7220_SendBufBase sendbufbase; + struct QIB_7220_SendBufAvailAddr sendbufavailaddr; + struct QIB_7220_SendCtrl sendctrl; + unsigned int i; + int rc; + + /* Retrieve SendBufBase */ + linda_readq ( linda, &sendbufbase, QIB_7220_SendBufBase_offset ); + linda->send_buffer_base = BIT_GET ( &sendbufbase, + BaseAddr_SmallPIO ); + DBGC ( linda, "Linda %p send buffers at %lx\n", + linda, linda->send_buffer_base ); + + /* Initialise the send_buf[] array */ + for ( i = 0 ; i < LINDA_MAX_SEND_BUFS ; i++ ) + linda->send_buf[i] = i; + + /* Allocate space for the SendBufAvail array */ + linda->sendbufavail = malloc_dma ( sizeof ( *linda->sendbufavail ), + LINDA_SENDBUFAVAIL_ALIGN ); + if ( ! linda->sendbufavail ) { + rc = -ENOMEM; + goto err_alloc_sendbufavail; + } + memset ( linda->sendbufavail, 0, sizeof ( linda->sendbufavail ) ); + + /* Program SendBufAvailAddr into the hardware */ + memset ( &sendbufavailaddr, 0, sizeof ( sendbufavailaddr ) ); + BIT_FILL_1 ( &sendbufavailaddr, SendBufAvailAddr, + ( virt_to_bus ( linda->sendbufavail ) >> 6 ) ); + linda_writeq ( linda, &sendbufavailaddr, + QIB_7220_SendBufAvailAddr_offset ); + + /* Enable sending and DMA of SendBufAvail */ + memset ( &sendctrl, 0, sizeof ( sendctrl ) ); + BIT_FILL_2 ( &sendctrl, + SendBufAvailUpd, 1, + SPioEnable, 1 ); + linda_writeq ( linda, &sendctrl, QIB_7220_SendCtrl_offset ); + + return 0; + + free_dma ( linda->sendbufavail, sizeof ( *linda->sendbufavail ) ); + err_alloc_sendbufavail: + return rc; +} + +/** + * Shut down send datapath + * + * @v linda Linda device + */ +static void linda_fini_send ( struct linda *linda ) { + struct QIB_7220_SendCtrl sendctrl; + + /* Disable sending and DMA of SendBufAvail */ + memset ( &sendctrl, 0, sizeof ( sendctrl ) ); + linda_writeq ( linda, &sendctrl, QIB_7220_SendCtrl_offset ); + mb(); + + /* Ensure hardware has seen this disable */ + linda_readq ( linda, &sendctrl, QIB_7220_SendCtrl_offset ); + + free_dma ( linda->sendbufavail, sizeof ( *linda->sendbufavail ) ); +} + +/*************************************************************************** + * + * Receive datapath + * + *************************************************************************** + */ + +/** + * Create receive work queue + * + * @v linda Linda device + * @v qp Queue pair + * @ret rc Return status code + */ +static int linda_create_recv_wq ( struct linda *linda, + struct ib_queue_pair *qp ) { + struct ib_work_queue *wq = &qp->recv; + struct linda_recv_work_queue *linda_wq = ib_wq_get_drvdata ( wq ); + struct QIB_7220_RcvHdrAddr0 rcvhdraddr; + struct QIB_7220_RcvHdrTailAddr0 rcvhdrtailaddr; + struct QIB_7220_RcvHdrHead0 rcvhdrhead; + struct QIB_7220_scalar rcvegrindexhead; + struct QIB_7220_RcvCtrl rcvctrl; + unsigned int ctx = linda_qpn_to_ctx ( qp->qpn ); + int rc; + + /* Reset context information */ + memset ( &linda_wq->header_prod, 0, + sizeof ( linda_wq->header_prod ) ); + linda_wq->header_cons = 0; + linda_wq->eager_prod = 0; + linda_wq->eager_cons = 0; + + /* Allocate receive header buffer */ + linda_wq->header = malloc_dma ( LINDA_RECV_HEADERS_SIZE, + LINDA_RECV_HEADERS_ALIGN ); + if ( ! linda_wq->header ) { + rc = -ENOMEM; + goto err_alloc_header; + } + + /* Enable context in hardware */ + memset ( &rcvhdraddr, 0, sizeof ( rcvhdraddr ) ); + BIT_FILL_1 ( &rcvhdraddr, RcvHdrAddr0, + ( virt_to_bus ( linda_wq->header ) >> 2 ) ); + linda_writeq_array8b ( linda, &rcvhdraddr, + QIB_7220_RcvHdrAddr0_offset, ctx ); + memset ( &rcvhdrtailaddr, 0, sizeof ( rcvhdrtailaddr ) ); + BIT_FILL_1 ( &rcvhdrtailaddr, RcvHdrTailAddr0, + ( virt_to_bus ( &linda_wq->header_prod ) >> 2 ) ); + linda_writeq_array8b ( linda, &rcvhdrtailaddr, + QIB_7220_RcvHdrTailAddr0_offset, ctx ); + memset ( &rcvhdrhead, 0, sizeof ( rcvhdrhead ) ); + BIT_FILL_1 ( &rcvhdrhead, counter, 1 ); + linda_writeq_array64k ( linda, &rcvhdrhead, + QIB_7220_RcvHdrHead0_offset, ctx ); + memset ( &rcvegrindexhead, 0, sizeof ( rcvegrindexhead ) ); + BIT_FILL_1 ( &rcvegrindexhead, Value, 1 ); + linda_writeq_array64k ( linda, &rcvegrindexhead, + QIB_7220_RcvEgrIndexHead0_offset, ctx ); + linda_readq ( linda, &rcvctrl, QIB_7220_RcvCtrl_offset ); + BIT_SET ( &rcvctrl, PortEnable[ctx], 1 ); + BIT_SET ( &rcvctrl, IntrAvail[ctx], 1 ); + linda_writeq ( linda, &rcvctrl, QIB_7220_RcvCtrl_offset ); + + DBGC ( linda, "Linda %p QPN %ld CTX %d hdrs [%lx,%lx) prod %lx\n", + linda, qp->qpn, ctx, virt_to_bus ( linda_wq->header ), + ( virt_to_bus ( linda_wq->header ) + LINDA_RECV_HEADERS_SIZE ), + virt_to_bus ( &linda_wq->header_prod ) ); + return 0; + + free_dma ( linda_wq->header, LINDA_RECV_HEADERS_SIZE ); + err_alloc_header: + return rc; +} + +/** + * Destroy receive work queue + * + * @v linda Linda device + * @v qp Queue pair + */ +static void linda_destroy_recv_wq ( struct linda *linda, + struct ib_queue_pair *qp ) { + struct ib_work_queue *wq = &qp->recv; + struct linda_recv_work_queue *linda_wq = ib_wq_get_drvdata ( wq ); + struct QIB_7220_RcvCtrl rcvctrl; + unsigned int ctx = linda_qpn_to_ctx ( qp->qpn ); + + /* Disable context in hardware */ + linda_readq ( linda, &rcvctrl, QIB_7220_RcvCtrl_offset ); + BIT_SET ( &rcvctrl, PortEnable[ctx], 0 ); + BIT_SET ( &rcvctrl, IntrAvail[ctx], 0 ); + linda_writeq ( linda, &rcvctrl, QIB_7220_RcvCtrl_offset ); + + /* Make sure the hardware has seen that the context is disabled */ + linda_readq ( linda, &rcvctrl, QIB_7220_RcvCtrl_offset ); + mb(); + + /* Free headers ring */ + free_dma ( linda_wq->header, LINDA_RECV_HEADERS_SIZE ); + + /* Free context */ + linda_free_ctx ( linda, ctx ); +} + +/** + * Initialise receive datapath + * + * @v linda Linda device + * @ret rc Return status code + */ +static int linda_init_recv ( struct linda *linda ) { + struct QIB_7220_RcvCtrl rcvctrl; + struct QIB_7220_scalar rcvegrbase; + struct QIB_7220_scalar rcvhdrentsize; + struct QIB_7220_scalar rcvhdrcnt; + struct QIB_7220_RcvBTHQP rcvbthqp; + unsigned int portcfg; + unsigned long egrbase; + unsigned int eager_array_size_0; + unsigned int eager_array_size_other; + unsigned int ctx; + + /* Select configuration based on number of contexts */ + switch ( LINDA_NUM_CONTEXTS ) { + case 5: + portcfg = LINDA_PORTCFG_5CTX; + eager_array_size_0 = LINDA_EAGER_ARRAY_SIZE_5CTX_0; + eager_array_size_other = LINDA_EAGER_ARRAY_SIZE_5CTX_OTHER; + break; + case 9: + portcfg = LINDA_PORTCFG_9CTX; + eager_array_size_0 = LINDA_EAGER_ARRAY_SIZE_9CTX_0; + eager_array_size_other = LINDA_EAGER_ARRAY_SIZE_9CTX_OTHER; + break; + case 17: + portcfg = LINDA_PORTCFG_17CTX; + eager_array_size_0 = LINDA_EAGER_ARRAY_SIZE_17CTX_0; + eager_array_size_other = LINDA_EAGER_ARRAY_SIZE_17CTX_OTHER; + break; + default: + linker_assert ( 0, invalid_LINDA_NUM_CONTEXTS ); + return -EINVAL; + } + + /* Configure number of contexts */ + memset ( &rcvctrl, 0, sizeof ( rcvctrl ) ); + BIT_FILL_3 ( &rcvctrl, + TailUpd, 1, + PortCfg, portcfg, + RcvQPMapEnable, 1 ); + linda_writeq ( linda, &rcvctrl, QIB_7220_RcvCtrl_offset ); + + /* Configure receive header buffer sizes */ + memset ( &rcvhdrcnt, 0, sizeof ( rcvhdrcnt ) ); + BIT_FILL_1 ( &rcvhdrcnt, Value, LINDA_RECV_HEADER_COUNT ); + linda_writeq ( linda, &rcvhdrcnt, QIB_7220_RcvHdrCnt_offset ); + memset ( &rcvhdrentsize, 0, sizeof ( rcvhdrentsize ) ); + BIT_FILL_1 ( &rcvhdrentsize, Value, ( LINDA_RECV_HEADER_SIZE >> 2 ) ); + linda_writeq ( linda, &rcvhdrentsize, QIB_7220_RcvHdrEntSize_offset ); + + /* Calculate eager array start addresses for each context */ + linda_readq ( linda, &rcvegrbase, QIB_7220_RcvEgrBase_offset ); + egrbase = BIT_GET ( &rcvegrbase, Value ); + linda->recv_wq[0].eager_array = egrbase; + linda->recv_wq[0].eager_entries = eager_array_size_0; + egrbase += ( eager_array_size_0 * sizeof ( struct QIB_7220_RcvEgr ) ); + for ( ctx = 1 ; ctx < LINDA_NUM_CONTEXTS ; ctx++ ) { + linda->recv_wq[ctx].eager_array = egrbase; + linda->recv_wq[ctx].eager_entries = eager_array_size_other; + egrbase += ( eager_array_size_other * + sizeof ( struct QIB_7220_RcvEgr ) ); + } + for ( ctx = 0 ; ctx < LINDA_NUM_CONTEXTS ; ctx++ ) { + DBGC ( linda, "Linda %p CTX %d eager array at %lx (%d " + "entries)\n", linda, ctx, + linda->recv_wq[ctx].eager_array, + linda->recv_wq[ctx].eager_entries ); + } + + /* Set the BTH QP for Infinipath packets to an unused value */ + memset ( &rcvbthqp, 0, sizeof ( rcvbthqp ) ); + BIT_FILL_1 ( &rcvbthqp, RcvBTHQP, LINDA_QP_IDETH ); + linda_writeq ( linda, &rcvbthqp, QIB_7220_RcvBTHQP_offset ); + + return 0; +} + +/** + * Shut down receive datapath + * + * @v linda Linda device + */ +static void linda_fini_recv ( struct linda *linda __unused ) { + /* Nothing to do; all contexts were already disabled when the + * queue pairs were destroyed + */ +} + +/*************************************************************************** + * + * Completion queue operations + * + *************************************************************************** + */ + +/** + * Create completion queue + * + * @v ibdev Infiniband device + * @v cq Completion queue + * @ret rc Return status code + */ +static int linda_create_cq ( struct ib_device *ibdev, + struct ib_completion_queue *cq ) { + struct linda *linda = ib_get_drvdata ( ibdev ); + static int cqn; + + /* The hardware has no concept of completion queues. We + * simply use the association between CQs and WQs (already + * handled by the IB core) to decide which WQs to poll. + * + * We do set a CQN, just to avoid confusing debug messages + * from the IB core. + */ + cq->cqn = ++cqn; + DBGC ( linda, "Linda %p CQN %ld created\n", linda, cq->cqn ); + + return 0; +} + +/** + * Destroy completion queue + * + * @v ibdev Infiniband device + * @v cq Completion queue + */ +static void linda_destroy_cq ( struct ib_device *ibdev, + struct ib_completion_queue *cq ) { + struct linda *linda = ib_get_drvdata ( ibdev ); + + /* Nothing to do */ + DBGC ( linda, "Linda %p CQN %ld destroyed\n", linda, cq->cqn ); +} + +/*************************************************************************** + * + * Queue pair operations + * + *************************************************************************** + */ + +/** + * Create queue pair + * + * @v ibdev Infiniband device + * @v qp Queue pair + * @ret rc Return status code + */ +static int linda_create_qp ( struct ib_device *ibdev, + struct ib_queue_pair *qp ) { + struct linda *linda = ib_get_drvdata ( ibdev ); + int ctx; + int rc; + + /* Locate an available context */ + ctx = linda_alloc_ctx ( linda ); + if ( ctx < 0 ) { + rc = ctx; + goto err_alloc_ctx; + } + + /* Set queue pair number based on context index */ + qp->qpn = linda_ctx_to_qpn ( ctx ); + + /* Set work-queue private data pointers */ + ib_wq_set_drvdata ( &qp->send, &linda->send_wq[ctx] ); + ib_wq_set_drvdata ( &qp->recv, &linda->recv_wq[ctx] ); + + /* Create receive work queue */ + if ( ( rc = linda_create_recv_wq ( linda, qp ) ) != 0 ) + goto err_create_recv_wq; + + /* Create send work queue */ + if ( ( rc = linda_create_send_wq ( linda, qp ) ) != 0 ) + goto err_create_send_wq; + + return 0; + + linda_destroy_send_wq ( linda, qp ); + err_create_send_wq: + linda_destroy_recv_wq ( linda, qp ); + err_create_recv_wq: + linda_free_ctx ( linda, ctx ); + err_alloc_ctx: + return rc; +} + +/** + * Modify queue pair + * + * @v ibdev Infiniband device + * @v qp Queue pair + * @v mod_list Modification list + * @ret rc Return status code + */ +static int linda_modify_qp ( struct ib_device *ibdev, + struct ib_queue_pair *qp, + unsigned long mod_list __unused ) { + struct linda *linda = ib_get_drvdata ( ibdev ); + + /* Nothing to do; the hardware doesn't have a notion of queue + * keys + */ + DBGC ( linda, "Linda %p QPN %ld modified\n", linda, qp->qpn ); + return 0; +} + +/** + * Destroy queue pair + * + * @v ibdev Infiniband device + * @v qp Queue pair + */ +static void linda_destroy_qp ( struct ib_device *ibdev, + struct ib_queue_pair *qp ) { + struct linda *linda = ib_get_drvdata ( ibdev ); + + linda_destroy_send_wq ( linda, qp ); + linda_destroy_recv_wq ( linda, qp ); +} + +/*************************************************************************** + * + * Work request operations + * + *************************************************************************** + */ + +/** + * Post send work queue entry + * + * @v ibdev Infiniband device + * @v qp Queue pair + * @v av Address vector + * @v iobuf I/O buffer + * @ret rc Return status code + */ +static int linda_post_send ( struct ib_device *ibdev, + struct ib_queue_pair *qp, + struct ib_address_vector *av, + struct io_buffer *iobuf ) { + struct linda *linda = ib_get_drvdata ( ibdev ); + struct ib_work_queue *wq = &qp->send; + struct linda_send_work_queue *linda_wq = ib_wq_get_drvdata ( wq ); + struct QIB_7220_SendPbc sendpbc; + uint8_t header_buf[IB_MAX_HEADER_SIZE]; + struct io_buffer headers; + unsigned int send_buf; + unsigned long start_offset; + unsigned long offset; + size_t len; + ssize_t frag_len; + uint32_t *data; + + /* Allocate send buffer and calculate offset */ + send_buf = linda_alloc_send_buf ( linda ); + start_offset = offset = linda_send_buffer_offset ( linda, send_buf ); + + /* Store I/O buffer and send buffer index */ + assert ( wq->iobufs[linda_wq->prod] == NULL ); + wq->iobufs[linda_wq->prod] = iobuf; + linda_wq->send_buf[linda_wq->prod] = send_buf; + + /* Construct headers */ + iob_populate ( &headers, header_buf, 0, sizeof ( header_buf ) ); + iob_reserve ( &headers, sizeof ( header_buf ) ); + ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), av ); + + /* Calculate packet length */ + len = ( ( sizeof ( sendpbc ) + iob_len ( &headers ) + + iob_len ( iobuf ) + 3 ) & ~3 ); + + /* Construct send per-buffer control word */ + memset ( &sendpbc, 0, sizeof ( sendpbc ) ); + BIT_FILL_2 ( &sendpbc, + LengthP1_toibc, ( ( len >> 2 ) - 1 ), + VL15, 1 ); + + /* Write SendPbc */ + DBG_DISABLE ( DBGLVL_IO ); + linda_writeq ( linda, &sendpbc, offset ); + offset += sizeof ( sendpbc ); + + /* Write headers */ + for ( data = headers.data, frag_len = iob_len ( &headers ) ; + frag_len > 0 ; data++, offset += 4, frag_len -= 4 ) { + linda_writel ( linda, *data, offset ); + } + + /* Write data */ + for ( data = iobuf->data, frag_len = iob_len ( iobuf ) ; + frag_len > 0 ; data++, offset += 4, frag_len -= 4 ) { + linda_writel ( linda, *data, offset ); + } + DBG_ENABLE ( DBGLVL_IO ); + + assert ( ( start_offset + len ) == offset ); + DBGC2 ( linda, "Linda %p QPN %ld TX %d(%d) posted [%lx,%lx)\n", + linda, qp->qpn, send_buf, linda_wq->prod, + start_offset, offset ); + + /* Increment producer counter */ + linda_wq->prod = ( ( linda_wq->prod + 1 ) & ( wq->num_wqes - 1 ) ); + + return 0; +} + +/** + * Complete send work queue entry + * + * @v ibdev Infiniband device + * @v qp Queue pair + * @v wqe_idx Work queue entry index + */ +static void linda_complete_send ( struct ib_device *ibdev, + struct ib_queue_pair *qp, + unsigned int wqe_idx ) { + struct linda *linda = ib_get_drvdata ( ibdev ); + struct ib_work_queue *wq = &qp->send; + struct linda_send_work_queue *linda_wq = ib_wq_get_drvdata ( wq ); + struct io_buffer *iobuf; + unsigned int send_buf; + + /* Parse completion */ + send_buf = linda_wq->send_buf[wqe_idx]; + DBGC2 ( linda, "Linda %p QPN %ld TX %d(%d) complete\n", + linda, qp->qpn, send_buf, wqe_idx ); + + /* Complete work queue entry */ + iobuf = wq->iobufs[wqe_idx]; + assert ( iobuf != NULL ); + ib_complete_send ( ibdev, qp, iobuf, 0 ); + wq->iobufs[wqe_idx] = NULL; + + /* Free send buffer */ + linda_free_send_buf ( linda, send_buf ); +} + +/** + * Poll send work queue + * + * @v ibdev Infiniband device + * @v qp Queue pair + */ +static void linda_poll_send_wq ( struct ib_device *ibdev, + struct ib_queue_pair *qp ) { + struct linda *linda = ib_get_drvdata ( ibdev ); + struct ib_work_queue *wq = &qp->send; + struct linda_send_work_queue *linda_wq = ib_wq_get_drvdata ( wq ); + unsigned int send_buf; + + /* Look for completions */ + while ( wq->fill ) { + + /* Check to see if send buffer has completed */ + send_buf = linda_wq->send_buf[linda_wq->cons]; + if ( linda_send_buf_in_use ( linda, send_buf ) ) + break; + + /* Complete this buffer */ + linda_complete_send ( ibdev, qp, linda_wq->cons ); + + /* Increment consumer counter */ + linda_wq->cons = ( ( linda_wq->cons + 1 ) & + ( wq->num_wqes - 1 ) ); + } +} + +/** + * Post receive work queue entry + * + * @v ibdev Infiniband device + * @v qp Queue pair + * @v iobuf I/O buffer + * @ret rc Return status code + */ +static int linda_post_recv ( struct ib_device *ibdev, + struct ib_queue_pair *qp, + struct io_buffer *iobuf ) { + struct linda *linda = ib_get_drvdata ( ibdev ); + struct ib_work_queue *wq = &qp->recv; + struct linda_recv_work_queue *linda_wq = ib_wq_get_drvdata ( wq ); + struct QIB_7220_RcvEgr rcvegr; + struct QIB_7220_scalar rcvegrindexhead; + unsigned int ctx = linda_qpn_to_ctx ( qp->qpn ); + physaddr_t addr; + size_t len; + unsigned int wqe_idx; + unsigned int bufsize; + + /* Sanity checks */ + addr = virt_to_bus ( iobuf->data ); + len = iob_tailroom ( iobuf ); + if ( addr & ( LINDA_EAGER_BUFFER_ALIGN - 1 ) ) { + DBGC ( linda, "Linda %p QPN %ld misaligned RX buffer " + "(%08lx)\n", linda, qp->qpn, addr ); + return -EINVAL; + } + if ( len != LINDA_RECV_PAYLOAD_SIZE ) { + DBGC ( linda, "Linda %p QPN %ld wrong RX buffer size (%d)\n", + linda, qp->qpn, len ); + return -EINVAL; + } + + /* Calculate eager producer index and WQE index */ + wqe_idx = ( linda_wq->eager_prod & ( wq->num_wqes - 1 ) ); + assert ( wq->iobufs[wqe_idx] == NULL ); + + /* Store I/O buffer */ + wq->iobufs[wqe_idx] = iobuf; + + /* Calculate buffer size */ + switch ( LINDA_RECV_PAYLOAD_SIZE ) { + case 2048: bufsize = LINDA_EAGER_BUFFER_2K; break; + case 4096: bufsize = LINDA_EAGER_BUFFER_4K; break; + case 8192: bufsize = LINDA_EAGER_BUFFER_8K; break; + case 16384: bufsize = LINDA_EAGER_BUFFER_16K; break; + case 32768: bufsize = LINDA_EAGER_BUFFER_32K; break; + case 65536: bufsize = LINDA_EAGER_BUFFER_64K; break; + default: linker_assert ( 0, invalid_rx_payload_size ); + bufsize = LINDA_EAGER_BUFFER_NONE; + } + + /* Post eager buffer */ + memset ( &rcvegr, 0, sizeof ( rcvegr ) ); + BIT_FILL_2 ( &rcvegr, + Addr, ( addr >> 11 ), + BufSize, bufsize ); + linda_writeq_array8b ( linda, &rcvegr, + linda_wq->eager_array, linda_wq->eager_prod ); + DBGC2 ( linda, "Linda %p QPN %ld RX egr %d(%d) posted [%lx,%lx)\n", + linda, qp->qpn, linda_wq->eager_prod, wqe_idx, + addr, ( addr + len ) ); + + /* Increment producer index */ + linda_wq->eager_prod = ( ( linda_wq->eager_prod + 1 ) & + ( linda_wq->eager_entries - 1 ) ); + + /* Update head index */ + memset ( &rcvegrindexhead, 0, sizeof ( rcvegrindexhead ) ); + BIT_FILL_1 ( &rcvegrindexhead, + Value, ( ( linda_wq->eager_prod + 1 ) & + ( linda_wq->eager_entries - 1 ) ) ); + linda_writeq_array64k ( linda, &rcvegrindexhead, + QIB_7220_RcvEgrIndexHead0_offset, ctx ); + + return 0; +} + +/** + * Complete receive work queue entry + * + * @v ibdev Infiniband device + * @v qp Queue pair + * @v header_offs Header offset + */ +static void linda_complete_recv ( struct ib_device *ibdev, + struct ib_queue_pair *qp, + unsigned int header_offs ) { + struct linda *linda = ib_get_drvdata ( ibdev ); + struct ib_work_queue *wq = &qp->recv; + struct linda_recv_work_queue *linda_wq = ib_wq_get_drvdata ( wq ); + struct QIB_7220_RcvHdrFlags *rcvhdrflags; + struct QIB_7220_RcvEgr rcvegr; + struct io_buffer headers; + struct io_buffer *iobuf; + struct ib_queue_pair *intended_qp; + struct ib_address_vector av; + unsigned int rcvtype; + unsigned int pktlen; + unsigned int egrindex; + unsigned int useegrbfr; + unsigned int iberr, mkerr, tiderr, khdrerr, mtuerr; + unsigned int lenerr, parityerr, vcrcerr, icrcerr; + unsigned int err; + unsigned int hdrqoffset; + unsigned int header_len; + unsigned int padded_payload_len; + unsigned int wqe_idx; + size_t payload_len; + int qp0; + int rc; + + /* RcvHdrFlags are at the end of the header entry */ + rcvhdrflags = ( linda_wq->header + header_offs + + LINDA_RECV_HEADER_SIZE - sizeof ( *rcvhdrflags ) ); + rcvtype = BIT_GET ( rcvhdrflags, RcvType ); + pktlen = ( BIT_GET ( rcvhdrflags, PktLen ) << 2 ); + egrindex = BIT_GET ( rcvhdrflags, EgrIndex ); + useegrbfr = BIT_GET ( rcvhdrflags, UseEgrBfr ); + hdrqoffset = ( BIT_GET ( rcvhdrflags, HdrqOffset ) << 2 ); + iberr = BIT_GET ( rcvhdrflags, IBErr ); + mkerr = BIT_GET ( rcvhdrflags, MKErr ); + tiderr = BIT_GET ( rcvhdrflags, TIDErr ); + khdrerr = BIT_GET ( rcvhdrflags, KHdrErr ); + mtuerr = BIT_GET ( rcvhdrflags, MTUErr ); + lenerr = BIT_GET ( rcvhdrflags, LenErr ); + parityerr = BIT_GET ( rcvhdrflags, ParityErr ); + vcrcerr = BIT_GET ( rcvhdrflags, VCRCErr ); + icrcerr = BIT_GET ( rcvhdrflags, ICRCErr ); + header_len = ( LINDA_RECV_HEADER_SIZE - hdrqoffset - + sizeof ( *rcvhdrflags ) ); + padded_payload_len = ( pktlen - header_len - 4 /* ICRC */ ); + err = ( iberr | mkerr | tiderr | khdrerr | mtuerr | + lenerr | parityerr | vcrcerr | icrcerr ); + /* IB header is placed immediately before RcvHdrFlags */ + iob_populate ( &headers, ( ( ( void * ) rcvhdrflags ) - header_len ), + header_len, header_len ); + + /* Dump diagnostic information */ + if ( err || ( ! useegrbfr ) ) { + DBGC ( linda, "Linda %p QPN %ld RX egr %d%s hdr %d type %d " + "len %d(%d+%d+4)%s%s%s%s%s%s%s%s%s%s%s\n", linda, + qp->qpn, egrindex, ( useegrbfr ? "" : "(unused)" ), + ( header_offs / LINDA_RECV_HEADER_SIZE ), rcvtype, + pktlen, header_len, padded_payload_len, + ( err ? " [Err" : "" ), ( iberr ? " IB" : "" ), + ( mkerr ? " MK" : "" ), ( tiderr ? " TID" : "" ), + ( khdrerr ? " KHdr" : "" ), ( mtuerr ? " MTU" : "" ), + ( lenerr ? " Len" : "" ), ( parityerr ? " Parity" : ""), + ( vcrcerr ? " VCRC" : "" ), ( icrcerr ? " ICRC" : "" ), + ( err ? "]" : "" ) ); + } else { + DBGC2 ( linda, "Linda %p QPN %ld RX egr %d hdr %d type %d " + "len %d(%d+%d+4)\n", linda, qp->qpn, egrindex, + ( header_offs / LINDA_RECV_HEADER_SIZE ), rcvtype, + pktlen, header_len, padded_payload_len ); + } + DBGCP_HDA ( linda, hdrqoffset, headers.data, + ( header_len + sizeof ( *rcvhdrflags ) ) ); + + /* Parse header to generate address vector */ + qp0 = ( qp->qpn == 0 ); + intended_qp = NULL; + if ( ( rc = ib_pull ( ibdev, &headers, ( qp0 ? &intended_qp : NULL ), + &payload_len, &av ) ) != 0 ) { + DBGC ( linda, "Linda %p could not parse headers: %s\n", + linda, strerror ( rc ) ); + err = 1; + } + if ( ! intended_qp ) + intended_qp = qp; + + /* Complete this buffer and any skipped buffers. Note that + * when the hardware runs out of buffers, it will repeatedly + * report the same buffer (the tail) as a TID error, and that + * it also has a habit of sometimes skipping over several + * buffers at once. + */ + while ( 1 ) { + + /* If we have caught up to the producer counter, stop. + * This will happen when the hardware first runs out + * of buffers and starts reporting TID errors against + * the eager buffer it wants to use next. + */ + if ( linda_wq->eager_cons == linda_wq->eager_prod ) + break; + + /* If we have caught up to where we should be after + * completing this egrindex, stop. We phrase the test + * this way to avoid completing the entire ring when + * we receive the same egrindex twice in a row. + */ + if ( ( linda_wq->eager_cons == + ( ( egrindex + 1 ) & ( linda_wq->eager_entries - 1 ) ))) + break; + + /* Identify work queue entry and corresponding I/O + * buffer. + */ + wqe_idx = ( linda_wq->eager_cons & ( wq->num_wqes - 1 ) ); + iobuf = wq->iobufs[wqe_idx]; + assert ( iobuf != NULL ); + wq->iobufs[wqe_idx] = NULL; + + /* Complete the eager buffer */ + if ( linda_wq->eager_cons == egrindex ) { + /* Completing the eager buffer described in + * this header entry. + */ + iob_put ( iobuf, payload_len ); + rc = ( err ? -EIO : ( useegrbfr ? 0 : -ECANCELED ) ); + /* Redirect to target QP if necessary */ + if ( qp != intended_qp ) { + DBGC ( linda, "Linda %p redirecting QPN %ld " + "=> %ld\n", + linda, qp->qpn, intended_qp->qpn ); + /* Compensate for incorrect fill levels */ + qp->recv.fill--; + intended_qp->recv.fill++; + } + ib_complete_recv ( ibdev, intended_qp, &av, iobuf, rc); + } else { + /* Completing on a skipped-over eager buffer */ + ib_complete_recv ( ibdev, qp, &av, iobuf, -ECANCELED ); + } + + /* Clear eager buffer */ + memset ( &rcvegr, 0, sizeof ( rcvegr ) ); + linda_writeq_array8b ( linda, &rcvegr, linda_wq->eager_array, + linda_wq->eager_cons ); + + /* Increment consumer index */ + linda_wq->eager_cons = ( ( linda_wq->eager_cons + 1 ) & + ( linda_wq->eager_entries - 1 ) ); + } +} + +/** + * Poll receive work queue + * + * @v ibdev Infiniband device + * @v qp Queue pair + */ +static void linda_poll_recv_wq ( struct ib_device *ibdev, + struct ib_queue_pair *qp ) { + struct linda *linda = ib_get_drvdata ( ibdev ); + struct ib_work_queue *wq = &qp->recv; + struct linda_recv_work_queue *linda_wq = ib_wq_get_drvdata ( wq ); + struct QIB_7220_RcvHdrHead0 rcvhdrhead; + unsigned int ctx = linda_qpn_to_ctx ( qp->qpn ); + unsigned int header_prod; + + /* Check for received packets */ + header_prod = ( BIT_GET ( &linda_wq->header_prod, Value ) << 2 ); + if ( header_prod == linda_wq->header_cons ) + return; + + /* Process all received packets */ + while ( linda_wq->header_cons != header_prod ) { + + /* Complete the receive */ + linda_complete_recv ( ibdev, qp, linda_wq->header_cons ); + + /* Increment the consumer offset */ + linda_wq->header_cons += LINDA_RECV_HEADER_SIZE; + linda_wq->header_cons %= LINDA_RECV_HEADERS_SIZE; + } + + /* Update consumer offset */ + memset ( &rcvhdrhead, 0, sizeof ( rcvhdrhead ) ); + BIT_FILL_2 ( &rcvhdrhead, + RcvHeadPointer, ( linda_wq->header_cons >> 2 ), + counter, 1 ); + linda_writeq_array64k ( linda, &rcvhdrhead, + QIB_7220_RcvHdrHead0_offset, ctx ); +} + +/** + * Poll completion queue + * + * @v ibdev Infiniband device + * @v cq Completion queue + */ +static void linda_poll_cq ( struct ib_device *ibdev, + struct ib_completion_queue *cq ) { + struct ib_work_queue *wq; + + /* Poll associated send and receive queues */ + list_for_each_entry ( wq, &cq->work_queues, list ) { + if ( wq->is_send ) { + linda_poll_send_wq ( ibdev, wq->qp ); + } else { + linda_poll_recv_wq ( ibdev, wq->qp ); + } + } +} + +/*************************************************************************** + * + * Event queues + * + *************************************************************************** + */ + +/** + * Poll event queue + * + * @v ibdev Infiniband device + */ +static void linda_poll_eq ( struct ib_device *ibdev ) { + struct linda *linda = ib_get_drvdata ( ibdev ); + struct QIB_7220_ErrStatus errstatus; + struct QIB_7220_ErrClear errclear; + + /* Check for link status changes */ + DBG_DISABLE ( DBGLVL_IO ); + linda_readq ( linda, &errstatus, QIB_7220_ErrStatus_offset ); + DBG_ENABLE ( DBGLVL_IO ); + if ( BIT_GET ( &errstatus, IBStatusChanged ) ) { + linda_link_state_changed ( ibdev ); + memset ( &errclear, 0, sizeof ( errclear ) ); + BIT_FILL_1 ( &errclear, IBStatusChangedClear, 1 ); + linda_writeq ( linda, &errclear, QIB_7220_ErrClear_offset ); + } +} + +/*************************************************************************** + * + * Infiniband link-layer operations + * + *************************************************************************** + */ + +/** + * Initialise Infiniband link + * + * @v ibdev Infiniband device + * @ret rc Return status code + */ +static int linda_open ( struct ib_device *ibdev ) { + struct linda *linda = ib_get_drvdata ( ibdev ); + struct QIB_7220_Control control; + + /* Disable link */ + linda_readq ( linda, &control, QIB_7220_Control_offset ); + BIT_SET ( &control, LinkEn, 1 ); + linda_writeq ( linda, &control, QIB_7220_Control_offset ); + return 0; +} + +/** + * Close Infiniband link + * + * @v ibdev Infiniband device + */ +static void linda_close ( struct ib_device *ibdev ) { + struct linda *linda = ib_get_drvdata ( ibdev ); + struct QIB_7220_Control control; + + /* Disable link */ + linda_readq ( linda, &control, QIB_7220_Control_offset ); + BIT_SET ( &control, LinkEn, 0 ); + linda_writeq ( linda, &control, QIB_7220_Control_offset ); +} + +/*************************************************************************** + * + * Multicast group operations + * + *************************************************************************** + */ + +/** + * Attach to multicast group + * + * @v ibdev Infiniband device + * @v qp Queue pair + * @v gid Multicast GID + * @ret rc Return status code + */ +static int linda_mcast_attach ( struct ib_device *ibdev, + struct ib_queue_pair *qp, + struct ib_gid *gid ) { + struct linda *linda = ib_get_drvdata ( ibdev ); + + ( void ) linda; + ( void ) qp; + ( void ) gid; + return 0; +} + +/** + * Detach from multicast group + * + * @v ibdev Infiniband device + * @v qp Queue pair + * @v gid Multicast GID + */ +static void linda_mcast_detach ( struct ib_device *ibdev, + struct ib_queue_pair *qp, + struct ib_gid *gid ) { + struct linda *linda = ib_get_drvdata ( ibdev ); + + ( void ) linda; + ( void ) qp; + ( void ) gid; +} + +/** Linda Infiniband operations */ +static struct ib_device_operations linda_ib_operations = { + .create_cq = linda_create_cq, + .destroy_cq = linda_destroy_cq, + .create_qp = linda_create_qp, + .modify_qp = linda_modify_qp, + .destroy_qp = linda_destroy_qp, + .post_send = linda_post_send, + .post_recv = linda_post_recv, + .poll_cq = linda_poll_cq, + .poll_eq = linda_poll_eq, + .open = linda_open, + .close = linda_close, + .mcast_attach = linda_mcast_attach, + .mcast_detach = linda_mcast_detach, +}; + +/*************************************************************************** + * + * I2C bus operations + * + *************************************************************************** + */ + +/** Linda I2C bit to GPIO mappings */ +static unsigned int linda_i2c_bits[] = { + [I2C_BIT_SCL] = ( 1 << LINDA_GPIO_SCL ), + [I2C_BIT_SDA] = ( 1 << LINDA_GPIO_SDA ), +}; + +/** + * Read Linda I2C line status + * + * @v basher Bit-bashing interface + * @v bit_id Bit number + * @ret zero Input is a logic 0 + * @ret non-zero Input is a logic 1 + */ +static int linda_i2c_read_bit ( struct bit_basher *basher, + unsigned int bit_id ) { + struct linda *linda = + container_of ( basher, struct linda, i2c.basher ); + struct QIB_7220_EXTStatus extstatus; + unsigned int status; + + DBG_DISABLE ( DBGLVL_IO ); + + linda_readq ( linda, &extstatus, QIB_7220_EXTStatus_offset ); + status = ( BIT_GET ( &extstatus, GPIOIn ) & linda_i2c_bits[bit_id] ); + + DBG_ENABLE ( DBGLVL_IO ); + + return status; +} + +/** + * Write Linda I2C line status + * + * @v basher Bit-bashing interface + * @v bit_id Bit number + * @v data Value to write + */ +static void linda_i2c_write_bit ( struct bit_basher *basher, + unsigned int bit_id, unsigned long data ) { + struct linda *linda = + container_of ( basher, struct linda, i2c.basher ); + struct QIB_7220_EXTCtrl extctrl; + struct QIB_7220_GPIO gpioout; + unsigned int bit = linda_i2c_bits[bit_id]; + unsigned int outputs = 0; + unsigned int output_enables = 0; + + DBG_DISABLE ( DBGLVL_IO ); + + /* Read current GPIO mask and outputs */ + linda_readq ( linda, &extctrl, QIB_7220_EXTCtrl_offset ); + linda_readq ( linda, &gpioout, QIB_7220_GPIOOut_offset ); + + /* Update outputs and output enables. I2C lines are tied + * high, so we always set the output to 0 and use the output + * enable to control the line. + */ + output_enables = BIT_GET ( &extctrl, GPIOOe ); + output_enables = ( ( output_enables & ~bit ) | ( ~data & bit ) ); + outputs = BIT_GET ( &gpioout, GPIO ); + outputs = ( outputs & ~bit ); + BIT_SET ( &extctrl, GPIOOe, output_enables ); + BIT_SET ( &gpioout, GPIO, outputs ); + + /* Write the output enable first; that way we avoid logic + * hazards. + */ + linda_writeq ( linda, &extctrl, QIB_7220_EXTCtrl_offset ); + linda_writeq ( linda, &gpioout, QIB_7220_GPIOOut_offset ); + mb(); + + DBG_ENABLE ( DBGLVL_IO ); +} + +/** Linda I2C bit-bashing interface operations */ +static struct bit_basher_operations linda_i2c_basher_ops = { + .read = linda_i2c_read_bit, + .write = linda_i2c_write_bit, +}; + +/** + * Initialise Linda I2C subsystem + * + * @v linda Linda device + * @ret rc Return status code + */ +static int linda_init_i2c ( struct linda *linda ) { + static int try_eeprom_address[] = { 0x51, 0x50 }; + unsigned int i; + int rc; + + /* Initialise bus */ + if ( ( rc = init_i2c_bit_basher ( &linda->i2c, + &linda_i2c_basher_ops ) ) != 0 ) { + DBGC ( linda, "Linda %p could not initialise I2C bus: %s\n", + linda, strerror ( rc ) ); + return rc; + } + + /* Probe for devices */ + for ( i = 0 ; i < ( sizeof ( try_eeprom_address ) / + sizeof ( try_eeprom_address[0] ) ) ; i++ ) { + init_i2c_eeprom ( &linda->eeprom, try_eeprom_address[i] ); + if ( ( rc = i2c_check_presence ( &linda->i2c.i2c, + &linda->eeprom ) ) == 0 ) { + DBGC2 ( linda, "Linda %p found EEPROM at %02x\n", + linda, try_eeprom_address[i] ); + return 0; + } + } + + DBGC ( linda, "Linda %p could not find EEPROM\n", linda ); + return -ENODEV; +} + +/** + * Read EEPROM parameters + * + * @v linda Linda device + * @v guid GUID to fill in + * @ret rc Return status code + */ +static int linda_read_eeprom ( struct linda *linda, + struct ib_gid_half *guid ) { + struct i2c_interface *i2c = &linda->i2c.i2c; + int rc; + + /* Read GUID */ + if ( ( rc = i2c->read ( i2c, &linda->eeprom, LINDA_EEPROM_GUID_OFFSET, + guid->bytes, sizeof ( *guid ) ) ) != 0 ) { + DBGC ( linda, "Linda %p could not read GUID: %s\n", + linda, strerror ( rc ) ); + return rc; + } + DBGC2 ( linda, "Linda %p has GUID %02x:%02x:%02x:%02x:%02x:%02x:" + "%02x:%02x\n", linda, guid->bytes[0], guid->bytes[1], + guid->bytes[2], guid->bytes[3], guid->bytes[4], + guid->bytes[5], guid->bytes[6], guid->bytes[7] ); + + /* Read serial number (debug only) */ + if ( DBG_LOG ) { + uint8_t serial[LINDA_EEPROM_SERIAL_SIZE + 1]; + + serial[ sizeof ( serial ) - 1 ] = '\0'; + if ( ( rc = i2c->read ( i2c, &linda->eeprom, + LINDA_EEPROM_SERIAL_OFFSET, serial, + ( sizeof ( serial ) - 1 ) ) ) != 0 ) { + DBGC ( linda, "Linda %p could not read serial: %s\n", + linda, strerror ( rc ) ); + return rc; + } + DBGC2 ( linda, "Linda %p has serial number \"%s\"\n", + linda, serial ); + } + + return 0; +} + +/*************************************************************************** + * + * External parallel bus access + * + *************************************************************************** + */ + +/** + * Request ownership of the IB external parallel bus + * + * @v linda Linda device + * @ret rc Return status code + */ +static int linda_ib_epb_request ( struct linda *linda ) { + struct QIB_7220_ibsd_epb_access_ctrl access; + unsigned int i; + + /* Request ownership */ + memset ( &access, 0, sizeof ( access ) ); + BIT_FILL_1 ( &access, sw_ib_epb_req, 1 ); + linda_writeq ( linda, &access, QIB_7220_ibsd_epb_access_ctrl_offset ); + + /* Wait for ownership to be granted */ + for ( i = 0 ; i < LINDA_EPB_REQUEST_MAX_WAIT_US ; i++ ) { + linda_readq ( linda, &access, + QIB_7220_ibsd_epb_access_ctrl_offset ); + if ( BIT_GET ( &access, sw_ib_epb_req_granted ) ) + return 0; + udelay ( 1 ); + } + + DBGC ( linda, "Linda %p timed out waiting for IB EPB request\n", + linda ); + return -ETIMEDOUT; +} + +/** + * Wait for IB external parallel bus transaction to complete + * + * @v linda Linda device + * @v xact Buffer to hold transaction result + * @ret rc Return status code + */ +static int linda_ib_epb_wait ( struct linda *linda, + struct QIB_7220_ibsd_epb_transaction_reg *xact ) { + unsigned int i; + + /* Discard first read to allow for signals crossing clock domains */ + linda_readq ( linda, xact, QIB_7220_ibsd_epb_transaction_reg_offset ); + + for ( i = 0 ; i < LINDA_EPB_XACT_MAX_WAIT_US ; i++ ) { + linda_readq ( linda, xact, + QIB_7220_ibsd_epb_transaction_reg_offset ); + if ( BIT_GET ( xact, ib_epb_rdy ) ) { + if ( BIT_GET ( xact, ib_epb_req_error ) ) { + DBGC ( linda, "Linda %p EPB transaction " + "failed\n", linda ); + return -EIO; + } else { + return 0; + } + } + udelay ( 1 ); + } + + DBGC ( linda, "Linda %p timed out waiting for IB EPB transaction\n", + linda ); + return -ETIMEDOUT; +} + +/** + * Release ownership of the IB external parallel bus + * + * @v linda Linda device + */ +static void linda_ib_epb_release ( struct linda *linda ) { + struct QIB_7220_ibsd_epb_access_ctrl access; + + memset ( &access, 0, sizeof ( access ) ); + BIT_FILL_1 ( &access, sw_ib_epb_req, 0 ); + linda_writeq ( linda, &access, QIB_7220_ibsd_epb_access_ctrl_offset ); +} + +/** + * Read data via IB external parallel bus + * + * @v linda Linda device + * @v location EPB location + * @ret data Data read, or negative error + * + * You must have already acquired ownership of the IB external + * parallel bus. + */ +static int linda_ib_epb_read ( struct linda *linda, unsigned int location ) { + struct QIB_7220_ibsd_epb_transaction_reg xact; + unsigned int data; + int rc; + + /* Ensure no transaction is currently in progress */ + if ( ( rc = linda_ib_epb_wait ( linda, &xact ) ) != 0 ) + return rc; + + /* Process data */ + memset ( &xact, 0, sizeof ( xact ) ); + BIT_FILL_3 ( &xact, + ib_epb_address, LINDA_EPB_LOC_ADDRESS ( location ), + ib_epb_read_write, LINDA_EPB_READ, + ib_epb_cs, LINDA_EPB_LOC_CS ( location ) ); + linda_writeq ( linda, &xact, + QIB_7220_ibsd_epb_transaction_reg_offset ); + + /* Wait for transaction to complete */ + if ( ( rc = linda_ib_epb_wait ( linda, &xact ) ) != 0 ) + return rc; + + data = BIT_GET ( &xact, ib_epb_data ); + return data; +} + +/** + * Write data via IB external parallel bus + * + * @v linda Linda device + * @v location EPB location + * @v data Data to write + * @ret rc Return status code + * + * You must have already acquired ownership of the IB external + * parallel bus. + */ +static int linda_ib_epb_write ( struct linda *linda, unsigned int location, + unsigned int data ) { + struct QIB_7220_ibsd_epb_transaction_reg xact; + int rc; + + /* Ensure no transaction is currently in progress */ + if ( ( rc = linda_ib_epb_wait ( linda, &xact ) ) != 0 ) + return rc; + + /* Process data */ + memset ( &xact, 0, sizeof ( xact ) ); + BIT_FILL_4 ( &xact, + ib_epb_data, data, + ib_epb_address, LINDA_EPB_LOC_ADDRESS ( location ), + ib_epb_read_write, LINDA_EPB_WRITE, + ib_epb_cs, LINDA_EPB_LOC_CS ( location ) ); + linda_writeq ( linda, &xact, + QIB_7220_ibsd_epb_transaction_reg_offset ); + + /* Wait for transaction to complete */ + if ( ( rc = linda_ib_epb_wait ( linda, &xact ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Read/modify/write EPB register + * + * @v linda Linda device + * @v cs Chip select + * @v channel Channel + * @v element Element + * @v reg Register + * @v value Value to set + * @v mask Mask to apply to old value + * @ret rc Return status code + */ +static int linda_ib_epb_mod_reg ( struct linda *linda, unsigned int cs, + unsigned int channel, unsigned int element, + unsigned int reg, unsigned int value, + unsigned int mask ) { + unsigned int location; + int old_value; + int rc; + + DBG_DISABLE ( DBGLVL_IO ); + + /* Sanity check */ + assert ( ( value & mask ) == value ); + + /* Acquire bus ownership */ + if ( ( rc = linda_ib_epb_request ( linda ) ) != 0 ) + goto out; + + /* Read existing value, if necessary */ + location = LINDA_EPB_LOC ( cs, channel, element, reg ); + if ( (~mask) & 0xff ) { + old_value = linda_ib_epb_read ( linda, location ); + if ( old_value < 0 ) { + rc = old_value; + goto out_release; + } + } else { + old_value = 0; + } + + /* Update value */ + value = ( ( old_value & ~mask ) | value ); + DBGCP ( linda, "Linda %p CS %d EPB(%d,%d,%#02x) %#02x => %#02x\n", + linda, cs, channel, element, reg, old_value, value ); + if ( ( rc = linda_ib_epb_write ( linda, location, value ) ) != 0 ) + goto out_release; + + out_release: + /* Release bus */ + linda_ib_epb_release ( linda ); + out: + DBG_ENABLE ( DBGLVL_IO ); + return rc; +} + +/** + * Transfer data to/from microcontroller RAM + * + * @v linda Linda device + * @v address Starting address + * @v write Data to write, or NULL + * @v read Data to read, or NULL + * @v len Length of data + * @ret rc Return status code + */ +static int linda_ib_epb_ram_xfer ( struct linda *linda, unsigned int address, + const void *write, void *read, + size_t len ) { + unsigned int control; + unsigned int address_hi; + unsigned int address_lo; + int data; + int rc; + + DBG_DISABLE ( DBGLVL_IO ); + + assert ( ! ( write && read ) ); + assert ( ( address % LINDA_EPB_UC_CHUNK_SIZE ) == 0 ); + assert ( ( len % LINDA_EPB_UC_CHUNK_SIZE ) == 0 ); + + /* Acquire bus ownership */ + if ( ( rc = linda_ib_epb_request ( linda ) ) != 0 ) + goto out; + + /* Process data */ + while ( len ) { + + /* Reset the address for each new chunk */ + if ( ( address % LINDA_EPB_UC_CHUNK_SIZE ) == 0 ) { + + /* Write the control register */ + control = ( read ? LINDA_EPB_UC_CTL_READ : + LINDA_EPB_UC_CTL_WRITE ); + if ( ( rc = linda_ib_epb_write ( linda, + LINDA_EPB_UC_CTL, + control ) ) != 0 ) + break; + + /* Write the address registers */ + address_hi = ( address >> 8 ); + if ( ( rc = linda_ib_epb_write ( linda, + LINDA_EPB_UC_ADDR_HI, + address_hi ) ) != 0 ) + break; + address_lo = ( address & 0xff ); + if ( ( rc = linda_ib_epb_write ( linda, + LINDA_EPB_UC_ADDR_LO, + address_lo ) ) != 0 ) + break; + } + + /* Read or write the data */ + if ( read ) { + data = linda_ib_epb_read ( linda, LINDA_EPB_UC_DATA ); + if ( data < 0 ) { + rc = data; + break; + } + *( ( uint8_t * ) read++ ) = data; + } else { + data = *( ( uint8_t * ) write++ ); + if ( ( rc = linda_ib_epb_write ( linda, + LINDA_EPB_UC_DATA, + data ) ) != 0 ) + break; + } + address++; + len--; + + /* Reset the control byte after each chunk */ + if ( ( address % LINDA_EPB_UC_CHUNK_SIZE ) == 0 ) { + if ( ( rc = linda_ib_epb_write ( linda, + LINDA_EPB_UC_CTL, + 0 ) ) != 0 ) + break; + } + } + + /* Release bus */ + linda_ib_epb_release ( linda ); + + out: + DBG_ENABLE ( DBGLVL_IO ); + return rc; +} + +/*************************************************************************** + * + * Infiniband SerDes initialisation + * + *************************************************************************** + */ + +/** A Linda SerDes parameter */ +struct linda_serdes_param { + /** EPB address as constructed by LINDA_EPB_ADDRESS() */ + uint16_t address; + /** Value to set */ + uint8_t value; + /** Mask to apply to old value */ + uint8_t mask; +} __packed; + +/** Magic "all channels" channel number */ +#define LINDA_EPB_ALL_CHANNELS 31 + +/** End of SerDes parameter list marker */ +#define LINDA_SERDES_PARAM_END { 0, 0, 0 } + +/** + * Program IB SerDes register(s) + * + * @v linda Linda device + * @v param SerDes parameter + * @ret rc Return status code + */ +static int linda_set_serdes_param ( struct linda *linda, + struct linda_serdes_param *param ) { + unsigned int channel; + unsigned int channel_start; + unsigned int channel_end; + unsigned int element; + unsigned int reg; + int rc; + + /* Break down the EPB address and determine channels */ + channel = LINDA_EPB_ADDRESS_CHANNEL ( param->address ); + element = LINDA_EPB_ADDRESS_ELEMENT ( param->address ); + reg = LINDA_EPB_ADDRESS_REG ( param->address ); + if ( channel == LINDA_EPB_ALL_CHANNELS ) { + channel_start = 0; + channel_end = 3; + } else { + channel_start = channel_end = channel; + } + + /* Modify register for each specified channel */ + for ( channel = channel_start ; channel <= channel_end ; channel++ ) { + if ( ( rc = linda_ib_epb_mod_reg ( linda, LINDA_EPB_CS_SERDES, + channel, element, reg, + param->value, + param->mask ) ) != 0 ) + return rc; + } + + return 0; +} + +/** + * Program IB SerDes registers + * + * @v linda Linda device + * @v param SerDes parameters + * @v count Number of parameters + * @ret rc Return status code + */ +static int linda_set_serdes_params ( struct linda *linda, + struct linda_serdes_param *params ) { + int rc; + + for ( ; params->mask != 0 ; params++ ){ + if ( ( rc = linda_set_serdes_param ( linda, + params ) ) != 0 ) + return rc; + } + + return 0; +} + +#define LINDA_DDS_VAL( amp_d, main_d, ipst_d, ipre_d, \ + amp_s, main_s, ipst_s, ipre_s ) \ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 9, 0x00 ), \ + ( ( ( amp_d & 0x1f ) << 1 ) | 1 ), 0xff }, \ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 9, 0x01 ), \ + ( ( ( amp_s & 0x1f ) << 1 ) | 1 ), 0xff }, \ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 9, 0x09 ), \ + ( ( main_d << 3 ) | 4 | ( ipre_d >> 2 ) ), 0xff }, \ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 9, 0x0a ), \ + ( ( main_s << 3 ) | 4 | ( ipre_s >> 2 ) ), 0xff }, \ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 9, 0x06 ), \ + ( ( ( ipst_d & 0xf ) << 1 ) | \ + ( ( ipre_d & 3 ) << 6 ) | 0x21 ), 0xff }, \ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 9, 0x07 ), \ + ( ( ( ipst_s & 0xf ) << 1 ) | \ + ( ( ipre_s & 3 ) << 6) | 0x21 ), 0xff } + +/** + * Linda SerDes default parameters + * + * These magic start-of-day values are taken from the Linux driver. + */ +static struct linda_serdes_param linda_serdes_defaults1[] = { + /* RXHSCTRL0 */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x00 ), 0xd4, 0xff }, + /* VCDL_DAC2 */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x05 ), 0x2d, 0xff }, + /* VCDL_CTRL2 */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x08 ), 0x03, 0x0f }, + /* START_EQ1 */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x27 ), 0x10, 0xff }, + /* START_EQ2 */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x28 ), 0x30, 0xff }, + /* BACTRL */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x0e ), 0x40, 0xff }, + /* LDOUTCTRL1 */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x06 ), 0x04, 0xff }, + /* RXHSSTATUS */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x0f ), 0x04, 0xff }, + /* End of this block */ + LINDA_SERDES_PARAM_END +}; +static struct linda_serdes_param linda_serdes_defaults2[] = { + /* LDOUTCTRL1 */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x06 ), 0x00, 0xff }, + /* DDS values */ + LINDA_DDS_VAL ( 31, 19, 12, 0, 29, 22, 9, 0 ), + /* Set Rcv Eq. to Preset node */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x27 ), 0x10, 0xff }, + /* DFELTHFDR */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x08 ), 0x00, 0xff }, + /* DFELTHHDR */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x21 ), 0x00, 0xff }, + /* TLTHFDR */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x09 ), 0x02, 0xff }, + /* TLTHHDR */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x23 ), 0x02, 0xff }, + /* ZFR */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x1b ), 0x0c, 0xff }, + /* ZCNT) */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x1c ), 0x0c, 0xff }, + /* GFR */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x1e ), 0x10, 0xff }, + /* GHR */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x1f ), 0x10, 0xff }, + /* VCDL_CTRL0 toggle */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x06 ), 0x20, 0xff }, + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 6, 0x06 ), 0x00, 0xff }, + /* CMUCTRL5 */ + { LINDA_EPB_ADDRESS ( 7, 0, 0x15 ), 0x80, 0xff }, + /* End of this block */ + LINDA_SERDES_PARAM_END +}; +static struct linda_serdes_param linda_serdes_defaults3[] = { + /* START_EQ1 */ + { LINDA_EPB_ADDRESS ( LINDA_EPB_ALL_CHANNELS, 7, 0x27 ), 0x00, 0x38 }, + /* End of this block */ + LINDA_SERDES_PARAM_END +}; + +/** + * Program the microcontroller RAM + * + * @v linda Linda device + * @ret rc Return status code + */ +static int linda_program_uc_ram ( struct linda *linda ) { + int rc; + + if ( ( rc = linda_ib_epb_ram_xfer ( linda, 0, linda_ib_fw, NULL, + sizeof ( linda_ib_fw ) ) ) != 0 ){ + DBGC ( linda, "Linda %p could not load IB firmware: %s\n", + linda, strerror ( rc ) ); + return rc; + } + + return 0; +} + +/** + * Verify the microcontroller RAM + * + * @v linda Linda device + * @ret rc Return status code + */ +static int linda_verify_uc_ram ( struct linda *linda ) { + uint8_t verify[LINDA_EPB_UC_CHUNK_SIZE]; + unsigned int offset; + int rc; + + for ( offset = 0 ; offset < sizeof ( linda_ib_fw ); + offset += sizeof ( verify ) ) { + if ( ( rc = linda_ib_epb_ram_xfer ( linda, offset, + NULL, verify, + sizeof (verify) )) != 0 ){ + DBGC ( linda, "Linda %p could not read back IB " + "firmware: %s\n", linda, strerror ( rc ) ); + return rc; + } + if ( memcmp ( ( linda_ib_fw + offset ), verify, + sizeof ( verify ) ) != 0 ) { + DBGC ( linda, "Linda %p firmware verification failed " + "at offset %#x\n", linda, offset ); + DBGC_HDA ( linda, offset, ( linda_ib_fw + offset ), + sizeof ( verify ) ); + DBGC_HDA ( linda, offset, verify, sizeof ( verify ) ); + return -EIO; + } + } + + DBGC2 ( linda, "Linda %p firmware verified ok\n", linda ); + return 0; +} + +/** + * Use the microcontroller to trim the IB link + * + * @v linda Linda device + * @ret rc Return status code + */ +static int linda_trim_ib ( struct linda *linda ) { + struct QIB_7220_IBSerDesCtrl ctrl; + struct QIB_7220_IntStatus intstatus; + unsigned int i; + int rc; + + /* Bring the microcontroller out of reset */ + linda_readq ( linda, &ctrl, QIB_7220_IBSerDesCtrl_offset ); + BIT_SET ( &ctrl, ResetIB_uC_Core, 0 ); + linda_writeq ( linda, &ctrl, QIB_7220_IBSerDesCtrl_offset ); + + /* Wait for the "trim done" signal */ + for ( i = 0 ; i < LINDA_TRIM_DONE_MAX_WAIT_MS ; i++ ) { + linda_readq ( linda, &intstatus, QIB_7220_IntStatus_offset ); + if ( BIT_GET ( &intstatus, IBSerdesTrimDone ) ) { + rc = 0; + goto out_reset; + } + mdelay ( 1 ); + } + + DBGC ( linda, "Linda %p timed out waiting for trim done\n", linda ); + rc = -ETIMEDOUT; + out_reset: + /* Put the microcontroller back into reset */ + BIT_SET ( &ctrl, ResetIB_uC_Core, 1 ); + linda_writeq ( linda, &ctrl, QIB_7220_IBSerDesCtrl_offset ); + + return rc; +} + +/** + * Initialise the IB SerDes + * + * @v linda Linda device + * @ret rc Return status code + */ +static int linda_init_ib_serdes ( struct linda *linda ) { + struct QIB_7220_Control control; + struct QIB_7220_IBCCtrl ibcctrl; + struct QIB_7220_IBCDDRCtrl ibcddrctrl; + struct QIB_7220_XGXSCfg xgxscfg; + int rc; + + /* Disable link */ + linda_readq ( linda, &control, QIB_7220_Control_offset ); + BIT_SET ( &control, LinkEn, 0 ); + linda_writeq ( linda, &control, QIB_7220_Control_offset ); + + /* Configure sensible defaults for IBC */ + memset ( &ibcctrl, 0, sizeof ( ibcctrl ) ); + BIT_FILL_6 ( &ibcctrl, /* Tuning values taken from Linux driver */ + FlowCtrlPeriod, 0x03, + FlowCtrlWaterMark, 0x05, + MaxPktLen, ( ( LINDA_RECV_HEADER_SIZE + + LINDA_RECV_PAYLOAD_SIZE + + 4 /* ICRC */ ) >> 2 ), + PhyerrThreshold, 0xf, + OverrunThreshold, 0xf, + CreditScale, 0x4 ); + linda_writeq ( linda, &ibcctrl, QIB_7220_IBCCtrl_offset ); + + /* Force SDR only to avoid needing all the DDR tuning, + * Mellanox compatibiltiy hacks etc. SDR is plenty for + * boot-time operation. + */ + linda_readq ( linda, &ibcddrctrl, QIB_7220_IBCDDRCtrl_offset ); + BIT_SET ( &ibcddrctrl, IB_ENHANCED_MODE, 0 ); + BIT_SET ( &ibcddrctrl, SD_SPEED_SDR, 1 ); + BIT_SET ( &ibcddrctrl, SD_SPEED_DDR, 0 ); + BIT_SET ( &ibcddrctrl, SD_SPEED_QDR, 0 ); + BIT_SET ( &ibcddrctrl, HRTBT_ENB, 0 ); + BIT_SET ( &ibcddrctrl, HRTBT_AUTO, 0 ); + linda_writeq ( linda, &ibcddrctrl, QIB_7220_IBCDDRCtrl_offset ); + + /* Set default SerDes parameters */ + if ( ( rc = linda_set_serdes_params ( linda, + linda_serdes_defaults1 ) ) != 0 ) + return rc; + udelay ( 415 ); /* Magic delay while SerDes sorts itself out */ + if ( ( rc = linda_set_serdes_params ( linda, + linda_serdes_defaults2 ) ) != 0 ) + return rc; + + /* Program the microcontroller RAM */ + if ( ( rc = linda_program_uc_ram ( linda ) ) != 0 ) + return rc; + + /* Verify the microcontroller RAM contents */ + if ( DBGLVL_LOG ) { + if ( ( rc = linda_verify_uc_ram ( linda ) ) != 0 ) + return rc; + } + + /* More SerDes tuning */ + if ( ( rc = linda_set_serdes_params ( linda, + linda_serdes_defaults3 ) ) != 0 ) + return rc; + + /* Use the microcontroller to trim the IB link */ + if ( ( rc = linda_trim_ib ( linda ) ) != 0 ) + return rc; + + /* Bring XGXS out of reset */ + linda_readq ( linda, &xgxscfg, QIB_7220_XGXSCfg_offset ); + BIT_SET ( &xgxscfg, tx_rx_reset, 0 ); + BIT_SET ( &xgxscfg, xcv_reset, 0 ); + linda_writeq ( linda, &xgxscfg, QIB_7220_XGXSCfg_offset ); + + return rc; +} + +/*************************************************************************** + * + * PCI layer interface + * + *************************************************************************** + */ + +/** + * Probe PCI device + * + * @v pci PCI device + * @v id PCI ID + * @ret rc Return status code + */ +static int linda_probe ( struct pci_device *pci, + const struct pci_device_id *id __unused ) { + struct ib_device *ibdev; + struct linda *linda; + struct QIB_7220_Revision revision; + int rc; + + /* Allocate Infiniband device */ + ibdev = alloc_ibdev ( sizeof ( *linda ) ); + if ( ! ibdev ) { + rc = -ENOMEM; + goto err_alloc_ibdev; + } + pci_set_drvdata ( pci, ibdev ); + linda = ib_get_drvdata ( ibdev ); + ibdev->op = &linda_ib_operations; + ibdev->dev = &pci->dev; + ibdev->port = 1; + + /* Fix up PCI device */ + adjust_pci_device ( pci ); + + /* Get PCI BARs */ + linda->regs = ioremap ( pci->membase, LINDA_BAR0_SIZE ); + DBGC2 ( linda, "Linda %p has BAR at %08lx\n", linda, pci->membase ); + + /* Print some general data */ + linda_readq ( linda, &revision, QIB_7220_Revision_offset ); + DBGC2 ( linda, "Linda %p board %02lx v%ld.%ld.%ld.%ld\n", linda, + BIT_GET ( &revision, BoardID ), + BIT_GET ( &revision, R_SW ), + BIT_GET ( &revision, R_Arch ), + BIT_GET ( &revision, R_ChipRevMajor ), + BIT_GET ( &revision, R_ChipRevMinor ) ); + + /* Initialise I2C subsystem */ + if ( ( rc = linda_init_i2c ( linda ) ) != 0 ) + goto err_init_i2c; + + /* Read EEPROM parameters */ + if ( ( rc = linda_read_eeprom ( linda, &ibdev->gid.u.half[1] ) ) != 0 ) + goto err_read_eeprom; + + /* Initialise send datapath */ + if ( ( rc = linda_init_send ( linda ) ) != 0 ) + goto err_init_send; + + /* Initialise receive datapath */ + if ( ( rc = linda_init_recv ( linda ) ) != 0 ) + goto err_init_recv; + + /* Initialise the IB SerDes */ + if ( ( rc = linda_init_ib_serdes ( linda ) ) != 0 ) + goto err_init_ib_serdes; + + /* Create the SMA */ + if ( ( rc = ib_create_sma ( &linda->sma, ibdev, + &linda_sma_operations ) ) != 0 ) + goto err_create_sma; + /* If the SMA doesn't get context 0, we're screwed */ + assert ( linda_qpn_to_ctx ( linda->sma.qp->qpn ) == 0 ); + + /* Register Infiniband device */ + if ( ( rc = register_ibdev ( ibdev ) ) != 0 ) { + DBGC ( linda, "Linda %p could not register IB " + "device: %s\n", linda, strerror ( rc ) ); + goto err_register_ibdev; + } + + return 0; + + unregister_ibdev ( ibdev ); + err_register_ibdev: + ib_destroy_sma ( &linda->sma ); + err_create_sma: + linda_fini_recv ( linda ); + err_init_recv: + linda_fini_send ( linda ); + err_init_send: + err_init_ib_serdes: + err_read_eeprom: + err_init_i2c: + ibdev_put ( ibdev ); + err_alloc_ibdev: + return rc; +} + +/** + * Remove PCI device + * + * @v pci PCI device + */ +static void linda_remove ( struct pci_device *pci ) { + struct ib_device *ibdev = pci_get_drvdata ( pci ); + struct linda *linda = ib_get_drvdata ( ibdev ); + + unregister_ibdev ( ibdev ); + ib_destroy_sma ( &linda->sma ); + linda_fini_recv ( linda ); + linda_fini_send ( linda ); + ibdev_put ( ibdev ); +} + +static struct pci_device_id linda_nics[] = { + PCI_ROM ( 0x1077, 0x7220, "iba7220", "QLE7240/7280 HCA driver" ), +}; + +struct pci_driver linda_driver __pci_driver = { + .ids = linda_nics, + .id_count = ( sizeof ( linda_nics ) / sizeof ( linda_nics[0] ) ), + .probe = linda_probe, + .remove = linda_remove, +}; diff --git a/gpxe/src/drivers/infiniband/linda.h b/gpxe/src/drivers/infiniband/linda.h new file mode 100644 index 00000000..dd1737a6 --- /dev/null +++ b/gpxe/src/drivers/infiniband/linda.h @@ -0,0 +1,271 @@ +#ifndef _LINDA_H +#define _LINDA_H + +/* + * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/** + * @file + * + * QLogic Linda Infiniband HCA + * + */ + +#define BITOPS_LITTLE_ENDIAN +#include <gpxe/bitops.h> +#include "qib_7220_regs.h" + +struct ib_device; + +/** A Linda GPIO register */ +struct QIB_7220_GPIO_pb { + pseudo_bit_t GPIO[16]; + pseudo_bit_t Reserved[48]; +}; +struct QIB_7220_GPIO { + PSEUDO_BIT_STRUCT ( struct QIB_7220_GPIO_pb ); +}; + +/** A Linda general scalar register */ +struct QIB_7220_scalar_pb { + pseudo_bit_t Value[64]; +}; +struct QIB_7220_scalar { + PSEUDO_BIT_STRUCT ( struct QIB_7220_scalar_pb ); +}; + +/** Linda send per-buffer control word */ +struct QIB_7220_SendPbc_pb { + pseudo_bit_t LengthP1_toibc[11]; + pseudo_bit_t Reserved1[4]; + pseudo_bit_t LengthP1_trigger[11]; + pseudo_bit_t Reserved2[3]; + pseudo_bit_t TestEbp[1]; + pseudo_bit_t Test[1]; + pseudo_bit_t Intr[1]; + pseudo_bit_t Reserved3[31]; + pseudo_bit_t VL15[1]; +}; +struct QIB_7220_SendPbc { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SendPbc_pb ); +}; + +/** Linda send buffer availability */ +struct QIB_7220_SendBufAvail_pb { + pseudo_bit_t InUseCheck[144][2]; + pseudo_bit_t Reserved[32]; +}; +struct QIB_7220_SendBufAvail { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SendBufAvail_pb ); +}; + +/** DMA alignment for send buffer availability */ +#define LINDA_SENDBUFAVAIL_ALIGN 64 + +/** A Linda eager receive descriptor */ +struct QIB_7220_RcvEgr_pb { + pseudo_bit_t Addr[37]; + pseudo_bit_t BufSize[3]; + pseudo_bit_t Reserved[24]; +}; +struct QIB_7220_RcvEgr { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvEgr_pb ); +}; + +/** Linda receive header flags */ +struct QIB_7220_RcvHdrFlags_pb { + pseudo_bit_t PktLen[11]; + pseudo_bit_t RcvType[3]; + pseudo_bit_t SoftB[1]; + pseudo_bit_t SoftA[1]; + pseudo_bit_t EgrIndex[12]; + pseudo_bit_t Reserved1[3]; + pseudo_bit_t UseEgrBfr[1]; + pseudo_bit_t RcvSeq[4]; + pseudo_bit_t HdrqOffset[11]; + pseudo_bit_t Reserved2[8]; + pseudo_bit_t IBErr[1]; + pseudo_bit_t MKErr[1]; + pseudo_bit_t TIDErr[1]; + pseudo_bit_t KHdrErr[1]; + pseudo_bit_t MTUErr[1]; + pseudo_bit_t LenErr[1]; + pseudo_bit_t ParityErr[1]; + pseudo_bit_t VCRCErr[1]; + pseudo_bit_t ICRCErr[1]; +}; +struct QIB_7220_RcvHdrFlags { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrFlags_pb ); +}; + +/** Linda memory BAR size */ +#define LINDA_BAR0_SIZE 0x400000 + +/** Linda I2C SCL line GPIO number */ +#define LINDA_GPIO_SCL 0 + +/** Linda I2C SDA line GPIO number */ +#define LINDA_GPIO_SDA 1 + +/** GUID offset within EEPROM */ +#define LINDA_EEPROM_GUID_OFFSET 3 + +/** GUID size within EEPROM */ +#define LINDA_EEPROM_GUID_SIZE 8 + +/** Board serial number offset within EEPROM */ +#define LINDA_EEPROM_SERIAL_OFFSET 12 + +/** Board serial number size within EEPROM */ +#define LINDA_EEPROM_SERIAL_SIZE 12 + +/** Maximum number of send buffers used + * + * This is a policy decision. Must be less than or equal to the total + * number of send buffers supported by the hardware (128). + */ +#define LINDA_MAX_SEND_BUFS 32 + +/** Linda send buffer size */ +#define LINDA_SEND_BUF_SIZE 4096 + +/** Number of contexts (including kernel context) + * + * This is a policy decision. Must be 5, 9 or 17. + */ +#define LINDA_NUM_CONTEXTS 5 + +/** PortCfg values for different numbers of contexts */ +enum linda_portcfg { + LINDA_PORTCFG_5CTX = 0, + LINDA_PORTCFG_9CTX = 1, + LINDA_PORTCFG_17CTX = 2, +}; + +/** PortCfg values for different numbers of contexts */ +#define LINDA_EAGER_ARRAY_SIZE_5CTX_0 2048 +#define LINDA_EAGER_ARRAY_SIZE_5CTX_OTHER 4096 +#define LINDA_EAGER_ARRAY_SIZE_9CTX_0 2048 +#define LINDA_EAGER_ARRAY_SIZE_9CTX_OTHER 2048 +#define LINDA_EAGER_ARRAY_SIZE_17CTX_0 2048 +#define LINDA_EAGER_ARRAY_SIZE_17CTX_OTHER 1024 + +/** Eager buffer required alignment */ +#define LINDA_EAGER_BUFFER_ALIGN 2048 + +/** Eager buffer size encodings */ +enum linda_eager_buffer_size { + LINDA_EAGER_BUFFER_NONE = 0, + LINDA_EAGER_BUFFER_2K = 1, + LINDA_EAGER_BUFFER_4K = 2, + LINDA_EAGER_BUFFER_8K = 3, + LINDA_EAGER_BUFFER_16K = 4, + LINDA_EAGER_BUFFER_32K = 5, + LINDA_EAGER_BUFFER_64K = 6, +}; + +/** Number of RX headers per context + * + * This is a policy decision. + */ +#define LINDA_RECV_HEADER_COUNT 8 + +/** Maximum size of each RX header + * + * This is a policy decision. Must be divisible by 4. + */ +#define LINDA_RECV_HEADER_SIZE 96 + +/** Total size of an RX header ring */ +#define LINDA_RECV_HEADERS_SIZE \ + ( LINDA_RECV_HEADER_SIZE * LINDA_RECV_HEADER_COUNT ) + +/** RX header alignment */ +#define LINDA_RECV_HEADERS_ALIGN 64 + +/** RX payload size + * + * This is a policy decision. Must be a valid eager buffer size. + */ +#define LINDA_RECV_PAYLOAD_SIZE 2048 + +/** QPN used for Infinipath Packets + * + * This is a policy decision. Must have bit 0 clear. Must not be a + * QPN that we will use. + */ +#define LINDA_QP_IDETH 0xdead0 + +/** Maximum time for wait for external parallel bus request, in us */ +#define LINDA_EPB_REQUEST_MAX_WAIT_US 500 + +/** Maximum time for wait for external parallel bus transaction, in us */ +#define LINDA_EPB_XACT_MAX_WAIT_US 500 + +/** Linda external parallel bus chip selects */ +#define LINDA_EPB_CS_SERDES 1 +#define LINDA_EPB_CS_UC 2 + +/** Linda external parallel bus read/write operations */ +#define LINDA_EPB_WRITE 0 +#define LINDA_EPB_READ 1 + +/** Linda external parallel bus register addresses */ +#define LINDA_EPB_ADDRESS( _channel, _element, _reg ) \ + ( (_element) | ( (_channel) << 4 ) | ( (_reg) << 9 ) ) +#define LINDA_EPB_ADDRESS_CHANNEL( _address ) ( ( (_address) >> 4 ) & 0x1f ) +#define LINDA_EPB_ADDRESS_ELEMENT( _address ) ( ( (_address) >> 0 ) & 0x0f ) +#define LINDA_EPB_ADDRESS_REG( _address ) ( ( (_address) >> 9 ) & 0x3f ) + +/** Linda external parallel bus locations + * + * The location is used by the driver to encode both the chip select + * and the EPB address. + */ +#define LINDA_EPB_LOC( _cs, _channel, _element, _reg) \ + ( ( (_cs) << 16 ) | LINDA_EPB_ADDRESS ( _channel, _element, _reg ) ) +#define LINDA_EPB_LOC_ADDRESS( _loc ) ( (_loc) & 0xffff ) +#define LINDA_EPB_LOC_CS( _loc ) ( (_loc) >> 16 ) + +/** Linda external parallel bus microcontroller register addresses */ +#define LINDA_EPB_UC_CHANNEL 6 +#define LINDA_EPB_UC_LOC( _reg ) \ + LINDA_EPB_LOC ( LINDA_EPB_CS_UC, LINDA_EPB_UC_CHANNEL, 0, (_reg) ) +#define LINDA_EPB_UC_CTL LINDA_EPB_UC_LOC ( 0 ) +#define LINDA_EPB_UC_CTL_WRITE 1 +#define LINDA_EPB_UC_CTL_READ 2 +#define LINDA_EPB_UC_ADDR_LO LINDA_EPB_UC_LOC ( 2 ) +#define LINDA_EPB_UC_ADDR_HI LINDA_EPB_UC_LOC ( 3 ) +#define LINDA_EPB_UC_DATA LINDA_EPB_UC_LOC ( 4 ) +#define LINDA_EPB_UC_CHUNK_SIZE 64 + +extern uint8_t linda_ib_fw[8192]; + +/** Maximum time to wait for "trim done" signal, in ms */ +#define LINDA_TRIM_DONE_MAX_WAIT_MS 1000 + +/** Linda link states */ +enum linda_link_state { + LINDA_LINK_STATE_DOWN = 0, + LINDA_LINK_STATE_INIT = 1, + LINDA_LINK_STATE_ARM = 2, + LINDA_LINK_STATE_ACTIVE = 3, + LINDA_LINK_STATE_ACT_DEFER = 4, +}; + +#endif /* _LINDA_H */ diff --git a/gpxe/src/drivers/infiniband/linda_fw.c b/gpxe/src/drivers/infiniband/linda_fw.c new file mode 100644 index 00000000..fc5ea077 --- /dev/null +++ b/gpxe/src/drivers/infiniband/linda_fw.c @@ -0,0 +1,1067 @@ +/* + * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * This file contains the memory image from the vendor, to be copied into + * the IB SERDES of the IBA7220 during initialization. + * The file also includes the two functions which use this image. + */ + +#include <stdint.h> +#include "linda.h" + +uint8_t linda_ib_fw[8192] = { +/*0000*/0x02, 0x0A, 0x29, 0x02, 0x0A, 0x87, 0xE5, 0xE6, + 0x30, 0xE6, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, +/*0010*/0x00, 0xE5, 0xE2, 0x30, 0xE4, 0x04, 0x7E, 0x01, + 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x5F, 0x60, 0x08, +/*0020*/0x53, 0xF9, 0xF7, 0xE4, 0xF5, 0xFE, 0x80, 0x08, + 0x7F, 0x0A, 0x12, 0x17, 0x31, 0x12, 0x0E, 0xA2, +/*0030*/0x75, 0xFC, 0x08, 0xE4, 0xF5, 0xFD, 0xE5, 0xE7, + 0x20, 0xE7, 0x03, 0x43, 0xF9, 0x08, 0x22, 0x00, +/*0040*/0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x75, + 0x51, 0x01, 0xE4, 0xF5, 0x52, 0xF5, 0x53, 0xF5, +/*0050*/0x52, 0xF5, 0x7E, 0x7F, 0x04, 0x02, 0x04, 0x38, + 0xC2, 0x36, 0x05, 0x52, 0xE5, 0x52, 0xD3, 0x94, +/*0060*/0x0C, 0x40, 0x05, 0x75, 0x52, 0x01, 0xD2, 0x36, + 0x90, 0x07, 0x0C, 0x74, 0x07, 0xF0, 0xA3, 0x74, +/*0070*/0xFF, 0xF0, 0xE4, 0xF5, 0x0C, 0xA3, 0xF0, 0x90, + 0x07, 0x14, 0xF0, 0xA3, 0xF0, 0x75, 0x0B, 0x20, +/*0080*/0xF5, 0x09, 0xE4, 0xF5, 0x08, 0xE5, 0x08, 0xD3, + 0x94, 0x30, 0x40, 0x03, 0x02, 0x04, 0x04, 0x12, +/*0090*/0x00, 0x06, 0x15, 0x0B, 0xE5, 0x08, 0x70, 0x04, + 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x09, +/*00A0*/0x70, 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, + 0xEE, 0x5F, 0x60, 0x05, 0x12, 0x18, 0x71, 0xD2, +/*00B0*/0x35, 0x53, 0xE1, 0xF7, 0xE5, 0x08, 0x45, 0x09, + 0xFF, 0xE5, 0x0B, 0x25, 0xE0, 0x25, 0xE0, 0x24, +/*00C0*/0x83, 0xF5, 0x82, 0xE4, 0x34, 0x07, 0xF5, 0x83, + 0xEF, 0xF0, 0x85, 0xE2, 0x20, 0xE5, 0x52, 0xD3, +/*00D0*/0x94, 0x01, 0x40, 0x0D, 0x12, 0x19, 0xF3, 0xE0, + 0x54, 0xA0, 0x64, 0x40, 0x70, 0x03, 0x02, 0x03, +/*00E0*/0xFB, 0x53, 0xF9, 0xF8, 0x90, 0x94, 0x70, 0xE4, + 0xF0, 0xE0, 0xF5, 0x10, 0xAF, 0x09, 0x12, 0x1E, +/*00F0*/0xB3, 0xAF, 0x08, 0xEF, 0x44, 0x08, 0xF5, 0x82, + 0x75, 0x83, 0x80, 0xE0, 0xF5, 0x29, 0xEF, 0x44, +/*0100*/0x07, 0x12, 0x1A, 0x3C, 0xF5, 0x22, 0x54, 0x40, + 0xD3, 0x94, 0x00, 0x40, 0x1E, 0xE5, 0x29, 0x54, +/*0110*/0xF0, 0x70, 0x21, 0x12, 0x19, 0xF3, 0xE0, 0x44, + 0x80, 0xF0, 0xE5, 0x22, 0x54, 0x30, 0x65, 0x08, +/*0120*/0x70, 0x09, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xBF, + 0xF0, 0x80, 0x09, 0x12, 0x19, 0xF3, 0x74, 0x40, +/*0130*/0xF0, 0x02, 0x03, 0xFB, 0x12, 0x1A, 0x12, 0x75, + 0x83, 0xAE, 0x74, 0xFF, 0xF0, 0xAF, 0x08, 0x7E, +/*0140*/0x00, 0xEF, 0x44, 0x07, 0xF5, 0x82, 0xE0, 0xFD, + 0xE5, 0x0B, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x81, +/*0150*/0xF5, 0x82, 0xE4, 0x34, 0x07, 0xF5, 0x83, 0xED, + 0xF0, 0x90, 0x07, 0x0E, 0xE0, 0x04, 0xF0, 0xEF, +/*0160*/0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0x98, 0xE0, + 0xF5, 0x28, 0x12, 0x1A, 0x23, 0x40, 0x0C, 0x12, +/*0170*/0x19, 0xF3, 0xE0, 0x44, 0x01, 0x12, 0x1A, 0x32, + 0x02, 0x03, 0xF6, 0xAF, 0x08, 0x7E, 0x00, 0x74, +/*0180*/0x80, 0xCD, 0xEF, 0xCD, 0x8D, 0x82, 0xF5, 0x83, + 0xE0, 0x30, 0xE0, 0x0A, 0x12, 0x19, 0xF3, 0xE0, +/*0190*/0x44, 0x20, 0xF0, 0x02, 0x03, 0xFB, 0x12, 0x19, + 0xF3, 0xE0, 0x54, 0xDF, 0xF0, 0xEE, 0x44, 0xAE, +/*01A0*/0x12, 0x1A, 0x43, 0x30, 0xE4, 0x03, 0x02, 0x03, + 0xFB, 0x74, 0x9E, 0x12, 0x1A, 0x05, 0x20, 0xE0, +/*01B0*/0x03, 0x02, 0x03, 0xFB, 0x8F, 0x82, 0x8E, 0x83, + 0xE0, 0x20, 0xE0, 0x03, 0x02, 0x03, 0xFB, 0x12, +/*01C0*/0x19, 0xF3, 0xE0, 0x44, 0x10, 0xF0, 0xE5, 0xE3, + 0x20, 0xE7, 0x08, 0xE5, 0x08, 0x12, 0x1A, 0x3A, +/*01D0*/0x44, 0x04, 0xF0, 0xAF, 0x08, 0x7E, 0x00, 0xEF, + 0x12, 0x1A, 0x3A, 0x20, 0xE2, 0x34, 0x12, 0x19, +/*01E0*/0xF3, 0xE0, 0x44, 0x08, 0xF0, 0xE5, 0xE4, 0x30, + 0xE6, 0x04, 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00, +/*01F0*/0xE5, 0x7E, 0xC3, 0x94, 0x04, 0x50, 0x04, 0x7C, + 0x01, 0x80, 0x02, 0x7C, 0x00, 0xEC, 0x4D, 0x60, +/*0200*/0x05, 0xC2, 0x35, 0x02, 0x03, 0xFB, 0xEE, 0x44, + 0xD2, 0x12, 0x1A, 0x43, 0x44, 0x40, 0xF0, 0x02, +/*0210*/0x03, 0xFB, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xF7, + 0xF0, 0x12, 0x1A, 0x12, 0x75, 0x83, 0xD2, 0xE0, +/*0220*/0x54, 0xBF, 0xF0, 0x90, 0x07, 0x14, 0xE0, 0x04, + 0xF0, 0xE5, 0x7E, 0x70, 0x03, 0x75, 0x7E, 0x01, +/*0230*/0xAF, 0x08, 0x7E, 0x00, 0x12, 0x1A, 0x23, 0x40, + 0x12, 0x12, 0x19, 0xF3, 0xE0, 0x44, 0x01, 0x12, +/*0240*/0x19, 0xF2, 0xE0, 0x54, 0x02, 0x12, 0x1A, 0x32, + 0x02, 0x03, 0xFB, 0x12, 0x19, 0xF3, 0xE0, 0x44, +/*0250*/0x02, 0x12, 0x19, 0xF2, 0xE0, 0x54, 0xFE, 0xF0, + 0xC2, 0x35, 0xEE, 0x44, 0x8A, 0x8F, 0x82, 0xF5, +/*0260*/0x83, 0xE0, 0xF5, 0x17, 0x54, 0x8F, 0x44, 0x40, + 0xF0, 0x74, 0x90, 0xFC, 0xE5, 0x08, 0x44, 0x07, +/*0270*/0xFD, 0xF5, 0x82, 0x8C, 0x83, 0xE0, 0x54, 0x3F, + 0x90, 0x07, 0x02, 0xF0, 0xE0, 0x54, 0xC0, 0x8D, +/*0280*/0x82, 0x8C, 0x83, 0xF0, 0x74, 0x92, 0x12, 0x1A, + 0x05, 0x90, 0x07, 0x03, 0x12, 0x1A, 0x19, 0x74, +/*0290*/0x82, 0x12, 0x1A, 0x05, 0x90, 0x07, 0x04, 0x12, + 0x1A, 0x19, 0x74, 0xB4, 0x12, 0x1A, 0x05, 0x90, +/*02A0*/0x07, 0x05, 0x12, 0x1A, 0x19, 0x74, 0x94, 0xFE, + 0xE5, 0x08, 0x44, 0x06, 0x12, 0x1A, 0x0A, 0xF5, +/*02B0*/0x10, 0x30, 0xE0, 0x04, 0xD2, 0x37, 0x80, 0x02, + 0xC2, 0x37, 0xE5, 0x10, 0x54, 0x7F, 0x8F, 0x82, +/*02C0*/0x8E, 0x83, 0xF0, 0x30, 0x44, 0x30, 0x12, 0x1A, + 0x03, 0x54, 0x80, 0xD3, 0x94, 0x00, 0x40, 0x04, +/*02D0*/0xD2, 0x39, 0x80, 0x02, 0xC2, 0x39, 0x8F, 0x82, + 0x8E, 0x83, 0xE0, 0x44, 0x80, 0xF0, 0x12, 0x1A, +/*02E0*/0x03, 0x54, 0x40, 0xD3, 0x94, 0x00, 0x40, 0x04, + 0xD2, 0x3A, 0x80, 0x02, 0xC2, 0x3A, 0x8F, 0x82, +/*02F0*/0x8E, 0x83, 0xE0, 0x44, 0x40, 0xF0, 0x74, 0x92, + 0xFE, 0xE5, 0x08, 0x44, 0x06, 0x12, 0x1A, 0x0A, +/*0300*/0x30, 0xE7, 0x04, 0xD2, 0x38, 0x80, 0x02, 0xC2, + 0x38, 0x8F, 0x82, 0x8E, 0x83, 0xE0, 0x54, 0x7F, +/*0310*/0xF0, 0x12, 0x1E, 0x46, 0xE4, 0xF5, 0x0A, 0x20, + 0x03, 0x02, 0x80, 0x03, 0x30, 0x43, 0x03, 0x12, +/*0320*/0x19, 0x95, 0x20, 0x02, 0x02, 0x80, 0x03, 0x30, + 0x42, 0x03, 0x12, 0x0C, 0x8F, 0x30, 0x30, 0x06, +/*0330*/0x12, 0x19, 0x95, 0x12, 0x0C, 0x8F, 0x12, 0x0D, + 0x47, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xFB, 0xF0, +/*0340*/0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40, 0x46, 0x43, + 0xE1, 0x08, 0x12, 0x19, 0xF3, 0xE0, 0x44, 0x04, +/*0350*/0xF0, 0xE5, 0xE4, 0x20, 0xE7, 0x2A, 0x12, 0x1A, + 0x12, 0x75, 0x83, 0xD2, 0xE0, 0x54, 0x08, 0xD3, +/*0360*/0x94, 0x00, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02, + 0x7F, 0x00, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40, +/*0370*/0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF, + 0x5E, 0x60, 0x05, 0x12, 0x1D, 0xD7, 0x80, 0x17, +/*0380*/0x12, 0x1A, 0x12, 0x75, 0x83, 0xD2, 0xE0, 0x44, + 0x08, 0xF0, 0x02, 0x03, 0xFB, 0x12, 0x1A, 0x12, +/*0390*/0x75, 0x83, 0xD2, 0xE0, 0x54, 0xF7, 0xF0, 0x12, + 0x1E, 0x46, 0x7F, 0x08, 0x12, 0x17, 0x31, 0x74, +/*03A0*/0x8E, 0xFE, 0x12, 0x1A, 0x12, 0x8E, 0x83, 0xE0, + 0xF5, 0x10, 0x54, 0xFE, 0xF0, 0xE5, 0x10, 0x44, +/*03B0*/0x01, 0xFF, 0xE5, 0x08, 0xFD, 0xED, 0x44, 0x07, + 0xF5, 0x82, 0xEF, 0xF0, 0xE5, 0x10, 0x54, 0xFE, +/*03C0*/0xFF, 0xED, 0x44, 0x07, 0xF5, 0x82, 0xEF, 0x12, + 0x1A, 0x11, 0x75, 0x83, 0x86, 0xE0, 0x44, 0x10, +/*03D0*/0x12, 0x1A, 0x11, 0xE0, 0x44, 0x10, 0xF0, 0x12, + 0x19, 0xF3, 0xE0, 0x54, 0xFD, 0x44, 0x01, 0xFF, +/*03E0*/0x12, 0x19, 0xF3, 0xEF, 0x12, 0x1A, 0x32, 0x30, + 0x32, 0x0C, 0xE5, 0x08, 0x44, 0x08, 0xF5, 0x82, +/*03F0*/0x75, 0x83, 0x82, 0x74, 0x05, 0xF0, 0xAF, 0x0B, + 0x12, 0x18, 0xD7, 0x74, 0x10, 0x25, 0x08, 0xF5, +/*0400*/0x08, 0x02, 0x00, 0x85, 0x05, 0x09, 0xE5, 0x09, + 0xD3, 0x94, 0x07, 0x50, 0x03, 0x02, 0x00, 0x82, +/*0410*/0xE5, 0x7E, 0xD3, 0x94, 0x00, 0x40, 0x04, 0x7F, + 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x7E, 0xC3, +/*0420*/0x94, 0xFA, 0x50, 0x04, 0x7E, 0x01, 0x80, 0x02, + 0x7E, 0x00, 0xEE, 0x5F, 0x60, 0x02, 0x05, 0x7E, +/*0430*/0x30, 0x35, 0x0B, 0x43, 0xE1, 0x01, 0x7F, 0x09, + 0x12, 0x17, 0x31, 0x02, 0x00, 0x58, 0x53, 0xE1, +/*0440*/0xFE, 0x02, 0x00, 0x58, 0x8E, 0x6A, 0x8F, 0x6B, + 0x8C, 0x6C, 0x8D, 0x6D, 0x75, 0x6E, 0x01, 0x75, +/*0450*/0x6F, 0x01, 0x75, 0x70, 0x01, 0xE4, 0xF5, 0x73, + 0xF5, 0x74, 0xF5, 0x75, 0x90, 0x07, 0x2F, 0xF0, +/*0460*/0xF5, 0x3C, 0xF5, 0x3E, 0xF5, 0x46, 0xF5, 0x47, + 0xF5, 0x3D, 0xF5, 0x3F, 0xF5, 0x6F, 0xE5, 0x6F, +/*0470*/0x70, 0x0F, 0xE5, 0x6B, 0x45, 0x6A, 0x12, 0x07, + 0x2A, 0x75, 0x83, 0x80, 0x74, 0x3A, 0xF0, 0x80, +/*0480*/0x09, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x80, 0x74, + 0x1A, 0xF0, 0xE4, 0xF5, 0x6E, 0xC3, 0x74, 0x3F, +/*0490*/0x95, 0x6E, 0xFF, 0x12, 0x08, 0x65, 0x75, 0x83, + 0x82, 0xEF, 0xF0, 0x12, 0x1A, 0x4D, 0x12, 0x08, +/*04A0*/0xC6, 0xE5, 0x33, 0xF0, 0x12, 0x08, 0xFA, 0x12, + 0x08, 0xB1, 0x40, 0xE1, 0xE5, 0x6F, 0x70, 0x0B, +/*04B0*/0x12, 0x07, 0x2A, 0x75, 0x83, 0x80, 0x74, 0x36, + 0xF0, 0x80, 0x09, 0x12, 0x07, 0x2A, 0x75, 0x83, +/*04C0*/0x80, 0x74, 0x16, 0xF0, 0x75, 0x6E, 0x01, 0x12, + 0x07, 0x2A, 0x75, 0x83, 0xB4, 0xE5, 0x6E, 0xF0, +/*04D0*/0x12, 0x1A, 0x4D, 0x74, 0x3F, 0x25, 0x6E, 0xF5, + 0x82, 0xE4, 0x34, 0x00, 0xF5, 0x83, 0xE5, 0x33, +/*04E0*/0xF0, 0x74, 0xBF, 0x25, 0x6E, 0xF5, 0x82, 0xE4, + 0x34, 0x00, 0x12, 0x08, 0xB1, 0x40, 0xD8, 0xE4, +/*04F0*/0xF5, 0x70, 0xF5, 0x46, 0xF5, 0x47, 0xF5, 0x6E, + 0x12, 0x08, 0xFA, 0xF5, 0x83, 0xE0, 0xFE, 0x12, +/*0500*/0x08, 0xC6, 0xE0, 0x7C, 0x00, 0x24, 0x00, 0xFF, + 0xEC, 0x3E, 0xFE, 0xAD, 0x3B, 0xD3, 0xEF, 0x9D, +/*0510*/0xEE, 0x9C, 0x50, 0x04, 0x7B, 0x01, 0x80, 0x02, + 0x7B, 0x00, 0xE5, 0x70, 0x70, 0x04, 0x7A, 0x01, +/*0520*/0x80, 0x02, 0x7A, 0x00, 0xEB, 0x5A, 0x60, 0x06, + 0x85, 0x6E, 0x46, 0x75, 0x70, 0x01, 0xD3, 0xEF, +/*0530*/0x9D, 0xEE, 0x9C, 0x50, 0x04, 0x7F, 0x01, 0x80, + 0x02, 0x7F, 0x00, 0xE5, 0x70, 0xB4, 0x01, 0x04, +/*0540*/0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF, 0x5E, + 0x60, 0x03, 0x85, 0x6E, 0x47, 0x05, 0x6E, 0xE5, +/*0550*/0x6E, 0x64, 0x7F, 0x70, 0xA3, 0xE5, 0x46, 0x60, + 0x05, 0xE5, 0x47, 0xB4, 0x7E, 0x03, 0x85, 0x46, +/*0560*/0x47, 0xE5, 0x6F, 0x70, 0x08, 0x85, 0x46, 0x76, + 0x85, 0x47, 0x77, 0x80, 0x0E, 0xC3, 0x74, 0x7F, +/*0570*/0x95, 0x46, 0xF5, 0x78, 0xC3, 0x74, 0x7F, 0x95, + 0x47, 0xF5, 0x79, 0xE5, 0x6F, 0x70, 0x37, 0xE5, +/*0580*/0x46, 0x65, 0x47, 0x70, 0x0C, 0x75, 0x73, 0x01, + 0x75, 0x74, 0x01, 0xF5, 0x3C, 0xF5, 0x3D, 0x80, +/*0590*/0x35, 0xE4, 0xF5, 0x4E, 0xC3, 0xE5, 0x47, 0x95, + 0x46, 0xF5, 0x3C, 0xC3, 0x13, 0xF5, 0x71, 0x25, +/*05A0*/0x46, 0xF5, 0x72, 0xC3, 0x94, 0x3F, 0x40, 0x05, + 0xE4, 0xF5, 0x3D, 0x80, 0x40, 0xC3, 0x74, 0x3F, +/*05B0*/0x95, 0x72, 0xF5, 0x3D, 0x80, 0x37, 0xE5, 0x46, + 0x65, 0x47, 0x70, 0x0F, 0x75, 0x73, 0x01, 0x75, +/*05C0*/0x75, 0x01, 0xF5, 0x3E, 0xF5, 0x3F, 0x75, 0x4E, + 0x01, 0x80, 0x22, 0xE4, 0xF5, 0x4E, 0xC3, 0xE5, +/*05D0*/0x47, 0x95, 0x46, 0xF5, 0x3E, 0xC3, 0x13, 0xF5, + 0x71, 0x25, 0x46, 0xF5, 0x72, 0xD3, 0x94, 0x3F, +/*05E0*/0x50, 0x05, 0xE4, 0xF5, 0x3F, 0x80, 0x06, 0xE5, + 0x72, 0x24, 0xC1, 0xF5, 0x3F, 0x05, 0x6F, 0xE5, +/*05F0*/0x6F, 0xC3, 0x94, 0x02, 0x50, 0x03, 0x02, 0x04, + 0x6E, 0xE5, 0x6D, 0x45, 0x6C, 0x70, 0x02, 0x80, +/*0600*/0x04, 0xE5, 0x74, 0x45, 0x75, 0x90, 0x07, 0x2F, + 0xF0, 0x7F, 0x01, 0xE5, 0x3E, 0x60, 0x04, 0xE5, +/*0610*/0x3C, 0x70, 0x14, 0xE4, 0xF5, 0x3C, 0xF5, 0x3D, + 0xF5, 0x3E, 0xF5, 0x3F, 0x12, 0x08, 0xD2, 0x70, +/*0620*/0x04, 0xF0, 0x02, 0x06, 0xA4, 0x80, 0x7A, 0xE5, + 0x3C, 0xC3, 0x95, 0x3E, 0x40, 0x07, 0xE5, 0x3C, +/*0630*/0x95, 0x3E, 0xFF, 0x80, 0x06, 0xC3, 0xE5, 0x3E, + 0x95, 0x3C, 0xFF, 0xE5, 0x76, 0xD3, 0x95, 0x79, +/*0640*/0x40, 0x05, 0x85, 0x76, 0x7A, 0x80, 0x03, 0x85, + 0x79, 0x7A, 0xE5, 0x77, 0xC3, 0x95, 0x78, 0x50, +/*0650*/0x05, 0x85, 0x77, 0x7B, 0x80, 0x03, 0x85, 0x78, + 0x7B, 0xE5, 0x7B, 0xD3, 0x95, 0x7A, 0x40, 0x30, +/*0660*/0xE5, 0x7B, 0x95, 0x7A, 0xF5, 0x3C, 0xF5, 0x3E, + 0xC3, 0xE5, 0x7B, 0x95, 0x7A, 0x90, 0x07, 0x19, +/*0670*/0xF0, 0xE5, 0x3C, 0xC3, 0x13, 0xF5, 0x71, 0x25, + 0x7A, 0xF5, 0x72, 0xC3, 0x94, 0x3F, 0x40, 0x05, +/*0680*/0xE4, 0xF5, 0x3D, 0x80, 0x1F, 0xC3, 0x74, 0x3F, + 0x95, 0x72, 0xF5, 0x3D, 0xF5, 0x3F, 0x80, 0x14, +/*0690*/0xE4, 0xF5, 0x3C, 0xF5, 0x3E, 0x90, 0x07, 0x19, + 0xF0, 0x12, 0x08, 0xD2, 0x70, 0x03, 0xF0, 0x80, +/*06A0*/0x03, 0x74, 0x01, 0xF0, 0x12, 0x08, 0x65, 0x75, + 0x83, 0xD0, 0xE0, 0x54, 0x0F, 0xFE, 0xAD, 0x3C, +/*06B0*/0x70, 0x02, 0x7E, 0x07, 0xBE, 0x0F, 0x02, 0x7E, + 0x80, 0xEE, 0xFB, 0xEF, 0xD3, 0x9B, 0x74, 0x80, +/*06C0*/0xF8, 0x98, 0x40, 0x1F, 0xE4, 0xF5, 0x3C, 0xF5, + 0x3E, 0x12, 0x08, 0xD2, 0x70, 0x03, 0xF0, 0x80, +/*06D0*/0x12, 0x74, 0x01, 0xF0, 0xE5, 0x08, 0xFB, 0xEB, + 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xD2, 0xE0, +/*06E0*/0x44, 0x10, 0xF0, 0xE5, 0x08, 0xFB, 0xEB, 0x44, + 0x09, 0xF5, 0x82, 0x75, 0x83, 0x9E, 0xED, 0xF0, +/*06F0*/0xEB, 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xCA, + 0xED, 0xF0, 0x12, 0x08, 0x65, 0x75, 0x83, 0xCC, +/*0700*/0xEF, 0xF0, 0x22, 0xE5, 0x08, 0x44, 0x07, 0xF5, + 0x82, 0x75, 0x83, 0xBC, 0xE0, 0x54, 0xF0, 0xF0, +/*0710*/0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, + 0xBE, 0xE0, 0x54, 0xF0, 0xF0, 0xE5, 0x08, 0x44, +/*0720*/0x07, 0xF5, 0x82, 0x75, 0x83, 0xC0, 0xE0, 0x54, + 0xF0, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82, +/*0730*/0x22, 0xF0, 0x90, 0x07, 0x28, 0xE0, 0xFE, 0xA3, + 0xE0, 0xF5, 0x82, 0x8E, 0x83, 0x22, 0x85, 0x42, +/*0740*/0x42, 0x85, 0x41, 0x41, 0x85, 0x40, 0x40, 0x74, + 0xC0, 0x2F, 0xF5, 0x82, 0x74, 0x02, 0x3E, 0xF5, +/*0750*/0x83, 0xE5, 0x42, 0xF0, 0x74, 0xE0, 0x2F, 0xF5, + 0x82, 0x74, 0x02, 0x3E, 0xF5, 0x83, 0x22, 0xE5, +/*0760*/0x42, 0x29, 0xFD, 0xE4, 0x33, 0xFC, 0xE5, 0x3C, + 0xC3, 0x9D, 0xEC, 0x64, 0x80, 0xF8, 0x74, 0x80, +/*0770*/0x98, 0x22, 0xF5, 0x83, 0xE0, 0x90, 0x07, 0x22, + 0x54, 0x1F, 0xFD, 0xE0, 0xFA, 0xA3, 0xE0, 0xF5, +/*0780*/0x82, 0x8A, 0x83, 0xED, 0xF0, 0x22, 0x90, 0x07, + 0x22, 0xE0, 0xFC, 0xA3, 0xE0, 0xF5, 0x82, 0x8C, +/*0790*/0x83, 0x22, 0x90, 0x07, 0x24, 0xFF, 0xED, 0x44, + 0x07, 0xCF, 0xF0, 0xA3, 0xEF, 0xF0, 0x22, 0x85, +/*07A0*/0x38, 0x38, 0x85, 0x39, 0x39, 0x85, 0x3A, 0x3A, + 0x74, 0xC0, 0x2F, 0xF5, 0x82, 0x74, 0x02, 0x3E, +/*07B0*/0xF5, 0x83, 0x22, 0x90, 0x07, 0x26, 0xFF, 0xED, + 0x44, 0x07, 0xCF, 0xF0, 0xA3, 0xEF, 0xF0, 0x22, +/*07C0*/0xF0, 0x74, 0xA0, 0x2F, 0xF5, 0x82, 0x74, 0x02, + 0x3E, 0xF5, 0x83, 0x22, 0x74, 0xC0, 0x25, 0x11, +/*07D0*/0xF5, 0x82, 0xE4, 0x34, 0x01, 0xF5, 0x83, 0x22, + 0x74, 0x00, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34, +/*07E0*/0x02, 0xF5, 0x83, 0x22, 0x74, 0x60, 0x25, 0x11, + 0xF5, 0x82, 0xE4, 0x34, 0x03, 0xF5, 0x83, 0x22, +/*07F0*/0x74, 0x80, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34, + 0x03, 0xF5, 0x83, 0x22, 0x74, 0xE0, 0x25, 0x11, +/*0800*/0xF5, 0x82, 0xE4, 0x34, 0x03, 0xF5, 0x83, 0x22, + 0x74, 0x40, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34, +/*0810*/0x06, 0xF5, 0x83, 0x22, 0x74, 0x80, 0x2F, 0xF5, + 0x82, 0x74, 0x02, 0x3E, 0xF5, 0x83, 0x22, 0xAF, +/*0820*/0x08, 0x7E, 0x00, 0xEF, 0x44, 0x07, 0xF5, 0x82, + 0x22, 0xF5, 0x83, 0xE5, 0x82, 0x44, 0x07, 0xF5, +/*0830*/0x82, 0xE5, 0x40, 0xF0, 0x22, 0x74, 0x40, 0x25, + 0x11, 0xF5, 0x82, 0xE4, 0x34, 0x02, 0xF5, 0x83, +/*0840*/0x22, 0x74, 0xC0, 0x25, 0x11, 0xF5, 0x82, 0xE4, + 0x34, 0x03, 0xF5, 0x83, 0x22, 0x74, 0x00, 0x25, +/*0850*/0x11, 0xF5, 0x82, 0xE4, 0x34, 0x06, 0xF5, 0x83, + 0x22, 0x74, 0x20, 0x25, 0x11, 0xF5, 0x82, 0xE4, +/*0860*/0x34, 0x06, 0xF5, 0x83, 0x22, 0xE5, 0x08, 0xFD, + 0xED, 0x44, 0x07, 0xF5, 0x82, 0x22, 0xE5, 0x41, +/*0870*/0xF0, 0xE5, 0x65, 0x64, 0x01, 0x45, 0x64, 0x22, + 0x7E, 0x00, 0xFB, 0x7A, 0x00, 0xFD, 0x7C, 0x00, +/*0880*/0x22, 0x74, 0x20, 0x25, 0x11, 0xF5, 0x82, 0xE4, + 0x34, 0x02, 0x22, 0x74, 0xA0, 0x25, 0x11, 0xF5, +/*0890*/0x82, 0xE4, 0x34, 0x03, 0x22, 0x85, 0x3E, 0x42, + 0x85, 0x3F, 0x41, 0x8F, 0x40, 0x22, 0x85, 0x3C, +/*08A0*/0x42, 0x85, 0x3D, 0x41, 0x8F, 0x40, 0x22, 0x75, + 0x45, 0x3F, 0x90, 0x07, 0x20, 0xE4, 0xF0, 0xA3, +/*08B0*/0x22, 0xF5, 0x83, 0xE5, 0x32, 0xF0, 0x05, 0x6E, + 0xE5, 0x6E, 0xC3, 0x94, 0x40, 0x22, 0xF0, 0xE5, +/*08C0*/0x08, 0x44, 0x06, 0xF5, 0x82, 0x22, 0x74, 0x00, + 0x25, 0x6E, 0xF5, 0x82, 0xE4, 0x34, 0x00, 0xF5, +/*08D0*/0x83, 0x22, 0xE5, 0x6D, 0x45, 0x6C, 0x90, 0x07, + 0x2F, 0x22, 0xE4, 0xF9, 0xE5, 0x3C, 0xD3, 0x95, +/*08E0*/0x3E, 0x22, 0x74, 0x80, 0x2E, 0xF5, 0x82, 0xE4, + 0x34, 0x02, 0xF5, 0x83, 0xE0, 0x22, 0x74, 0xA0, +/*08F0*/0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x02, 0xF5, 0x83, + 0xE0, 0x22, 0x74, 0x80, 0x25, 0x6E, 0xF5, 0x82, +/*0900*/0xE4, 0x34, 0x00, 0x22, 0x25, 0x42, 0xFD, 0xE4, + 0x33, 0xFC, 0x22, 0x85, 0x42, 0x42, 0x85, 0x41, +/*0910*/0x41, 0x85, 0x40, 0x40, 0x22, 0xED, 0x4C, 0x60, + 0x03, 0x02, 0x09, 0xE5, 0xEF, 0x4E, 0x70, 0x37, +/*0920*/0x90, 0x07, 0x26, 0x12, 0x07, 0x89, 0xE0, 0xFD, + 0x12, 0x07, 0xCC, 0xED, 0xF0, 0x90, 0x07, 0x28, +/*0930*/0x12, 0x07, 0x89, 0xE0, 0xFD, 0x12, 0x07, 0xD8, + 0xED, 0xF0, 0x12, 0x07, 0x86, 0xE0, 0x54, 0x1F, +/*0940*/0xFD, 0x12, 0x08, 0x81, 0xF5, 0x83, 0xED, 0xF0, + 0x90, 0x07, 0x24, 0x12, 0x07, 0x89, 0xE0, 0x54, +/*0950*/0x1F, 0xFD, 0x12, 0x08, 0x35, 0xED, 0xF0, 0xEF, + 0x64, 0x04, 0x4E, 0x70, 0x37, 0x90, 0x07, 0x26, +/*0960*/0x12, 0x07, 0x89, 0xE0, 0xFD, 0x12, 0x07, 0xE4, + 0xED, 0xF0, 0x90, 0x07, 0x28, 0x12, 0x07, 0x89, +/*0970*/0xE0, 0xFD, 0x12, 0x07, 0xF0, 0xED, 0xF0, 0x12, + 0x07, 0x86, 0xE0, 0x54, 0x1F, 0xFD, 0x12, 0x08, +/*0980*/0x8B, 0xF5, 0x83, 0xED, 0xF0, 0x90, 0x07, 0x24, + 0x12, 0x07, 0x89, 0xE0, 0x54, 0x1F, 0xFD, 0x12, +/*0990*/0x08, 0x41, 0xED, 0xF0, 0xEF, 0x64, 0x01, 0x4E, + 0x70, 0x04, 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00, +/*09A0*/0xEF, 0x64, 0x02, 0x4E, 0x70, 0x04, 0x7F, 0x01, + 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x4D, 0x60, 0x78, +/*09B0*/0x90, 0x07, 0x26, 0x12, 0x07, 0x35, 0xE0, 0xFF, + 0x12, 0x07, 0xFC, 0xEF, 0x12, 0x07, 0x31, 0xE0, +/*09C0*/0xFF, 0x12, 0x08, 0x08, 0xEF, 0xF0, 0x90, 0x07, + 0x22, 0x12, 0x07, 0x35, 0xE0, 0x54, 0x1F, 0xFF, +/*09D0*/0x12, 0x08, 0x4D, 0xEF, 0xF0, 0x90, 0x07, 0x24, + 0x12, 0x07, 0x35, 0xE0, 0x54, 0x1F, 0xFF, 0x12, +/*09E0*/0x08, 0x59, 0xEF, 0xF0, 0x22, 0x12, 0x07, 0xCC, + 0xE4, 0xF0, 0x12, 0x07, 0xD8, 0xE4, 0xF0, 0x12, +/*09F0*/0x08, 0x81, 0xF5, 0x83, 0xE4, 0xF0, 0x12, 0x08, + 0x35, 0x74, 0x14, 0xF0, 0x12, 0x07, 0xE4, 0xE4, +/*0A00*/0xF0, 0x12, 0x07, 0xF0, 0xE4, 0xF0, 0x12, 0x08, + 0x8B, 0xF5, 0x83, 0xE4, 0xF0, 0x12, 0x08, 0x41, +/*0A10*/0x74, 0x14, 0xF0, 0x12, 0x07, 0xFC, 0xE4, 0xF0, + 0x12, 0x08, 0x08, 0xE4, 0xF0, 0x12, 0x08, 0x4D, +/*0A20*/0xE4, 0xF0, 0x12, 0x08, 0x59, 0x74, 0x14, 0xF0, + 0x22, 0x53, 0xF9, 0xF7, 0x75, 0xFC, 0x10, 0xE4, +/*0A30*/0xF5, 0xFD, 0x75, 0xFE, 0x30, 0xF5, 0xFF, 0xE5, + 0xE7, 0x20, 0xE7, 0x03, 0x43, 0xF9, 0x08, 0xE5, +/*0A40*/0xE6, 0x20, 0xE7, 0x0B, 0x78, 0xFF, 0xE4, 0xF6, + 0xD8, 0xFD, 0x53, 0xE6, 0xFE, 0x80, 0x09, 0x78, +/*0A50*/0x08, 0xE4, 0xF6, 0xD8, 0xFD, 0x53, 0xE6, 0xFE, + 0x75, 0x81, 0x80, 0xE4, 0xF5, 0xA8, 0xD2, 0xA8, +/*0A60*/0xC2, 0xA9, 0xD2, 0xAF, 0xE5, 0xE2, 0x20, 0xE5, + 0x05, 0x20, 0xE6, 0x02, 0x80, 0x03, 0x43, 0xE1, +/*0A70*/0x02, 0xE5, 0xE2, 0x20, 0xE0, 0x0E, 0x90, 0x00, + 0x00, 0x7F, 0x00, 0x7E, 0x08, 0xE4, 0xF0, 0xA3, +/*0A80*/0xDF, 0xFC, 0xDE, 0xFA, 0x02, 0x0A, 0xDB, 0x43, + 0xFA, 0x01, 0xC0, 0xE0, 0xC0, 0xF0, 0xC0, 0x83, +/*0A90*/0xC0, 0x82, 0xC0, 0xD0, 0x12, 0x1C, 0xE7, 0xD0, + 0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, 0xD0, +/*0AA0*/0xE0, 0x53, 0xFA, 0xFE, 0x32, 0x02, 0x1B, 0x55, + 0xE4, 0x93, 0xA3, 0xF8, 0xE4, 0x93, 0xA3, 0xF6, +/*0AB0*/0x08, 0xDF, 0xF9, 0x80, 0x29, 0xE4, 0x93, 0xA3, + 0xF8, 0x54, 0x07, 0x24, 0x0C, 0xC8, 0xC3, 0x33, +/*0AC0*/0xC4, 0x54, 0x0F, 0x44, 0x20, 0xC8, 0x83, 0x40, + 0x04, 0xF4, 0x56, 0x80, 0x01, 0x46, 0xF6, 0xDF, +/*0AD0*/0xE4, 0x80, 0x0B, 0x01, 0x02, 0x04, 0x08, 0x10, + 0x20, 0x40, 0x80, 0x90, 0x00, 0x3F, 0xE4, 0x7E, +/*0AE0*/0x01, 0x93, 0x60, 0xC1, 0xA3, 0xFF, 0x54, 0x3F, + 0x30, 0xE5, 0x09, 0x54, 0x1F, 0xFE, 0xE4, 0x93, +/*0AF0*/0xA3, 0x60, 0x01, 0x0E, 0xCF, 0x54, 0xC0, 0x25, + 0xE0, 0x60, 0xAD, 0x40, 0xB8, 0x80, 0xFE, 0x8C, +/*0B00*/0x64, 0x8D, 0x65, 0x8A, 0x66, 0x8B, 0x67, 0xE4, + 0xF5, 0x69, 0xEF, 0x4E, 0x70, 0x03, 0x02, 0x1D, +/*0B10*/0x55, 0xE4, 0xF5, 0x68, 0xE5, 0x67, 0x45, 0x66, + 0x70, 0x32, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x90, +/*0B20*/0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE4, + 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0xE4, 0x12, +/*0B30*/0x08, 0x70, 0x70, 0x29, 0x12, 0x07, 0x2A, 0x75, + 0x83, 0x92, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, +/*0B40*/0xC6, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC8, + 0xE4, 0xF0, 0x80, 0x11, 0x90, 0x07, 0x26, 0x12, +/*0B50*/0x07, 0x35, 0xE4, 0x12, 0x08, 0x70, 0x70, 0x05, + 0x12, 0x07, 0x32, 0xE4, 0xF0, 0x12, 0x1D, 0x55, +/*0B60*/0x12, 0x1E, 0xBF, 0xE5, 0x67, 0x45, 0x66, 0x70, + 0x33, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x90, 0xE5, +/*0B70*/0x41, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE5, + 0x41, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0x12, +/*0B80*/0x08, 0x6E, 0x70, 0x29, 0x12, 0x07, 0x2A, 0x75, + 0x83, 0x92, 0xE5, 0x40, 0x12, 0x07, 0x29, 0x75, +/*0B90*/0x83, 0xC6, 0xE5, 0x40, 0x12, 0x07, 0x29, 0x75, + 0x83, 0xC8, 0x80, 0x0E, 0x90, 0x07, 0x26, 0x12, +/*0BA0*/0x07, 0x35, 0x12, 0x08, 0x6E, 0x70, 0x06, 0x12, + 0x07, 0x32, 0xE5, 0x40, 0xF0, 0xAF, 0x69, 0x7E, +/*0BB0*/0x00, 0xAD, 0x67, 0xAC, 0x66, 0x12, 0x04, 0x44, + 0x12, 0x07, 0x2A, 0x75, 0x83, 0xCA, 0xE0, 0xD3, +/*0BC0*/0x94, 0x00, 0x50, 0x0C, 0x05, 0x68, 0xE5, 0x68, + 0xC3, 0x94, 0x05, 0x50, 0x03, 0x02, 0x0B, 0x14, +/*0BD0*/0x22, 0x8C, 0x60, 0x8D, 0x61, 0x12, 0x08, 0xDA, + 0x74, 0x20, 0x40, 0x0D, 0x2F, 0xF5, 0x82, 0x74, +/*0BE0*/0x03, 0x3E, 0xF5, 0x83, 0xE5, 0x3E, 0xF0, 0x80, + 0x0B, 0x2F, 0xF5, 0x82, 0x74, 0x03, 0x3E, 0xF5, +/*0BF0*/0x83, 0xE5, 0x3C, 0xF0, 0xE5, 0x3C, 0xD3, 0x95, + 0x3E, 0x40, 0x3C, 0xE5, 0x61, 0x45, 0x60, 0x70, +/*0C00*/0x10, 0xE9, 0x12, 0x09, 0x04, 0xE5, 0x3E, 0x12, + 0x07, 0x68, 0x40, 0x3B, 0x12, 0x08, 0x95, 0x80, +/*0C10*/0x18, 0xE5, 0x3E, 0xC3, 0x95, 0x38, 0x40, 0x1D, + 0x85, 0x3E, 0x38, 0xE5, 0x3E, 0x60, 0x05, 0x85, +/*0C20*/0x3F, 0x39, 0x80, 0x03, 0x85, 0x39, 0x39, 0x8F, + 0x3A, 0x12, 0x08, 0x14, 0xE5, 0x3E, 0x12, 0x07, +/*0C30*/0xC0, 0xE5, 0x3F, 0xF0, 0x22, 0x80, 0x43, 0xE5, + 0x61, 0x45, 0x60, 0x70, 0x19, 0x12, 0x07, 0x5F, +/*0C40*/0x40, 0x05, 0x12, 0x08, 0x9E, 0x80, 0x27, 0x12, + 0x09, 0x0B, 0x12, 0x08, 0x14, 0xE5, 0x42, 0x12, +/*0C50*/0x07, 0xC0, 0xE5, 0x41, 0xF0, 0x22, 0xE5, 0x3C, + 0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3C, 0x38, +/*0C60*/0xE5, 0x3C, 0x60, 0x05, 0x85, 0x3D, 0x39, 0x80, + 0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12, 0x08, +/*0C70*/0x14, 0xE5, 0x3C, 0x12, 0x07, 0xC0, 0xE5, 0x3D, + 0xF0, 0x22, 0x85, 0x38, 0x38, 0x85, 0x39, 0x39, +/*0C80*/0x85, 0x3A, 0x3A, 0x12, 0x08, 0x14, 0xE5, 0x38, + 0x12, 0x07, 0xC0, 0xE5, 0x39, 0xF0, 0x22, 0x7F, +/*0C90*/0x06, 0x12, 0x17, 0x31, 0x12, 0x1D, 0x23, 0x12, + 0x0E, 0x04, 0x12, 0x0E, 0x33, 0xE0, 0x44, 0x0A, +/*0CA0*/0xF0, 0x74, 0x8E, 0xFE, 0x12, 0x0E, 0x04, 0x12, + 0x0E, 0x0B, 0xEF, 0xF0, 0xE5, 0x28, 0x30, 0xE5, +/*0CB0*/0x03, 0xD3, 0x80, 0x01, 0xC3, 0x40, 0x05, 0x75, + 0x14, 0x20, 0x80, 0x03, 0x75, 0x14, 0x08, 0x12, +/*0CC0*/0x0E, 0x04, 0x75, 0x83, 0x8A, 0xE5, 0x14, 0xF0, + 0xB4, 0xFF, 0x05, 0x75, 0x12, 0x80, 0x80, 0x06, +/*0CD0*/0xE5, 0x14, 0xC3, 0x13, 0xF5, 0x12, 0xE4, 0xF5, + 0x16, 0xF5, 0x7F, 0x12, 0x19, 0x36, 0x12, 0x13, +/*0CE0*/0xA3, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x50, 0x09, + 0x05, 0x16, 0xE5, 0x16, 0xC3, 0x94, 0x14, 0x40, +/*0CF0*/0xEA, 0xE5, 0xE4, 0x20, 0xE7, 0x28, 0x12, 0x0E, + 0x04, 0x75, 0x83, 0xD2, 0xE0, 0x54, 0x08, 0xD3, +/*0D00*/0x94, 0x00, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02, + 0x7F, 0x00, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40, +/*0D10*/0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF, + 0x5E, 0x60, 0x03, 0x12, 0x1D, 0xD7, 0xE5, 0x7F, +/*0D20*/0xC3, 0x94, 0x11, 0x40, 0x14, 0x12, 0x0E, 0x04, + 0x75, 0x83, 0xD2, 0xE0, 0x44, 0x80, 0xF0, 0xE5, +/*0D30*/0xE4, 0x20, 0xE7, 0x0F, 0x12, 0x1D, 0xD7, 0x80, + 0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0xD2, 0xE0, +/*0D40*/0x54, 0x7F, 0xF0, 0x12, 0x1D, 0x23, 0x22, 0x74, + 0x8A, 0x85, 0x08, 0x82, 0xF5, 0x83, 0xE5, 0x17, +/*0D50*/0xF0, 0x12, 0x0E, 0x3A, 0xE4, 0xF0, 0x90, 0x07, + 0x02, 0xE0, 0x12, 0x0E, 0x17, 0x75, 0x83, 0x90, +/*0D60*/0xEF, 0xF0, 0x74, 0x92, 0xFE, 0xE5, 0x08, 0x44, + 0x07, 0xFF, 0xF5, 0x82, 0x8E, 0x83, 0xE0, 0x54, +/*0D70*/0xC0, 0xFD, 0x90, 0x07, 0x03, 0xE0, 0x54, 0x3F, + 0x4D, 0x8F, 0x82, 0x8E, 0x83, 0xF0, 0x90, 0x07, +/*0D80*/0x04, 0xE0, 0x12, 0x0E, 0x17, 0x75, 0x83, 0x82, + 0xEF, 0xF0, 0x90, 0x07, 0x05, 0xE0, 0xFF, 0xED, +/*0D90*/0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xB4, 0xEF, + 0x12, 0x0E, 0x03, 0x75, 0x83, 0x80, 0xE0, 0x54, +/*0DA0*/0xBF, 0xF0, 0x30, 0x37, 0x0A, 0x12, 0x0E, 0x91, + 0x75, 0x83, 0x94, 0xE0, 0x44, 0x80, 0xF0, 0x30, +/*0DB0*/0x38, 0x0A, 0x12, 0x0E, 0x91, 0x75, 0x83, 0x92, + 0xE0, 0x44, 0x80, 0xF0, 0xE5, 0x28, 0x30, 0xE4, +/*0DC0*/0x1A, 0x20, 0x39, 0x0A, 0x12, 0x0E, 0x04, 0x75, + 0x83, 0x88, 0xE0, 0x54, 0x7F, 0xF0, 0x20, 0x3A, +/*0DD0*/0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0x88, 0xE0, + 0x54, 0xBF, 0xF0, 0x74, 0x8C, 0xFE, 0x12, 0x0E, +/*0DE0*/0x04, 0x8E, 0x83, 0xE0, 0x54, 0x0F, 0x12, 0x0E, + 0x03, 0x75, 0x83, 0x86, 0xE0, 0x54, 0xBF, 0xF0, +/*0DF0*/0xE5, 0x08, 0x44, 0x06, 0x12, 0x0D, 0xFD, 0x75, + 0x83, 0x8A, 0xE4, 0xF0, 0x22, 0xF5, 0x82, 0x75, +/*0E00*/0x83, 0x82, 0xE4, 0xF0, 0xE5, 0x08, 0x44, 0x07, + 0xF5, 0x82, 0x22, 0x8E, 0x83, 0xE0, 0xF5, 0x10, +/*0E10*/0x54, 0xFE, 0xF0, 0xE5, 0x10, 0x44, 0x01, 0xFF, + 0xE5, 0x08, 0xFD, 0xED, 0x44, 0x07, 0xF5, 0x82, +/*0E20*/0x22, 0xE5, 0x15, 0xC4, 0x54, 0x07, 0xFF, 0xE5, + 0x08, 0xFD, 0xED, 0x44, 0x08, 0xF5, 0x82, 0x75, +/*0E30*/0x83, 0x82, 0x22, 0x75, 0x83, 0x80, 0xE0, 0x44, + 0x40, 0xF0, 0xE5, 0x08, 0x44, 0x08, 0xF5, 0x82, +/*0E40*/0x75, 0x83, 0x8A, 0x22, 0xE5, 0x16, 0x25, 0xE0, + 0x25, 0xE0, 0x24, 0xAF, 0xF5, 0x82, 0xE4, 0x34, +/*0E50*/0x1A, 0xF5, 0x83, 0xE4, 0x93, 0xF5, 0x0D, 0x22, + 0x43, 0xE1, 0x10, 0x43, 0xE1, 0x80, 0x53, 0xE1, +/*0E60*/0xFD, 0x85, 0xE1, 0x10, 0x22, 0xE5, 0x16, 0x25, + 0xE0, 0x25, 0xE0, 0x24, 0xB2, 0xF5, 0x82, 0xE4, +/*0E70*/0x34, 0x1A, 0xF5, 0x83, 0xE4, 0x93, 0x22, 0x85, + 0x55, 0x82, 0x85, 0x54, 0x83, 0xE5, 0x15, 0xF0, +/*0E80*/0x22, 0xE5, 0xE2, 0x54, 0x20, 0xD3, 0x94, 0x00, + 0x22, 0xE5, 0xE2, 0x54, 0x40, 0xD3, 0x94, 0x00, +/*0E90*/0x22, 0xE5, 0x08, 0x44, 0x06, 0xF5, 0x82, 0x22, + 0xFD, 0xE5, 0x08, 0xFB, 0xEB, 0x44, 0x07, 0xF5, +/*0EA0*/0x82, 0x22, 0x53, 0xF9, 0xF7, 0x75, 0xFE, 0x30, + 0x22, 0xEF, 0x4E, 0x70, 0x26, 0x12, 0x07, 0xCC, +/*0EB0*/0xE0, 0xFD, 0x90, 0x07, 0x26, 0x12, 0x07, 0x7B, + 0x12, 0x07, 0xD8, 0xE0, 0xFD, 0x90, 0x07, 0x28, +/*0EC0*/0x12, 0x07, 0x7B, 0x12, 0x08, 0x81, 0x12, 0x07, + 0x72, 0x12, 0x08, 0x35, 0xE0, 0x90, 0x07, 0x24, +/*0ED0*/0x12, 0x07, 0x78, 0xEF, 0x64, 0x04, 0x4E, 0x70, + 0x29, 0x12, 0x07, 0xE4, 0xE0, 0xFD, 0x90, 0x07, +/*0EE0*/0x26, 0x12, 0x07, 0x7B, 0x12, 0x07, 0xF0, 0xE0, + 0xFD, 0x90, 0x07, 0x28, 0x12, 0x07, 0x7B, 0x12, +/*0EF0*/0x08, 0x8B, 0x12, 0x07, 0x72, 0x12, 0x08, 0x41, + 0xE0, 0x54, 0x1F, 0xFD, 0x90, 0x07, 0x24, 0x12, +/*0F00*/0x07, 0x7B, 0xEF, 0x64, 0x01, 0x4E, 0x70, 0x04, + 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00, 0xEF, 0x64, +/*0F10*/0x02, 0x4E, 0x70, 0x04, 0x7F, 0x01, 0x80, 0x02, + 0x7F, 0x00, 0xEF, 0x4D, 0x60, 0x35, 0x12, 0x07, +/*0F20*/0xFC, 0xE0, 0xFF, 0x90, 0x07, 0x26, 0x12, 0x07, + 0x89, 0xEF, 0xF0, 0x12, 0x08, 0x08, 0xE0, 0xFF, +/*0F30*/0x90, 0x07, 0x28, 0x12, 0x07, 0x89, 0xEF, 0xF0, + 0x12, 0x08, 0x4D, 0xE0, 0x54, 0x1F, 0xFF, 0x12, +/*0F40*/0x07, 0x86, 0xEF, 0xF0, 0x12, 0x08, 0x59, 0xE0, + 0x54, 0x1F, 0xFF, 0x90, 0x07, 0x24, 0x12, 0x07, +/*0F50*/0x89, 0xEF, 0xF0, 0x22, 0xE4, 0xF5, 0x53, 0x12, + 0x0E, 0x81, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02, +/*0F60*/0x7F, 0x00, 0x12, 0x0E, 0x89, 0x40, 0x04, 0x7E, + 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x70, +/*0F70*/0x03, 0x02, 0x0F, 0xF6, 0x85, 0xE1, 0x10, 0x43, + 0xE1, 0x02, 0x53, 0xE1, 0x0F, 0x85, 0xE1, 0x10, +/*0F80*/0xE4, 0xF5, 0x51, 0xE5, 0xE3, 0x54, 0x3F, 0xF5, + 0x52, 0x12, 0x0E, 0x89, 0x40, 0x1D, 0xAD, 0x52, +/*0F90*/0xAF, 0x51, 0x12, 0x11, 0x18, 0xEF, 0x60, 0x08, + 0x85, 0xE1, 0x10, 0x43, 0xE1, 0x40, 0x80, 0x0B, +/*0FA0*/0x53, 0xE1, 0xBF, 0x12, 0x0E, 0x58, 0x12, 0x00, + 0x06, 0x80, 0xFB, 0xE5, 0xE3, 0x54, 0x3F, 0xF5, +/*0FB0*/0x51, 0xE5, 0xE4, 0x54, 0x3F, 0xF5, 0x52, 0x12, + 0x0E, 0x81, 0x40, 0x1D, 0xAD, 0x52, 0xAF, 0x51, +/*0FC0*/0x12, 0x11, 0x18, 0xEF, 0x60, 0x08, 0x85, 0xE1, + 0x10, 0x43, 0xE1, 0x20, 0x80, 0x0B, 0x53, 0xE1, +/*0FD0*/0xDF, 0x12, 0x0E, 0x58, 0x12, 0x00, 0x06, 0x80, + 0xFB, 0x12, 0x0E, 0x81, 0x40, 0x04, 0x7F, 0x01, +/*0FE0*/0x80, 0x02, 0x7F, 0x00, 0x12, 0x0E, 0x89, 0x40, + 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, +/*0FF0*/0x4F, 0x60, 0x03, 0x12, 0x0E, 0x5B, 0x22, 0x12, + 0x0E, 0x21, 0xEF, 0xF0, 0x12, 0x10, 0x91, 0x22, +/*1000*/0x02, 0x11, 0x00, 0x02, 0x10, 0x40, 0x02, 0x10, + 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1010*/0x01, 0x20, 0x01, 0x20, 0xE4, 0xF5, 0x57, 0x12, + 0x16, 0xBD, 0x12, 0x16, 0x44, 0xE4, 0x12, 0x10, +/*1020*/0x56, 0x12, 0x14, 0xB7, 0x90, 0x07, 0x26, 0x12, + 0x07, 0x35, 0xE4, 0x12, 0x07, 0x31, 0xE4, 0xF0, +/*1030*/0x12, 0x10, 0x56, 0x12, 0x14, 0xB7, 0x90, 0x07, + 0x26, 0x12, 0x07, 0x35, 0xE5, 0x41, 0x12, 0x07, +/*1040*/0x31, 0xE5, 0x40, 0xF0, 0xAF, 0x57, 0x7E, 0x00, + 0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44, 0xAF, +/*1050*/0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0xFF, 0x90, + 0x07, 0x20, 0xA3, 0xE0, 0xFD, 0xE4, 0xF5, 0x56, +/*1060*/0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA, 0x12, + 0x11, 0x51, 0x7F, 0x0F, 0x7D, 0x18, 0xE4, 0xF5, +/*1070*/0x56, 0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA, + 0x12, 0x15, 0x41, 0xAF, 0x56, 0x7E, 0x00, 0x12, +/*1080*/0x1A, 0xFF, 0xE4, 0xFF, 0xF5, 0x56, 0x7D, 0x1F, + 0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA, 0x22, +/*1090*/0x22, 0xE4, 0xF5, 0x55, 0xE5, 0x08, 0xFD, 0x74, + 0xA0, 0xF5, 0x56, 0xED, 0x44, 0x07, 0xF5, 0x57, +/*10A0*/0xE5, 0x28, 0x30, 0xE5, 0x03, 0xD3, 0x80, 0x01, + 0xC3, 0x40, 0x05, 0x7F, 0x28, 0xEF, 0x80, 0x04, +/*10B0*/0x7F, 0x14, 0xEF, 0xC3, 0x13, 0xF5, 0x54, 0xE4, + 0xF9, 0x12, 0x0E, 0x18, 0x75, 0x83, 0x8E, 0xE0, +/*10C0*/0xF5, 0x10, 0xCE, 0xEF, 0xCE, 0xEE, 0xD3, 0x94, + 0x00, 0x40, 0x26, 0xE5, 0x10, 0x54, 0xFE, 0x12, +/*10D0*/0x0E, 0x98, 0x75, 0x83, 0x8E, 0xED, 0xF0, 0xE5, + 0x10, 0x44, 0x01, 0xFD, 0xEB, 0x44, 0x07, 0xF5, +/*10E0*/0x82, 0xED, 0xF0, 0x85, 0x57, 0x82, 0x85, 0x56, + 0x83, 0xE0, 0x30, 0xE3, 0x01, 0x09, 0x1E, 0x80, +/*10F0*/0xD4, 0xC2, 0x34, 0xE9, 0xC3, 0x95, 0x54, 0x40, + 0x02, 0xD2, 0x34, 0x22, 0x02, 0x00, 0x06, 0x22, +/*1100*/0x30, 0x30, 0x11, 0x90, 0x10, 0x00, 0xE4, 0x93, + 0xF5, 0x10, 0x90, 0x10, 0x10, 0xE4, 0x93, 0xF5, +/*1110*/0x10, 0x12, 0x10, 0x90, 0x12, 0x11, 0x50, 0x22, + 0xE4, 0xFC, 0xC3, 0xED, 0x9F, 0xFA, 0xEF, 0xF5, +/*1120*/0x83, 0x75, 0x82, 0x00, 0x79, 0xFF, 0xE4, 0x93, + 0xCC, 0x6C, 0xCC, 0xA3, 0xD9, 0xF8, 0xDA, 0xF6, +/*1130*/0xE5, 0xE2, 0x30, 0xE4, 0x02, 0x8C, 0xE5, 0xED, + 0x24, 0xFF, 0xFF, 0xEF, 0x75, 0x82, 0xFF, 0xF5, +/*1140*/0x83, 0xE4, 0x93, 0x6C, 0x70, 0x03, 0x7F, 0x01, + 0x22, 0x7F, 0x00, 0x22, 0x22, 0x11, 0x00, 0x00, +/*1150*/0x22, 0x8E, 0x58, 0x8F, 0x59, 0x8C, 0x5A, 0x8D, + 0x5B, 0x8A, 0x5C, 0x8B, 0x5D, 0x75, 0x5E, 0x01, +/*1160*/0xE4, 0xF5, 0x5F, 0xF5, 0x60, 0xF5, 0x62, 0x12, + 0x07, 0x2A, 0x75, 0x83, 0xD0, 0xE0, 0xFF, 0xC4, +/*1170*/0x54, 0x0F, 0xF5, 0x61, 0x12, 0x1E, 0xA5, 0x85, + 0x59, 0x5E, 0xD3, 0xE5, 0x5E, 0x95, 0x5B, 0xE5, +/*1180*/0x5A, 0x12, 0x07, 0x6B, 0x50, 0x4B, 0x12, 0x07, + 0x03, 0x75, 0x83, 0xBC, 0xE0, 0x45, 0x5E, 0x12, +/*1190*/0x07, 0x29, 0x75, 0x83, 0xBE, 0xE0, 0x45, 0x5E, + 0x12, 0x07, 0x29, 0x75, 0x83, 0xC0, 0xE0, 0x45, +/*11A0*/0x5E, 0xF0, 0xAF, 0x5F, 0xE5, 0x60, 0x12, 0x08, + 0x78, 0x12, 0x0A, 0xFF, 0xAF, 0x62, 0x7E, 0x00, +/*11B0*/0xAD, 0x5D, 0xAC, 0x5C, 0x12, 0x04, 0x44, 0xE5, + 0x61, 0xAF, 0x5E, 0x7E, 0x00, 0xB4, 0x03, 0x05, +/*11C0*/0x12, 0x1E, 0x21, 0x80, 0x07, 0xAD, 0x5D, 0xAC, + 0x5C, 0x12, 0x13, 0x17, 0x05, 0x5E, 0x02, 0x11, +/*11D0*/0x7A, 0x12, 0x07, 0x03, 0x75, 0x83, 0xBC, 0xE0, + 0x45, 0x40, 0x12, 0x07, 0x29, 0x75, 0x83, 0xBE, +/*11E0*/0xE0, 0x45, 0x40, 0x12, 0x07, 0x29, 0x75, 0x83, + 0xC0, 0xE0, 0x45, 0x40, 0xF0, 0x22, 0x8E, 0x58, +/*11F0*/0x8F, 0x59, 0x75, 0x5A, 0x01, 0x79, 0x01, 0x75, + 0x5B, 0x01, 0xE4, 0xFB, 0x12, 0x07, 0x2A, 0x75, +/*1200*/0x83, 0xAE, 0xE0, 0x54, 0x1A, 0xFF, 0x12, 0x08, + 0x65, 0xE0, 0xC4, 0x13, 0x54, 0x07, 0xFE, 0xEF, +/*1210*/0x70, 0x0C, 0xEE, 0x65, 0x35, 0x70, 0x07, 0x90, + 0x07, 0x2F, 0xE0, 0xB4, 0x01, 0x0D, 0xAF, 0x35, +/*1220*/0x7E, 0x00, 0x12, 0x0E, 0xA9, 0xCF, 0xEB, 0xCF, + 0x02, 0x1E, 0x60, 0xE5, 0x59, 0x64, 0x02, 0x45, +/*1230*/0x58, 0x70, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, + 0x00, 0xE5, 0x59, 0x45, 0x58, 0x70, 0x04, 0x7E, +/*1240*/0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x60, + 0x23, 0x85, 0x41, 0x49, 0x85, 0x40, 0x4B, 0xE5, +/*1250*/0x59, 0x45, 0x58, 0x70, 0x2C, 0xAF, 0x5A, 0xFE, + 0xCD, 0xE9, 0xCD, 0xFC, 0xAB, 0x59, 0xAA, 0x58, +/*1260*/0x12, 0x0A, 0xFF, 0xAF, 0x5B, 0x7E, 0x00, 0x12, + 0x1E, 0x60, 0x80, 0x15, 0xAF, 0x5B, 0x7E, 0x00, +/*1270*/0x12, 0x1E, 0x60, 0x90, 0x07, 0x26, 0x12, 0x07, + 0x35, 0xE5, 0x49, 0x12, 0x07, 0x31, 0xE5, 0x4B, +/*1280*/0xF0, 0xE4, 0xFD, 0xAF, 0x35, 0xFE, 0xFC, 0x12, + 0x09, 0x15, 0x22, 0x8C, 0x64, 0x8D, 0x65, 0x12, +/*1290*/0x08, 0xDA, 0x40, 0x3C, 0xE5, 0x65, 0x45, 0x64, + 0x70, 0x10, 0x12, 0x09, 0x04, 0xC3, 0xE5, 0x3E, +/*12A0*/0x12, 0x07, 0x69, 0x40, 0x3B, 0x12, 0x08, 0x95, + 0x80, 0x18, 0xE5, 0x3E, 0xC3, 0x95, 0x38, 0x40, +/*12B0*/0x1D, 0x85, 0x3E, 0x38, 0xE5, 0x3E, 0x60, 0x05, + 0x85, 0x3F, 0x39, 0x80, 0x03, 0x85, 0x39, 0x39, +/*12C0*/0x8F, 0x3A, 0x12, 0x07, 0xA8, 0xE5, 0x3E, 0x12, + 0x07, 0x53, 0xE5, 0x3F, 0xF0, 0x22, 0x80, 0x3B, +/*12D0*/0xE5, 0x65, 0x45, 0x64, 0x70, 0x11, 0x12, 0x07, + 0x5F, 0x40, 0x05, 0x12, 0x08, 0x9E, 0x80, 0x1F, +/*12E0*/0x12, 0x07, 0x3E, 0xE5, 0x41, 0xF0, 0x22, 0xE5, + 0x3C, 0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3C, +/*12F0*/0x38, 0xE5, 0x3C, 0x60, 0x05, 0x85, 0x3D, 0x39, + 0x80, 0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12, +/*1300*/0x07, 0xA8, 0xE5, 0x3C, 0x12, 0x07, 0x53, 0xE5, + 0x3D, 0xF0, 0x22, 0x12, 0x07, 0x9F, 0xE5, 0x38, +/*1310*/0x12, 0x07, 0x53, 0xE5, 0x39, 0xF0, 0x22, 0x8C, + 0x63, 0x8D, 0x64, 0x12, 0x08, 0xDA, 0x40, 0x3C, +/*1320*/0xE5, 0x64, 0x45, 0x63, 0x70, 0x10, 0x12, 0x09, + 0x04, 0xC3, 0xE5, 0x3E, 0x12, 0x07, 0x69, 0x40, +/*1330*/0x3B, 0x12, 0x08, 0x95, 0x80, 0x18, 0xE5, 0x3E, + 0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3E, 0x38, +/*1340*/0xE5, 0x3E, 0x60, 0x05, 0x85, 0x3F, 0x39, 0x80, + 0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12, 0x07, +/*1350*/0xA8, 0xE5, 0x3E, 0x12, 0x07, 0x53, 0xE5, 0x3F, + 0xF0, 0x22, 0x80, 0x3B, 0xE5, 0x64, 0x45, 0x63, +/*1360*/0x70, 0x11, 0x12, 0x07, 0x5F, 0x40, 0x05, 0x12, + 0x08, 0x9E, 0x80, 0x1F, 0x12, 0x07, 0x3E, 0xE5, +/*1370*/0x41, 0xF0, 0x22, 0xE5, 0x3C, 0xC3, 0x95, 0x38, + 0x40, 0x1D, 0x85, 0x3C, 0x38, 0xE5, 0x3C, 0x60, +/*1380*/0x05, 0x85, 0x3D, 0x39, 0x80, 0x03, 0x85, 0x39, + 0x39, 0x8F, 0x3A, 0x12, 0x07, 0xA8, 0xE5, 0x3C, +/*1390*/0x12, 0x07, 0x53, 0xE5, 0x3D, 0xF0, 0x22, 0x12, + 0x07, 0x9F, 0xE5, 0x38, 0x12, 0x07, 0x53, 0xE5, +/*13A0*/0x39, 0xF0, 0x22, 0xE5, 0x0D, 0xFE, 0xE5, 0x08, + 0x8E, 0x54, 0x44, 0x05, 0xF5, 0x55, 0x75, 0x15, +/*13B0*/0x0F, 0xF5, 0x82, 0x12, 0x0E, 0x7A, 0x12, 0x17, + 0xA3, 0x20, 0x31, 0x05, 0x75, 0x15, 0x03, 0x80, +/*13C0*/0x03, 0x75, 0x15, 0x0B, 0xE5, 0x0A, 0xC3, 0x94, + 0x01, 0x50, 0x38, 0x12, 0x14, 0x20, 0x20, 0x31, +/*13D0*/0x06, 0x05, 0x15, 0x05, 0x15, 0x80, 0x04, 0x15, + 0x15, 0x15, 0x15, 0xE5, 0x0A, 0xC3, 0x94, 0x01, +/*13E0*/0x50, 0x21, 0x12, 0x14, 0x20, 0x20, 0x31, 0x04, + 0x05, 0x15, 0x80, 0x02, 0x15, 0x15, 0xE5, 0x0A, +/*13F0*/0xC3, 0x94, 0x01, 0x50, 0x0E, 0x12, 0x0E, 0x77, + 0x12, 0x17, 0xA3, 0x20, 0x31, 0x05, 0x05, 0x15, +/*1400*/0x12, 0x0E, 0x77, 0xE5, 0x15, 0xB4, 0x08, 0x04, + 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x15, +/*1410*/0xB4, 0x07, 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, + 0x00, 0xEE, 0x4F, 0x60, 0x02, 0x05, 0x7F, 0x22, +/*1420*/0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xE5, 0x15, + 0xF0, 0x12, 0x17, 0xA3, 0x22, 0x12, 0x07, 0x2A, +/*1430*/0x75, 0x83, 0xAE, 0x74, 0xFF, 0x12, 0x07, 0x29, + 0xE0, 0x54, 0x1A, 0xF5, 0x34, 0xE0, 0xC4, 0x13, +/*1440*/0x54, 0x07, 0xF5, 0x35, 0x24, 0xFE, 0x60, 0x24, + 0x24, 0xFE, 0x60, 0x3C, 0x24, 0x04, 0x70, 0x63, +/*1450*/0x75, 0x31, 0x2D, 0xE5, 0x08, 0xFD, 0x74, 0xB6, + 0x12, 0x07, 0x92, 0x74, 0xBC, 0x90, 0x07, 0x22, +/*1460*/0x12, 0x07, 0x95, 0x74, 0x90, 0x12, 0x07, 0xB3, + 0x74, 0x92, 0x80, 0x3C, 0x75, 0x31, 0x3A, 0xE5, +/*1470*/0x08, 0xFD, 0x74, 0xBA, 0x12, 0x07, 0x92, 0x74, + 0xC0, 0x90, 0x07, 0x22, 0x12, 0x07, 0xB6, 0x74, +/*1480*/0xC4, 0x12, 0x07, 0xB3, 0x74, 0xC8, 0x80, 0x20, + 0x75, 0x31, 0x35, 0xE5, 0x08, 0xFD, 0x74, 0xB8, +/*1490*/0x12, 0x07, 0x92, 0x74, 0xBE, 0xFF, 0xED, 0x44, + 0x07, 0x90, 0x07, 0x22, 0xCF, 0xF0, 0xA3, 0xEF, +/*14A0*/0xF0, 0x74, 0xC2, 0x12, 0x07, 0xB3, 0x74, 0xC6, + 0xFF, 0xED, 0x44, 0x07, 0xA3, 0xCF, 0xF0, 0xA3, +/*14B0*/0xEF, 0xF0, 0x22, 0x75, 0x34, 0x01, 0x22, 0x8E, + 0x58, 0x8F, 0x59, 0x8C, 0x5A, 0x8D, 0x5B, 0x8A, +/*14C0*/0x5C, 0x8B, 0x5D, 0x75, 0x5E, 0x01, 0xE4, 0xF5, + 0x5F, 0x12, 0x1E, 0xA5, 0x85, 0x59, 0x5E, 0xD3, +/*14D0*/0xE5, 0x5E, 0x95, 0x5B, 0xE5, 0x5A, 0x12, 0x07, + 0x6B, 0x50, 0x57, 0xE5, 0x5D, 0x45, 0x5C, 0x70, +/*14E0*/0x30, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x92, 0xE5, + 0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC6, 0xE5, +/*14F0*/0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC8, 0xE5, + 0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0x90, 0xE5, +/*1500*/0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE5, + 0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0x80, +/*1510*/0x03, 0x12, 0x07, 0x32, 0xE5, 0x5E, 0xF0, 0xAF, + 0x5F, 0x7E, 0x00, 0xAD, 0x5D, 0xAC, 0x5C, 0x12, +/*1520*/0x04, 0x44, 0xAF, 0x5E, 0x7E, 0x00, 0xAD, 0x5D, + 0xAC, 0x5C, 0x12, 0x0B, 0xD1, 0x05, 0x5E, 0x02, +/*1530*/0x14, 0xCF, 0xAB, 0x5D, 0xAA, 0x5C, 0xAD, 0x5B, + 0xAC, 0x5A, 0xAF, 0x59, 0xAE, 0x58, 0x02, 0x1B, +/*1540*/0xFB, 0x8C, 0x5C, 0x8D, 0x5D, 0x8A, 0x5E, 0x8B, + 0x5F, 0x75, 0x60, 0x01, 0xE4, 0xF5, 0x61, 0xF5, +/*1550*/0x62, 0xF5, 0x63, 0x12, 0x1E, 0xA5, 0x8F, 0x60, + 0xD3, 0xE5, 0x60, 0x95, 0x5D, 0xE5, 0x5C, 0x12, +/*1560*/0x07, 0x6B, 0x50, 0x61, 0xE5, 0x5F, 0x45, 0x5E, + 0x70, 0x27, 0x12, 0x07, 0x2A, 0x75, 0x83, 0xB6, +/*1570*/0xE5, 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0xB8, + 0xE5, 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0xBA, +/*1580*/0xE5, 0x60, 0xF0, 0xAF, 0x61, 0x7E, 0x00, 0xE5, + 0x62, 0x12, 0x08, 0x7A, 0x12, 0x0A, 0xFF, 0x80, +/*1590*/0x19, 0x90, 0x07, 0x24, 0x12, 0x07, 0x35, 0xE5, + 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0x8E, 0xE4, +/*15A0*/0x12, 0x07, 0x29, 0x74, 0x01, 0x12, 0x07, 0x29, + 0xE4, 0xF0, 0xAF, 0x63, 0x7E, 0x00, 0xAD, 0x5F, +/*15B0*/0xAC, 0x5E, 0x12, 0x04, 0x44, 0xAF, 0x60, 0x7E, + 0x00, 0xAD, 0x5F, 0xAC, 0x5E, 0x12, 0x12, 0x8B, +/*15C0*/0x05, 0x60, 0x02, 0x15, 0x58, 0x22, 0x90, 0x11, + 0x4D, 0xE4, 0x93, 0x90, 0x07, 0x2E, 0xF0, 0x12, +/*15D0*/0x08, 0x1F, 0x75, 0x83, 0xAE, 0xE0, 0x54, 0x1A, + 0xF5, 0x34, 0x70, 0x67, 0xEF, 0x44, 0x07, 0xF5, +/*15E0*/0x82, 0x75, 0x83, 0xCE, 0xE0, 0xFF, 0x13, 0x13, + 0x13, 0x54, 0x07, 0xF5, 0x36, 0x54, 0x0F, 0xD3, +/*15F0*/0x94, 0x00, 0x40, 0x06, 0x12, 0x14, 0x2D, 0x12, + 0x1B, 0xA9, 0xE5, 0x36, 0x54, 0x0F, 0x24, 0xFE, +/*1600*/0x60, 0x0C, 0x14, 0x60, 0x0C, 0x14, 0x60, 0x19, + 0x24, 0x03, 0x70, 0x37, 0x80, 0x10, 0x02, 0x1E, +/*1610*/0x91, 0x12, 0x1E, 0x91, 0x12, 0x07, 0x2A, 0x75, + 0x83, 0xCE, 0xE0, 0x54, 0xEF, 0xF0, 0x02, 0x1D, +/*1620*/0xAE, 0x12, 0x10, 0x14, 0xE4, 0xF5, 0x55, 0x12, + 0x1D, 0x85, 0x05, 0x55, 0xE5, 0x55, 0xC3, 0x94, +/*1630*/0x05, 0x40, 0xF4, 0x12, 0x07, 0x2A, 0x75, 0x83, + 0xCE, 0xE0, 0x54, 0xC7, 0x12, 0x07, 0x29, 0xE0, +/*1640*/0x44, 0x08, 0xF0, 0x22, 0xE4, 0xF5, 0x58, 0xF5, + 0x59, 0xAF, 0x08, 0xEF, 0x44, 0x07, 0xF5, 0x82, +/*1650*/0x75, 0x83, 0xD0, 0xE0, 0xFD, 0xC4, 0x54, 0x0F, + 0xF5, 0x5A, 0xEF, 0x44, 0x07, 0xF5, 0x82, 0x75, +/*1660*/0x83, 0x80, 0x74, 0x01, 0xF0, 0x12, 0x08, 0x21, + 0x75, 0x83, 0x82, 0xE5, 0x45, 0xF0, 0xEF, 0x44, +/*1670*/0x07, 0xF5, 0x82, 0x75, 0x83, 0x8A, 0x74, 0xFF, + 0xF0, 0x12, 0x1A, 0x4D, 0x12, 0x07, 0x2A, 0x75, +/*1680*/0x83, 0xBC, 0xE0, 0x54, 0xEF, 0x12, 0x07, 0x29, + 0x75, 0x83, 0xBE, 0xE0, 0x54, 0xEF, 0x12, 0x07, +/*1690*/0x29, 0x75, 0x83, 0xC0, 0xE0, 0x54, 0xEF, 0x12, + 0x07, 0x29, 0x75, 0x83, 0xBC, 0xE0, 0x44, 0x10, +/*16A0*/0x12, 0x07, 0x29, 0x75, 0x83, 0xBE, 0xE0, 0x44, + 0x10, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC0, 0xE0, +/*16B0*/0x44, 0x10, 0xF0, 0xAF, 0x58, 0xE5, 0x59, 0x12, + 0x08, 0x78, 0x02, 0x0A, 0xFF, 0xE4, 0xF5, 0x58, +/*16C0*/0x7D, 0x01, 0xF5, 0x59, 0xAF, 0x35, 0xFE, 0xFC, + 0x12, 0x09, 0x15, 0x12, 0x07, 0x2A, 0x75, 0x83, +/*16D0*/0xB6, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83, + 0xB8, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83, +/*16E0*/0xBA, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83, + 0xBC, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83, +/*16F0*/0xBE, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83, + 0xC0, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83, +/*1700*/0x90, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, + 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0xE4, +/*1710*/0x12, 0x07, 0x29, 0x75, 0x83, 0x92, 0xE4, 0x12, + 0x07, 0x29, 0x75, 0x83, 0xC6, 0xE4, 0x12, 0x07, +/*1720*/0x29, 0x75, 0x83, 0xC8, 0xE4, 0xF0, 0xAF, 0x58, + 0xFE, 0xE5, 0x59, 0x12, 0x08, 0x7A, 0x02, 0x0A, +/*1730*/0xFF, 0xE5, 0xE2, 0x30, 0xE4, 0x6C, 0xE5, 0xE7, + 0x54, 0xC0, 0x64, 0x40, 0x70, 0x64, 0xE5, 0x09, +/*1740*/0xC4, 0x54, 0x30, 0xFE, 0xE5, 0x08, 0x25, 0xE0, + 0x25, 0xE0, 0x54, 0xC0, 0x4E, 0xFE, 0xEF, 0x54, +/*1750*/0x3F, 0x4E, 0xFD, 0xE5, 0x2B, 0xAE, 0x2A, 0x78, + 0x02, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, +/*1760*/0xF5, 0x82, 0x8E, 0x83, 0xED, 0xF0, 0xE5, 0x2B, + 0xAE, 0x2A, 0x78, 0x02, 0xC3, 0x33, 0xCE, 0x33, +/*1770*/0xCE, 0xD8, 0xF9, 0xFF, 0xF5, 0x82, 0x8E, 0x83, + 0xA3, 0xE5, 0xFE, 0xF0, 0x8F, 0x82, 0x8E, 0x83, +/*1780*/0xA3, 0xA3, 0xE5, 0xFD, 0xF0, 0x8F, 0x82, 0x8E, + 0x83, 0xA3, 0xA3, 0xA3, 0xE5, 0xFC, 0xF0, 0xC3, +/*1790*/0xE5, 0x2B, 0x94, 0xFA, 0xE5, 0x2A, 0x94, 0x00, + 0x50, 0x08, 0x05, 0x2B, 0xE5, 0x2B, 0x70, 0x02, +/*17A0*/0x05, 0x2A, 0x22, 0xE4, 0xFF, 0xE4, 0xF5, 0x58, + 0xF5, 0x56, 0xF5, 0x57, 0x74, 0x82, 0xFC, 0x12, +/*17B0*/0x0E, 0x04, 0x8C, 0x83, 0xE0, 0xF5, 0x10, 0x54, + 0x7F, 0xF0, 0xE5, 0x10, 0x44, 0x80, 0x12, 0x0E, +/*17C0*/0x98, 0xED, 0xF0, 0x7E, 0x0A, 0x12, 0x0E, 0x04, + 0x75, 0x83, 0xA0, 0xE0, 0x20, 0xE0, 0x26, 0xDE, +/*17D0*/0xF4, 0x05, 0x57, 0xE5, 0x57, 0x70, 0x02, 0x05, + 0x56, 0xE5, 0x14, 0x24, 0x01, 0xFD, 0xE4, 0x33, +/*17E0*/0xFC, 0xD3, 0xE5, 0x57, 0x9D, 0xE5, 0x56, 0x9C, + 0x40, 0xD9, 0xE5, 0x0A, 0x94, 0x20, 0x50, 0x02, +/*17F0*/0x05, 0x0A, 0x43, 0xE1, 0x08, 0xC2, 0x31, 0x12, + 0x0E, 0x04, 0x75, 0x83, 0xA6, 0xE0, 0x55, 0x12, +/*1800*/0x65, 0x12, 0x70, 0x03, 0xD2, 0x31, 0x22, 0xC2, + 0x31, 0x22, 0x90, 0x07, 0x26, 0xE0, 0xFA, 0xA3, +/*1810*/0xE0, 0xF5, 0x82, 0x8A, 0x83, 0xE0, 0xF5, 0x41, + 0xE5, 0x39, 0xC3, 0x95, 0x41, 0x40, 0x26, 0xE5, +/*1820*/0x39, 0x95, 0x41, 0xC3, 0x9F, 0xEE, 0x12, 0x07, + 0x6B, 0x40, 0x04, 0x7C, 0x01, 0x80, 0x02, 0x7C, +/*1830*/0x00, 0xE5, 0x41, 0x64, 0x3F, 0x60, 0x04, 0x7B, + 0x01, 0x80, 0x02, 0x7B, 0x00, 0xEC, 0x5B, 0x60, +/*1840*/0x29, 0x05, 0x41, 0x80, 0x28, 0xC3, 0xE5, 0x41, + 0x95, 0x39, 0xC3, 0x9F, 0xEE, 0x12, 0x07, 0x6B, +/*1850*/0x40, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, + 0xE5, 0x41, 0x60, 0x04, 0x7E, 0x01, 0x80, 0x02, +/*1860*/0x7E, 0x00, 0xEF, 0x5E, 0x60, 0x04, 0x15, 0x41, + 0x80, 0x03, 0x85, 0x39, 0x41, 0x85, 0x3A, 0x40, +/*1870*/0x22, 0xE5, 0xE2, 0x30, 0xE4, 0x60, 0xE5, 0xE1, + 0x30, 0xE2, 0x5B, 0xE5, 0x09, 0x70, 0x04, 0x7F, +/*1880*/0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x08, 0x70, + 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, +/*1890*/0x5F, 0x60, 0x43, 0x53, 0xF9, 0xF8, 0xE5, 0xE2, + 0x30, 0xE4, 0x3B, 0xE5, 0xE1, 0x30, 0xE2, 0x2E, +/*18A0*/0x43, 0xFA, 0x02, 0x53, 0xFA, 0xFB, 0xE4, 0xF5, + 0x10, 0x90, 0x94, 0x70, 0xE5, 0x10, 0xF0, 0xE5, +/*18B0*/0xE1, 0x30, 0xE2, 0xE7, 0x90, 0x94, 0x70, 0xE0, + 0x65, 0x10, 0x60, 0x03, 0x43, 0xFA, 0x04, 0x05, +/*18C0*/0x10, 0x90, 0x94, 0x70, 0xE5, 0x10, 0xF0, 0x70, + 0xE6, 0x12, 0x00, 0x06, 0x80, 0xE1, 0x53, 0xFA, +/*18D0*/0xFD, 0x53, 0xFA, 0xFB, 0x80, 0xC0, 0x22, 0x8F, + 0x54, 0x12, 0x00, 0x06, 0xE5, 0xE1, 0x30, 0xE0, +/*18E0*/0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, + 0x7E, 0xD3, 0x94, 0x05, 0x40, 0x04, 0x7E, 0x01, +/*18F0*/0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x60, 0x3D, + 0x85, 0x54, 0x11, 0xE5, 0xE2, 0x20, 0xE1, 0x32, +/*1900*/0x74, 0xCE, 0x12, 0x1A, 0x05, 0x30, 0xE7, 0x04, + 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00, 0x8F, 0x82, +/*1910*/0x8E, 0x83, 0xE0, 0x30, 0xE6, 0x04, 0x7F, 0x01, + 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x5D, 0x70, 0x15, +/*1920*/0x12, 0x15, 0xC6, 0x74, 0xCE, 0x12, 0x1A, 0x05, + 0x30, 0xE6, 0x07, 0xE0, 0x44, 0x80, 0xF0, 0x43, +/*1930*/0xF9, 0x80, 0x12, 0x18, 0x71, 0x22, 0x12, 0x0E, + 0x44, 0xE5, 0x16, 0x25, 0xE0, 0x25, 0xE0, 0x24, +/*1940*/0xB0, 0xF5, 0x82, 0xE4, 0x34, 0x1A, 0xF5, 0x83, + 0xE4, 0x93, 0xF5, 0x0F, 0xE5, 0x16, 0x25, 0xE0, +/*1950*/0x25, 0xE0, 0x24, 0xB1, 0xF5, 0x82, 0xE4, 0x34, + 0x1A, 0xF5, 0x83, 0xE4, 0x93, 0xF5, 0x0E, 0x12, +/*1960*/0x0E, 0x65, 0xF5, 0x10, 0xE5, 0x0F, 0x54, 0xF0, + 0x12, 0x0E, 0x17, 0x75, 0x83, 0x8C, 0xEF, 0xF0, +/*1970*/0xE5, 0x0F, 0x30, 0xE0, 0x0C, 0x12, 0x0E, 0x04, + 0x75, 0x83, 0x86, 0xE0, 0x44, 0x40, 0xF0, 0x80, +/*1980*/0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0x86, 0xE0, + 0x54, 0xBF, 0xF0, 0x12, 0x0E, 0x91, 0x75, 0x83, +/*1990*/0x82, 0xE5, 0x0E, 0xF0, 0x22, 0x7F, 0x05, 0x12, + 0x17, 0x31, 0x12, 0x0E, 0x04, 0x12, 0x0E, 0x33, +/*19A0*/0x74, 0x02, 0xF0, 0x74, 0x8E, 0xFE, 0x12, 0x0E, + 0x04, 0x12, 0x0E, 0x0B, 0xEF, 0xF0, 0x75, 0x15, +/*19B0*/0x70, 0x12, 0x0F, 0xF7, 0x20, 0x34, 0x05, 0x75, + 0x15, 0x10, 0x80, 0x03, 0x75, 0x15, 0x50, 0x12, +/*19C0*/0x0F, 0xF7, 0x20, 0x34, 0x04, 0x74, 0x10, 0x80, + 0x02, 0x74, 0xF0, 0x25, 0x15, 0xF5, 0x15, 0x12, +/*19D0*/0x0E, 0x21, 0xEF, 0xF0, 0x12, 0x10, 0x91, 0x20, + 0x34, 0x17, 0xE5, 0x15, 0x64, 0x30, 0x60, 0x0C, +/*19E0*/0x74, 0x10, 0x25, 0x15, 0xF5, 0x15, 0xB4, 0x80, + 0x03, 0xE4, 0xF5, 0x15, 0x12, 0x0E, 0x21, 0xEF, +/*19F0*/0xF0, 0x22, 0xF0, 0xE5, 0x0B, 0x25, 0xE0, 0x25, + 0xE0, 0x24, 0x82, 0xF5, 0x82, 0xE4, 0x34, 0x07, +/*1A00*/0xF5, 0x83, 0x22, 0x74, 0x88, 0xFE, 0xE5, 0x08, + 0x44, 0x07, 0xFF, 0xF5, 0x82, 0x8E, 0x83, 0xE0, +/*1A10*/0x22, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82, + 0x22, 0xF0, 0xE0, 0x54, 0xC0, 0x8F, 0x82, 0x8E, +/*1A20*/0x83, 0xF0, 0x22, 0xEF, 0x44, 0x07, 0xF5, 0x82, + 0x75, 0x83, 0x86, 0xE0, 0x54, 0x10, 0xD3, 0x94, +/*1A30*/0x00, 0x22, 0xF0, 0x90, 0x07, 0x15, 0xE0, 0x04, + 0xF0, 0x22, 0x44, 0x06, 0xF5, 0x82, 0x75, 0x83, +/*1A40*/0x9E, 0xE0, 0x22, 0xFE, 0xEF, 0x44, 0x07, 0xF5, + 0x82, 0x8E, 0x83, 0xE0, 0x22, 0xE4, 0x90, 0x07, +/*1A50*/0x2A, 0xF0, 0xA3, 0xF0, 0x12, 0x07, 0x2A, 0x75, + 0x83, 0x82, 0xE0, 0x54, 0x7F, 0x12, 0x07, 0x29, +/*1A60*/0xE0, 0x44, 0x80, 0xF0, 0x12, 0x10, 0xFC, 0x12, + 0x08, 0x1F, 0x75, 0x83, 0xA0, 0xE0, 0x20, 0xE0, +/*1A70*/0x1A, 0x90, 0x07, 0x2B, 0xE0, 0x04, 0xF0, 0x70, + 0x06, 0x90, 0x07, 0x2A, 0xE0, 0x04, 0xF0, 0x90, +/*1A80*/0x07, 0x2A, 0xE0, 0xB4, 0x10, 0xE1, 0xA3, 0xE0, + 0xB4, 0x00, 0xDC, 0xEE, 0x44, 0xA6, 0xFC, 0xEF, +/*1A90*/0x44, 0x07, 0xF5, 0x82, 0x8C, 0x83, 0xE0, 0xF5, + 0x32, 0xEE, 0x44, 0xA8, 0xFE, 0xEF, 0x44, 0x07, +/*1AA0*/0xF5, 0x82, 0x8E, 0x83, 0xE0, 0xF5, 0x33, 0x22, + 0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x90, +/*1AB0*/0x00, 0x20, 0x0F, 0x92, 0x00, 0x21, 0x0F, 0x94, + 0x00, 0x22, 0x0F, 0x96, 0x00, 0x23, 0x0F, 0x98, +/*1AC0*/0x00, 0x24, 0x0F, 0x9A, 0x00, 0x25, 0x0F, 0x9C, + 0x00, 0x26, 0x0F, 0x9E, 0x00, 0x27, 0x0F, 0xA0, +/*1AD0*/0x01, 0x20, 0x01, 0xA2, 0x01, 0x21, 0x01, 0xA4, + 0x01, 0x22, 0x01, 0xA6, 0x01, 0x23, 0x01, 0xA8, +/*1AE0*/0x01, 0x24, 0x01, 0xAA, 0x01, 0x25, 0x01, 0xAC, + 0x01, 0x26, 0x01, 0xAE, 0x01, 0x27, 0x01, 0xB0, +/*1AF0*/0x01, 0x28, 0x01, 0xB4, 0x00, 0x28, 0x0F, 0xB6, + 0x40, 0x28, 0x0F, 0xB8, 0x61, 0x28, 0x01, 0xCB, +/*1B00*/0xEF, 0xCB, 0xCA, 0xEE, 0xCA, 0x7F, 0x01, 0xE4, + 0xFD, 0xEB, 0x4A, 0x70, 0x24, 0xE5, 0x08, 0xF5, +/*1B10*/0x82, 0x74, 0xB6, 0x12, 0x08, 0x29, 0xE5, 0x08, + 0xF5, 0x82, 0x74, 0xB8, 0x12, 0x08, 0x29, 0xE5, +/*1B20*/0x08, 0xF5, 0x82, 0x74, 0xBA, 0x12, 0x08, 0x29, + 0x7E, 0x00, 0x7C, 0x00, 0x12, 0x0A, 0xFF, 0x80, +/*1B30*/0x12, 0x90, 0x07, 0x26, 0x12, 0x07, 0x35, 0xE5, + 0x41, 0xF0, 0x90, 0x07, 0x24, 0x12, 0x07, 0x35, +/*1B40*/0xE5, 0x40, 0xF0, 0x12, 0x07, 0x2A, 0x75, 0x83, + 0x8E, 0xE4, 0x12, 0x07, 0x29, 0x74, 0x01, 0x12, +/*1B50*/0x07, 0x29, 0xE4, 0xF0, 0x22, 0xE4, 0xF5, 0x26, + 0xF5, 0x27, 0x53, 0xE1, 0xFE, 0xF5, 0x2A, 0x75, +/*1B60*/0x2B, 0x01, 0xF5, 0x08, 0x7F, 0x01, 0x12, 0x17, + 0x31, 0x30, 0x30, 0x1C, 0x90, 0x1A, 0xA9, 0xE4, +/*1B70*/0x93, 0xF5, 0x10, 0x90, 0x1F, 0xF9, 0xE4, 0x93, + 0xF5, 0x10, 0x90, 0x00, 0x41, 0xE4, 0x93, 0xF5, +/*1B80*/0x10, 0x90, 0x1E, 0xCA, 0xE4, 0x93, 0xF5, 0x10, + 0x7F, 0x02, 0x12, 0x17, 0x31, 0x12, 0x0F, 0x54, +/*1B90*/0x7F, 0x03, 0x12, 0x17, 0x31, 0x12, 0x00, 0x06, + 0xE5, 0xE2, 0x30, 0xE7, 0x09, 0x12, 0x10, 0x00, +/*1BA0*/0x30, 0x30, 0x03, 0x12, 0x11, 0x00, 0x02, 0x00, + 0x47, 0x12, 0x08, 0x1F, 0x75, 0x83, 0xD0, 0xE0, +/*1BB0*/0xC4, 0x54, 0x0F, 0xFD, 0x75, 0x43, 0x01, 0x75, + 0x44, 0xFF, 0x12, 0x08, 0xAA, 0x74, 0x04, 0xF0, +/*1BC0*/0x75, 0x3B, 0x01, 0xED, 0x14, 0x60, 0x0C, 0x14, + 0x60, 0x0B, 0x14, 0x60, 0x0F, 0x24, 0x03, 0x70, +/*1BD0*/0x0B, 0x80, 0x09, 0x80, 0x00, 0x12, 0x08, 0xA7, + 0x04, 0xF0, 0x80, 0x06, 0x12, 0x08, 0xA7, 0x74, +/*1BE0*/0x04, 0xF0, 0xEE, 0x44, 0x82, 0xFE, 0xEF, 0x44, + 0x07, 0xF5, 0x82, 0x8E, 0x83, 0xE5, 0x45, 0x12, +/*1BF0*/0x08, 0xBE, 0x75, 0x83, 0x82, 0xE5, 0x31, 0xF0, + 0x02, 0x11, 0x4C, 0x8E, 0x60, 0x8F, 0x61, 0x12, +/*1C00*/0x1E, 0xA5, 0xE4, 0xFF, 0xCE, 0xED, 0xCE, 0xEE, + 0xD3, 0x95, 0x61, 0xE5, 0x60, 0x12, 0x07, 0x6B, +/*1C10*/0x40, 0x39, 0x74, 0x20, 0x2E, 0xF5, 0x82, 0xE4, + 0x34, 0x03, 0xF5, 0x83, 0xE0, 0x70, 0x03, 0xFF, +/*1C20*/0x80, 0x26, 0x12, 0x08, 0xE2, 0xFD, 0xC3, 0x9F, + 0x40, 0x1E, 0xCF, 0xED, 0xCF, 0xEB, 0x4A, 0x70, +/*1C30*/0x0B, 0x8D, 0x42, 0x12, 0x08, 0xEE, 0xF5, 0x41, + 0x8E, 0x40, 0x80, 0x0C, 0x12, 0x08, 0xE2, 0xF5, +/*1C40*/0x38, 0x12, 0x08, 0xEE, 0xF5, 0x39, 0x8E, 0x3A, + 0x1E, 0x80, 0xBC, 0x22, 0x75, 0x58, 0x01, 0xE5, +/*1C50*/0x35, 0x70, 0x0C, 0x12, 0x07, 0xCC, 0xE0, 0xF5, + 0x4A, 0x12, 0x07, 0xD8, 0xE0, 0xF5, 0x4C, 0xE5, +/*1C60*/0x35, 0xB4, 0x04, 0x0C, 0x12, 0x07, 0xE4, 0xE0, + 0xF5, 0x4A, 0x12, 0x07, 0xF0, 0xE0, 0xF5, 0x4C, +/*1C70*/0xE5, 0x35, 0xB4, 0x01, 0x04, 0x7F, 0x01, 0x80, + 0x02, 0x7F, 0x00, 0xE5, 0x35, 0xB4, 0x02, 0x04, +/*1C80*/0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, + 0x60, 0x0C, 0x12, 0x07, 0xFC, 0xE0, 0xF5, 0x4A, +/*1C90*/0x12, 0x08, 0x08, 0xE0, 0xF5, 0x4C, 0x85, 0x41, + 0x49, 0x85, 0x40, 0x4B, 0x22, 0x75, 0x5B, 0x01, +/*1CA0*/0x90, 0x07, 0x24, 0x12, 0x07, 0x35, 0xE0, 0x54, + 0x1F, 0xFF, 0xD3, 0x94, 0x02, 0x50, 0x04, 0x8F, +/*1CB0*/0x58, 0x80, 0x05, 0xEF, 0x24, 0xFE, 0xF5, 0x58, + 0xEF, 0xC3, 0x94, 0x18, 0x40, 0x05, 0x75, 0x59, +/*1CC0*/0x18, 0x80, 0x04, 0xEF, 0x04, 0xF5, 0x59, 0x85, + 0x43, 0x5A, 0xAF, 0x58, 0x7E, 0x00, 0xAD, 0x59, +/*1CD0*/0x7C, 0x00, 0xAB, 0x5B, 0x7A, 0x00, 0x12, 0x15, + 0x41, 0xAF, 0x5A, 0x7E, 0x00, 0x12, 0x18, 0x0A, +/*1CE0*/0xAF, 0x5B, 0x7E, 0x00, 0x02, 0x1A, 0xFF, 0xE5, + 0xE2, 0x30, 0xE7, 0x0E, 0x12, 0x10, 0x03, 0xC2, +/*1CF0*/0x30, 0x30, 0x30, 0x03, 0x12, 0x10, 0xFF, 0x20, + 0x33, 0x28, 0xE5, 0xE7, 0x30, 0xE7, 0x05, 0x12, +/*1D00*/0x0E, 0xA2, 0x80, 0x0D, 0xE5, 0xFE, 0xC3, 0x94, + 0x20, 0x50, 0x06, 0x12, 0x0E, 0xA2, 0x43, 0xF9, +/*1D10*/0x08, 0xE5, 0xF2, 0x30, 0xE7, 0x03, 0x53, 0xF9, + 0x7F, 0xE5, 0xF1, 0x54, 0x70, 0xD3, 0x94, 0x00, +/*1D20*/0x50, 0xD8, 0x22, 0x12, 0x0E, 0x04, 0x75, 0x83, + 0x80, 0xE4, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0x12, +/*1D30*/0x0D, 0xFD, 0x75, 0x83, 0x84, 0x12, 0x0E, 0x02, + 0x75, 0x83, 0x86, 0x12, 0x0E, 0x02, 0x75, 0x83, +/*1D40*/0x8C, 0xE0, 0x54, 0xF3, 0x12, 0x0E, 0x03, 0x75, + 0x83, 0x8E, 0x12, 0x0E, 0x02, 0x75, 0x83, 0x94, +/*1D50*/0xE0, 0x54, 0xFB, 0xF0, 0x22, 0x12, 0x07, 0x2A, + 0x75, 0x83, 0x8E, 0xE4, 0x12, 0x07, 0x29, 0x74, +/*1D60*/0x01, 0x12, 0x07, 0x29, 0xE4, 0x12, 0x08, 0xBE, + 0x75, 0x83, 0x8C, 0xE0, 0x44, 0x20, 0x12, 0x08, +/*1D70*/0xBE, 0xE0, 0x54, 0xDF, 0xF0, 0x74, 0x84, 0x85, + 0x08, 0x82, 0xF5, 0x83, 0xE0, 0x54, 0x7F, 0xF0, +/*1D80*/0xE0, 0x44, 0x80, 0xF0, 0x22, 0x75, 0x56, 0x01, + 0xE4, 0xFD, 0xF5, 0x57, 0xAF, 0x35, 0xFE, 0xFC, +/*1D90*/0x12, 0x09, 0x15, 0x12, 0x1C, 0x9D, 0x12, 0x1E, + 0x7A, 0x12, 0x1C, 0x4C, 0xAF, 0x57, 0x7E, 0x00, +/*1DA0*/0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44, 0xAF, + 0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0x75, 0x56, +/*1DB0*/0x01, 0xE4, 0xFD, 0xF5, 0x57, 0xAF, 0x35, 0xFE, + 0xFC, 0x12, 0x09, 0x15, 0x12, 0x1C, 0x9D, 0x12, +/*1DC0*/0x1E, 0x7A, 0x12, 0x1C, 0x4C, 0xAF, 0x57, 0x7E, + 0x00, 0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44, +/*1DD0*/0xAF, 0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0xE4, + 0xF5, 0x16, 0x12, 0x0E, 0x44, 0xFE, 0xE5, 0x08, +/*1DE0*/0x44, 0x05, 0xFF, 0x12, 0x0E, 0x65, 0x8F, 0x82, + 0x8E, 0x83, 0xF0, 0x05, 0x16, 0xE5, 0x16, 0xC3, +/*1DF0*/0x94, 0x14, 0x40, 0xE6, 0xE5, 0x08, 0x12, 0x0E, + 0x2B, 0xE4, 0xF0, 0x22, 0xE4, 0xF5, 0x58, 0xF5, +/*1E00*/0x59, 0xF5, 0x5A, 0xFF, 0xFE, 0xAD, 0x58, 0xFC, + 0x12, 0x09, 0x15, 0x7F, 0x04, 0x7E, 0x00, 0xAD, +/*1E10*/0x58, 0x7C, 0x00, 0x12, 0x09, 0x15, 0x7F, 0x02, + 0x7E, 0x00, 0xAD, 0x58, 0x7C, 0x00, 0x02, 0x09, +/*1E20*/0x15, 0xE5, 0x3C, 0x25, 0x3E, 0xFC, 0xE5, 0x42, + 0x24, 0x00, 0xFB, 0xE4, 0x33, 0xFA, 0xEC, 0xC3, +/*1E30*/0x9B, 0xEA, 0x12, 0x07, 0x6B, 0x40, 0x0B, 0x8C, + 0x42, 0xE5, 0x3D, 0x25, 0x3F, 0xF5, 0x41, 0x8F, +/*1E40*/0x40, 0x22, 0x12, 0x09, 0x0B, 0x22, 0x74, 0x84, + 0xF5, 0x18, 0x85, 0x08, 0x19, 0x85, 0x19, 0x82, +/*1E50*/0x85, 0x18, 0x83, 0xE0, 0x54, 0x7F, 0xF0, 0xE0, + 0x44, 0x80, 0xF0, 0xE0, 0x44, 0x80, 0xF0, 0x22, +/*1E60*/0xEF, 0x4E, 0x70, 0x0B, 0x12, 0x07, 0x2A, 0x75, + 0x83, 0xD2, 0xE0, 0x54, 0xDF, 0xF0, 0x22, 0x12, +/*1E70*/0x07, 0x2A, 0x75, 0x83, 0xD2, 0xE0, 0x44, 0x20, + 0xF0, 0x22, 0x75, 0x58, 0x01, 0x90, 0x07, 0x26, +/*1E80*/0x12, 0x07, 0x35, 0xE0, 0x54, 0x3F, 0xF5, 0x41, + 0x12, 0x07, 0x32, 0xE0, 0x54, 0x3F, 0xF5, 0x40, +/*1E90*/0x22, 0x75, 0x56, 0x02, 0xE4, 0xF5, 0x57, 0x12, + 0x1D, 0xFC, 0xAF, 0x57, 0x7E, 0x00, 0xAD, 0x56, +/*1EA0*/0x7C, 0x00, 0x02, 0x04, 0x44, 0xE4, 0xF5, 0x42, + 0xF5, 0x41, 0xF5, 0x40, 0xF5, 0x38, 0xF5, 0x39, +/*1EB0*/0xF5, 0x3A, 0x22, 0xEF, 0x54, 0x07, 0xFF, 0xE5, + 0xF9, 0x54, 0xF8, 0x4F, 0xF5, 0xF9, 0x22, 0x7F, +/*1EC0*/0x01, 0xE4, 0xFE, 0x0F, 0x0E, 0xBE, 0xFF, 0xFB, + 0x22, 0x01, 0x20, 0x00, 0x01, 0x04, 0x20, 0x00, +/*1ED0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1EE0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1EF0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1F00*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1F10*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1F20*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1F30*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1F40*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1F50*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1F60*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1F70*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1F80*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1F90*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1FA0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1FB0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1FC0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1FD0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1FE0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/*1FF0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x81 +}; diff --git a/gpxe/src/drivers/infiniband/qib_7220_regs.h b/gpxe/src/drivers/infiniband/qib_7220_regs.h new file mode 100644 index 00000000..0dd3c53d --- /dev/null +++ b/gpxe/src/drivers/infiniband/qib_7220_regs.h @@ -0,0 +1,1763 @@ +/* + * Copyright (c) 2008 QLogic Corporation. All rights reserved. + * + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * This file is mechanically generated. Any hand-edits will be lost. + * If not now, soon. + */ + +/* This file has been further processed by ./drivers/infiniband/qib_genbits.pl */ + + +#define QIB_7220_Revision_offset 0x00000000UL +struct QIB_7220_Revision_pb { + pseudo_bit_t R_ChipRevMinor[8]; + pseudo_bit_t R_ChipRevMajor[8]; + pseudo_bit_t R_Arch[8]; + pseudo_bit_t R_SW[8]; + pseudo_bit_t BoardID[8]; + pseudo_bit_t R_Palldium_Revcode[22]; + pseudo_bit_t R_Palladium[1]; + pseudo_bit_t R_Simulator[1]; +}; +struct QIB_7220_Revision { + PSEUDO_BIT_STRUCT ( struct QIB_7220_Revision_pb ); +}; + +#define QIB_7220_Control_offset 0x00000008UL +struct QIB_7220_Control_pb { + pseudo_bit_t SyncReset[1]; + pseudo_bit_t FreezeMode[1]; + pseudo_bit_t LinkEn[1]; + pseudo_bit_t PCIERetryBufDiagEn[1]; + pseudo_bit_t TxLatency[1]; + pseudo_bit_t Reserved[1]; + pseudo_bit_t PCIECplQDiagEn[1]; + pseudo_bit_t SyncResetExceptPcieIRAMRST[1]; + pseudo_bit_t _unused_0[56]; +}; +struct QIB_7220_Control { + PSEUDO_BIT_STRUCT ( struct QIB_7220_Control_pb ); +}; + +#define QIB_7220_PageAlign_offset 0x00000010UL + +#define QIB_7220_PortCnt_offset 0x00000018UL + +#define QIB_7220_DbgPortSel_offset 0x00000020UL +struct QIB_7220_DbgPortSel_pb { + pseudo_bit_t NibbleSel0[4]; + pseudo_bit_t NibbleSel1[4]; + pseudo_bit_t NibbleSel2[4]; + pseudo_bit_t NibbleSel3[4]; + pseudo_bit_t NibbleSel4[4]; + pseudo_bit_t NibbleSel5[4]; + pseudo_bit_t NibbleSel6[4]; + pseudo_bit_t NibbleSel7[4]; + pseudo_bit_t SrcMuxSel[14]; + pseudo_bit_t DbgClkPortSel[5]; + pseudo_bit_t EnDbgPort[1]; + pseudo_bit_t EnEnhancedDebugMode[1]; + pseudo_bit_t EnhMode_SrcMuxSelIndex[10]; + pseudo_bit_t EnhMode_SrcMuxSelWrEn[1]; +}; +struct QIB_7220_DbgPortSel { + PSEUDO_BIT_STRUCT ( struct QIB_7220_DbgPortSel_pb ); +}; + +#define QIB_7220_DebugSigsIntSel_offset 0x00000028UL +struct QIB_7220_DebugSigsIntSel_pb { + pseudo_bit_t debug_port_sel_pcs_pipe_lane07[3]; + pseudo_bit_t debug_port_sel_pcs_pipe_lane815[3]; + pseudo_bit_t debug_port_sel_pcs_sdout[1]; + pseudo_bit_t debug_port_sel_pcs_symlock_elfifo_lane[4]; + pseudo_bit_t debug_port_sel_pcs_rxdet_encdec_lane[4]; + pseudo_bit_t debug_port_sel_pcie_rx_tx[1]; + pseudo_bit_t debug_port_sel_xgxs[4]; + pseudo_bit_t debug_port_sel_epb_pcie[1]; + pseudo_bit_t _unused_0[43]; +}; +struct QIB_7220_DebugSigsIntSel { + PSEUDO_BIT_STRUCT ( struct QIB_7220_DebugSigsIntSel_pb ); +}; + +#define QIB_7220_SendRegBase_offset 0x00000030UL + +#define QIB_7220_UserRegBase_offset 0x00000038UL + +#define QIB_7220_CntrRegBase_offset 0x00000040UL + +#define QIB_7220_Scratch_offset 0x00000048UL + +#define QIB_7220_REG_000050_offset 0x00000050UL + +#define QIB_7220_IntBlocked_offset 0x00000060UL +struct QIB_7220_IntBlocked_pb { + pseudo_bit_t RcvAvail0IntBlocked[1]; + pseudo_bit_t RcvAvail1IntBlocked[1]; + pseudo_bit_t RcvAvail2IntBlocked[1]; + pseudo_bit_t RcvAvail3IntBlocked[1]; + pseudo_bit_t RcvAvail4IntBlocked[1]; + pseudo_bit_t RcvAvail5IntBlocked[1]; + pseudo_bit_t RcvAvail6IntBlocked[1]; + pseudo_bit_t RcvAvail7IntBlocked[1]; + pseudo_bit_t RcvAvail8IntBlocked[1]; + pseudo_bit_t RcvAvail9IntBlocked[1]; + pseudo_bit_t RcvAvail10IntBlocked[1]; + pseudo_bit_t RcvAvail11IntBlocked[1]; + pseudo_bit_t RcvAvail12IntBlocked[1]; + pseudo_bit_t RcvAvail13IntBlocked[1]; + pseudo_bit_t RcvAvail14IntBlocked[1]; + pseudo_bit_t RcvAvail15IntBlocked[1]; + pseudo_bit_t RcvAvail16IntBlocked[1]; + pseudo_bit_t Reserved1[9]; + pseudo_bit_t JIntBlocked[1]; + pseudo_bit_t IBSerdesTrimDoneIntBlocked[1]; + pseudo_bit_t assertGPIOIntBlocked[1]; + pseudo_bit_t PioBufAvailIntBlocked[1]; + pseudo_bit_t PioSetIntBlocked[1]; + pseudo_bit_t ErrorIntBlocked[1]; + pseudo_bit_t RcvUrg0IntBlocked[1]; + pseudo_bit_t RcvUrg1IntBlocked[1]; + pseudo_bit_t RcvUrg2IntBlocked[1]; + pseudo_bit_t RcvUrg3IntBlocked[1]; + pseudo_bit_t RcvUrg4IntBlocked[1]; + pseudo_bit_t RcvUrg5IntBlocked[1]; + pseudo_bit_t RcvUrg6IntBlocked[1]; + pseudo_bit_t RcvUrg7IntBlocked[1]; + pseudo_bit_t RcvUrg8IntBlocked[1]; + pseudo_bit_t RcvUrg9IntBlocked[1]; + pseudo_bit_t RcvUrg10IntBlocked[1]; + pseudo_bit_t RcvUrg11IntBlocked[1]; + pseudo_bit_t RcvUrg12IntBlocked[1]; + pseudo_bit_t RcvUrg13IntBlocked[1]; + pseudo_bit_t RcvUrg14IntBlocked[1]; + pseudo_bit_t RcvUrg15IntBlocked[1]; + pseudo_bit_t RcvUrg16IntBlocked[1]; + pseudo_bit_t Reserved[13]; + pseudo_bit_t SDmaDisabledBlocked[1]; + pseudo_bit_t SDmaIntBlocked[1]; +}; +struct QIB_7220_IntBlocked { + PSEUDO_BIT_STRUCT ( struct QIB_7220_IntBlocked_pb ); +}; + +#define QIB_7220_IntMask_offset 0x00000068UL +struct QIB_7220_IntMask_pb { + pseudo_bit_t RcvAvail0IntMask[1]; + pseudo_bit_t RcvAvail1IntMask[1]; + pseudo_bit_t RcvAvail2IntMask[1]; + pseudo_bit_t RcvAvail3IntMask[1]; + pseudo_bit_t RcvAvail4IntMask[1]; + pseudo_bit_t RcvAvail5IntMask[1]; + pseudo_bit_t RcvAvail6IntMask[1]; + pseudo_bit_t RcvAvail7IntMask[1]; + pseudo_bit_t RcvAvail8IntMask[1]; + pseudo_bit_t RcvAvail9IntMask[1]; + pseudo_bit_t RcvAvail10IntMask[1]; + pseudo_bit_t RcvAvail11IntMask[1]; + pseudo_bit_t RcvAvail12IntMask[1]; + pseudo_bit_t RcvAvail13IntMask[1]; + pseudo_bit_t RcvAvail14IntMask[1]; + pseudo_bit_t RcvAvail15IntMask[1]; + pseudo_bit_t RcvAvail16IntMask[1]; + pseudo_bit_t Reserved1[9]; + pseudo_bit_t JIntMask[1]; + pseudo_bit_t IBSerdesTrimDoneIntMask[1]; + pseudo_bit_t assertGPIOIntMask[1]; + pseudo_bit_t PioBufAvailIntMask[1]; + pseudo_bit_t PioSetIntMask[1]; + pseudo_bit_t ErrorIntMask[1]; + pseudo_bit_t RcvUrg0IntMask[1]; + pseudo_bit_t RcvUrg1IntMask[1]; + pseudo_bit_t RcvUrg2IntMask[1]; + pseudo_bit_t RcvUrg3IntMask[1]; + pseudo_bit_t RcvUrg4IntMask[1]; + pseudo_bit_t RcvUrg5IntMask[1]; + pseudo_bit_t RcvUrg6IntMask[1]; + pseudo_bit_t RcvUrg7IntMask[1]; + pseudo_bit_t RcvUrg8IntMask[1]; + pseudo_bit_t RcvUrg9IntMask[1]; + pseudo_bit_t RcvUrg10IntMask[1]; + pseudo_bit_t RcvUrg11IntMask[1]; + pseudo_bit_t RcvUrg12IntMask[1]; + pseudo_bit_t RcvUrg13IntMask[1]; + pseudo_bit_t RcvUrg14IntMask[1]; + pseudo_bit_t RcvUrg15IntMask[1]; + pseudo_bit_t RcvUrg16IntMask[1]; + pseudo_bit_t Reserved[13]; + pseudo_bit_t SDmaDisabledMasked[1]; + pseudo_bit_t SDmaIntMask[1]; +}; +struct QIB_7220_IntMask { + PSEUDO_BIT_STRUCT ( struct QIB_7220_IntMask_pb ); +}; + +#define QIB_7220_IntStatus_offset 0x00000070UL +struct QIB_7220_IntStatus_pb { + pseudo_bit_t RcvAvail0[1]; + pseudo_bit_t RcvAvail1[1]; + pseudo_bit_t RcvAvail2[1]; + pseudo_bit_t RcvAvail3[1]; + pseudo_bit_t RcvAvail4[1]; + pseudo_bit_t RcvAvail5[1]; + pseudo_bit_t RcvAvail6[1]; + pseudo_bit_t RcvAvail7[1]; + pseudo_bit_t RcvAvail8[1]; + pseudo_bit_t RcvAvail9[1]; + pseudo_bit_t RcvAvail10[1]; + pseudo_bit_t RcvAvail11[1]; + pseudo_bit_t RcvAvail12[1]; + pseudo_bit_t RcvAvail13[1]; + pseudo_bit_t RcvAvail14[1]; + pseudo_bit_t RcvAvail15[1]; + pseudo_bit_t RcvAvail16[1]; + pseudo_bit_t Reserved1[9]; + pseudo_bit_t JInt[1]; + pseudo_bit_t IBSerdesTrimDone[1]; + pseudo_bit_t assertGPIO[1]; + pseudo_bit_t PioBufAvail[1]; + pseudo_bit_t PioSent[1]; + pseudo_bit_t Error[1]; + pseudo_bit_t RcvUrg0[1]; + pseudo_bit_t RcvUrg1[1]; + pseudo_bit_t RcvUrg2[1]; + pseudo_bit_t RcvUrg3[1]; + pseudo_bit_t RcvUrg4[1]; + pseudo_bit_t RcvUrg5[1]; + pseudo_bit_t RcvUrg6[1]; + pseudo_bit_t RcvUrg7[1]; + pseudo_bit_t RcvUrg8[1]; + pseudo_bit_t RcvUrg9[1]; + pseudo_bit_t RcvUrg10[1]; + pseudo_bit_t RcvUrg11[1]; + pseudo_bit_t RcvUrg12[1]; + pseudo_bit_t RcvUrg13[1]; + pseudo_bit_t RcvUrg14[1]; + pseudo_bit_t RcvUrg15[1]; + pseudo_bit_t RcvUrg16[1]; + pseudo_bit_t Reserved[13]; + pseudo_bit_t SDmaDisabled[1]; + pseudo_bit_t SDmaInt[1]; +}; +struct QIB_7220_IntStatus { + PSEUDO_BIT_STRUCT ( struct QIB_7220_IntStatus_pb ); +}; + +#define QIB_7220_IntClear_offset 0x00000078UL +struct QIB_7220_IntClear_pb { + pseudo_bit_t RcvAvail0IntClear[1]; + pseudo_bit_t RcvAvail1IntClear[1]; + pseudo_bit_t RcvAvail2IntClear[1]; + pseudo_bit_t RcvAvail3IntClear[1]; + pseudo_bit_t RcvAvail4IntClear[1]; + pseudo_bit_t RcvAvail5IntClear[1]; + pseudo_bit_t RcvAvail6IntClear[1]; + pseudo_bit_t RcvAvail7IntClear[1]; + pseudo_bit_t RcvAvail8IntClear[1]; + pseudo_bit_t RcvAvail9IntClear[1]; + pseudo_bit_t RcvAvail10IntClear[1]; + pseudo_bit_t RcvAvail11IntClear[1]; + pseudo_bit_t RcvAvail12IntClear[1]; + pseudo_bit_t RcvAvail13IntClear[1]; + pseudo_bit_t RcvAvail14IntClear[1]; + pseudo_bit_t RcvAvail15IntClear[1]; + pseudo_bit_t RcvAvail16IntClear[1]; + pseudo_bit_t Reserved1[9]; + pseudo_bit_t JIntClear[1]; + pseudo_bit_t IBSerdesTrimDoneClear[1]; + pseudo_bit_t assertGPIOIntClear[1]; + pseudo_bit_t PioBufAvailIntClear[1]; + pseudo_bit_t PioSetIntClear[1]; + pseudo_bit_t ErrorIntClear[1]; + pseudo_bit_t RcvUrg0IntClear[1]; + pseudo_bit_t RcvUrg1IntClear[1]; + pseudo_bit_t RcvUrg2IntClear[1]; + pseudo_bit_t RcvUrg3IntClear[1]; + pseudo_bit_t RcvUrg4IntClear[1]; + pseudo_bit_t RcvUrg5IntClear[1]; + pseudo_bit_t RcvUrg6IntClear[1]; + pseudo_bit_t RcvUrg7IntClear[1]; + pseudo_bit_t RcvUrg8IntClear[1]; + pseudo_bit_t RcvUrg9IntClear[1]; + pseudo_bit_t RcvUrg10IntClear[1]; + pseudo_bit_t RcvUrg11IntClear[1]; + pseudo_bit_t RcvUrg12IntClear[1]; + pseudo_bit_t RcvUrg13IntClear[1]; + pseudo_bit_t RcvUrg14IntClear[1]; + pseudo_bit_t RcvUrg15IntClear[1]; + pseudo_bit_t RcvUrg16IntClear[1]; + pseudo_bit_t Reserved[13]; + pseudo_bit_t SDmaDisabledClear[1]; + pseudo_bit_t SDmaIntClear[1]; +}; +struct QIB_7220_IntClear { + PSEUDO_BIT_STRUCT ( struct QIB_7220_IntClear_pb ); +}; + +#define QIB_7220_ErrMask_offset 0x00000080UL +struct QIB_7220_ErrMask_pb { + pseudo_bit_t RcvFormatErrMask[1]; + pseudo_bit_t RcvVCRCErrMask[1]; + pseudo_bit_t RcvICRCErrMask[1]; + pseudo_bit_t RcvMinPktLenErrMask[1]; + pseudo_bit_t RcvMaxPktLenErrMask[1]; + pseudo_bit_t RcvLongPktLenErrMask[1]; + pseudo_bit_t RcvShortPktLenErrMask[1]; + pseudo_bit_t RcvUnexpectedCharErrMask[1]; + pseudo_bit_t RcvUnsupportedVLErrMask[1]; + pseudo_bit_t RcvEBPErrMask[1]; + pseudo_bit_t RcvIBFlowErrMask[1]; + pseudo_bit_t RcvBadVersionErrMask[1]; + pseudo_bit_t RcvEgrFullErrMask[1]; + pseudo_bit_t RcvHdrFullErrMask[1]; + pseudo_bit_t RcvBadTidErrMask[1]; + pseudo_bit_t RcvHdrLenErrMask[1]; + pseudo_bit_t RcvHdrErrMask[1]; + pseudo_bit_t RcvIBLostLinkErrMask[1]; + pseudo_bit_t Reserved1[9]; + pseudo_bit_t SendSpecialTriggerErrMask[1]; + pseudo_bit_t SDmaDisabledErrMask[1]; + pseudo_bit_t SendMinPktLenErrMask[1]; + pseudo_bit_t SendMaxPktLenErrMask[1]; + pseudo_bit_t SendUnderRunErrMask[1]; + pseudo_bit_t SendPktLenErrMask[1]; + pseudo_bit_t SendDroppedSmpPktErrMask[1]; + pseudo_bit_t SendDroppedDataPktErrMask[1]; + pseudo_bit_t SendPioArmLaunchErrMask[1]; + pseudo_bit_t SendUnexpectedPktNumErrMask[1]; + pseudo_bit_t SendUnsupportedVLErrMask[1]; + pseudo_bit_t SendBufMisuseErrMask[1]; + pseudo_bit_t SDmaGenMismatchErrMask[1]; + pseudo_bit_t SDmaOutOfBoundErrMask[1]; + pseudo_bit_t SDmaTailOutOfBoundErrMask[1]; + pseudo_bit_t SDmaBaseErrMask[1]; + pseudo_bit_t SDma1stDescErrMask[1]; + pseudo_bit_t SDmaRpyTagErrMask[1]; + pseudo_bit_t SDmaDwEnErrMask[1]; + pseudo_bit_t SDmaMissingDwErrMask[1]; + pseudo_bit_t SDmaUnexpDataErrMask[1]; + pseudo_bit_t IBStatusChangedMask[1]; + pseudo_bit_t InvalidAddrErrMask[1]; + pseudo_bit_t ResetNegatedMask[1]; + pseudo_bit_t HardwareErrMask[1]; + pseudo_bit_t SDmaDescAddrMisalignErrMask[1]; + pseudo_bit_t InvalidEEPCmdMask[1]; + pseudo_bit_t Reserved[10]; +}; +struct QIB_7220_ErrMask { + PSEUDO_BIT_STRUCT ( struct QIB_7220_ErrMask_pb ); +}; + +#define QIB_7220_ErrStatus_offset 0x00000088UL +struct QIB_7220_ErrStatus_pb { + pseudo_bit_t RcvFormatErr[1]; + pseudo_bit_t RcvVCRCErr[1]; + pseudo_bit_t RcvICRCErr[1]; + pseudo_bit_t RcvMinPktLenErr[1]; + pseudo_bit_t RcvMaxPktLenErr[1]; + pseudo_bit_t RcvLongPktLenErr[1]; + pseudo_bit_t RcvShortPktLenErr[1]; + pseudo_bit_t RcvUnexpectedCharErr[1]; + pseudo_bit_t RcvUnsupportedVLErr[1]; + pseudo_bit_t RcvEBPErr[1]; + pseudo_bit_t RcvIBFlowErr[1]; + pseudo_bit_t RcvBadVersionErr[1]; + pseudo_bit_t RcvEgrFullErr[1]; + pseudo_bit_t RcvHdrFullErr[1]; + pseudo_bit_t RcvBadTidErr[1]; + pseudo_bit_t RcvHdrLenErr[1]; + pseudo_bit_t RcvHdrErr[1]; + pseudo_bit_t RcvIBLostLinkErr[1]; + pseudo_bit_t Reserved1[9]; + pseudo_bit_t SendSpecialTriggerErr[1]; + pseudo_bit_t SDmaDisabledErr[1]; + pseudo_bit_t SendMinPktLenErr[1]; + pseudo_bit_t SendMaxPktLenErr[1]; + pseudo_bit_t SendUnderRunErr[1]; + pseudo_bit_t SendPktLenErr[1]; + pseudo_bit_t SendDroppedSmpPktErr[1]; + pseudo_bit_t SendDroppedDataPktErr[1]; + pseudo_bit_t SendPioArmLaunchErr[1]; + pseudo_bit_t SendUnexpectedPktNumErr[1]; + pseudo_bit_t SendUnsupportedVLErr[1]; + pseudo_bit_t SendBufMisuseErr[1]; + pseudo_bit_t SDmaGenMismatchErr[1]; + pseudo_bit_t SDmaOutOfBoundErr[1]; + pseudo_bit_t SDmaTailOutOfBoundErr[1]; + pseudo_bit_t SDmaBaseErr[1]; + pseudo_bit_t SDma1stDescErr[1]; + pseudo_bit_t SDmaRpyTagErr[1]; + pseudo_bit_t SDmaDwEnErr[1]; + pseudo_bit_t SDmaMissingDwErr[1]; + pseudo_bit_t SDmaUnexpDataErr[1]; + pseudo_bit_t IBStatusChanged[1]; + pseudo_bit_t InvalidAddrErr[1]; + pseudo_bit_t ResetNegated[1]; + pseudo_bit_t HardwareErr[1]; + pseudo_bit_t SDmaDescAddrMisalignErr[1]; + pseudo_bit_t InvalidEEPCmdErr[1]; + pseudo_bit_t Reserved[10]; +}; +struct QIB_7220_ErrStatus { + PSEUDO_BIT_STRUCT ( struct QIB_7220_ErrStatus_pb ); +}; + +#define QIB_7220_ErrClear_offset 0x00000090UL +struct QIB_7220_ErrClear_pb { + pseudo_bit_t RcvFormatErrClear[1]; + pseudo_bit_t RcvVCRCErrClear[1]; + pseudo_bit_t RcvICRCErrClear[1]; + pseudo_bit_t RcvMinPktLenErrClear[1]; + pseudo_bit_t RcvMaxPktLenErrClear[1]; + pseudo_bit_t RcvLongPktLenErrClear[1]; + pseudo_bit_t RcvShortPktLenErrClear[1]; + pseudo_bit_t RcvUnexpectedCharErrClear[1]; + pseudo_bit_t RcvUnsupportedVLErrClear[1]; + pseudo_bit_t RcvEBPErrClear[1]; + pseudo_bit_t RcvIBFlowErrClear[1]; + pseudo_bit_t RcvBadVersionErrClear[1]; + pseudo_bit_t RcvEgrFullErrClear[1]; + pseudo_bit_t RcvHdrFullErrClear[1]; + pseudo_bit_t RcvBadTidErrClear[1]; + pseudo_bit_t RcvHdrLenErrClear[1]; + pseudo_bit_t RcvHdrErrClear[1]; + pseudo_bit_t RcvIBLostLinkErrClear[1]; + pseudo_bit_t Reserved1[9]; + pseudo_bit_t SendSpecialTriggerErrClear[1]; + pseudo_bit_t SDmaDisabledErrClear[1]; + pseudo_bit_t SendMinPktLenErrClear[1]; + pseudo_bit_t SendMaxPktLenErrClear[1]; + pseudo_bit_t SendUnderRunErrClear[1]; + pseudo_bit_t SendPktLenErrClear[1]; + pseudo_bit_t SendDroppedSmpPktErrClear[1]; + pseudo_bit_t SendDroppedDataPktErrClear[1]; + pseudo_bit_t SendPioArmLaunchErrClear[1]; + pseudo_bit_t SendUnexpectedPktNumErrClear[1]; + pseudo_bit_t SendUnsupportedVLErrClear[1]; + pseudo_bit_t SendBufMisuseErrClear[1]; + pseudo_bit_t SDmaGenMismatchErrClear[1]; + pseudo_bit_t SDmaOutOfBoundErrClear[1]; + pseudo_bit_t SDmaTailOutOfBoundErrClear[1]; + pseudo_bit_t SDmaBaseErrClear[1]; + pseudo_bit_t SDma1stDescErrClear[1]; + pseudo_bit_t SDmaRpyTagErrClear[1]; + pseudo_bit_t SDmaDwEnErrClear[1]; + pseudo_bit_t SDmaMissingDwErrClear[1]; + pseudo_bit_t SDmaUnexpDataErrClear[1]; + pseudo_bit_t IBStatusChangedClear[1]; + pseudo_bit_t InvalidAddrErrClear[1]; + pseudo_bit_t ResetNegatedClear[1]; + pseudo_bit_t HardwareErrClear[1]; + pseudo_bit_t SDmaDescAddrMisalignErrClear[1]; + pseudo_bit_t InvalidEEPCmdErrClear[1]; + pseudo_bit_t Reserved[10]; +}; +struct QIB_7220_ErrClear { + PSEUDO_BIT_STRUCT ( struct QIB_7220_ErrClear_pb ); +}; + +#define QIB_7220_HwErrMask_offset 0x00000098UL +struct QIB_7220_HwErrMask_pb { + pseudo_bit_t PCIeMemParityErrMask[8]; + pseudo_bit_t Reserved3[20]; + pseudo_bit_t SDmaMemReadErrMask[1]; + pseudo_bit_t PoisonedTLPMask[1]; + pseudo_bit_t PcieCplTimeoutMask[1]; + pseudo_bit_t PCIeBusParityErrMask[3]; + pseudo_bit_t Reserved2[2]; + pseudo_bit_t PCIEOct0_uC_MemoryParityErrMask[1]; + pseudo_bit_t PCIEOct1_uC_MemoryParityErrMask[1]; + pseudo_bit_t IB_uC_MemoryParityErrMask[1]; + pseudo_bit_t DDSRXEQMemoryParityErrMask[1]; + pseudo_bit_t TXEMemParityErrMask[4]; + pseudo_bit_t RXEMemParityErrMask[7]; + pseudo_bit_t Reserved1[3]; + pseudo_bit_t PowerOnBISTFailedMask[1]; + pseudo_bit_t Reserved[1]; + pseudo_bit_t PCIESerdesQ0PClkNotDetectMask[1]; + pseudo_bit_t PCIESerdesQ1PClkNotDetectMask[1]; + pseudo_bit_t PCIESerdesQ2PClkNotDetectMask[1]; + pseudo_bit_t PCIESerdesQ3PClkNotDetectMask[1]; + pseudo_bit_t IBSerdesPClkNotDetectMask[1]; + pseudo_bit_t Clk_uC_PLLNotLockedMask[1]; + pseudo_bit_t IBCBusToSPCParityErrMask[1]; + pseudo_bit_t IBCBusFromSPCParityErrMask[1]; +}; +struct QIB_7220_HwErrMask { + PSEUDO_BIT_STRUCT ( struct QIB_7220_HwErrMask_pb ); +}; + +#define QIB_7220_HwErrStatus_offset 0x000000a0UL +struct QIB_7220_HwErrStatus_pb { + pseudo_bit_t PCIeMemParity[8]; + pseudo_bit_t Reserved3[20]; + pseudo_bit_t SDmaMemReadErr[1]; + pseudo_bit_t PoisenedTLP[1]; + pseudo_bit_t PcieCplTimeout[1]; + pseudo_bit_t PCIeBusParity[3]; + pseudo_bit_t Reserved2[2]; + pseudo_bit_t PCIE_uC_Oct0MemoryParityErr[1]; + pseudo_bit_t PCIE_uC_Oct1MemoryParityErr[1]; + pseudo_bit_t IB_uC_MemoryParityErr[1]; + pseudo_bit_t DDSRXEQMemoryParityErr[1]; + pseudo_bit_t TXEMemParity[4]; + pseudo_bit_t RXEMemParity[7]; + pseudo_bit_t Reserved1[3]; + pseudo_bit_t PowerOnBISTFailed[1]; + pseudo_bit_t Reserved[1]; + pseudo_bit_t PCIESerdesQ0PClkNotDetect[1]; + pseudo_bit_t PCIESerdesQ1PClkNotDetect[1]; + pseudo_bit_t PCIESerdesQ2PClkNotDetect[1]; + pseudo_bit_t PCIESerdesQ3PClkNotDetect[1]; + pseudo_bit_t IBSerdesPClkNotDetect[1]; + pseudo_bit_t Clk_uC_PLLNotLocked[1]; + pseudo_bit_t IBCBusToSPCParityErr[1]; + pseudo_bit_t IBCBusFromSPCParityErr[1]; +}; +struct QIB_7220_HwErrStatus { + PSEUDO_BIT_STRUCT ( struct QIB_7220_HwErrStatus_pb ); +}; + +#define QIB_7220_HwErrClear_offset 0x000000a8UL +struct QIB_7220_HwErrClear_pb { + pseudo_bit_t PCIeMemParityClr[8]; + pseudo_bit_t Reserved3[20]; + pseudo_bit_t SDmaMemReadErrClear[1]; + pseudo_bit_t PoisonedTLPClear[1]; + pseudo_bit_t PcieCplTimeoutClear[1]; + pseudo_bit_t PCIeBusParityClr[3]; + pseudo_bit_t Reserved2[2]; + pseudo_bit_t PCIE_uC_Oct0MemoryParityErrClear[1]; + pseudo_bit_t PCIE_uC_Oct1MemoryParityErrClear[1]; + pseudo_bit_t IB_uC_MemoryParityErrClear[1]; + pseudo_bit_t DDSRXEQMemoryParityErrClear[1]; + pseudo_bit_t TXEMemParityClear[4]; + pseudo_bit_t RXEMemParityClear[7]; + pseudo_bit_t Reserved1[3]; + pseudo_bit_t PowerOnBISTFailedClear[1]; + pseudo_bit_t Reserved[1]; + pseudo_bit_t PCIESerdesQ0PClkNotDetectClear[1]; + pseudo_bit_t PCIESerdesQ1PClkNotDetectClear[1]; + pseudo_bit_t PCIESerdesQ2PClkNotDetectClear[1]; + pseudo_bit_t PCIESerdesQ3PClkNotDetectClear[1]; + pseudo_bit_t IBSerdesPClkNotDetectClear[1]; + pseudo_bit_t Clk_uC_PLLNotLockedClear[1]; + pseudo_bit_t IBCBusToSPCparityErrClear[1]; + pseudo_bit_t IBCBusFromSPCParityErrClear[1]; +}; +struct QIB_7220_HwErrClear { + PSEUDO_BIT_STRUCT ( struct QIB_7220_HwErrClear_pb ); +}; + +#define QIB_7220_HwDiagCtrl_offset 0x000000b0UL +struct QIB_7220_HwDiagCtrl_pb { + pseudo_bit_t forcePCIeMemParity[8]; + pseudo_bit_t Reserved2[23]; + pseudo_bit_t forcePCIeBusParity[4]; + pseudo_bit_t Reserved1[1]; + pseudo_bit_t ForcePCIE_uC_Oct0MemoryParityErr[1]; + pseudo_bit_t ForcePCIE_uC_Oct1MemoryParityErr[1]; + pseudo_bit_t ForceIB_uC_MemoryParityErr[1]; + pseudo_bit_t ForceDDSRXEQMemoryParityErr[1]; + pseudo_bit_t ForceTxMemparityErr[4]; + pseudo_bit_t ForceRxMemParityErr[7]; + pseudo_bit_t Reserved[9]; + pseudo_bit_t CounterDisable[1]; + pseudo_bit_t CounterWrEnable[1]; + pseudo_bit_t ForceIBCBusToSPCParityErr[1]; + pseudo_bit_t ForceIBCBusFromSPCParityErr[1]; +}; +struct QIB_7220_HwDiagCtrl { + PSEUDO_BIT_STRUCT ( struct QIB_7220_HwDiagCtrl_pb ); +}; + +#define QIB_7220_REG_0000B8_offset 0x000000b8UL + +#define QIB_7220_IBCStatus_offset 0x000000c0UL +struct QIB_7220_IBCStatus_pb { + pseudo_bit_t LinkTrainingState[5]; + pseudo_bit_t LinkState[3]; + pseudo_bit_t LinkSpeedActive[1]; + pseudo_bit_t LinkWidthActive[1]; + pseudo_bit_t DDS_RXEQ_FAIL[1]; + pseudo_bit_t IB_SERDES_TRIM_DONE[1]; + pseudo_bit_t IBRxLaneReversed[1]; + pseudo_bit_t IBTxLaneReversed[1]; + pseudo_bit_t Reserved[16]; + pseudo_bit_t TxReady[1]; + pseudo_bit_t TxCreditOk[1]; + pseudo_bit_t _unused_0[32]; +}; +struct QIB_7220_IBCStatus { + PSEUDO_BIT_STRUCT ( struct QIB_7220_IBCStatus_pb ); +}; + +#define QIB_7220_IBCCtrl_offset 0x000000c8UL +struct QIB_7220_IBCCtrl_pb { + pseudo_bit_t FlowCtrlPeriod[8]; + pseudo_bit_t FlowCtrlWaterMark[8]; + pseudo_bit_t LinkInitCmd[3]; + pseudo_bit_t LinkCmd[2]; + pseudo_bit_t MaxPktLen[11]; + pseudo_bit_t PhyerrThreshold[4]; + pseudo_bit_t OverrunThreshold[4]; + pseudo_bit_t CreditScale[3]; + pseudo_bit_t Reserved[19]; + pseudo_bit_t LinkDownDefaultState[1]; + pseudo_bit_t Loopback[1]; +}; +struct QIB_7220_IBCCtrl { + PSEUDO_BIT_STRUCT ( struct QIB_7220_IBCCtrl_pb ); +}; + +#define QIB_7220_EXTStatus_offset 0x000000d0UL +struct QIB_7220_EXTStatus_pb { + pseudo_bit_t Reserved2[14]; + pseudo_bit_t MemBISTEndTest[1]; + pseudo_bit_t MemBISTDisabled[1]; + pseudo_bit_t Reserved1[16]; + pseudo_bit_t Reserved[16]; + pseudo_bit_t GPIOIn[16]; +}; +struct QIB_7220_EXTStatus { + PSEUDO_BIT_STRUCT ( struct QIB_7220_EXTStatus_pb ); +}; + +#define QIB_7220_EXTCtrl_offset 0x000000d8UL +struct QIB_7220_EXTCtrl_pb { + pseudo_bit_t LEDGblErrRedOff[1]; + pseudo_bit_t LEDGblOkGreenOn[1]; + pseudo_bit_t LEDPriPortYellowOn[1]; + pseudo_bit_t LEDPriPortGreenOn[1]; + pseudo_bit_t Reserved[28]; + pseudo_bit_t GPIOInvert[16]; + pseudo_bit_t GPIOOe[16]; +}; +struct QIB_7220_EXTCtrl { + PSEUDO_BIT_STRUCT ( struct QIB_7220_EXTCtrl_pb ); +}; + +#define QIB_7220_GPIOOut_offset 0x000000e0UL + +#define QIB_7220_GPIOMask_offset 0x000000e8UL + +#define QIB_7220_GPIOStatus_offset 0x000000f0UL + +#define QIB_7220_GPIOClear_offset 0x000000f8UL + +#define QIB_7220_RcvCtrl_offset 0x00000100UL +struct QIB_7220_RcvCtrl_pb { + pseudo_bit_t PortEnable[17]; + pseudo_bit_t IntrAvail[17]; + pseudo_bit_t RcvPartitionKeyDisable[1]; + pseudo_bit_t TailUpd[1]; + pseudo_bit_t PortCfg[2]; + pseudo_bit_t RcvQPMapEnable[1]; + pseudo_bit_t Reserved[25]; +}; +struct QIB_7220_RcvCtrl { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvCtrl_pb ); +}; + +#define QIB_7220_RcvBTHQP_offset 0x00000108UL +struct QIB_7220_RcvBTHQP_pb { + pseudo_bit_t RcvBTHQP[24]; + pseudo_bit_t Reserved[8]; + pseudo_bit_t _unused_0[32]; +}; +struct QIB_7220_RcvBTHQP { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvBTHQP_pb ); +}; + +#define QIB_7220_RcvHdrSize_offset 0x00000110UL + +#define QIB_7220_RcvHdrCnt_offset 0x00000118UL + +#define QIB_7220_RcvHdrEntSize_offset 0x00000120UL + +#define QIB_7220_RcvTIDBase_offset 0x00000128UL + +#define QIB_7220_RcvTIDCnt_offset 0x00000130UL + +#define QIB_7220_RcvEgrBase_offset 0x00000138UL + +#define QIB_7220_RcvEgrCnt_offset 0x00000140UL + +#define QIB_7220_RcvBufBase_offset 0x00000148UL + +#define QIB_7220_RcvBufSize_offset 0x00000150UL + +#define QIB_7220_RxIntMemBase_offset 0x00000158UL + +#define QIB_7220_RxIntMemSize_offset 0x00000160UL + +#define QIB_7220_RcvPartitionKey_offset 0x00000168UL + +#define QIB_7220_RcvQPMulticastPort_offset 0x00000170UL +struct QIB_7220_RcvQPMulticastPort_pb { + pseudo_bit_t RcvQpMcPort[5]; + pseudo_bit_t Reserved[59]; +}; +struct QIB_7220_RcvQPMulticastPort { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvQPMulticastPort_pb ); +}; + +#define QIB_7220_RcvPktLEDCnt_offset 0x00000178UL +struct QIB_7220_RcvPktLEDCnt_pb { + pseudo_bit_t OFFperiod[32]; + pseudo_bit_t ONperiod[32]; +}; +struct QIB_7220_RcvPktLEDCnt { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvPktLEDCnt_pb ); +}; + +#define QIB_7220_IBCDDRCtrl_offset 0x00000180UL +struct QIB_7220_IBCDDRCtrl_pb { + pseudo_bit_t IB_ENHANCED_MODE[1]; + pseudo_bit_t SD_SPEED[1]; + pseudo_bit_t SD_SPEED_SDR[1]; + pseudo_bit_t SD_SPEED_DDR[1]; + pseudo_bit_t SD_SPEED_QDR[1]; + pseudo_bit_t IB_NUM_CHANNELS[2]; + pseudo_bit_t IB_POLARITY_REV_SUPP[1]; + pseudo_bit_t IB_LANE_REV_SUPPORTED[1]; + pseudo_bit_t SD_RX_EQUAL_ENABLE[1]; + pseudo_bit_t SD_ADD_ENB[1]; + pseudo_bit_t SD_DDSV[1]; + pseudo_bit_t SD_DDS[4]; + pseudo_bit_t HRTBT_ENB[1]; + pseudo_bit_t HRTBT_AUTO[1]; + pseudo_bit_t HRTBT_PORT[8]; + pseudo_bit_t HRTBT_REQ[1]; + pseudo_bit_t Reserved[5]; + pseudo_bit_t IB_DLID[16]; + pseudo_bit_t IB_DLID_MASK[16]; +}; +struct QIB_7220_IBCDDRCtrl { + PSEUDO_BIT_STRUCT ( struct QIB_7220_IBCDDRCtrl_pb ); +}; + +#define QIB_7220_HRTBT_GUID_offset 0x00000188UL + +#define QIB_7220_IB_SDTEST_IF_TX_offset 0x00000190UL +struct QIB_7220_IB_SDTEST_IF_TX_pb { + pseudo_bit_t TS_T_TX_VALID[1]; + pseudo_bit_t TS_3_TX_VALID[1]; + pseudo_bit_t Reserved1[9]; + pseudo_bit_t TS_TX_OPCODE[2]; + pseudo_bit_t TS_TX_SPEED[3]; + pseudo_bit_t Reserved[16]; + pseudo_bit_t TS_TX_TX_CFG[16]; + pseudo_bit_t TS_TX_RX_CFG[16]; +}; +struct QIB_7220_IB_SDTEST_IF_TX { + PSEUDO_BIT_STRUCT ( struct QIB_7220_IB_SDTEST_IF_TX_pb ); +}; + +#define QIB_7220_IB_SDTEST_IF_RX_offset 0x00000198UL +struct QIB_7220_IB_SDTEST_IF_RX_pb { + pseudo_bit_t TS_T_RX_VALID[1]; + pseudo_bit_t TS_3_RX_VALID[1]; + pseudo_bit_t Reserved[14]; + pseudo_bit_t TS_RX_A[8]; + pseudo_bit_t TS_RX_B[8]; + pseudo_bit_t TS_RX_TX_CFG[16]; + pseudo_bit_t TS_RX_RX_CFG[16]; +}; +struct QIB_7220_IB_SDTEST_IF_RX { + PSEUDO_BIT_STRUCT ( struct QIB_7220_IB_SDTEST_IF_RX_pb ); +}; + +#define QIB_7220_IBCDDRCtrl2_offset 0x000001a0UL +struct QIB_7220_IBCDDRCtrl2_pb { + pseudo_bit_t IB_FRONT_PORCH[5]; + pseudo_bit_t IB_BACK_PORCH[5]; + pseudo_bit_t _unused_0[54]; +}; +struct QIB_7220_IBCDDRCtrl2 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_IBCDDRCtrl2_pb ); +}; + +#define QIB_7220_IBCDDRStatus_offset 0x000001a8UL +struct QIB_7220_IBCDDRStatus_pb { + pseudo_bit_t LinkRoundTripLatency[26]; + pseudo_bit_t ReqDDSLocalFromRmt[4]; + pseudo_bit_t RxEqLocalDevice[2]; + pseudo_bit_t heartbeat_crosstalk[4]; + pseudo_bit_t heartbeat_timed_out[1]; + pseudo_bit_t _unused_0[27]; +}; +struct QIB_7220_IBCDDRStatus { + PSEUDO_BIT_STRUCT ( struct QIB_7220_IBCDDRStatus_pb ); +}; + +#define QIB_7220_JIntReload_offset 0x000001b0UL +struct QIB_7220_JIntReload_pb { + pseudo_bit_t J_reload[16]; + pseudo_bit_t J_limit_reload[16]; + pseudo_bit_t _unused_0[32]; +}; +struct QIB_7220_JIntReload { + PSEUDO_BIT_STRUCT ( struct QIB_7220_JIntReload_pb ); +}; + +#define QIB_7220_IBNCModeCtrl_offset 0x000001b8UL +struct QIB_7220_IBNCModeCtrl_pb { + pseudo_bit_t TSMEnable_send_TS1[1]; + pseudo_bit_t TSMEnable_send_TS2[1]; + pseudo_bit_t TSMEnable_ignore_TSM_on_rx[1]; + pseudo_bit_t Reserved1[5]; + pseudo_bit_t TSMCode_TS1[9]; + pseudo_bit_t TSMCode_TS2[9]; + pseudo_bit_t Reserved[38]; +}; +struct QIB_7220_IBNCModeCtrl { + PSEUDO_BIT_STRUCT ( struct QIB_7220_IBNCModeCtrl_pb ); +}; + +#define QIB_7220_SendCtrl_offset 0x000001c0UL +struct QIB_7220_SendCtrl_pb { + pseudo_bit_t Abort[1]; + pseudo_bit_t SendIntBufAvail[1]; + pseudo_bit_t SendBufAvailUpd[1]; + pseudo_bit_t SPioEnable[1]; + pseudo_bit_t SSpecialTriggerEn[1]; + pseudo_bit_t Reserved2[4]; + pseudo_bit_t SDmaIntEnable[1]; + pseudo_bit_t SDmaSingleDescriptor[1]; + pseudo_bit_t SDmaEnable[1]; + pseudo_bit_t SDmaHalt[1]; + pseudo_bit_t Reserved1[3]; + pseudo_bit_t DisarmPIOBuf[8]; + pseudo_bit_t AvailUpdThld[5]; + pseudo_bit_t Reserved[2]; + pseudo_bit_t Disarm[1]; + pseudo_bit_t _unused_0[32]; +}; +struct QIB_7220_SendCtrl { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SendCtrl_pb ); +}; + +#define QIB_7220_SendBufBase_offset 0x000001c8UL +struct QIB_7220_SendBufBase_pb { + pseudo_bit_t BaseAddr_SmallPIO[21]; + pseudo_bit_t Reserved1[11]; + pseudo_bit_t BaseAddr_LargePIO[21]; + pseudo_bit_t Reserved[11]; +}; +struct QIB_7220_SendBufBase { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SendBufBase_pb ); +}; + +#define QIB_7220_SendBufSize_offset 0x000001d0UL +struct QIB_7220_SendBufSize_pb { + pseudo_bit_t Size_SmallPIO[12]; + pseudo_bit_t Reserved1[20]; + pseudo_bit_t Size_LargePIO[13]; + pseudo_bit_t Reserved[19]; +}; +struct QIB_7220_SendBufSize { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SendBufSize_pb ); +}; + +#define QIB_7220_SendBufCnt_offset 0x000001d8UL +struct QIB_7220_SendBufCnt_pb { + pseudo_bit_t Num_SmallBuffers[9]; + pseudo_bit_t Reserved1[23]; + pseudo_bit_t Num_LargeBuffers[4]; + pseudo_bit_t Reserved[28]; +}; +struct QIB_7220_SendBufCnt { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SendBufCnt_pb ); +}; + +#define QIB_7220_SendBufAvailAddr_offset 0x000001e0UL +struct QIB_7220_SendBufAvailAddr_pb { + pseudo_bit_t Reserved[6]; + pseudo_bit_t SendBufAvailAddr[34]; + pseudo_bit_t _unused_0[24]; +}; +struct QIB_7220_SendBufAvailAddr { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SendBufAvailAddr_pb ); +}; + +#define QIB_7220_TxIntMemBase_offset 0x000001e8UL + +#define QIB_7220_TxIntMemSize_offset 0x000001f0UL + +#define QIB_7220_SendDmaBase_offset 0x000001f8UL +struct QIB_7220_SendDmaBase_pb { + pseudo_bit_t SendDmaBase[48]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_SendDmaBase { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SendDmaBase_pb ); +}; + +#define QIB_7220_SendDmaLenGen_offset 0x00000200UL +struct QIB_7220_SendDmaLenGen_pb { + pseudo_bit_t Length[16]; + pseudo_bit_t Generation[3]; + pseudo_bit_t Reserved[45]; +}; +struct QIB_7220_SendDmaLenGen { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SendDmaLenGen_pb ); +}; + +#define QIB_7220_SendDmaTail_offset 0x00000208UL +struct QIB_7220_SendDmaTail_pb { + pseudo_bit_t SendDmaTail[16]; + pseudo_bit_t Reserved[48]; +}; +struct QIB_7220_SendDmaTail { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SendDmaTail_pb ); +}; + +#define QIB_7220_SendDmaHead_offset 0x00000210UL +struct QIB_7220_SendDmaHead_pb { + pseudo_bit_t SendDmaHead[16]; + pseudo_bit_t Reserved1[16]; + pseudo_bit_t InternalSendDmaHead[16]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_SendDmaHead { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SendDmaHead_pb ); +}; + +#define QIB_7220_SendDmaHeadAddr_offset 0x00000218UL +struct QIB_7220_SendDmaHeadAddr_pb { + pseudo_bit_t SendDmaHeadAddr[48]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_SendDmaHeadAddr { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SendDmaHeadAddr_pb ); +}; + +#define QIB_7220_SendDmaBufMask0_offset 0x00000220UL +struct QIB_7220_SendDmaBufMask0_pb { + pseudo_bit_t BufMask_63_0[0]; + pseudo_bit_t _unused_0[64]; +}; +struct QIB_7220_SendDmaBufMask0 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SendDmaBufMask0_pb ); +}; + +#define QIB_7220_SendDmaStatus_offset 0x00000238UL +struct QIB_7220_SendDmaStatus_pb { + pseudo_bit_t SplFifoDescIndex[16]; + pseudo_bit_t SplFifoBufNum[8]; + pseudo_bit_t SplFifoFull[1]; + pseudo_bit_t SplFifoEmpty[1]; + pseudo_bit_t SplFifoDisarmed[1]; + pseudo_bit_t SplFifoReadyToGo[1]; + pseudo_bit_t ScbFetchDescFlag[1]; + pseudo_bit_t ScbEntryValid[1]; + pseudo_bit_t ScbEmpty[1]; + pseudo_bit_t ScbFull[1]; + pseudo_bit_t RpyTag_7_0[8]; + pseudo_bit_t RpyLowAddr_6_0[7]; + pseudo_bit_t ScbDescIndex_13_0[14]; + pseudo_bit_t InternalSDmaEnable[1]; + pseudo_bit_t AbortInProg[1]; + pseudo_bit_t ScoreBoardDrainInProg[1]; +}; +struct QIB_7220_SendDmaStatus { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SendDmaStatus_pb ); +}; + +#define QIB_7220_SendBufErr0_offset 0x00000240UL +struct QIB_7220_SendBufErr0_pb { + pseudo_bit_t SendBufErr_63_0[0]; + pseudo_bit_t _unused_0[64]; +}; +struct QIB_7220_SendBufErr0 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SendBufErr0_pb ); +}; + +#define QIB_7220_REG_000258_offset 0x00000258UL + +#define QIB_7220_AvailUpdCount_offset 0x00000268UL +struct QIB_7220_AvailUpdCount_pb { + pseudo_bit_t AvailUpdCount[5]; + pseudo_bit_t _unused_0[59]; +}; +struct QIB_7220_AvailUpdCount { + PSEUDO_BIT_STRUCT ( struct QIB_7220_AvailUpdCount_pb ); +}; + +#define QIB_7220_RcvHdrAddr0_offset 0x00000270UL +struct QIB_7220_RcvHdrAddr0_pb { + pseudo_bit_t Reserved[2]; + pseudo_bit_t RcvHdrAddr0[38]; + pseudo_bit_t _unused_0[24]; +}; +struct QIB_7220_RcvHdrAddr0 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrAddr0_pb ); +}; + +#define QIB_7220_REG_0002F8_offset 0x000002f8UL + +#define QIB_7220_RcvHdrTailAddr0_offset 0x00000300UL +struct QIB_7220_RcvHdrTailAddr0_pb { + pseudo_bit_t Reserved[2]; + pseudo_bit_t RcvHdrTailAddr0[38]; + pseudo_bit_t _unused_0[24]; +}; +struct QIB_7220_RcvHdrTailAddr0 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrTailAddr0_pb ); +}; + +#define QIB_7220_REG_000388_offset 0x00000388UL + +#define QIB_7220_ibsd_epb_access_ctrl_offset 0x000003c0UL +struct QIB_7220_ibsd_epb_access_ctrl_pb { + pseudo_bit_t sw_ib_epb_req[1]; + pseudo_bit_t Reserved[7]; + pseudo_bit_t sw_ib_epb_req_granted[1]; + pseudo_bit_t _unused_0[55]; +}; +struct QIB_7220_ibsd_epb_access_ctrl { + PSEUDO_BIT_STRUCT ( struct QIB_7220_ibsd_epb_access_ctrl_pb ); +}; + +#define QIB_7220_ibsd_epb_transaction_reg_offset 0x000003c8UL +struct QIB_7220_ibsd_epb_transaction_reg_pb { + pseudo_bit_t ib_epb_data[8]; + pseudo_bit_t ib_epb_address[15]; + pseudo_bit_t Reserved2[1]; + pseudo_bit_t ib_epb_read_write[1]; + pseudo_bit_t ib_epb_cs[2]; + pseudo_bit_t Reserved1[1]; + pseudo_bit_t mem_data_parity[1]; + pseudo_bit_t Reserved[1]; + pseudo_bit_t ib_epb_req_error[1]; + pseudo_bit_t ib_epb_rdy[1]; + pseudo_bit_t _unused_0[32]; +}; +struct QIB_7220_ibsd_epb_transaction_reg { + PSEUDO_BIT_STRUCT ( struct QIB_7220_ibsd_epb_transaction_reg_pb ); +}; + +#define QIB_7220_REG_0003D0_offset 0x000003d0UL + +#define QIB_7220_XGXSCfg_offset 0x000003d8UL +struct QIB_7220_XGXSCfg_pb { + pseudo_bit_t tx_rx_reset[1]; + pseudo_bit_t Reserved2[1]; + pseudo_bit_t xcv_reset[1]; + pseudo_bit_t Reserved1[6]; + pseudo_bit_t link_sync_mask[10]; + pseudo_bit_t Reserved[44]; + pseudo_bit_t sel_link_down_for_fctrl_lane_sync_reset[1]; +}; +struct QIB_7220_XGXSCfg { + PSEUDO_BIT_STRUCT ( struct QIB_7220_XGXSCfg_pb ); +}; + +#define QIB_7220_IBSerDesCtrl_offset 0x000003e0UL +struct QIB_7220_IBSerDesCtrl_pb { + pseudo_bit_t ResetIB_uC_Core[1]; + pseudo_bit_t Reserved2[7]; + pseudo_bit_t NumSerDesRegsToWrForDDS[5]; + pseudo_bit_t NumSerDesRegsToWrForRXEQ[5]; + pseudo_bit_t Reserved1[14]; + pseudo_bit_t TXINV[1]; + pseudo_bit_t RXINV[1]; + pseudo_bit_t RXIDLE[1]; + pseudo_bit_t TWC[1]; + pseudo_bit_t TXOBPD[1]; + pseudo_bit_t PLLM[3]; + pseudo_bit_t PLLN[2]; + pseudo_bit_t CKSEL_uC[2]; + pseudo_bit_t INT_uC[1]; + pseudo_bit_t Reserved[19]; +}; +struct QIB_7220_IBSerDesCtrl { + PSEUDO_BIT_STRUCT ( struct QIB_7220_IBSerDesCtrl_pb ); +}; + +#define QIB_7220_EEPCtlStat_offset 0x000003e8UL +struct QIB_7220_EEPCtlStat_pb { + pseudo_bit_t EPAccEn[2]; + pseudo_bit_t EPReset[1]; + pseudo_bit_t ByteProg[1]; + pseudo_bit_t PageMode[1]; + pseudo_bit_t LstDatWr[1]; + pseudo_bit_t CmdWrErr[1]; + pseudo_bit_t Reserved[24]; + pseudo_bit_t CtlrStat[1]; + pseudo_bit_t _unused_0[32]; +}; +struct QIB_7220_EEPCtlStat { + PSEUDO_BIT_STRUCT ( struct QIB_7220_EEPCtlStat_pb ); +}; + +#define QIB_7220_EEPAddrCmd_offset 0x000003f0UL +struct QIB_7220_EEPAddrCmd_pb { + pseudo_bit_t EPAddr[24]; + pseudo_bit_t EPCmd[8]; + pseudo_bit_t _unused_0[32]; +}; +struct QIB_7220_EEPAddrCmd { + PSEUDO_BIT_STRUCT ( struct QIB_7220_EEPAddrCmd_pb ); +}; + +#define QIB_7220_EEPData_offset 0x000003f8UL + +#define QIB_7220_pciesd_epb_access_ctrl_offset 0x00000400UL +struct QIB_7220_pciesd_epb_access_ctrl_pb { + pseudo_bit_t sw_pcie_epb_req[1]; + pseudo_bit_t sw_pcieepb_star_en[2]; + pseudo_bit_t Reserved[5]; + pseudo_bit_t sw_pcie_epb_req_granted[1]; + pseudo_bit_t _unused_0[55]; +}; +struct QIB_7220_pciesd_epb_access_ctrl { + PSEUDO_BIT_STRUCT ( struct QIB_7220_pciesd_epb_access_ctrl_pb ); +}; + +#define QIB_7220_pciesd_epb_transaction_reg_offset 0x00000408UL +struct QIB_7220_pciesd_epb_transaction_reg_pb { + pseudo_bit_t pcie_epb_data[8]; + pseudo_bit_t pcie_epb_address[15]; + pseudo_bit_t Reserved1[1]; + pseudo_bit_t pcie_epb_read_write[1]; + pseudo_bit_t pcie_epb_cs[3]; + pseudo_bit_t mem_data_parity[1]; + pseudo_bit_t Reserved[1]; + pseudo_bit_t pcie_epb_req_error[1]; + pseudo_bit_t pcie_epb_rdy[1]; + pseudo_bit_t _unused_0[32]; +}; +struct QIB_7220_pciesd_epb_transaction_reg { + PSEUDO_BIT_STRUCT ( struct QIB_7220_pciesd_epb_transaction_reg_pb ); +}; + +#define QIB_7220_efuse_control_reg_offset 0x00000410UL +struct QIB_7220_efuse_control_reg_pb { + pseudo_bit_t start_op[1]; + pseudo_bit_t operation[1]; + pseudo_bit_t read_valid[1]; + pseudo_bit_t req_error[1]; + pseudo_bit_t Reserved[27]; + pseudo_bit_t rdy[1]; + pseudo_bit_t _unused_0[32]; +}; +struct QIB_7220_efuse_control_reg { + PSEUDO_BIT_STRUCT ( struct QIB_7220_efuse_control_reg_pb ); +}; + +#define QIB_7220_efuse_rddata0_reg_offset 0x00000418UL + +#define QIB_7220_procmon_register_offset 0x00000438UL +struct QIB_7220_procmon_register_pb { + pseudo_bit_t interval_time[12]; + pseudo_bit_t Reserved1[2]; + pseudo_bit_t clear_counter[1]; + pseudo_bit_t start_counter[1]; + pseudo_bit_t procmon_count[9]; + pseudo_bit_t Reserved[6]; + pseudo_bit_t procmon_count_valid[1]; + pseudo_bit_t _unused_0[32]; +}; +struct QIB_7220_procmon_register { + PSEUDO_BIT_STRUCT ( struct QIB_7220_procmon_register_pb ); +}; + +#define QIB_7220_PcieRbufTestReg0_offset 0x00000440UL + +#define QIB_7220_PcieRBufTestReg1_offset 0x00000448UL + +#define QIB_7220_SPC_JTAG_ACCESS_REG_offset 0x00000460UL +struct QIB_7220_SPC_JTAG_ACCESS_REG_pb { + pseudo_bit_t rdy[1]; + pseudo_bit_t tdo[1]; + pseudo_bit_t tdi[1]; + pseudo_bit_t opcode[2]; + pseudo_bit_t bist_en[5]; + pseudo_bit_t SPC_JTAG_ACCESS_EN[1]; + pseudo_bit_t _unused_0[53]; +}; +struct QIB_7220_SPC_JTAG_ACCESS_REG { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SPC_JTAG_ACCESS_REG_pb ); +}; + +#define QIB_7220_LAControlReg_offset 0x00000468UL +struct QIB_7220_LAControlReg_pb { + pseudo_bit_t Finished[1]; + pseudo_bit_t Address[8]; + pseudo_bit_t Mode[2]; + pseudo_bit_t Delay[20]; + pseudo_bit_t Reserved[1]; + pseudo_bit_t _unused_0[32]; +}; +struct QIB_7220_LAControlReg { + PSEUDO_BIT_STRUCT ( struct QIB_7220_LAControlReg_pb ); +}; + +#define QIB_7220_GPIODebugSelReg_offset 0x00000470UL +struct QIB_7220_GPIODebugSelReg_pb { + pseudo_bit_t GPIOSourceSelDebug[16]; + pseudo_bit_t SelPulse[16]; + pseudo_bit_t _unused_0[32]; +}; +struct QIB_7220_GPIODebugSelReg { + PSEUDO_BIT_STRUCT ( struct QIB_7220_GPIODebugSelReg_pb ); +}; + +#define QIB_7220_DebugPortValueReg_offset 0x00000478UL + +#define QIB_7220_SendDmaBufUsed0_offset 0x00000480UL +struct QIB_7220_SendDmaBufUsed0_pb { + pseudo_bit_t BufUsed_63_0[0]; + pseudo_bit_t _unused_0[64]; +}; +struct QIB_7220_SendDmaBufUsed0 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SendDmaBufUsed0_pb ); +}; + +#define QIB_7220_SendDmaReqTagUsed_offset 0x00000498UL +struct QIB_7220_SendDmaReqTagUsed_pb { + pseudo_bit_t ReqTagUsed_7_0[8]; + pseudo_bit_t _unused_0[8]; + pseudo_bit_t Reserved[48]; + pseudo_bit_t _unused_1[8]; +}; +struct QIB_7220_SendDmaReqTagUsed { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SendDmaReqTagUsed_pb ); +}; + +#define QIB_7220_efuse_pgm_data0_offset 0x000004a0UL + +#define QIB_7220_MEM_0004B0_offset 0x000004b0UL + +#define QIB_7220_SerDes_DDSRXEQ0_offset 0x00000500UL +struct QIB_7220_SerDes_DDSRXEQ0_pb { + pseudo_bit_t element_num[4]; + pseudo_bit_t reg_addr[6]; + pseudo_bit_t _unused_0[54]; +}; +struct QIB_7220_SerDes_DDSRXEQ0 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SerDes_DDSRXEQ0_pb ); +}; + +#define QIB_7220_MEM_0005F0_offset 0x000005f0UL + +#define QIB_7220_LAMemory_offset 0x00000600UL + +#define QIB_7220_MEM_0007F0_offset 0x000007f0UL + +#define QIB_7220_SendBufAvail0_offset 0x00001000UL +struct QIB_7220_SendBufAvail0_pb { + pseudo_bit_t SendBuf_31_0[0]; + pseudo_bit_t _unused_0[64]; +}; +struct QIB_7220_SendBufAvail0 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_SendBufAvail0_pb ); +}; + +#define QIB_7220_MEM_001028_offset 0x00001028UL + +#define QIB_7220_LBIntCnt_offset 0x00013000UL + +#define QIB_7220_LBFlowStallCnt_offset 0x00013008UL + +#define QIB_7220_TxSDmaDescCnt_offset 0x00013010UL + +#define QIB_7220_TxUnsupVLErrCnt_offset 0x00013018UL + +#define QIB_7220_TxDataPktCnt_offset 0x00013020UL + +#define QIB_7220_TxFlowPktCnt_offset 0x00013028UL + +#define QIB_7220_TxDwordCnt_offset 0x00013030UL + +#define QIB_7220_TxLenErrCnt_offset 0x00013038UL + +#define QIB_7220_TxMaxMinLenErrCnt_offset 0x00013040UL + +#define QIB_7220_TxUnderrunCnt_offset 0x00013048UL + +#define QIB_7220_TxFlowStallCnt_offset 0x00013050UL + +#define QIB_7220_TxDroppedPktCnt_offset 0x00013058UL + +#define QIB_7220_RxDroppedPktCnt_offset 0x00013060UL + +#define QIB_7220_RxDataPktCnt_offset 0x00013068UL + +#define QIB_7220_RxFlowPktCnt_offset 0x00013070UL + +#define QIB_7220_RxDwordCnt_offset 0x00013078UL + +#define QIB_7220_RxLenErrCnt_offset 0x00013080UL + +#define QIB_7220_RxMaxMinLenErrCnt_offset 0x00013088UL + +#define QIB_7220_RxICRCErrCnt_offset 0x00013090UL + +#define QIB_7220_RxVCRCErrCnt_offset 0x00013098UL + +#define QIB_7220_RxFlowCtrlViolCnt_offset 0x000130a0UL + +#define QIB_7220_RxVersionErrCnt_offset 0x000130a8UL + +#define QIB_7220_RxLinkMalformCnt_offset 0x000130b0UL + +#define QIB_7220_RxEBPCnt_offset 0x000130b8UL + +#define QIB_7220_RxLPCRCErrCnt_offset 0x000130c0UL + +#define QIB_7220_RxBufOvflCnt_offset 0x000130c8UL + +#define QIB_7220_RxTIDFullErrCnt_offset 0x000130d0UL + +#define QIB_7220_RxTIDValidErrCnt_offset 0x000130d8UL + +#define QIB_7220_RxPKeyMismatchCnt_offset 0x000130e0UL + +#define QIB_7220_RxP0HdrEgrOvflCnt_offset 0x000130e8UL + +#define QIB_7220_IBStatusChangeCnt_offset 0x00013170UL + +#define QIB_7220_IBLinkErrRecoveryCnt_offset 0x00013178UL + +#define QIB_7220_IBLinkDownedCnt_offset 0x00013180UL + +#define QIB_7220_IBSymbolErrCnt_offset 0x00013188UL + +#define QIB_7220_RxVL15DroppedPktCnt_offset 0x00013190UL + +#define QIB_7220_RxOtherLocalPhyErrCnt_offset 0x00013198UL + +#define QIB_7220_PcieRetryBufDiagQwordCnt_offset 0x000131a0UL + +#define QIB_7220_ExcessBufferOvflCnt_offset 0x000131a8UL + +#define QIB_7220_LocalLinkIntegrityErrCnt_offset 0x000131b0UL + +#define QIB_7220_RxVlErrCnt_offset 0x000131b8UL + +#define QIB_7220_RxDlidFltrCnt_offset 0x000131c0UL + +#define QIB_7220_CNT_0131C8_offset 0x000131c8UL + +#define QIB_7220_PSStat_offset 0x00013200UL + +#define QIB_7220_PSStart_offset 0x00013208UL + +#define QIB_7220_PSInterval_offset 0x00013210UL + +#define QIB_7220_PSRcvDataCount_offset 0x00013218UL + +#define QIB_7220_PSRcvPktsCount_offset 0x00013220UL + +#define QIB_7220_PSXmitDataCount_offset 0x00013228UL + +#define QIB_7220_PSXmitPktsCount_offset 0x00013230UL + +#define QIB_7220_PSXmitWaitCount_offset 0x00013238UL + +#define QIB_7220_CNT_013240_offset 0x00013240UL + +#define QIB_7220_RcvEgrArray_offset 0x00014000UL + +#define QIB_7220_MEM_038000_offset 0x00038000UL + +#define QIB_7220_RcvTIDArray0_offset 0x00053000UL + +#define QIB_7220_PIOLaunchFIFO_offset 0x00064000UL + +#define QIB_7220_MEM_064480_offset 0x00064480UL + +#define QIB_7220_SendPIOpbcCache_offset 0x00064800UL + +#define QIB_7220_MEM_064C80_offset 0x00064c80UL + +#define QIB_7220_PreLaunchFIFO_offset 0x00065000UL + +#define QIB_7220_MEM_065080_offset 0x00065080UL + +#define QIB_7220_ScoreBoard_offset 0x00065400UL + +#define QIB_7220_MEM_065440_offset 0x00065440UL + +#define QIB_7220_DescriptorFIFO_offset 0x00065800UL + +#define QIB_7220_MEM_065880_offset 0x00065880UL + +#define QIB_7220_RcvBuf1_offset 0x00072000UL + +#define QIB_7220_MEM_074800_offset 0x00074800UL + +#define QIB_7220_RcvBuf2_offset 0x00075000UL + +#define QIB_7220_MEM_076400_offset 0x00076400UL + +#define QIB_7220_RcvFlags_offset 0x00077000UL + +#define QIB_7220_MEM_078400_offset 0x00078400UL + +#define QIB_7220_RcvLookupBuf1_offset 0x00079000UL + +#define QIB_7220_MEM_07A400_offset 0x0007a400UL + +#define QIB_7220_RcvDMADatBuf_offset 0x0007b000UL + +#define QIB_7220_RcvDMAHdrBuf_offset 0x0007b800UL + +#define QIB_7220_MiscRXEIntMem_offset 0x0007c000UL + +#define QIB_7220_MEM_07D400_offset 0x0007d400UL + +#define QIB_7220_PCIERcvBuf_offset 0x00080000UL + +#define QIB_7220_PCIERetryBuf_offset 0x00084000UL + +#define QIB_7220_PCIERcvBufRdToWrAddr_offset 0x00088000UL + +#define QIB_7220_PCIECplBuf_offset 0x00090000UL + +#define QIB_7220_IBSerDesMappTable_offset 0x00094000UL + +#define QIB_7220_MEM_095000_offset 0x00095000UL + +#define QIB_7220_SendBuf0_MA_offset 0x00100000UL + +#define QIB_7220_MEM_1A0000_offset 0x001a0000UL + +#define QIB_7220_RcvHdrTail0_offset 0x00200000UL + +#define QIB_7220_RcvHdrHead0_offset 0x00200008UL +struct QIB_7220_RcvHdrHead0_pb { + pseudo_bit_t RcvHeadPointer[32]; + pseudo_bit_t counter[16]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_RcvHdrHead0 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead0_pb ); +}; + +#define QIB_7220_RcvEgrIndexTail0_offset 0x00200010UL + +#define QIB_7220_RcvEgrIndexHead0_offset 0x00200018UL + +#define QIB_7220_MEM_200020_offset 0x00200020UL + +#define QIB_7220_RcvHdrTail1_offset 0x00210000UL + +#define QIB_7220_RcvHdrHead1_offset 0x00210008UL +struct QIB_7220_RcvHdrHead1_pb { + pseudo_bit_t RcvHeadPointer[32]; + pseudo_bit_t counter[16]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_RcvHdrHead1 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead1_pb ); +}; + +#define QIB_7220_RcvEgrIndexTail1_offset 0x00210010UL + +#define QIB_7220_RcvEgrIndexHead1_offset 0x00210018UL + +#define QIB_7220_MEM_210020_offset 0x00210020UL + +#define QIB_7220_RcvHdrTail2_offset 0x00220000UL + +#define QIB_7220_RcvHdrHead2_offset 0x00220008UL +struct QIB_7220_RcvHdrHead2_pb { + pseudo_bit_t RcvHeadPointer[32]; + pseudo_bit_t counter[16]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_RcvHdrHead2 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead2_pb ); +}; + +#define QIB_7220_RcvEgrIndexTail2_offset 0x00220010UL + +#define QIB_7220_RcvEgrIndexHead2_offset 0x00220018UL + +#define QIB_7220_MEM_220020_offset 0x00220020UL + +#define QIB_7220_RcvHdrTail3_offset 0x00230000UL + +#define QIB_7220_RcvHdrHead3_offset 0x00230008UL +struct QIB_7220_RcvHdrHead3_pb { + pseudo_bit_t RcvHeadPointer[32]; + pseudo_bit_t counter[16]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_RcvHdrHead3 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead3_pb ); +}; + +#define QIB_7220_RcvEgrIndexTail3_offset 0x00230010UL + +#define QIB_7220_RcvEgrIndexHead3_offset 0x00230018UL + +#define QIB_7220_MEM_230020_offset 0x00230020UL + +#define QIB_7220_RcvHdrTail4_offset 0x00240000UL + +#define QIB_7220_RcvHdrHead4_offset 0x00240008UL +struct QIB_7220_RcvHdrHead4_pb { + pseudo_bit_t RcvHeadPointer[32]; + pseudo_bit_t counter[16]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_RcvHdrHead4 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead4_pb ); +}; + +#define QIB_7220_RcvEgrIndexTail4_offset 0x00240010UL + +#define QIB_7220_RcvEgrIndexHead4_offset 0x00240018UL + +#define QIB_7220_MEM_240020_offset 0x00240020UL + +#define QIB_7220_RcvHdrTail5_offset 0x00250000UL + +#define QIB_7220_RcvHdrHead5_offset 0x00250008UL +struct QIB_7220_RcvHdrHead5_pb { + pseudo_bit_t RcvHeadPointer[32]; + pseudo_bit_t counter[16]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_RcvHdrHead5 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead5_pb ); +}; + +#define QIB_7220_RcvEgrIndexTail5_offset 0x00250010UL + +#define QIB_7220_RcvEgrIndexHead5_offset 0x00250018UL + +#define QIB_7220_MEM_250020_offset 0x00250020UL + +#define QIB_7220_RcvHdrTail6_offset 0x00260000UL + +#define QIB_7220_RcvHdrHead6_offset 0x00260008UL +struct QIB_7220_RcvHdrHead6_pb { + pseudo_bit_t RcvHeadPointer[32]; + pseudo_bit_t counter[16]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_RcvHdrHead6 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead6_pb ); +}; + +#define QIB_7220_RcvEgrIndexTail6_offset 0x00260010UL + +#define QIB_7220_RcvEgrIndexHead6_offset 0x00260018UL + +#define QIB_7220_MEM_260020_offset 0x00260020UL + +#define QIB_7220_RcvHdrTail7_offset 0x00270000UL + +#define QIB_7220_RcvHdrHead7_offset 0x00270008UL +struct QIB_7220_RcvHdrHead7_pb { + pseudo_bit_t RcvHeadPointer[32]; + pseudo_bit_t counter[16]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_RcvHdrHead7 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead7_pb ); +}; + +#define QIB_7220_RcvEgrIndexTail7_offset 0x00270010UL + +#define QIB_7220_RcvEgrIndexHead7_offset 0x00270018UL + +#define QIB_7220_MEM_270020_offset 0x00270020UL + +#define QIB_7220_RcvHdrTail8_offset 0x00280000UL + +#define QIB_7220_RcvHdrHead8_offset 0x00280008UL +struct QIB_7220_RcvHdrHead8_pb { + pseudo_bit_t RcvHeadPointer[32]; + pseudo_bit_t counter[16]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_RcvHdrHead8 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead8_pb ); +}; + +#define QIB_7220_RcvEgrIndexTail8_offset 0x00280010UL + +#define QIB_7220_RcvEgrIndexHead8_offset 0x00280018UL + +#define QIB_7220_MEM_280020_offset 0x00280020UL + +#define QIB_7220_RcvHdrTail9_offset 0x00290000UL + +#define QIB_7220_RcvHdrHead9_offset 0x00290008UL +struct QIB_7220_RcvHdrHead9_pb { + pseudo_bit_t RcvHeadPointer[32]; + pseudo_bit_t counter[16]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_RcvHdrHead9 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead9_pb ); +}; + +#define QIB_7220_RcvEgrIndexTail9_offset 0x00290010UL + +#define QIB_7220_RcvEgrIndexHead9_offset 0x00290018UL + +#define QIB_7220_MEM_290020_offset 0x00290020UL + +#define QIB_7220_RcvHdrTail10_offset 0x002a0000UL + +#define QIB_7220_RcvHdrHead10_offset 0x002a0008UL +struct QIB_7220_RcvHdrHead10_pb { + pseudo_bit_t RcvHeadPointer[32]; + pseudo_bit_t counter[16]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_RcvHdrHead10 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead10_pb ); +}; + +#define QIB_7220_RcvEgrIndexTail10_offset 0x002a0010UL + +#define QIB_7220_RcvEgrIndexHead10_offset 0x002a0018UL + +#define QIB_7220_MEM_2A0020_offset 0x002a0020UL + +#define QIB_7220_RcvHdrTail11_offset 0x002b0000UL + +#define QIB_7220_RcvHdrHead11_offset 0x002b0008UL +struct QIB_7220_RcvHdrHead11_pb { + pseudo_bit_t RcvHeadPointer[32]; + pseudo_bit_t counter[16]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_RcvHdrHead11 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead11_pb ); +}; + +#define QIB_7220_RcvEgrIndexTail11_offset 0x002b0010UL + +#define QIB_7220_RcvEgrIndexHead11_offset 0x002b0018UL + +#define QIB_7220_MEM_2B0020_offset 0x002b0020UL + +#define QIB_7220_RcvHdrTail12_offset 0x002c0000UL + +#define QIB_7220_RcvHdrHead12_offset 0x002c0008UL +struct QIB_7220_RcvHdrHead12_pb { + pseudo_bit_t RcvHeadPointer[32]; + pseudo_bit_t counter[16]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_RcvHdrHead12 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead12_pb ); +}; + +#define QIB_7220_RcvEgrIndexTail12_offset 0x002c0010UL + +#define QIB_7220_RcvEgrIndexHead12_offset 0x002c0018UL + +#define QIB_7220_MEM_2C0020_offset 0x002c0020UL + +#define QIB_7220_RcvHdrTail13_offset 0x002d0000UL + +#define QIB_7220_RcvHdrHead13_offset 0x002d0008UL +struct QIB_7220_RcvHdrHead13_pb { + pseudo_bit_t RcvHeadPointer[32]; + pseudo_bit_t counter[16]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_RcvHdrHead13 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead13_pb ); +}; + +#define QIB_7220_RcvEgrIndexTail13_offset 0x002d0010UL + +#define QIB_7220_RcvEgrIndexHead13_offset 0x002d0018UL + +#define QIB_7220_MEM_2D0020_offset 0x002d0020UL + +#define QIB_7220_RcvHdrTail14_offset 0x002e0000UL + +#define QIB_7220_RcvHdrHead14_offset 0x002e0008UL +struct QIB_7220_RcvHdrHead14_pb { + pseudo_bit_t RcvHeadPointer[32]; + pseudo_bit_t counter[16]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_RcvHdrHead14 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead14_pb ); +}; + +#define QIB_7220_RcvEgrIndexTail14_offset 0x002e0010UL + +#define QIB_7220_RcvEgrIndexHead14_offset 0x002e0018UL + +#define QIB_7220_MEM_2E0020_offset 0x002e0020UL + +#define QIB_7220_RcvHdrTail15_offset 0x002f0000UL + +#define QIB_7220_RcvHdrHead15_offset 0x002f0008UL +struct QIB_7220_RcvHdrHead15_pb { + pseudo_bit_t RcvHeadPointer[32]; + pseudo_bit_t counter[16]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_RcvHdrHead15 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead15_pb ); +}; + +#define QIB_7220_RcvEgrIndexTail15_offset 0x002f0010UL + +#define QIB_7220_RcvEgrIndexHead15_offset 0x002f0018UL + +#define QIB_7220_MEM_2F0020_offset 0x002f0020UL + +#define QIB_7220_RcvHdrTail16_offset 0x00300000UL + +#define QIB_7220_RcvHdrHead16_offset 0x00300008UL +struct QIB_7220_RcvHdrHead16_pb { + pseudo_bit_t RcvHeadPointer[32]; + pseudo_bit_t counter[16]; + pseudo_bit_t Reserved[16]; +}; +struct QIB_7220_RcvHdrHead16 { + PSEUDO_BIT_STRUCT ( struct QIB_7220_RcvHdrHead16_pb ); +}; + +#define QIB_7220_RcvEgrIndexTail16_offset 0x00300010UL + +#define QIB_7220_RcvEgrIndexHead16_offset 0x00300018UL + +#define QIB_7220_MEM_300020_offset 0x00300020UL + diff --git a/gpxe/src/drivers/infiniband/qib_genbits.pl b/gpxe/src/drivers/infiniband/qib_genbits.pl new file mode 100644 index 00000000..9eba4da5 --- /dev/null +++ b/gpxe/src/drivers/infiniband/qib_genbits.pl @@ -0,0 +1,95 @@ +#!/usr/bin/perl -w +# +# Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +use strict; +use warnings; + +my $offsets = {}; +my $structures = {}; +my $structure = ""; + +while ( <> ) { + chomp; + if ( /^\#define (\S+)_OFFS (\S+)$/ ) { + $structure = $1; + $offsets->{$structure} = $2; + } elsif ( /^\#define ${structure}_(\S+)_LSB (\S+)$/ ) { + $structures->{$structure}->{$1}->{LSB} = $2; + } elsif ( /^\#define ${structure}_(\S+)_RMASK (\S+)$/ ) { + $structures->{$structure}->{$1}->{RMASK} = $2; + } elsif ( /^\s*$/ ) { + # Do nothing + } else { + print "$_\n"; + } +} + +my $data = [ map { { name => $_, offset => $offsets->{$_} }; } + sort { hex ( $offsets->{$a} ) <=> hex ( $offsets->{$b} ) } + keys %$offsets ]; + +foreach my $datum ( @$data ) { + next unless exists $structures->{$datum->{name}}; + $structure = $structures->{$datum->{name}}; + my $fields = [ map { { name => $_, lsb => $structure->{$_}->{LSB}, + rmask => $structure->{$_}->{RMASK} }; } + sort { hex ( $structure->{$a}->{LSB} ) <=> + hex ( $structure->{$b}->{LSB} ) } + keys %$structure ]; + $datum->{fields} = $fields; +} + +print "\n/* This file has been further processed by $0 */\n\n\n"; + +foreach my $datum ( @$data ) { + printf "#define %s_offset 0x%08xUL\n", + $datum->{name}, hex ( $datum->{offset} ); + if ( exists $datum->{fields} ) { + my $lsb = 0; + my $reserved_idx = 0; + printf "struct %s_pb {\n", $datum->{name}; + foreach my $field ( @{$datum->{fields}} ) { + my $pad_width = ( hex ( $field->{lsb} ) - $lsb ); + die "Inconsistent LSB/RMASK in $datum->{name}\n" if $pad_width < 0; + printf "\tpseudo_bit_t _unused_%u[%u];\n", $reserved_idx++, $pad_width + if $pad_width; + # Damn Perl can't cope with 64-bit hex constants + my $width = 0; + my $rmask = $field->{rmask}; + while ( $rmask =~ /^(0x.+)f$/i ) { + $width += 4; + $rmask = $1; + } + $rmask = hex ( $rmask ); + while ( $rmask ) { + $width++; + $rmask >>= 1; + } + printf "\tpseudo_bit_t %s[%u];\n", $field->{name}, $width; + $lsb += $width; + } + my $pad_width = ( 64 - $lsb ); + die "Inconsistent LSB/RMASK in $datum->{name}\n" if $pad_width < 0; + printf "\tpseudo_bit_t _unused_%u[%u];\n", $reserved_idx++, $pad_width + if $pad_width; + printf "};\n"; + printf "struct %s {\n\tPSEUDO_BIT_STRUCT ( struct %s_pb );\n};\n", + $datum->{name}, $datum->{name}; + } + print "\n"; +} |