make oldconfig will rebuild these...
[linux-2.4.21-pre4.git] / drivers / scsi / eata_dma_proc.c
1 void swap_statistics(u8 *p)
2 {
3     u32 y;
4     u32 *lp, h_lp;
5     u16 *sp, h_sp;
6     u8 *bp;
7     
8     lp = (u32 *)p;
9     sp = ((short *)lp) + 1;         /* Convert Header */
10     h_sp = *sp = ntohs(*sp);
11     lp++;
12
13     do {
14         sp = (u16 *)lp;           /* Convert SubHeader */
15         *sp = ntohs(*sp);
16         bp = (u8 *) lp;
17         y = *(bp + 3);
18         lp++;
19         for (h_lp = (u32)lp; (u32)lp < h_lp + ((u32)*(bp + 3)); lp++)
20             *lp = ntohl(*lp);
21     }while ((u32)lp < ((u32)p) + 4 + h_sp);
22
23 }
24
25 /*
26  * eata_set_info
27  * buffer : pointer to the data that has been written to the hostfile
28  * length : number of bytes written to the hostfile
29  * HBA_ptr: pointer to the Scsi_Host struct
30  */
31 int eata_set_info(char *buffer, int length, struct Scsi_Host *HBA_ptr)
32 {
33     int orig_length = length;
34
35     if (length >= 8 && strncmp(buffer, "eata_dma", 8) == 0) {
36         buffer += 9;
37         length -= 9;
38         if(length >= 8 && strncmp(buffer, "latency", 7) == 0) {
39             SD(HBA_ptr)->do_latency = TRUE;
40             return(orig_length);
41         } 
42         
43         if(length >=10 && strncmp(buffer, "nolatency", 9) == 0) {
44             SD(HBA_ptr)->do_latency = FALSE;
45             return(orig_length);
46         } 
47         
48         printk("Unknown command:%s length: %d\n", buffer, length);
49     } else 
50         printk("Wrong Signature:%10s\n", buffer);
51     
52     return(-EINVAL);
53 }
54
55 /*
56  * eata_proc_info
57  * inout : decides on the direction of the dataflow and the meaning of the 
58  *         variables
59  * buffer: If inout==FALSE data is being written to it else read from it
60  * *start: If inout==FALSE start of the valid data in the buffer
61  * offset: If inout==FALSE offset from the beginning of the imaginary file 
62  *         from which we start writing into the buffer
63  * length: If inout==FALSE max number of bytes to be written into the buffer 
64  *         else number of bytes in the buffer
65  */
66 int eata_proc_info(char *buffer, char **start, off_t offset, int length, 
67                    int hostno, int inout)
68 {
69
70     Scsi_Device *scd, *SDev;
71     struct Scsi_Host *HBA_ptr;
72     Scsi_Request  * scmd;
73     char cmnd[MAX_COMMAND_SIZE];
74     static u8 buff[512];
75     static u8 buff2[512];
76     hst_cmd_stat *rhcs, *whcs;
77     coco         *cc;
78     scsitrans    *st;
79     scsimod      *sm;
80     hobu         *hb;
81     scbu         *sb;
82     boty         *bt;
83     memco        *mc;
84     firm         *fm;
85     subinf       *si; 
86     pcinf        *pi;
87     arrlim       *al;
88     int i, x; 
89     int   size, len = 0;
90     off_t begin = 0;
91     off_t pos = 0;
92     scd = NULL;
93
94     HBA_ptr = first_HBA;
95     for (i = 1; i <= registered_HBAs; i++) {
96         if (HBA_ptr->host_no == hostno)
97             break;
98         HBA_ptr = SD(HBA_ptr)->next;
99     }        
100
101     if(inout == TRUE) /* Has data been written to the file ? */ 
102         return(eata_set_info(buffer, length, HBA_ptr));
103
104     if (offset == 0)
105         memset(buff, 0, sizeof(buff));
106
107     cc = (coco *)     (buff + 0x148);
108     st = (scsitrans *)(buff + 0x164); 
109     sm = (scsimod *)  (buff + 0x16c);
110     hb = (hobu *)     (buff + 0x172);
111     sb = (scbu *)     (buff + 0x178);
112     bt = (boty *)     (buff + 0x17e);
113     mc = (memco *)    (buff + 0x186);
114     fm = (firm *)     (buff + 0x18e);
115     si = (subinf *)   (buff + 0x196); 
116     pi = (pcinf *)    (buff + 0x19c);
117     al = (arrlim *)   (buff + 0x1a2);
118
119     size = sprintf(buffer+len, "EATA (Extended Attachment) driver version: "
120                    "%d.%d%s\n",VER_MAJOR, VER_MINOR, VER_SUB);
121     len += size; pos = begin + len;
122     size = sprintf(buffer + len, "queued commands:     %10ld\n"
123                    "processed interrupts:%10ld\n", queue_counter, int_counter);
124     len += size; pos = begin + len;
125
126     size = sprintf(buffer + len, "\nscsi%-2d: HBA %.10s\n",
127                    HBA_ptr->host_no, SD(HBA_ptr)->name);
128     len += size; 
129     pos = begin + len;
130     size = sprintf(buffer + len, "Firmware revision: v%s\n", 
131                    SD(HBA_ptr)->revision);
132     len += size;
133     pos = begin + len;
134     size = sprintf(buffer + len, "Hardware Configuration:\n");
135     len += size; 
136     pos = begin + len;
137     
138     if(SD(HBA_ptr)->broken_INQUIRY == TRUE) {
139         if (HBA_ptr->dma_channel == BUSMASTER)
140             size = sprintf(buffer + len, "DMA: BUSMASTER\n");
141         else
142             size = sprintf(buffer + len, "DMA: %d\n", HBA_ptr->dma_channel);
143         len += size; 
144         pos = begin + len;
145
146         size = sprintf(buffer + len, "Base IO : %#.4x\n", (u32) HBA_ptr->base);
147         len += size; 
148         pos = begin + len;
149
150         size = sprintf(buffer + len, "Host Bus: EISA\n"); 
151         len += size; 
152         pos = begin + len;
153
154     } else {
155         SDev = scsi_get_host_dev(HBA_ptr);
156         
157         if(SDev == NULL)
158             return -ENOMEM;
159                 
160         scmd  = scsi_allocate_request(SDev);
161         
162         if(scmd == NULL)
163         {
164             scsi_free_host_dev(SDev);
165             return -ENOMEM;
166         }
167         
168
169         cmnd[0] = LOG_SENSE;
170         cmnd[1] = 0;
171         cmnd[2] = 0x33 + (3<<6);
172         cmnd[3] = 0;
173         cmnd[4] = 0;
174         cmnd[5] = 0;
175         cmnd[6] = 0;
176         cmnd[7] = 0x00;
177         cmnd[8] = 0x66;
178         cmnd[9] = 0;
179
180         scmd->sr_cmd_len = 10;
181         scmd->sr_data_direction = SCSI_DATA_READ;
182         
183         /*
184          * Do the command and wait for it to finish.
185          */     
186         scsi_wait_req (scmd, cmnd, buff + 0x144, 0x66,  
187                        1 * HZ, 1);
188
189         size = sprintf(buffer + len, "IRQ: %2d, %s triggered\n", cc->interrupt,
190                        (cc->intt == TRUE)?"level":"edge");
191         len += size; 
192         pos = begin + len;
193         if (HBA_ptr->dma_channel == 0xff)
194             size = sprintf(buffer + len, "DMA: BUSMASTER\n");
195         else
196             size = sprintf(buffer + len, "DMA: %d\n", HBA_ptr->dma_channel);
197         len += size; 
198         pos = begin + len;
199         size = sprintf(buffer + len, "CPU: MC680%02d %dMHz\n", bt->cpu_type,
200                        bt->cpu_speed);
201         len += size; 
202         pos = begin + len;
203         size = sprintf(buffer + len, "Base IO : %#.4x\n", (u32) HBA_ptr->base);
204         len += size; 
205         pos = begin + len;
206         size = sprintf(buffer + len, "Host Bus: %s\n", 
207                        (SD(HBA_ptr)->bustype == IS_PCI)?"PCI ":
208                        (SD(HBA_ptr)->bustype == IS_EISA)?"EISA":"ISA ");
209         
210         len += size; 
211         pos = begin + len;
212         size = sprintf(buffer + len, "SCSI Bus:%s%s Speed: %sMB/sec. %s\n",
213                        (sb->wide == TRUE)?" WIDE":"", 
214                        (sb->dif == TRUE)?" DIFFERENTIAL":"",
215                        (sb->speed == 0)?"5":(sb->speed == 1)?"10":"20",
216                        (sb->ext == TRUE)?"With external cable detection":"");
217         len += size; 
218         pos = begin + len;
219         size = sprintf(buffer + len, "SCSI channel expansion Module: %s present\n",
220                        (bt->sx1 == TRUE)?"SX1 (one channel)":
221                        ((bt->sx2 == TRUE)?"SX2 (two channels)":"not"));
222         len += size; 
223         pos = begin + len;
224         size = sprintf(buffer + len, "SmartRAID hardware: %spresent.\n",
225                        (cc->srs == TRUE)?"":"not ");
226         len += size; 
227         pos = begin + len;
228         size = sprintf(buffer + len, "    Type: %s\n",
229                        ((cc->key == TRUE)?((bt->dmi == TRUE)?"integrated"
230                                            :((bt->dm4 == TRUE)?"DM401X"
231                                            :(bt->dm4k == TRUE)?"DM4000"
232                                            :"-"))
233                                            :"-"));
234         len += size; 
235         pos = begin + len;
236         
237         size = sprintf(buffer + len, "    Max array groups:              %d\n",
238                        (al->code == 0x0e)?al->max_groups:7);
239         len += size; 
240         pos = begin + len;
241         size = sprintf(buffer + len, "    Max drives per RAID 0 array:   %d\n",
242                        (al->code == 0x0e)?al->raid0_drv:7);
243         len += size; 
244         pos = begin + len;
245         size = sprintf(buffer + len, "    Max drives per RAID 3/5 array: %d\n",
246                        (al->code == 0x0e)?al->raid35_drv:7);
247         len += size; 
248         pos = begin + len;
249         size = sprintf(buffer + len, "Cache Module: %spresent.\n",
250                        (cc->csh)?"":"not ");
251         len += size; 
252         pos = begin + len;
253         size = sprintf(buffer + len, "    Type: %s\n",
254                        ((cc->csh == TRUE)?((bt->cmi == TRUE)?"integrated"
255                                          :((bt->cm4 == TRUE)?"CM401X"
256                                          :((bt->cm4k == TRUE)?"CM4000"
257                                          :"-")))
258                                          :"-"));
259         len += size; 
260         pos = begin + len;
261         for (x = 0; x <= 3; x++) {
262             size = sprintf(buffer + len, "    Bank%d: %dMB with%s ECC\n",x,
263                            mc->banksize[x] & 0x7f, 
264                            (mc->banksize[x] & 0x80)?"":"out");
265             len += size; 
266             pos = begin + len;      
267         }   
268         size = sprintf(buffer + len, "Timer Mod.: %spresent\n",
269                        (cc->tmr == TRUE)?"":"not ");
270         len += size; 
271         pos = begin + len;
272         size = sprintf(buffer + len, "NVRAM     : %spresent\n",
273                        (cc->nvr == TRUE)?"":"not ");
274         len += size; 
275         pos = begin + len;
276         size = sprintf(buffer + len, "SmartROM  : %sabled\n",
277                        (bt->srom == TRUE)?"dis":"en");
278         len += size; 
279         pos = begin + len;
280         size = sprintf(buffer + len, "Alarm     : %s\n",
281                        (bt->alrm == TRUE)?"on":"off");
282         len += size; 
283         pos = begin + len;
284         
285         if (pos < offset) {
286             len = 0;
287             begin = pos;
288         }
289         if (pos > offset + length)
290             goto stop_output; 
291
292         if(SD(HBA_ptr)->do_latency == FALSE) { 
293
294             cmnd[0] = LOG_SENSE;
295             cmnd[1] = 0;
296             cmnd[2] = 0x32 + (3<<6); 
297             cmnd[3] = 0;
298             cmnd[4] = 0;
299             cmnd[5] = 0;
300             cmnd[6] = 0;
301             cmnd[7] = 0x01;
302             cmnd[8] = 0x44;
303             cmnd[9] = 0;
304             
305             scmd->sr_cmd_len = 10;
306             scmd->sr_data_direction = SCSI_DATA_READ;
307
308             /*
309              * Do the command and wait for it to finish.
310              */ 
311             scsi_wait_req (scmd, cmnd, buff2, 0x144,
312                            1 * HZ, 1);
313
314             swap_statistics(buff2);
315             rhcs = (hst_cmd_stat *)(buff2 + 0x2c); 
316             whcs = (hst_cmd_stat *)(buff2 + 0x8c);               
317             
318             for (x = 0; x <= 11; x++) {
319                 SD(HBA_ptr)->reads[x] += rhcs->sizes[x];
320                 SD(HBA_ptr)->writes[x] += whcs->sizes[x];
321                 SD(HBA_ptr)->reads[12] += rhcs->sizes[x];
322                 SD(HBA_ptr)->writes[12] += whcs->sizes[x];
323             }
324             size = sprintf(buffer + len, "Host<->Disk command statistics:\n"
325                            "         Reads:          Writes:\n");
326             len += size; 
327             pos = begin + len;
328             for (x = 0; x <= 10; x++) {
329                 size = sprintf(buffer+len,"%5dk:%12u %12u\n", 1 << x,
330                                SD(HBA_ptr)->reads[x], 
331                                SD(HBA_ptr)->writes[x]);
332                 len += size; 
333                 pos = begin + len;
334             }
335             size = sprintf(buffer+len,">1024k:%12u %12u\n",
336                            SD(HBA_ptr)->reads[11], 
337                            SD(HBA_ptr)->writes[11]);
338             len += size; 
339             pos = begin + len;
340             size = sprintf(buffer+len,"Sum   :%12u %12u\n",
341                            SD(HBA_ptr)->reads[12], 
342                            SD(HBA_ptr)->writes[12]);
343             len += size; 
344             pos = begin + len;
345         }
346
347         scsi_release_request(scmd);
348         scsi_free_host_dev(SDev);
349     }
350     
351     if (pos < offset) {
352         len = 0;
353         begin = pos;
354     }
355     if (pos > offset + length)
356         goto stop_output;
357
358     if(SD(HBA_ptr)->do_latency == TRUE) {
359         int factor = 1024/HZ;
360         size = sprintf(buffer + len, "Host Latency Command Statistics:\n"
361                        "Current timer resolution: %2dms\n"
362                        "         Reads:       Min:(ms)     Max:(ms)     Ave:(ms)\n",
363                        factor);
364         len += size; 
365         pos = begin + len;
366         for (x = 0; x <= 10; x++) {
367             size = sprintf(buffer+len,"%5dk:%12u %12u %12u %12u\n", 
368                            1 << x,
369                            SD(HBA_ptr)->reads_lat[x][0], 
370                            (SD(HBA_ptr)->reads_lat[x][1] == 0xffffffff) 
371                            ? 0:(SD(HBA_ptr)->reads_lat[x][1] * factor), 
372                            SD(HBA_ptr)->reads_lat[x][2] * factor, 
373                            SD(HBA_ptr)->reads_lat[x][3] * factor /
374                            ((SD(HBA_ptr)->reads_lat[x][0])
375                             ? SD(HBA_ptr)->reads_lat[x][0]:1));
376             len += size; 
377             pos = begin + len;
378         }
379         size = sprintf(buffer+len,">1024k:%12u %12u %12u %12u\n",
380                            SD(HBA_ptr)->reads_lat[11][0], 
381                            (SD(HBA_ptr)->reads_lat[11][1] == 0xffffffff)
382                            ? 0:(SD(HBA_ptr)->reads_lat[11][1] * factor), 
383                            SD(HBA_ptr)->reads_lat[11][2] * factor, 
384                            SD(HBA_ptr)->reads_lat[11][3] * factor /
385                            ((SD(HBA_ptr)->reads_lat[x][0])
386                             ? SD(HBA_ptr)->reads_lat[x][0]:1));
387         len += size; 
388         pos = begin + len;
389
390         if (pos < offset) {
391             len = 0;
392             begin = pos;
393         }
394         if (pos > offset + length)
395             goto stop_output;
396
397         size = sprintf(buffer + len,
398                        "         Writes:      Min:(ms)     Max:(ms)     Ave:(ms)\n");
399         len += size; 
400         pos = begin + len;
401         for (x = 0; x <= 10; x++) {
402             size = sprintf(buffer+len,"%5dk:%12u %12u %12u %12u\n", 
403                            1 << x,
404                            SD(HBA_ptr)->writes_lat[x][0], 
405                            (SD(HBA_ptr)->writes_lat[x][1] == 0xffffffff)
406                            ? 0:(SD(HBA_ptr)->writes_lat[x][1] * factor), 
407                            SD(HBA_ptr)->writes_lat[x][2] * factor, 
408                            SD(HBA_ptr)->writes_lat[x][3] * factor /
409                            ((SD(HBA_ptr)->writes_lat[x][0])
410                             ? SD(HBA_ptr)->writes_lat[x][0]:1));
411             len += size; 
412             pos = begin + len;
413         }
414         size = sprintf(buffer+len,">1024k:%12u %12u %12u %12u\n",
415                            SD(HBA_ptr)->writes_lat[11][0], 
416                            (SD(HBA_ptr)->writes_lat[11][1] == 0xffffffff)
417                            ? 0:(SD(HBA_ptr)->writes_lat[x][1] * factor), 
418                            SD(HBA_ptr)->writes_lat[11][2] * factor, 
419                            SD(HBA_ptr)->writes_lat[11][3] * factor /
420                            ((SD(HBA_ptr)->writes_lat[x][0])
421                             ? SD(HBA_ptr)->writes_lat[x][0]:1));
422         len += size; 
423         pos = begin + len;
424
425         if (pos < offset) {
426             len = 0;
427             begin = pos;
428         }
429         if (pos > offset + length)
430             goto stop_output;
431     }
432
433     size = sprintf(buffer+len,"Attached devices: %s\n", 
434                    (HBA_ptr->host_queue)?"":"none");
435     len += size; 
436     pos = begin + len;
437     
438     for(scd = HBA_ptr->host_queue; scd; scd = scd->next) {
439             proc_print_scsidevice(scd, buffer, &size, len);
440             len += size; 
441             pos = begin + len;
442             
443             if (pos < offset) {
444                 len = 0;
445                 begin = pos;
446             }
447             if (pos > offset + length)
448                 goto stop_output;
449     }
450     
451  stop_output:
452     DBG(DBG_PROC, printk("2pos: %ld offset: %ld len: %d\n", pos, offset, len));
453     *start=buffer+(offset-begin);   /* Start of wanted data */
454     len-=(offset-begin);            /* Start slop */
455     if(len>length)
456         len = length;               /* Ending slop */
457     DBG(DBG_PROC, printk("3pos: %ld offset: %ld len: %d\n", pos, offset, len));
458     
459     return (len);     
460 }
461
462 /*
463  * Overrides for Emacs so that we follow Linus's tabbing style.
464  * Emacs will notice this stuff at the end of the file and automatically
465  * adjust the settings for this buffer only.  This must remain at the end
466  * of the file.
467  * ---------------------------------------------------------------------------
468  * Local variables:
469  * c-indent-level: 4
470  * c-brace-imaginary-offset: 0
471  * c-brace-offset: -4
472  * c-argdecl-indent: 4
473  * c-label-offset: -4
474  * c-continued-statement-offset: 4
475  * c-continued-brace-offset: 0
476  * tab-width: 8
477  * End:
478  */