1/*
2 *	SiS 190/191 NIC Driver.
3 *	Copyright (c) 2009 S.Zharski <imker@gmx.li>
4 *	Distributed under the terms of the MIT license.
5 *
6 */
7
8
9#include "Settings.h"
10
11#include <stdlib.h>
12#include <stdio.h>
13#include <string.h>
14
15#include <lock.h> // for mutex
16
17
18bool gTraceOn = false;
19bool gTruncateLogFile = false;
20bool gTraceFlow = false;
21bool gAddTimeStamp = true;
22static char *gLogFilePath = NULL;
23
24mutex gLogLock;
25
26
27//
28//	Logging, tracing and settings
29//
30
31static
32void create_log()
33{
34	if (gLogFilePath == NULL)
35		return;
36
37	int flags = O_WRONLY | O_CREAT | ((gTruncateLogFile) ? O_TRUNC : 0);
38	int fd = open(gLogFilePath, flags, 0666);
39	if (fd >= 0)
40		close(fd);
41
42	mutex_init(&gLogLock, DRIVER_NAME"-logging");
43}
44
45
46void load_settings()
47{
48	void *handle = load_driver_settings(DRIVER_NAME);
49	if (handle == 0)
50		return;
51
52	gTraceOn = get_driver_boolean_parameter(
53			handle, "trace", gTraceOn, true);
54
55	gTruncateLogFile = get_driver_boolean_parameter(
56			handle,	"truncate_logfile", gTruncateLogFile, true);
57
58	gTraceFlow = get_driver_boolean_parameter(
59			handle, "trace_flow", gTraceFlow, true);
60
61	gAddTimeStamp = get_driver_boolean_parameter(
62			handle, "add_timestamp", gAddTimeStamp, true);
63
64	const char * logFilePath = get_driver_parameter(
65			handle, "logfile", NULL, "/var/log/"DRIVER_NAME".log");
66	if (logFilePath != NULL) {
67		gLogFilePath = strdup(logFilePath);
68	}
69
70	unload_driver_settings(handle);
71
72	create_log();
73}
74
75
76void release_settings()
77{
78	if (gLogFilePath != NULL) {
79		mutex_destroy(&gLogLock);
80		free(gLogFilePath);
81	}
82}
83
84
85void SiS19X_trace(bool force, const char* func, const char *fmt, ...)
86{
87	if (!(force || gTraceOn)) {
88		return;
89	}
90
91	va_list arg_list;
92	static const char *prefix = DRIVER_NAME":";
93	static char buffer[1024];
94	char *buf_ptr = buffer;
95	if (gLogFilePath == NULL) {
96		strlcpy(buffer, prefix, sizeof(buffer));
97		buf_ptr += strlen(prefix);
98	}
99
100	if (gAddTimeStamp) {
101		bigtime_t time = system_time();
102		uint32 msec = time / 1000;
103		uint32 sec  = msec / 1000;
104		sprintf(buf_ptr, "%02" B_PRId32 ".%02" B_PRId32 ".%03" B_PRId32 ":",
105			sec / 60, sec % 60, msec % 1000);
106		buf_ptr += strlen(buf_ptr);
107	}
108
109	if (func	!= NULL) {
110		sprintf(buf_ptr, "%s::", func);
111		buf_ptr += strlen(buf_ptr);
112	}
113
114	va_start(arg_list, fmt);
115	vsprintf(buf_ptr, fmt, arg_list);
116	va_end(arg_list);
117
118	if (gLogFilePath == NULL) {
119		dprintf(buffer);
120		return;
121	}
122
123	mutex_lock(&gLogLock);
124	int fd = open(gLogFilePath, O_WRONLY | O_APPEND);
125	if (fd >= 0) {
126		write(fd, buffer, strlen(buffer));
127		close(fd);
128	}
129	mutex_unlock(&gLogLock);
130}
131
132
133//
134//	Rx/Tx traffic statistic harvesting
135//
136
137Statistics::Statistics()
138{
139	memset(this, 0, sizeof(Statistics));
140}
141
142
143void
144Statistics::PutStatus(uint32 status)
145{
146	fInterrupts++;
147	if (status & (INT_TXDONE /*| INT_TXIDLE*/)) fTxInterrupts++;
148	if (status & (INT_RXDONE /*| INT_RXIDLE*/)) fRxInterrupts++;
149
150	if (status & INT_TXHALT)	fTxHalt++;
151	if (status & INT_RXHALT)	fRxHalt++;
152	if (status & INT_TXDONE)	fTxDone++;
153	if (status & INT_TXIDLE)	fTxIdle++;
154	if (status & INT_RXDONE)	fRxDone++;
155	if (status & INT_RXIDLE)	fRxIdle++;
156	if (status & INT_LINK)		fLink++;
157	if (status & INT_WAKEF)		fWakeUp++;
158	if (status & INT_MAGICP)	fMagic++;
159	if (status & INT_PAUSEF)	fPause++;
160	if (status & INT_TIMER)		fTimer++;
161	if (status & INT_SOFT)		fSoft++;
162}
163
164
165void
166Statistics::PutTxStatus(uint32 status, uint32 size)
167{
168	if (status & TDS_CRS)	fCarrier++;
169	if (status & TDS_FIFO)	fFIFO++;
170	if (status & TDS_ABT)	fTxAbort++;
171	if (status & TDS_OWC)	fWindow++;
172	if ((status & txErrorStatusBits) == 0) {
173		fCollisions += (status & TDS_COLLS) - 1;
174		fTransmitted += (size & TxDescriptorSize);
175	}
176}
177
178
179void
180Statistics::PutRxStatus(uint32 status)
181{
182	if (!(status & RDS_CRCOK)) fCRC++;
183	if (status & RDS_COLON) fColon++;
184	if (status & RDS_NIBON) fNibon++;
185	if (status & RDS_OVRUN) fOverrun++;
186	if (status & RDS_MIIER) fMIIError++;
187	if (status & RDS_LIMIT) fLimit++;
188	if (status & RDS_SHORT) fShort++;
189	if (status & RDS_ABORT) fRxAbort++;
190	if ((status & rxErrorStatusBits) == 0) {
191		fReceived += (status & RDS_SIZE) - 4; // exclude CRC?
192	}
193}
194
195
196void Statistics::Trace()
197{
198	TRACE("Ints:%d;Lnk:%d;WkUps:%d;Mgic:%d;Pause:%d;Tmr:%d;Sft:%d\n",
199			fInterrupts, fLink, fWakeUp, fMagic, fPause, fTimer, fSoft);
200
201	TRACE("TX:Ints:%d;Bts:%llu;Drop:%d;Hlts:%d;Done:%d;Idle:%d;"
202		"Colls:%d;Carr:%d;FIFO:%d;Abrt:%d;Wndw:%d;\n",
203			fTxInterrupts, fTransmitted, fDropped, fTxHalt, fTxDone,
204			fTxIdle, fCollisions, fCarrier, fFIFO, fTxAbort, fWindow);
205
206	TRACE("RX:Ints:%d;Bts:%llu;Hlts:%d;Done:%d;Idle:%d;CRC:%d;Cln:%d;"
207		"Nibon:%d;Ovrrn:%d;MIIErr:%d;Lmt:%d;Shrt:%d;Abrt:%d\n",
208			fRxInterrupts, fReceived, fRxHalt, fRxDone, fRxIdle, fCRC, fColon,
209			fNibon, fOverrun, fMIIError, fLimit, fShort, fRxAbort);
210}
211
212