Browse Source

Remove old initialisation code from hashfast, use hf protocol library where possible and prepare for new driver model.

nfactor-troky
Con Kolivas 11 years ago
parent
commit
df6873eff9
  1. 117
      driver-hashfast.c
  2. 208
      driver-hashfast.h
  3. 1
      hf_protocol.h

117
driver-hashfast.c

@ -25,7 +25,7 @@
static unsigned char crc8_table[256]; /* CRC-8 table */ static unsigned char crc8_table[256]; /* CRC-8 table */
void hf_init_crc8(void) static void hf_init_crc8(void)
{ {
int i,j; int i,j;
unsigned char crc; unsigned char crc;
@ -50,8 +50,6 @@ static unsigned char __maybe_unused hf_crc8(unsigned char *h)
return crc; return crc;
} }
static hf_info_t **hashfast_infos;
struct hf_cmd { struct hf_cmd {
int cmd; int cmd;
char *cmd_name; char *cmd_name;
@ -115,106 +113,13 @@ static int __maybe_unused hashfast_send_frame(struct cgpu_info *hashfast, uint8_
return 0; return 0;
} }
static int hashfast_reset(struct cgpu_info __maybe_unused *hashfast) static int __maybe_unused hashfast_reset(struct cgpu_info __maybe_unused *hashfast)
{ {
return 0; return 0;
} }
static bool hashfast_detect_common(struct cgpu_info *hashfast, int baud) static bool hashfast_detect_common(struct cgpu_info __maybe_unused *hashfast)
{ {
hf_core_t **c, *core;
hf_info_t *info;
hf_job_t *j;
int i, k, ret;
hashfast_infos = realloc(hashfast_infos, sizeof(hf_info_t *) * (total_devices + 1));
if (unlikely(!hashfast_infos))
quit(1, "Failed to realloc hashfast_infos in hashfast_detect_common");
// Assume success, allocate info ahead of reset, so reset can fill fields in
info = calloc(sizeof(hf_info_t), 1);
if (unlikely(!info))
quit(1, "Failed to calloc info in hashfast_detect_common");
hashfast_infos[hashfast->device_id] = info;
info->tacho_enable = 1;
info->miner_count = 1;
info->max_search_difficulty = 12;
info->baud_rate = baud;
ret = hashfast_reset(hashfast);
if (unlikely(ret)) {
free(info);
hashfast_infos[hashfast->device_id] = NULL;
return false;
}
/* 1 Pending, 1 active for each */
info->inflight_target = info->asic_count * info->core_count *2;
switch (info->device_type) {
default:
case HFD_G1:
/* Implies hash_loops = 0 for full nonce range */
break;
case HFD_ExpressAGX:
/* ExpressAGX */
info->hash_loops = 1 << 26;
break;
case HFD_VC709:
/* Virtex 7
* Adjust according to fast or slow configuration */
if (info->core_count > 5)
info->hash_loops = 1 << 26;
else
info->hash_loops = 1 << 30;
break;
}
applog(LOG_INFO, "Hashfast Detect: chips %d cores %d inflight_target %d entries",
info->asic_count, info->core_count, info->inflight_target);
/* Initialize list heads */
info->active.next = &info->active;
info->active.prev = &info->active;
info->inactive.next = &info->inactive;
info->inactive.prev = &info->inactive;
/* Allocate core data structures */
info->cores = calloc(info->asic_count, sizeof(hf_core_t *));
if (unlikely(!info->cores))
quit(1, "Failed to calloc info cores in hashfast_detect_common");
c = info->cores;
for (i = 0; i < info->asic_count; i++) {
*c = calloc(info->core_count, sizeof(hf_core_t));
if (unlikely(!*c))
quit(1, "Failed to calloc hf_core_t in hashfast_detect_common");
for (k = 0, core = *c; k < info->core_count; k++, core++)
core->enabled = 1;
c++;
}
/* Now allocate enough structures to hold all the in-flight work
* 2 per core - one active and one pending. These go on the inactive
* queue, and get used/recycled as required. */
for (i = 0; i < info->asic_count * info->core_count * 2; i++) {
j = calloc(sizeof(hf_job_t), 1);
if (unlikely(!j))
quit(1, "Failed to calloc hf_job_t in hashfast_detect_common");
list_add(&info->inactive, &j->l);
}
info->inactive_count = info->asic_count * info->core_count * 2;
applog(LOG_INFO, "Hashfast Detect: Allocated %d job entries",
info->inflight_target);
// Finally, allocate enough space to hold the work array.
info->max_work = info->inflight_target;
info->num_sequence = 1024;
info->work = calloc(info->max_work, sizeof(hf_work_t));
if (unlikely(!info->work))
quit(1, "Failed to calloc info work in hashfast_detect_common");
applog(LOG_INFO, "Hashfast Detect: Allocated space for %d work entries", info->inflight_target);
return true; return true;
} }
@ -228,7 +133,6 @@ static void hashfast_usb_initialise(struct cgpu_info *hashfast)
static bool hashfast_detect_one_usb(libusb_device *dev, struct usb_find_devices *found) static bool hashfast_detect_one_usb(libusb_device *dev, struct usb_find_devices *found)
{ {
struct cgpu_info *hashfast; struct cgpu_info *hashfast;
int baud = DEFAULT_BAUD_RATE;
hashfast = usb_alloc_cgpu(&hashfast_drv, HASHFAST_MINER_THREADS); hashfast = usb_alloc_cgpu(&hashfast_drv, HASHFAST_MINER_THREADS);
if (!hashfast) if (!hashfast)
@ -242,12 +146,11 @@ static bool hashfast_detect_one_usb(libusb_device *dev, struct usb_find_devices
} }
hashfast->usbdev->usb_type = USB_TYPE_STD; hashfast->usbdev->usb_type = USB_TYPE_STD;
usb_set_pps(hashfast, HASHFAST_USB_PACKETSIZE);
hashfast_usb_initialise(hashfast); hashfast_usb_initialise(hashfast);
add_cgpu(hashfast); add_cgpu(hashfast);
return hashfast_detect_common(hashfast, baud); return hashfast_detect_common(hashfast);
} }
static void hashfast_detect(bool hotplug) static void hashfast_detect(bool hotplug)
@ -263,12 +166,7 @@ static bool hashfast_prepare(struct thr_info __maybe_unused *thr)
return true; return true;
} }
static bool hashfast_fill(struct cgpu_info __maybe_unused *hashfast) static int64_t hashfast_scanwork(struct thr_info __maybe_unused *thr)
{
return true;
}
static int64_t hashfast_scanhash(struct thr_info __maybe_unused *thr)
{ {
return 0; return 0;
} }
@ -293,9 +191,8 @@ struct device_drv hashfast_drv = {
.name = "HFA", .name = "HFA",
.drv_detect = hashfast_detect, .drv_detect = hashfast_detect,
.thread_prepare = hashfast_prepare, .thread_prepare = hashfast_prepare,
.hash_work = hash_queued_work, .hash_work = &hash_driver_work,
.queue_full = hashfast_fill, .scanwork = hashfast_scanwork,
.scanwork = hashfast_scanhash,
.get_api_stats = hashfast_api_stats, .get_api_stats = hashfast_api_stats,
.reinit_device = hashfast_init, .reinit_device = hashfast_init,
.thread_shutdown = hashfast_shutdown, .thread_shutdown = hashfast_shutdown,

208
driver-hashfast.h

@ -14,213 +14,9 @@
#ifdef USE_HASHFAST #ifdef USE_HASHFAST
#include "miner.h" #include "miner.h"
#include "elist.h" #include "elist.h"
#include "hf_protocol.h"
#define HASHFAST_MINER_THREADS 1 #define HASHFAST_MINER_THREADS 1
// Some serial protocol definitions
#define DEFAULT_BAUD_RATE 115200
#define HF_PREAMBLE (uint8_t) 0xaa
#define HF_BROADCAST_ADDRESS (uint8_t) 0xff
// Operation codes (Second header byte)
#define OP_NULL 0
#define OP_ROOT 1
#define OP_RESET 2
#define OP_PLL_CONFIG 3
#define OP_ADDRESS 4
#define OP_READDRESS 5
#define OP_HIGHEST 6
#define OP_BAUD 7
#define OP_UNROOT 8
#define OP_HASH 9
#define OP_NONCE 10
#define OP_ABORT 11
#define OP_STATUS 12
#define OP_GPIO 13
#define OP_CONFIG 14
#define OP_STATISTICS 15
#define OP_GROUP 16
#define OP_CLOCKGATE 17
// All packets begin with a standard 8 byte header
struct hf_header {
uint8_t preamble; // Always 0xaa
uint8_t operation_code;
uint8_t chip_address;
uint8_t core_address;
uint16_t hdata; // Header specific data
uint8_t data_length; // .. of data frame to follow, in 4 byte blocks, 0=no data
uint8_t crc8; // Computed across bytes 1-6 inclusive
} __attribute__((packed,aligned(4))); // 8 bytes total
// Body of packet for an OP_HASH operation
struct hf_hash {
uint8_t midstate[32]; // Computed from first half of block header
uint8_t merkle_residual[4]; // From block header
uint32_t timestamp; // From block header
uint32_t bits; // Actual difficulty target for block header
uint32_t starting_nonce; // Usually set to 0
uint32_t nonce_loops; // How many nonces to search, or 0 for 2^32
uint16_t ntime_loops:12; // How many times to roll timestamp, or 0
uint16_t spare1:4;
uint8_t search_difficulty; // Search difficulty to use, number of leading '0' bits required
uint8_t spare2;
uint32_t spare3;
uint32_t crc32; // Computed across all preceding data fields
} __attribute__((packed,aligned(4))); // 64 bytes total, including CRC
// How nonces are returned in OP_NONCE packets
struct hf_candidate_nonce {
uint32_t nonce; // Candidate nonce
uint16_t sequence; // Sequence number from corresponding OP_HASH
uint16_t ntime:12; // ntime offset, if ntime roll occurred
uint16_t search:1; // Search forward next 128 nonces to find solution
uint16_t spare:3;
} __attribute__((packed,aligned(4)));
// Body of packet for an OP_CONFIG operation
struct hf_config_data {
uint16_t status_period:11; // Periodic status time, msec
uint16_t enable_periodic_status:1; // Send periodic status
uint16_t send_status_on_core_idle:1; // Schedule status whenever core goes idle
uint16_t send_status_on_pending_empty:1; // Schedule status whenever core pending goes idle
uint16_t pwm_active_level:1; // Active level of PWM outputs, if used
uint16_t forward_all_privileged_packets:1; // Forward priv pkts -- diagnostic
uint8_t status_batch_delay; // Batching delay, time to wait before actually sending status
uint8_t watchdog:7; // Watchdog timeout, seconds
uint8_t disable_sensors:1; // Diagnostic
uint8_t rx_header_timeout:7; // Header timeout in char times
uint8_t rx_ignore_header_crc:1; // Ignore rx header crc's (diagnostic)
uint8_t rx_data_timeout:7; // Data timeout in char times / 16
uint8_t rx_ignore_data_crc:1; // Ignore rx data crc's (diagnostic)
uint8_t stats_interval:7; // Minimum interval to report statistics (seconds)
uint8_t stat_diagnostic:1; // Never set this
uint8_t measure_interval; // Die temperature measurment interval (msec)
uint32_t one_usec:12; // How many LF clocks per usec.
uint32_t max_nonces_per_frame:4; // Maximum # of nonces to combine in a single frame
uint32_t voltage_sample_points:8; // Bit mask for sample points (up to 5 bits set)
uint32_t pwm_phases:2; // phases - 1
uint32_t trim:4; // Trim value for temperature measurements
uint32_t clock_diagnostic:1; // Never set this
uint32_t forward_all_packets:1; // Forward everything - diagnostic.
uint16_t pwm_period; // Period of PWM outputs, in reference clock cycles
uint16_t pwm_pulse_period; // Initial count, phase 0
} __attribute__((packed,aligned(4)));
// What comes back in the body of an OP_STATISTICS frame
struct hf_statistics {
uint8_t rx_header_crc; // Header CRC's
uint8_t rx_body_crc; // Data CRC's
uint8_t rx_header_timeouts; // Header timeouts
uint8_t rx_body_timeouts; // Data timeouts
uint8_t core_nonce_fifo_full; // Core nonce Q overrun events
uint8_t array_nonce_fifo_full; // System nonce Q overrun events
uint8_t stats_overrun; // Overrun in statistics reporting
uint8_t spare;
} __attribute__((packed,aligned(4)));
// Not really necessary (could just link directly to CGMiner's work structures), but these are
// here as an internal place to stage split jobs in the future, e.g. ntime rolling across
// multiple cores.
typedef struct hf_work_t {
struct work *work; // Finally out to cgminer's work
uint8_t data[128]; // XXX These are only replicated here to help de-couple the
uint8_t midstate[32]; // XXX driver code from cgminer's specifics, since this is
uint8_t target[32]; // XXX a sample driver. There's no other reason.
int split_count; // How many cores this is split between
} hf_work_t;
// Internal representation of a "job". Each core should normally have one active job and one pending job queued to it.
// This is where the ALL IMPORTANT sequence number is kept. When jobs are created, this structure is put in the "active"
// list (unique to the asic/core), and an incrementing sequence number is assigned to the job. Only when a sequence number
// that matches or exceeds (modulo <max sequence>) this number in a returned OP_STATUS, do we know that the "busy" bits
// associated with this same core represent the job status, i.e. the associated OP_HASH is no longer in flight.
typedef struct hf_job_t {
struct list_head l;
uint8_t chip; // Chip address
uint8_t core; // Core address
uint16_t sequence; // Copy of the active sequence number
hf_work_t *work; // Pointer to the work block
} hf_job_t;
// Per-core structure
typedef struct hf_core_t {
hf_job_t *active; // Active job on this core, NULL if none
hf_job_t *pending; // Pending job on this core, NULL if none
uint8_t enabled; // 1 = enabled, 0 = disabled
uint8_t inflight; // How many jobs are "inflight": 0, 1 or 2
uint8_t seen_allbusy; // We've seen both active and pending queues busy
} hf_core_t; // since the last OP_HASH was queued
// Per device structure. This is found by looking up an array, which is indexed
// by CGMiner's cgpu_info.device_id field.
typedef struct hf_info_t {
int miner_count;
int timeout;
int baud_rate; // Baud rate, if applicable
int ref_frequency; // Reference clock rate
int asic_count; // # of chips in the chain
int core_count; // # of cores per chip
int device_type; // What sort of device this is
int max_search_difficulty; // # of bits set to 0 in hash
int inflight_target; // Set to chips * cores * 2 (1 active, 1 pending each core)
int hash_sequence; // The last hash sequence #
int num_sequence; // A power of 2. What the sequence number range is.
int num_work; // Number of "work" entries in work queue
int max_work; // Target maximum number of "work" entries in work queue
// If work is split between cores, then max_work < inflight_target.
int last_log; // Last OP_STATUS log time in seconds
float thermal_trip_temperature; // Thermal trip temperature in degrees C
int thermal_trip_limit; // Thermal trip limit in raw device adc counts (derived from above)
int tacho_enable; // Set if there is a tacho to be read
uint64_t hash_loops; // XXX Temp. How many nonces to cycle through (range limited for FPGA emulation)
int no_matching_work;
struct list_head active; // Double linked list through all ACTIVE in-flight jobs (hf_job_t's)
struct list_head inactive; // Double linked list through all INACTIVE job blocks (hf_job_t's)
int active_count; // How many active hf_job_t's are out there
int inactive_count; // How many inactive hf_job_t's are out there
hf_core_t **cores; // Points to array of chips, which each point to array of cores
hf_work_t *work; // Points to array of work
} hf_info_t;
// The sequence distance between a sent and received sequence number.
#define SEQUENCE_DISTANCE(tx,rx) ((tx)>=(rx)?((tx)-(rx)):(info->num_sequence+(tx)-(rx)))
// Values info->device_type can take, comes from a completed OP_ADDRESS cycle
#define HFD_G1 1 /* A real G-1 ASIC */
#define HFD_VC709 128 /* FPGA Emulation */
#define HFD_ExpressAGX 129 /* FPGA Emulation */
// Some USB defines
#define HASHFAST_USB_PACKETSIZE 512 /* XXX Fix this. */
// Some low level serial defines
#define HASHFAST_READ_TIME(baud) ((double)HASHFAST_READ_SIZE * (double)8.0 / (double)(baud))
#define ASSERT1(condition) __maybe_unused static char sizeof_uint32_t_must_be_4[(condition)?1:-1]
ASSERT1(sizeof(uint32_t) == 4);
hf_info_t **hashfast_info;
void hf_init_crc8(void);
void hf_init_crc32(void);
#endif /* USE_HASHFAST */ #endif /* USE_HASHFAST */
#endif /* HASHFAST_H */ #endif /* HASHFAST_H */

1
hf_protocol.h

@ -22,6 +22,7 @@
#define HF_GWQ_ADDRESS (uint8_t) 254 #define HF_GWQ_ADDRESS (uint8_t) 254
// Serial protocol operation codes (Second header byte) // Serial protocol operation codes (Second header byte)
#define OP_NULL 0
#define OP_ROOT 1 #define OP_ROOT 1
#define OP_RESET 2 #define OP_RESET 2
#define OP_PLL_CONFIG 3 #define OP_PLL_CONFIG 3

Loading…
Cancel
Save