Browse Source

API V1.26 update ASIC support

Kano 12 years ago
parent
commit
a73ed9665a
2 changed files with 319 additions and 18 deletions
  1. 52 14
      API-README
  2. 267 4
      api.c

+ 52 - 14
API-README

@@ -60,7 +60,7 @@ response, otherwise it replies with text formatted as described further below.
 The JSON request format required is '{"command":"CMD","parameter":"PARAM"}'
 The JSON request format required is '{"command":"CMD","parameter":"PARAM"}'
 (though of course parameter is not required for all requests)
 (though of course parameter is not required for all requests)
 where "CMD" is from the "Request" column below and "PARAM" would be e.g.
 where "CMD" is from the "Request" column below and "PARAM" would be e.g.
-the CPU/GPU number if required.
+the ASC/GPU number if required.
 
 
 An example request in both formats to set GPU 0 fan to 80%:
 An example request in both formats to set GPU 0 fan to 80%:
   gpufan|0,80
   gpufan|0,80
@@ -115,8 +115,8 @@ The list of requests - a (*) means it requires privileged access - and replies a
 
 
  config        CONFIG         Some miner configuration information:
  config        CONFIG         Some miner configuration information:
                               GPU Count=N, <- the number of GPUs
                               GPU Count=N, <- the number of GPUs
+                              ASC Count=N, <- the number of ASCs
                               PGA Count=N, <- the number of PGAs
                               PGA Count=N, <- the number of PGAs
-                              CPU Count=N, <- the number of CPUs
                               Pool Count=N, <- the number of Pools
                               Pool Count=N, <- the number of Pools
                               ADL=X, <- Y or N if ADL is compiled in the code
                               ADL=X, <- Y or N if ADL is compiled in the code
                               ADL in use=X, <- Y or N if any GPU has ADL
                               ADL in use=X, <- Y or N if any GPU has ADL
@@ -135,7 +135,7 @@ The list of requests - a (*) means it requires privileged access - and replies a
  pools         POOLS          The status of each pool
  pools         POOLS          The status of each pool
                               e.g. Pool=0,URL=http://pool.com:6311,Status=Alive,...|
                               e.g. Pool=0,URL=http://pool.com:6311,Status=Alive,...|
 
 
- devs          DEVS           Each available GPU, PGA and CPU with their details
+ devs          DEVS           Each available GPU, PGA and ASC with their details
                               e.g. GPU=0,Accepted=NN,MHS av=NNN,...,Intensity=D|
                               e.g. GPU=0,Accepted=NN,MHS av=NNN,...,Intensity=D|
                               Last Share Time=NNN, <- standand long time in seconds
                               Last Share Time=NNN, <- standand long time in seconds
                                (or 0 if none) of last accepted share
                                (or 0 if none) of last accepted share
@@ -143,7 +143,7 @@ The list of requests - a (*) means it requires privileged access - and replies a
                               Last Valid Work=NNN, <- standand long time in seconds
                               Last Valid Work=NNN, <- standand long time in seconds
                                of last work returned that wasn't an HW:
                                of last work returned that wasn't an HW:
                               Will not report PGAs if PGA mining is disabled
                               Will not report PGAs if PGA mining is disabled
-                              Will not report CPUs if CPU mining is disabled
+                              Will not report ASCs if ASC mining is disabled
 
 
  gpu|N         GPU            The details of a single GPU number N in the same
  gpu|N         GPU            The details of a single GPU number N in the same
                               format and details as for DEVS
                               format and details as for DEVS
@@ -153,19 +153,11 @@ The list of requests - a (*) means it requires privileged access - and replies a
                               This is only available if PGA mining is enabled
                               This is only available if PGA mining is enabled
                               Use 'pgacount' or 'config' first to see if there are any
                               Use 'pgacount' or 'config' first to see if there are any
 
 
- cpu|N         CPU            The details of a single CPU number N in the same
-                              format and details as for DEVS
-                              This is only available if CPU mining is enabled
-                              Use 'cpucount' or 'config' first to see if there are any
-
  gpucount      GPUS           Count=N| <- the number of GPUs
  gpucount      GPUS           Count=N| <- the number of GPUs
 
 
  pgacount      PGAS           Count=N| <- the number of PGAs
  pgacount      PGAS           Count=N| <- the number of PGAs
                               Always returns 0 if PGA mining is disabled
                               Always returns 0 if PGA mining is disabled
 
 
