/* 3b2_ni.h: CM195A Network Interface CIO Card Copyright (c) 2018-2022, Seth J. Morabito Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 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. Except as contained in this notice, the name of the author shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the author. */ #ifndef _3B2_NI_H_ #define _3B2_NI_H_ #include "3b2_defs.h" #include "sim_ether.h" #define NI_ID 0x0002 #define NI_IPL 12 /* Opcodes for NI card */ #define NI_SETID 6 #define NI_TURNOFF 7 #define NI_TURNON 8 #define NI_SEND 11 #define NI_RECV 12 #define NI_STATS 13 #define NI_SANITY 15 #define NI_SEND_A 22 #define MAC_SIZE_BYTES 6 #define MAC_SIZE_CHARS 20 #define NIQESIZE 12 #define NI_QUE_MAX 1024 #define NI_INT_DELAY 10000 #define NI_SANITY_INTERVAL_US 5000000 /* Maximum allowed number of multicast addresses */ #define NI_MULTI_MAX 64 /* At least two filter addresses are always configured: * 1. The host MAC * 2. The broadcast address */ #define NI_FILTER_MIN 2 /* Maximum total allowed number of filter addresses, including the * host's MAC and the broadcast address. */ #define NI_FILTER_MAX NI_MULTI_MAX + NI_FILTER_MIN /* Indexes in the internal filter address table of the * host's MAC and the broadcast address */ #define NI_NIC_MAC 0 #define NI_BCST_MAC 1 /* * For performance reasons, there are two modes of polling the receive * queues. Initially, polling is VERY aggressive as we race the * filling of the receive queues. Once we've taken three jobs from * each of the two receive queues, we switch to slow polling, * which uses coscheduling. */ #define NI_QPOLL_FAST 100 #define NI_QPOLL_SLOW 50000 #define EIG_TABLE_SIZE 40 #define PKT_HEADER_LEN_OFFSET EIG_TABLE_SIZE #define PKT_START_OFFSET (PKT_HEADER_LEN_OFFSET + 4) /* * The NI card has two request queues for packet receive: One for * small packets, and one for large packets. The small queue is meant * for packets smaller than 128 bytes. The large queue is meant for * packets up to 1500 bytes (no jumbo frames allowed) */ #define GE_QUEUE 0 /* General request CIO queue */ #define SM_QUEUE 0 /* Small packet receive queue number */ #define LG_QUEUE 1 /* Large packet receive queue number */ #define SM_PKT_MAX 106 /* Max size of small packets (excluding CRC) */ #define LG_PKT_MAX 1514 /* Max size of large packets (excluding CRC) */ /* * NI-specific debugging flags */ #define DBG_TRACE 0x01 #define DBG_IO 0x02 #define DBG_CACHE 0x04 #define DBG_DAT 0x08 #define DBG_ERR 0x10 #define DBG_ETH 0x20 #define CHAR(c) ((((c) >= 0x20) && ((c) < 0x7f)) ? (c) : '.') #define NI_CACHE_HAS_SPACE(i) (((ni.job_cache[(i)].wp + 1) % NI_CACHE_LEN) != ni.job_cache[(i)].rp) /* Determine whether both job caches have available slots */ #define NI_BUFFERS_AVAIL ((ni.job_cache[0].wp != ni.job_cache[0].rp) && \ (ni.job_cache[1].wp != ni.job_cache[1].rp)) /* * The NI card caches up to three jobs taken from each of the two * packet receive queues so that they are available immediately after * receipt of a packet. These jobs are kept in small circular buffers. * Each job is represented by an ni_rec_job structure, containing a * buffer pointer and a slot number. The slot number is used by both * the driver and the firmware to correlate a packet receive buffer * with a completion queue event. */ typedef struct { uint32 addr; /* address of job's buffer */ uint8 slot; /* slot number of the job */ } ni_rec_job; #define NI_CACHE_LEN 4 typedef struct { ni_rec_job req[NI_CACHE_LEN]; /* the cache */ int wp; /* write pointer */ int rp; /* read pointer */ } ni_job_cache; /* * When the NI driver submits a packet send request to the general * request queue, it constructs one or more ni_prot_info structs in * main memory that point to the protocol-specific byte data of the * packet (minus the Ethernet frame). These structs are packed one * after the other following the Ethernet frame header in the job's * request buffer. The last entry has its "last" bit set to non-zero. */ typedef struct { uint32 addr; /* Physical address of the buffer in system RAM */ uint16 size; /* Length of the buffer */ uint16 last; /* Is this the last entry in the list? */ } ni_prot_info; typedef struct { uint32 rq_taken; uint32 tx_fail; uint32 rx_dropped; uint32 rx_pkt; uint32 tx_pkt; uint32 rx_bytes; uint32 tx_bytes; } ni_stat_info; typedef struct { uint8 slot; t_bool enabled; uint32 crc; uint32 poll_rate; char mac_str[MAC_SIZE_CHARS]; uint8 mac_bytes[MAC_SIZE_BYTES]; ni_job_cache job_cache[2]; ni_prot_info prot; ni_stat_info stats; uint8 fcf_seq; ETH_DEV* eth; ETH_PACK rd_buf; ETH_PACK wr_buf; ETH_MAC macs[NI_FILTER_MAX]; /* List of all filter addresses */ int filter_count; /* Number of filters available */ ETH_PCALLBACK callback; } NI_STATE; void ni_recv_callback(int status); t_stat ni_reset(DEVICE *dptr); t_stat ni_rcv_svc(UNIT *uptr); t_stat ni_sanity_svc(UNIT *uptr); t_stat ni_rq_svc(UNIT *uptr); t_stat ni_cio_svc(UNIT *uptr); t_stat ni_attach(UNIT *uptr, CONST char *cptr); t_stat ni_detach(UNIT *uptr); t_stat ni_setmac(UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat ni_showmac(FILE* st, UNIT *uptr, int32 val, CONST void *desc); t_stat ni_try_job(uint8 slot); t_stat ni_show_stats(FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat ni_set_stats(UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat ni_show_poll(FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat ni_show_filters(FILE *st, UNIT *uptr, int32 val, CONST void *desc); const char *ni_description(DEVICE *dptr); t_stat ni_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); void ni_cio_reset(uint8 slot); void ni_process_packet(); void ni_int_ack(uint8 slot); void ni_sysgen(uint8 slot); void ni_express(uint8 slot); void ni_full(uint8 slot); #endif /* _3B2_NI_H_ */