text: /*
   * Copyright 2015, International Business Machines
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  /*
   * Specialized DDCB execution implementation.
   */
  
  #include <stdint.h>
  #include <stdbool.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <ctype.h>
  #include <unistd.h>
  #include <errno.h>
  #include <malloc.h>
  #include <time.h>
  #include <limits.h>
  #include <fcntl.h>
  #include <signal.h>
  #include <pthread.h>
  #include <semaphore.h>
  
  #include <sys/ioctl.h>
  #include <sys/mman.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <sys/socket.h>
  #include <asm/byteorder.h>
  #include <sys/time.h>
  #include <sys/resource.h>
  #include <dirent.h>
  
  #include <libddcb.h>		/* outside interface */
  #include <libcard.h>		/* internal implementation */
  
  static void *card_open(int card_no, unsigned int mode, int *card_rc,
  		       uint64_t appl_id, uint64_t appl_id_mask)
  {
  	return genwqe_card_open(card_no, mode, card_rc, appl_id, appl_id_mask);
  }
  
  static int card_close(void *card_data)
  {
  	return genwqe_card_close(card_data);
  }
  
  static int ddcb_execute(void *card_data, struct ddcb_cmd *req)
  {
  	return genwqe_card_execute_ddcb(card_data,
  					(struct genwqe_ddcb_cmd *)req);
  }
  
  static const char *_card_strerror(void *card_data __attribute__((unused)),
  				  int card_rc)
  {
  	return card_strerror(card_rc);
  }
  
  static uint64_t card_read_reg64(void *card_data, uint32_t offs,
  			     int *card_rc)
  {
  	return genwqe_card_read_reg64(card_data, offs, card_rc);
  }
  
  static uint32_t card_read_reg32(void *card_data, uint32_t offs,
  			     int *card_rc)
  {
  	return genwqe_card_read_reg32(card_data, offs, card_rc);
  }
  
  static int card_write_reg64(void *card_data, uint32_t offs,
  			 uint64_t val)
  {
  	return genwqe_card_write_reg64(card_data, offs, val);
  }
  
  static int card_write_reg32(void *card_data, uint32_t offs, uint32_t val)
  {
  	return genwqe_card_write_reg32(card_data, offs, val);
  }
  
  static uint64_t _card_get_app_id(void *card_data)
  {
  	return card_get_app_id(card_data);
  }
  
  static uint64_t _card_get_frequency(void *card_data)
  {
  	uint16_t speed; /*		   MHz	MHz  MHz  MHz */
  	static const int speed_grade[] = { 250, 200, 166, 175 };
  	uint64_t slu_unitcfg;
  
  	slu_unitcfg = card_read_reg64(card_data, IO_SLU_UNITCFG, NULL);
  	speed = (uint16_t)((slu_unitcfg >> 28) & 0x0full);
  	if (speed >= ARRAY_SIZE(speed_grade))
  		return 0;       /* illegal value */
  
  	return speed_grade[speed] * 1000000;  /* in Hz */
  }
  
  static void card_dump_hardware_version(void *card_data, FILE *fp)
  {
  	uint64_t slu_unitcfg;
  	uint64_t app_unitcfg;
  
  	slu_unitcfg = card_read_reg64(card_data, IO_SLU_UNITCFG, NULL);
  	app_unitcfg = card_read_reg64(card_data, IO_APP_UNITCFG, NULL);
  
  	fprintf(fp,
  		" Version Reg:        0x%016llx\n"
  		" Appl. Reg:          0x%016llx\n",
  		(long long)slu_unitcfg, (long long)app_unitcfg);
  }
  
  /**
   * Special formular is required to get the right time for our GenWQE
   * implementation.
   */
  static uint64_t _card_get_queue_work_time(void *card_data)
  {
  	uint64_t queue_wtime;
  
  	queue_wtime = card_read_reg64(card_data, IO_SLC_QUEUE_WTIME, NULL);
  	return queue_wtime * 8;
  }
  
  static int card_pin_memory(void *card_data, const void *addr, size_t size,
  			   int dir)
  {
  	return genwqe_pin_memory(card_data, addr, size, dir);
  }
  
  static int card_unpin_memory(void *card_data, const void *addr, size_t size)
  {
  	return genwqe_unpin_memory(card_data, addr, size);
  }
  
  static void *card_malloc(void *card_data, size_t size)
  {
  	return genwqe_card_malloc(card_data, size);
  }
  
  static int card_free(void *card_data, void *ptr, size_t size)
  {
  	return genwqe_card_free(card_data, ptr, size);
  }
  
  static int _card_dump_statistics(FILE *fp)
  {
  	return genwqe_dump_statistics(fp);
  }
  
  static struct ddcb_accel_funcs accel_funcs = {
  	.card_type = DDCB_TYPE_GENWQE,
  	.card_name = "GENWQE",
  
  	/* functions */
  	.card_open = card_open,
  	.card_close = card_close,
  	.ddcb_execute = ddcb_execute,
  	.card_strerror = _card_strerror,
  	.card_read_reg64 = card_read_reg64,
  	.card_read_reg32 = card_read_reg32,
  	.card_write_reg64 = card_write_reg64,
  	.card_write_reg32 = card_write_reg32,
  	.card_get_app_id = _card_get_app_id,
  	.card_get_queue_work_time = _card_get_queue_work_time,
  	.card_get_frequency = _card_get_frequency,
  	.card_dump_hardware_version = card_dump_hardware_version,
  	.card_pin_memory = card_pin_memory,
  	.card_unpin_memory = card_unpin_memory,
  	.card_malloc = card_malloc,
  	.card_free = card_free,
  
  	/* statistics */
  	.dump_statistics = _card_dump_statistics,
  	.num_open = 0,
  	.num_close = 0,
  	.num_execute = 0,
  	.time_open = 0,
  	.time_execute = 0,
  	.time_close = 0,
  
  	.priv_data = NULL,
  };
  
  static void genwqe_card_init(void) __attribute__((constructor));
  
  /* constructor */
  static void genwqe_card_init(void)
  {
  	ddcb_register_accelerator(&accel_funcs);
  }
  