- cpucount      CPUS           Count=N| <- the number of CPUs
-                              Always returns 0 if CPU mining is disabled
-
  switchpool|N (*)
  switchpool|N (*)
                none           There is no reply section just the STATUS section
                none           There is no reply section just the STATUS section
                               stating the results of switching pool N to the
                               stating the results of switching pool N to the
@@ -370,8 +362,39 @@ The list of requests - a (*) means it requires privileged access - and replies a
                               If N>0 && <=9999, then hotplug will check for new
                               If N>0 && <=9999, then hotplug will check for new
                               devices every N seconds
                               devices every N seconds
 
 
-When you enable, disable or restart a GPU or PGA, you will also get Thread messages
-in the cgminer status window
+ asc|N         ASC            The details of a single ASC number N in the same
+                              format and details as for DEVS
+                              This is only available if ASC mining is enabled
+                              Use 'asccount' or 'config' first to see if there
+                              are any
+
+ ascenable|N (*)
+               none           There is no reply section just the STATUS section
+                              stating the results of the enable request
+                              You cannot enable a ASC if it's status is not WELL
+                              This is only available if ASC mining is enabled
+
+ ascdisable|N (*)
+               none           There is no reply section just the STATUS section
+                              stating the results of the disable request
+                              This is only available if ASC mining is enabled
+
+ ascidentify|N (*)
+               none           There is no reply section just the STATUS section
+                              stating the results of the identify request
+                              This is only available if ASC mining is enabled
+                              and currently only BFL ASICs support this command
+                              On a BFL single it will flash the led on the front
+                              of the device for appoximately 4s
+                              All other non BFL ASIC devices will return a
+                              warning status message stating that they dont
+                              support it
+
+ asccount      ASCS           Count=N| <- the number of ASCs
+                              Always returns 0 if ASC mining is disabled
+
+When you enable, disable or restart a GPU, PGA or ASC, you will also get
+Thread messages in the cgminer status window
 
 
 The 'poolpriority' command can be used to reset the priority order of multiple
 The 'poolpriority' command can be used to reset the priority order of multiple
 pools with a single command - 'switchpool' only sets a single pool to first priority
 pools with a single command - 'switchpool' only sets a single pool to first priority
@@ -423,6 +446,21 @@ miner.php - an example web page to access the API
 Feature Changelog for external applications using the API:
 Feature Changelog for external applications using the API:
 
 
 
 
+API V1.26 (cgminer v3.2.3)
+
+Remove all CPU support (cgminer v3.0.0)
+
+Added API commands:
+ 'asc'
+ 'ascenable'
+ 'ascdisable'
+ 'ascidentify|N' (only works for BFL ASICs so far)
+ 'asccount'
+
+Various additions to the debug 'stats' command
+
+----------
+
 API V1.25
 API V1.25
 
 
 Added API commands:
 Added API commands:

+ 267 - 4
api.c

@@ -134,7 +134,7 @@ static const char SEPARATOR = '|';
 #define SEPSTR "|"
 #define SEPSTR "|"
 static const char GPUSEP = ',';
 static const char GPUSEP = ',';
 
 
-static const char *APIVERSION = "1.25";
+static const char *APIVERSION = "1.26";
 static const char *DEAD = "Dead";
 static const char *DEAD = "Dead";
 #if defined(HAVE_OPENCL) || defined(HAVE_AN_FPGA) || defined(HAVE_AN_ASIC)
 #if defined(HAVE_OPENCL) || defined(HAVE_AN_FPGA) || defined(HAVE_AN_ASIC)
 static const char *SICK = "Sick";
 static const char *SICK = "Sick";
@@ -219,8 +219,13 @@ static const char *OSINFO =
 #define _PGA		"PGA"
 #define _PGA		"PGA"
 #endif
 #endif
 
 
+#ifdef HAVE_AN_ASIC
+#define _ASC		"ASC"
+#endif
+
 #define _GPUS		"GPUS"
 #define _GPUS		"GPUS"
 #define _PGAS		"PGAS"
 #define _PGAS		"PGAS"
+#define _ASCS		"ASCS"
 #define _NOTIFY		"NOTIFY"
 #define _NOTIFY		"NOTIFY"
 #define _DEVDETAILS	"DEVDETAILS"
 #define _DEVDETAILS	"DEVDETAILS"
 #define _BYE		"BYE"
 #define _BYE		"BYE"
