1235537Sgber/*- 2235537Sgber * Copyright (C) 2009-2012 Semihalf 3235537Sgber * All rights reserved. 4235537Sgber * 5235537Sgber * Redistribution and use in source and binary forms, with or without 6235537Sgber * modification, are permitted provided that the following conditions 7235537Sgber * are met: 8235537Sgber * 1. Redistributions of source code must retain the above copyright 9235537Sgber * notice, this list of conditions and the following disclaimer. 10235537Sgber * 2. Redistributions in binary form must reproduce the above copyright 11235537Sgber * notice, this list of conditions and the following disclaimer in the 12235537Sgber * documentation and/or other materials provided with the distribution. 13235537Sgber * 14235537Sgber * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15235537Sgber * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16235537Sgber * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17235537Sgber * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18235537Sgber * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19235537Sgber * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20235537Sgber * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21235537Sgber * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22235537Sgber * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23235537Sgber * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24235537Sgber * SUCH DAMAGE. 25235537Sgber */ 26235537Sgber 27235537Sgber#include <sys/cdefs.h> 28235537Sgber__FBSDID("$FreeBSD$"); 29235537Sgber 30235537Sgber#include <sys/param.h> 31235537Sgber#include <sys/systm.h> 32235537Sgber#include <sys/kernel.h> 33235537Sgber#include <sys/module.h> 34235537Sgber#include <sys/malloc.h> 35235537Sgber#include <sys/proc.h> 36235537Sgber#include <sys/alq.h> 37235537Sgber#include <sys/time.h> 38235537Sgber 39235537Sgber#include <machine/stdarg.h> 40235537Sgber 41235537Sgber#include <dev/nand/nandsim_log.h> 42235537Sgber 43235537Sgberint nandsim_log_level; 44235537Sgberint nandsim_log_output; 45235537Sgberint log_size = NANDSIM_RAM_LOG_SIZE; 46235537Sgber 47235537Sgberstatic int nandsim_entry_size = NANDSIM_ENTRY_SIZE; 48235537Sgberstatic int nandsim_entry_count = NANDSIM_ENTRY_COUNT; 49235537Sgberstatic int str_index = 0; 50235537Sgberstatic char string[NANDSIM_ENTRY_SIZE + 1] = {0}; 51235537Sgber 52235537Sgberint 53235537Sgbernandsim_log_init(struct nandsim_softc *sc, char *filename) 54235537Sgber{ 55235537Sgber int error = 0; 56235537Sgber 57235537Sgber if (nandsim_log_output == NANDSIM_OUTPUT_FILE) { 58235537Sgber error = alq_open(&sc->alq, filename, 59235537Sgber curthread->td_ucred, 0644, 60235537Sgber nandsim_entry_size, nandsim_entry_count); 61235537Sgber } else if (nandsim_log_output == NANDSIM_OUTPUT_RAM) { 62235537Sgber sc->log_buff = malloc(log_size, M_NANDSIM, M_WAITOK | M_ZERO); 63235537Sgber if (!sc->log_buff) 64235537Sgber error = ENOMEM; 65235537Sgber } 66235537Sgber 67235537Sgber return (error); 68235537Sgber} 69235537Sgber 70235537Sgbervoid 71235537Sgbernandsim_log_close(struct nandsim_softc *sc) 72235537Sgber{ 73235537Sgber 74235537Sgber if (nandsim_log_output == NANDSIM_OUTPUT_FILE) { 75235537Sgber memset(&string[str_index], 0, NANDSIM_ENTRY_SIZE - str_index); 76235537Sgber alq_write(sc->alq, (void *) string, ALQ_NOWAIT); 77235537Sgber str_index = 0; 78235537Sgber string[0] = '\0'; 79235537Sgber alq_close(sc->alq); 80235537Sgber } else if (nandsim_log_output == NANDSIM_OUTPUT_RAM) { 81235537Sgber free(sc->log_buff, M_NANDSIM); 82235537Sgber sc->log_buff = NULL; 83235537Sgber } 84235537Sgber} 85235537Sgber 86235537Sgbervoid 87235537Sgbernandsim_log(struct nandsim_chip *chip, int level, const char *fmt, ...) 88235537Sgber{ 89235537Sgber char hdr[TIME_STR_SIZE]; 90235537Sgber char tmp[NANDSIM_ENTRY_SIZE]; 91235537Sgber struct nandsim_softc *sc; 92235537Sgber struct timeval currtime; 93235537Sgber va_list ap; 94235537Sgber int hdr_len, len, rest; 95235537Sgber 96235537Sgber if (nandsim_log_output == NANDSIM_OUTPUT_NONE) 97235537Sgber return; 98235537Sgber 99235537Sgber if (chip == NULL) 100235537Sgber return; 101235537Sgber 102235537Sgber sc = chip->sc; 103235537Sgber if (!sc->alq && nandsim_log_output == NANDSIM_OUTPUT_FILE) 104235537Sgber return; 105235537Sgber 106235537Sgber if (level <= nandsim_log_level) { 107235537Sgber microtime(&currtime); 108235537Sgber hdr_len = sprintf(hdr, "%08jd.%08li [chip:%d, ctrl:%d]: ", 109235537Sgber (intmax_t)currtime.tv_sec, currtime.tv_usec, 110235537Sgber chip->chip_num, chip->ctrl_num); 111235537Sgber 112235537Sgber switch(nandsim_log_output) { 113235537Sgber case NANDSIM_OUTPUT_CONSOLE: 114235537Sgber printf("%s", hdr); 115235537Sgber va_start(ap, fmt); 116235537Sgber vprintf(fmt, ap); 117235537Sgber va_end(ap); 118235537Sgber break; 119235537Sgber case NANDSIM_OUTPUT_RAM: 120235537Sgber va_start(ap, fmt); 121235537Sgber len = vsnprintf(tmp, NANDSIM_ENTRY_SIZE - 1, fmt, ap); 122235537Sgber tmp[NANDSIM_ENTRY_SIZE - 1] = 0; 123235537Sgber va_end(ap); 124235537Sgber 125235537Sgber rest = log_size - sc->log_idx - 1; 126235537Sgber if (rest >= hdr_len) { 127235537Sgber bcopy(hdr, &sc->log_buff[sc->log_idx], 128235537Sgber hdr_len); 129235537Sgber sc->log_idx += hdr_len; 130235537Sgber sc->log_buff[sc->log_idx] = 0; 131235537Sgber } else { 132235537Sgber bcopy(hdr, &sc->log_buff[sc->log_idx], rest); 133235537Sgber bcopy(&hdr[rest], sc->log_buff, 134235537Sgber hdr_len - rest); 135235537Sgber sc->log_idx = hdr_len - rest; 136235537Sgber sc->log_buff[sc->log_idx] = 0; 137235537Sgber } 138235537Sgber 139235537Sgber rest = log_size - sc->log_idx - 1; 140235537Sgber if (rest >= len) { 141235537Sgber bcopy(tmp, &sc->log_buff[sc->log_idx], len); 142235537Sgber sc->log_idx += len; 143235537Sgber sc->log_buff[sc->log_idx] = 0; 144235537Sgber } else { 145235537Sgber bcopy(tmp, &sc->log_buff[sc->log_idx], rest); 146235537Sgber bcopy(&tmp[rest], sc->log_buff, len - rest); 147235537Sgber sc->log_idx = len - rest; 148235537Sgber sc->log_buff[sc->log_idx] = 0; 149235537Sgber } 150235537Sgber 151235537Sgber break; 152235537Sgber 153235537Sgber case NANDSIM_OUTPUT_FILE: 154235537Sgber va_start(ap, fmt); 155235537Sgber len = vsnprintf(tmp, NANDSIM_ENTRY_SIZE - 1, fmt, ap); 156235537Sgber tmp[NANDSIM_ENTRY_SIZE - 1] = 0; 157235537Sgber va_end(ap); 158235537Sgber 159235537Sgber rest = NANDSIM_ENTRY_SIZE - str_index; 160235537Sgber if (rest >= hdr_len) { 161235537Sgber strcat(string, hdr); 162235537Sgber str_index += hdr_len; 163235537Sgber } else { 164235537Sgber strlcat(string, hdr, NANDSIM_ENTRY_SIZE + 1); 165235537Sgber alq_write(sc->alq, (void *) string, 166235537Sgber ALQ_NOWAIT); 167235537Sgber strcpy(string, &hdr[rest]); 168235537Sgber str_index = hdr_len - rest; 169235537Sgber } 170235537Sgber rest = NANDSIM_ENTRY_SIZE - str_index; 171235537Sgber if (rest >= len) { 172235537Sgber strcat(string, tmp); 173235537Sgber str_index += len; 174235537Sgber } else { 175235537Sgber strlcat(string, tmp, NANDSIM_ENTRY_SIZE + 1); 176235537Sgber alq_write(sc->alq, (void *) string, 177235537Sgber ALQ_NOWAIT); 178235537Sgber strcpy(string, &tmp[rest]); 179235537Sgber str_index = len - rest; 180235537Sgber } 181235537Sgber break; 182235537Sgber default: 183235537Sgber break; 184235537Sgber } 185235537Sgber } 186235537Sgber} 187