#include "smartpqi_includes.h"
void
os_get_time(struct bmic_host_wellness_time *host_wellness_time)
{
struct timespec ts;
struct clocktime ct = {0};
getnanotime(&ts);
clock_ts_to_ct(&ts, &ct);
host_wellness_time->hour= (uint8_t)bin2bcd(ct.hour);
host_wellness_time->min = (uint8_t)bin2bcd(ct.min);
host_wellness_time->sec= (uint8_t)bin2bcd(ct.sec);
host_wellness_time->reserved = 0;
host_wellness_time->month = (uint8_t)bin2bcd(ct.mon);
host_wellness_time->day = (uint8_t)bin2bcd(ct.day);
host_wellness_time->century = (uint8_t)bin2bcd(ct.year / 100);
host_wellness_time->year = (uint8_t)bin2bcd(ct.year % 100);
}
void
os_wellness_periodic(void *data)
{
struct pqisrc_softstate *softs = (struct pqisrc_softstate *)data;
int ret;
if (!pqisrc_ctrl_offline(softs)){
if( (ret = pqisrc_write_current_time_to_host_wellness(softs)) != 0 )
DBG_ERR("Failed to update time to FW in periodic ret = %d\n", ret);
}
callout_reset(&softs->os_specific.wellness_periodic,
PQI_HOST_WELLNESS_TIMEOUT_SEC * hz, os_wellness_periodic, softs);
}
void
os_stop_heartbeat_timer(pqisrc_softstate_t *softs)
{
DBG_FUNC("IN\n");
callout_stop(&softs->os_specific.heartbeat_timeout_id);
DBG_FUNC("OUT\n");
}
void
os_start_heartbeat_timer(void *data)
{
struct pqisrc_softstate *softs = (struct pqisrc_softstate *)data;
DBG_FUNC("IN\n");
pqisrc_heartbeat_timer_handler(softs);
if (!pqisrc_ctrl_offline(softs)) {
callout_reset(&softs->os_specific.heartbeat_timeout_id,
PQI_HEARTBEAT_TIMEOUT_SEC * hz,
os_start_heartbeat_timer, softs);
}
DBG_FUNC("OUT\n");
}
int
os_init_spinlock(struct pqisrc_softstate *softs, struct mtx *lock,
char *lockname)
{
mtx_init(lock, lockname, NULL, MTX_SPIN);
return 0;
}
void
os_uninit_spinlock(struct mtx *lock)
{
mtx_destroy(lock);
return;
}
int
os_create_semaphore(const char *name, int value, struct sema *sema)
{
sema_init(sema, value, name);
return PQI_STATUS_SUCCESS;
}
int
os_destroy_semaphore(struct sema *sema)
{
sema_destroy(sema);
return PQI_STATUS_SUCCESS;
}
void inline
os_sema_lock(struct sema *sema)
{
sema_post(sema);
}
void inline
os_sema_unlock(struct sema *sema)
{
sema_wait(sema);
}
int
os_strlcpy(char *dst, char *src, int size)
{
return strlcpy(dst, src, size);
}
int
bsd_status_to_pqi_status(int bsd_status)
{
if (bsd_status == BSD_SUCCESS)
return PQI_STATUS_SUCCESS;
else
return PQI_STATUS_FAILURE;
}
boolean_t
check_device_hint_status(struct pqisrc_softstate *softs, unsigned int feature_bit)
{
DBG_FUNC("IN\n");
switch(feature_bit) {
case PQI_FIRMWARE_FEATURE_RAID_1_WRITE_BYPASS:
if (!softs->hint.aio_raid1_write_status)
return true;
break;
case PQI_FIRMWARE_FEATURE_RAID_5_WRITE_BYPASS:
if (!softs->hint.aio_raid5_write_status)
return true;
break;
case PQI_FIRMWARE_FEATURE_RAID_6_WRITE_BYPASS:
if (!softs->hint.aio_raid6_write_status)
return true;
break;
case PQI_FIRMWARE_FEATURE_UNIQUE_SATA_WWN:
if (!softs->hint.sata_unique_wwn_status)
return true;
break;
default:
return false;
}
DBG_FUNC("OUT\n");
return false;
}
static void
bsd_set_hint_adapter_queue_depth(struct pqisrc_softstate *softs)
{
uint32_t queue_depth = softs->pqi_cap.max_outstanding_io;
DBG_FUNC("IN\n");
if ((!softs->hint.queue_depth) || (softs->hint.queue_depth >
softs->pqi_cap.max_outstanding_io)) {
}
else if (softs->hint.queue_depth < PQISRC_MIN_OUTSTANDING_REQ) {
}
else {
softs->pqi_cap.max_outstanding_io =
softs->hint.queue_depth;
}
DBG_NOTE("Adapter queue depth before hint set = %u, Queue depth after hint set = %u\n",
queue_depth, softs->pqi_cap.max_outstanding_io);
DBG_FUNC("OUT\n");
}
static void
bsd_set_hint_scatter_gather_config(struct pqisrc_softstate *softs)
{
uint32_t pqi_sg_segments = softs->pqi_cap.max_sg_elem;
DBG_FUNC("IN\n");
if ((!softs->hint.sg_segments) || (softs->hint.sg_segments >
softs->pqi_cap.max_sg_elem)) {
}
else if (softs->hint.sg_segments < BSD_MIN_SG_SEGMENTS)
{
}
else {
softs->pqi_cap.max_sg_elem = softs->hint.sg_segments;
}
DBG_NOTE("SG segments before hint set = %u, SG segments after hint set = %u\n",
pqi_sg_segments, softs->pqi_cap.max_sg_elem);
DBG_FUNC("OUT\n");
}
void
bsd_set_hint_adapter_cap(struct pqisrc_softstate *softs)
{
DBG_FUNC("IN\n");
bsd_set_hint_adapter_queue_depth(softs);
bsd_set_hint_scatter_gather_config(softs);
DBG_FUNC("OUT\n");
}