@@ -255,8 +260,13 @@ static const char ISJSON = '{';
 #define JSON_PGA	JSON1 _PGA JSON2
 #define JSON_PGA	JSON1 _PGA JSON2
 #endif
 #endif
 
 
+#ifdef HAVE_AN_ASIC
+#define JSON_ASC	JSON1 _ASC JSON2
+#endif
+
 #define JSON_GPUS	JSON1 _GPUS JSON2
 #define JSON_GPUS	JSON1 _GPUS JSON2
 #define JSON_PGAS	JSON1 _PGAS JSON2
 #define JSON_PGAS	JSON1 _PGAS JSON2
+#define JSON_ASCS	JSON1 _ASCS JSON2
 #define JSON_NOTIFY	JSON1 _NOTIFY JSON2
 #define JSON_NOTIFY	JSON1 _NOTIFY JSON2
 #define JSON_DEVDETAILS	JSON1 _DEVDETAILS JSON2
 #define JSON_DEVDETAILS	JSON1 _DEVDETAILS JSON2
 #define JSON_BYE	JSON1 _BYE JSON1
 #define JSON_BYE	JSON1 _BYE JSON1
@@ -381,13 +391,28 @@ static const char *JSON_PARAMETER = "parameter";
 #define MSG_ZERINV 95
 #define MSG_ZERINV 95
 #define MSG_ZERSUM 96
 #define MSG_ZERSUM 96
 #define MSG_ZERNOSUM 97
 #define MSG_ZERNOSUM 97
-#define MSG_USBNODEV 98
+#define MSG_PGAUSBNODEV 98
 #define MSG_INVHPLG 99
 #define MSG_INVHPLG 99
 #define MSG_HOTPLUG 100
 #define MSG_HOTPLUG 100
 #define MSG_DISHPLG 101
 #define MSG_DISHPLG 101
 #define MSG_NOHPLG 102
 #define MSG_NOHPLG 102
 #define MSG_MISHPLG 103
 #define MSG_MISHPLG 103
 
 
