more changes on original files
[linux-2.4.git] / arch / ppc64 / kernel / flight_recorder.c
1 /************************************************************************
2  * flight_recorder.c
3  ************************************************************************
4  * This code supports the a generic flight recorder.                    *
5  * Copyright (C) 20yy  <Allan H Trautman> <IBM Corp>                    * 
6  *                                                                      *
7  * This program is free software; you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation; either version 2 of the License, or    *
10  * (at your option) any later version.                                  *
11  *                                                                      *
12  * This program is distributed in the hope that it will be useful,      * 
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
15  * GNU General Public License for more details.                         *
16  *                                                                      *
17  * You should have received a copy of the GNU General Public License    * 
18  * along with this program; if not, write to the:                       *
19  * Free Software Foundation, Inc.,                                      * 
20  * 59 Temple Place, Suite 330,                                          * 
21  * Boston, MA  02111-1307  USA                                          *
22  ************************************************************************
23  * This is a simple text based flight recorder.  Useful for logging 
24  * information the you may want to retreive at a latter time.  Errors or 
25  * debug inforamtion are good examples.   A good method to dump the 
26  * information is via the proc file system. 
27  *
28  * To use. 
29  * 1. Create the flight recorder object.  Passing a NULL pointer will 
30  *    kmalloc the space for you.  If it is too early for kmalloc, create 
31  *    space for the object.   Beware, don't lie about the size, you will
32  *    pay for that later. 
33  *              FlightRecorder* TestFr = alloc_Flight_Recorder(NULL,"TestFr",4096);
34  *   
35  * 2. Log any notable events, initialzation, error conditions, etc. 
36  *              LOGFR(TestFr,"5. Stack Variable(10) %d",StackVariable);
37  * 
38  * 3. Dump the information to a buffer. 
39  *              fr_Dump(TestFr, proc_file_buffer, proc_file_buffer_size);
40  *
41  ************************************************************************/
42 #include <stdarg.h>
43 #include <linux/kernel.h>
44 #include <linux/rtc.h>
45 #include <linux/slab.h>
46 #include <asm/string.h>
47 #include <asm/time.h>
48 #include <asm/flight_recorder.h>
49
50 static  char       LogText[512];
51 static  int        LogTextIndex;
52 static  int        LogCount = 0;
53 static  spinlock_t Fr_Lock;
54
55 /************************************************************************
56  * Build the log time prefix based on Flags.
57  *  00 = No time prefix
58  *  01 = Date(mmddyy) Time(hhmmss) prefix
59  *  02 = Day(dd) Time(hhmmss) prefix
60  *  03 = Time(hhmmss) prefix
61  ************************************************************************/
62 static void fr_Log_Time(FlightRecorder* Fr)
63 {
64         struct  timeval  TimeClock;
65         struct  rtc_time LogTime;
66
67         do_gettimeofday(&TimeClock);
68         to_tm(TimeClock.tv_sec, &LogTime);
69
70         if (Fr->Flags == 1) {    
71                 LogTextIndex = sprintf(LogText,"%02d%02d%02d %02d%02d%02d ",
72                                        LogTime.tm_mon, LogTime.tm_mday, LogTime.tm_year-2000,
73                                   LogTime.tm_hour,LogTime.tm_min, LogTime.tm_sec);
74         }
75         else if (Fr->Flags == 2) {    
76                 LogTextIndex = sprintf(LogText,"%02d %02d%02d%02d ",
77                                        LogTime.tm_mday,
78                                   LogTime.tm_hour,LogTime.tm_min, LogTime.tm_sec);
79         }
80
81         else if (Fr->Flags == 3) {    
82                 LogTextIndex = sprintf(LogText,"%02d%02d%02d ",
83                                   LogTime.tm_hour,LogTime.tm_min, LogTime.tm_sec);
84         }
85         else {
86                 ++LogCount;
87                 LogTextIndex = sprintf(LogText,"%04d. ",LogCount);
88         }
89 }
90
91 /************************************************************************/
92 /* Log entry into buffer,                                               */
93 /* ->If entry is going to wrap, log "WRAP" and start at the top.        */
94 /************************************************************************/
95 static void fr_Log_Data(FlightRecorder* Fr)
96 {
97         int     TextLen  = strlen(LogText);
98         int     Residual = ( Fr->EndPointer - Fr->NextPointer)-15;
99         if (TextLen > Residual) {
100                 strcpy(Fr->NextPointer,"WRAP");
101                 Fr->WrapPointer = Fr->NextPointer + 5;
102                 Fr->NextPointer = Fr->StartPointer;
103         }
104         strcpy(Fr->NextPointer,LogText);
105         Fr->NextPointer += TextLen+1;
106         strcpy(Fr->NextPointer,"<=");
107 }
108 /************************************************************************
109  * Build the log text, support variable args.
110  ************************************************************************/
111 void fr_Log_Entry(struct flightRecorder* LogFr, const char *fmt, ...)
112 {
113         va_list arg_ptr;
114         spin_lock(&Fr_Lock);
115
116         fr_Log_Time(LogFr); 
117         va_start(arg_ptr, fmt);
118         vsprintf(LogText+LogTextIndex, fmt, arg_ptr);
119         va_end(arg_ptr);
120         fr_Log_Data(LogFr);
121
122         spin_unlock(&Fr_Lock);
123
124 }
125 /************************************************************************
126  * Dump Flight Recorder into buffer.
127  * -> Handles the buffer wrapping.
128  ************************************************************************/
129 int fr_Dump(FlightRecorder* Fr, char *Buffer, int BufferLen)
130 {
131         int   LineLen = 0;
132         char* StartEntry;
133         char* EndEntry;
134         spin_lock(&Fr_Lock);
135         /****************************************************************
136          * If Buffer has wrapped, find last usable entry to start with.
137          ****************************************************************/
138         if (Fr->WrapPointer != NULL) {
139                 StartEntry  = Fr->NextPointer+3;
140                 StartEntry += strlen(StartEntry)+1;
141                 EndEntry    = Fr->WrapPointer;
142
143                 while (EndEntry > StartEntry && LineLen < BufferLen) {
144                         LineLen    += sprintf(Buffer+LineLen,"%s\n",StartEntry);
145                         StartEntry += strlen(StartEntry) + 1;
146                 }
147         }
148
149         /****************************************************************
150          * Dump from the beginning to the last logged entry
151          ****************************************************************/
152         StartEntry = Fr->StartPointer;
153         EndEntry   = Fr->NextPointer;
154         while (EndEntry > StartEntry && LineLen < BufferLen) {
155                 LineLen    += sprintf(Buffer+LineLen,"%s\n",StartEntry);
156                 StartEntry += strlen(StartEntry) + 1;
157         }
158         spin_unlock(&Fr_Lock);
159         return LineLen;
160 }
161
162 /************************************************************************
163  * Allocate and Initialized the Flight Recorder
164  * -> If no FlightRecorder pointer is passed, the space is kmalloc.
165  ************************************************************************/
166 FlightRecorder* alloc_Flight_Recorder(FlightRecorder* FrPtr, char* Signature, int SizeOfFr)
167 {
168         FlightRecorder* Fr     = FrPtr;                         /* Pointer to Object */
169         int             FrSize = (SizeOfFr/16)*16;      /* Could be static   */
170         if (Fr == NULL)
171                 Fr = (FlightRecorder*)kmalloc(SizeOfFr, GFP_KERNEL);
172         memset(Fr,0,SizeOfFr);
173         strcpy(Fr->Signature,Signature);
174         Fr->Size         = FrSize;
175         Fr->Flags        = 0;
176         Fr->StartPointer = (char*)&Fr->Buffer;
177         Fr->EndPointer   = (char*)Fr + Fr->Size;
178         Fr->NextPointer  = Fr->StartPointer;
179
180         fr_Log_Entry(Fr,"Initialized.");
181         return Fr;
182 }