+#define MSG_NUMASC 104
+#ifdef HAVE_AN_ASIC
+#define MSG_ASCNON 105
+#define MSG_ASCDEV 106
+#define MSG_INVASC 107
+#define MSG_ASCLRENA 108
+#define MSG_ASCLRDIS 109
+#define MSG_ASCENA 110
+#define MSG_ASCDIS 111
+#define MSG_ASCUNW 112
+#define MSG_ASCIDENT 113
+#define MSG_ASCNOID 114
+#define MSG_ASCUSBNODEV 115
+#endif
+
 enum code_severity {
 enum code_severity {
 	SEVERITY_ERR,
 	SEVERITY_ERR,
 	SEVERITY_WARN,
 	SEVERITY_WARN,
@@ -399,9 +424,11 @@ enum code_severity {
 enum code_parameters {
 enum code_parameters {
 	PARAM_GPU,
 	PARAM_GPU,
 	PARAM_PGA,
 	PARAM_PGA,
+	PARAM_ASC,
 	PARAM_PID,
 	PARAM_PID,
 	PARAM_GPUMAX,
 	PARAM_GPUMAX,
 	PARAM_PGAMAX,
 	PARAM_PGAMAX,
+	PARAM_ASCMAX,
 	PARAM_PMAX,
 	PARAM_PMAX,
 	PARAM_POOLMAX,
 	PARAM_POOLMAX,
 
 
@@ -487,6 +514,7 @@ struct CODES {
 #endif
 #endif
  { SEVERITY_SUCC,  MSG_NUMGPU,	PARAM_NONE,	"GPU count" },
  { SEVERITY_SUCC,  MSG_NUMGPU,	PARAM_NONE,	"GPU count" },
  { SEVERITY_SUCC,  MSG_NUMPGA,	PARAM_NONE,	"PGA count" },
  { SEVERITY_SUCC,  MSG_NUMPGA,	PARAM_NONE,	"PGA count" },
+ { SEVERITY_SUCC,  MSG_NUMASC,	PARAM_NONE,	"ASC count" },
  { SEVERITY_SUCC,  MSG_VERSION,	PARAM_NONE,	"CGMiner versions" },
  { SEVERITY_SUCC,  MSG_VERSION,	PARAM_NONE,	"CGMiner versions" },
  { SEVERITY_ERR,   MSG_INVJSON,	PARAM_NONE,	"Invalid JSON" },
  { SEVERITY_ERR,   MSG_INVJSON,	PARAM_NONE,	"Invalid JSON" },
  { SEVERITY_ERR,   MSG_MISCMD,	PARAM_CMD,	"Missing JSON '%s'" },
  { SEVERITY_ERR,   MSG_MISCMD,	PARAM_CMD,	"Missing JSON '%s'" },
@@ -561,13 +589,26 @@ struct CODES {
  { SEVERITY_SUCC,  MSG_ZERSUM,	PARAM_STR,	"Zeroed %s stats with summary" },
  { SEVERITY_SUCC,  MSG_ZERSUM,	PARAM_STR,	"Zeroed %s stats with summary" },
  { SEVERITY_SUCC,  MSG_ZERNOSUM, PARAM_STR,	"Zeroed %s stats without summary" },
  { SEVERITY_SUCC,  MSG_ZERNOSUM, PARAM_STR,	"Zeroed %s stats without summary" },
 #ifdef USE_USBUTILS
 #ifdef USE_USBUTILS
- { SEVERITY_ERR,   MSG_USBNODEV, PARAM_PGA,	"PGA%d has no device" },
+ { SEVERITY_ERR,   MSG_PGAUSBNODEV, PARAM_PGA,	"PGA%d has no device" },
+ { SEVERITY_ERR,   MSG_ASCUSBNODEV, PARAM_PGA,	"ASC%d has no device" },
 #endif
 #endif
  { SEVERITY_ERR,   MSG_INVHPLG,	PARAM_STR,	"Invalid value for hotplug (%s) must be 0..9999" },
  { SEVERITY_ERR,   MSG_INVHPLG,	PARAM_STR,	"Invalid value for hotplug (%s) must be 0..9999" },
  { SEVERITY_SUCC,  MSG_HOTPLUG,	PARAM_INT,	"Hotplug check set to %ds" },
  { SEVERITY_SUCC,  MSG_HOTPLUG,	PARAM_INT,	"Hotplug check set to %ds" },
  { SEVERITY_SUCC,  MSG_DISHPLG,	PARAM_NONE,	"Hotplug disabled" },
  { SEVERITY_SUCC,  MSG_DISHPLG,	PARAM_NONE,	"Hotplug disabled" },
  { SEVERITY_WARN,  MSG_NOHPLG,	PARAM_NONE,	"Hotplug is not available" },
  { SEVERITY_WARN,  MSG_NOHPLG,	PARAM_NONE,	"Hotplug is not available" },
  { SEVERITY_ERR,   MSG_MISHPLG,	PARAM_NONE,	"Missing hotplug parameter" },
  { SEVERITY_ERR,   MSG_MISHPLG,	PARAM_NONE,	"Missing hotplug parameter" },
+#ifdef HAVE_AN_ASIC
+ { SEVERITY_ERR,   MSG_ASCNON,	PARAM_NONE,	"No ASCs" },
+ { SEVERITY_SUCC,  MSG_ASCDEV,	PARAM_ASC,	"ASC%d" },
+ { SEVERITY_ERR,   MSG_INVASC,	PARAM_ASCMAX,	"Invalid ASC id %d - range is 0 - %d" },
+ { SEVERITY_INFO,  MSG_ASCLRENA,PARAM_ASC,	"ASC %d already enabled" },
+ { SEVERITY_INFO,  MSG_ASCLRDIS,PARAM_ASC,	"ASC %d already disabled" },
+ { SEVERITY_INFO,  MSG_ASCENA,	PARAM_ASC,	"ASC %d sent enable message" },
+ { SEVERITY_INFO,  MSG_ASCDIS,	PARAM_ASC,	"ASC %d set disable flag" },
+ { SEVERITY_ERR,   MSG_ASCUNW,	PARAM_ASC,	"ASC %d is not flagged WELL, cannot enable" },
+ { SEVERITY_SUCC,  MSG_ASCIDENT,PARAM_ASC,	"Identify command sent to ASC%d" },
+ { SEVERITY_WARN,  MSG_ASCNOID,	PARAM_ASC,	"ASC%d does not support identify" },
+#endif
  { SEVERITY_FAIL, 0, 0, NULL }
  { SEVERITY_FAIL, 0, 0, NULL }
 };
 };
 
 
@@ -1296,6 +1337,7 @@ static void message(struct io_data *io_data, int messageid, int paramid, char *p
 			switch(codes[i].params) {
 			switch(codes[i].params) {
 				case PARAM_GPU:
 				case PARAM_GPU:
 				case PARAM_PGA:
 				case PARAM_PGA:
+				case PARAM_ASC:
 				case PARAM_PID:
 				case PARAM_PID:
 				case PARAM_INT:
 				case PARAM_INT:
 					sprintf(buf, codes[i].description, paramid);
 					sprintf(buf, codes[i].description, paramid);
@@ -1313,6 +1355,12 @@ static void message(struct io_data *io_data, int messageid, int paramid, char *p
 					pga = numpgas();
 					pga = numpgas();
 					sprintf(buf, codes[i].description, paramid, pga - 1);
 					sprintf(buf, codes[i].description, paramid, pga - 1);
 					break;
 					break;
+#endif
+#ifdef HAVE_AN_ASIC
+				case PARAM_ASCMAX:
+					asc = numascs();
+					sprintf(buf, codes[i].description, paramid, asc - 1);
+					break;
 #endif
 #endif
 				case PARAM_PMAX:
 				case PARAM_PMAX:
 					sprintf(buf, codes[i].description, total_pools);
 					sprintf(buf, codes[i].description, total_pools);
@@ -1901,7 +1949,7 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char
 
 
 #ifdef USE_USBUTILS
 #ifdef USE_USBUTILS
 	if (cgpu->usbinfo.nodev) {
 	if (cgpu->usbinfo.nodev) {
-		message(io_data, MSG_USBNODEV, id, NULL, isjson);
+		message(io_data, MSG_PGAUSBNODEV, id, NULL, isjson);
 		return;
 		return;
 	}
 	}
 #endif
 #endif
@@ -3386,6 +3434,214 @@ static void dohotplug(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __ma
 #endif
 #endif
 }
 }
 
 
+#ifdef HAVE_AN_ASIC
+static void ascdev(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
+{
+	bool io_open = false;
+	int numasc = numascs();
+	int id;
+
+	if (numasc == 0) {
+		message(io_data, MSG_ASCNON, 0, NULL, isjson);
+		return;
+	}
+
+	if (param == NULL || *param == '\0') {
+		message(io_data, MSG_MISID, 0, NULL, isjson);
+		return;
+	}
+
+	id = atoi(param);
+	if (id < 0 || id >= numasc) {
+		message(io_data, MSG_INVASC, id, NULL, isjson);
+		return;
+	}
+
+	message(io_data, MSG_ASCDEV, id, NULL, isjson);
+
+	if (isjson)
+		io_open = io_add(io_data, COMSTR JSON_ASC);
+
+	ascstatus(io_data, id, isjson, false);
+
+	if (isjson && io_open)
+		io_close(io_data);
+}
+
+static void ascenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
+{
+	struct cgpu_info *cgpu;
+	int numasc = numascs();
+	struct thr_info *thr;
+	int asc;
+	int id;
+	int i;
+
+	if (numasc == 0) {
+		message(io_data, MSG_ASCNON, 0, NULL, isjson);
+		return;
+	}
+
+	if (param == NULL || *param == '\0') {
+		message(io_data, MSG_MISID, 0, NULL, isjson);
+		return;
+	}
+
+	id = atoi(param);
+	if (id < 0 || id >= numasc) {
+		message(io_data, MSG_INVASC, id, NULL, isjson);
+		return;
+	}
+
+	int dev = ascdevice(id);
+	if (dev < 0) { // Should never happen
+		message(io_data, MSG_INVASC, id, NULL, isjson);
+		return;
+	}
+
+	cgpu = get_devices(dev);
+
+	applog(LOG_DEBUG, "API: request to ascenable ascid %d device %d %s%u",
+			id, dev, cgpu->drv->name, cgpu->device_id);
+
+	if (cgpu->deven != DEV_DISABLED) {
+		message(io_data, MSG_ASCLRENA, id, NULL, isjson);
+		return;
+	}
+
+#if 0 /* A DISABLED device wont change status FIXME: should disabling make it WELL? */
+	if (cgpu->status != LIFE_WELL) {
+		message(io_data, MSG_ASCUNW, id, NULL, isjson);
+		return;
+	}
+#endif
+
+#ifdef USE_USBUTILS
+	if (cgpu->usbinfo.nodev) {
+		message(io_data, MSG_ASCUSBNODEV, id, NULL, isjson);
+		return;
+	}
+#endif
+
+	for (i = 0; i < mining_threads; i++) {
+		thr = get_thread(i);
+		asc = thr->cgpu->cgminer_id;
+		if (asc == dev) {
+			cgpu->deven = DEV_ENABLED;
+			applog(LOG_DEBUG, "API: Pushing sem post to thread %d", thr->id);
+			cgsem_post(&thr->sem);
+		}
+	}
+
+	message(io_data, MSG_ASCENA, id, NULL, isjson);
+}
+
+static void ascdisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
+{
+	struct cgpu_info *cgpu;
+	int numasc = numascs();
+	int id;
+
+	if (numasc == 0) {
+		message(io_data, MSG_ASCNON, 0, NULL, isjson);
+		return;
+	}
+
+	if (param == NULL || *param == '\0') {
+		message(io_data, MSG_MISID, 0, NULL, isjson);
+		return;
+	}
+
+	id = atoi(param);
+	if (id < 0 || id >= numasc) {
+		message(io_data, MSG_INVASC, id, NULL, isjson);
+		return;
+	}
+
+	int dev = ascdevice(id);
+	if (dev < 0) { // Should never happen
+		message(io_data, MSG_INVASC, id, NULL, isjson);
+		return;
+	}
+
+	cgpu = get_devices(dev);
+
+	applog(LOG_DEBUG, "API: request to ascdisable ascid %d device %d %s%u",
+			id, dev, cgpu->drv->name, cgpu->device_id);
+
+	if (cgpu->deven == DEV_DISABLED) {
+		message(io_data, MSG_ASCLRDIS, id, NULL, isjson);
+		return;
+	}
+
+	cgpu->deven = DEV_DISABLED;
+
+	message(io_data, MSG_ASCDIS, id, NULL, isjson);
+}
+
+static void ascidentify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
+{
+	struct cgpu_info *cgpu;
+	struct device_drv *drv;
+	int numasc = numascs();
+	int id;
+
+	if (numasc == 0) {
+		message(io_data, MSG_ASCNON, 0, NULL, isjson);
+		return;
+	}
+
+	if (param == NULL || *param == '\0') {
+		message(io_data, MSG_MISID, 0, NULL, isjson);
+		return;
+	}
+
+	id = atoi(param);
+	if (id < 0 || id >= numasc) {
+		message(io_data, MSG_INVASC, id, NULL, isjson);
+		return;
+	}
+
+	int dev = ascdevice(id);
+	if (dev < 0) { // Should never happen
+		message(io_data, MSG_INVASC, id, NULL, isjson);
+		return;
+	}
+
+	cgpu = get_devices(dev);
+	drv = cgpu->drv;
+
+	if (!drv->identify_device)
+		message(io_data, MSG_ASCNOID, id, NULL, isjson);
+	else {
+		drv->identify_device(cgpu);
+		message(io_data, MSG_ASCIDENT, id, NULL, isjson);
+	}
+}
+#endif
+
+static void asccount(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
+{
+	struct api_data *root = NULL;
+	char buf[TMPBUFSIZ];
+	bool io_open;
+	int count = 0;
+
+#ifdef HAVE_AN_ASIC
+	count = numascs();
+#endif
+
+	message(io_data, MSG_NUMASC, 0, NULL, isjson);
+	io_open = io_add(io_data, isjson ? COMSTR JSON_ASCS : _ASCS COMSTR);
+
+	root = api_add_int(root, "Count", &count, false);
+
+	root = print_data(root, buf, isjson, false);
+	io_add(io_data, buf);
+	if (isjson && io_open)
+		io_close(io_data);
+}
+
 static void checkcommand(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, char group);
 static void checkcommand(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, char group);
 
 
 struct CMDS {
 struct CMDS {
@@ -3443,6 +3699,13 @@ struct CMDS {
 #endif
 #endif
 	{ "zero",		dozero,		true },
 	{ "zero",		dozero,		true },
 	{ "hotplug",		dohotplug,	true },
 	{ "hotplug",		dohotplug,	true },
+#ifdef HAVE_AN_ASIC
+	{ "asc",		ascdev,		false },
+	{ "ascenable",		ascenable,	true },
+	{ "ascdisable",		ascdisable,	true },
+	{ "ascidentify",	ascidentify,	true },
+#endif
+	{ "asccount",		asccount,	false },
 	{ NULL,			NULL,		false }
 	{ NULL,			NULL,		false }
 };
 };