2 * $Id: gdth_proc.c,v 1.43 2006/01/11 16:15:00 achim Exp $
5 #include <linux/completion.h>
7 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
8 int gdth_proc_info(struct Scsi_Host
*host
, char *buffer
,char **start
,off_t offset
,int length
,
13 TRACE2(("gdth_proc_info() length %d offs %d inout %d\n",
14 length
,(int)offset
,inout
));
16 hanum
= NUMDATA(host
)->hanum
;
17 busnum
= NUMDATA(host
)->busnum
;
20 return(gdth_set_info(buffer
,length
,host
,hanum
,busnum
));
22 return(gdth_get_info(buffer
,start
,offset
,length
,host
,hanum
,busnum
));
25 int gdth_proc_info(char *buffer
,char **start
,off_t offset
,int length
,int hostno
,
30 TRACE2(("gdth_proc_info() length %d offs %d inout %d\n",
31 length
,(int)offset
,inout
));
33 for (i
= 0; i
< gdth_ctr_vcount
; ++i
) {
34 if (gdth_ctr_vtab
[i
]->host_no
== hostno
)
37 if (i
== gdth_ctr_vcount
)
40 hanum
= NUMDATA(gdth_ctr_vtab
[i
])->hanum
;
41 busnum
= NUMDATA(gdth_ctr_vtab
[i
])->busnum
;
44 return(gdth_set_info(buffer
,length
,gdth_ctr_vtab
[i
],hanum
,busnum
));
46 return(gdth_get_info(buffer
,start
,offset
,length
,
47 gdth_ctr_vtab
[i
],hanum
,busnum
));
51 static int gdth_set_info(char *buffer
,int length
,struct Scsi_Host
*host
,
54 int ret_val
= -EINVAL
;
56 TRACE2(("gdth_set_info() ha %d bus %d\n",hanum
,busnum
));
59 if (strncmp(buffer
,"gdth",4) == 0) {
62 ret_val
= gdth_set_asc_info(host
, buffer
, length
, hanum
);
69 static int gdth_set_asc_info(struct Scsi_Host
*host
, char *buffer
,
72 int orig_length
, drive
, wb_mode
;
79 char cmnd
[MAX_COMMAND_SIZE
];
80 memset(cmnd
, 0xff, 12);
81 memset(&gdtcmd
, 0, sizeof(gdth_cmd_str
));
83 TRACE2(("gdth_set_asc_info() ha %d\n",hanum
));
84 ha
= HADATA(gdth_ctr_tab
[hanum
]);
85 orig_length
= length
+ 5;
90 if (length
>= 5 && strncmp(buffer
,"flush",5)==0) {
93 if (length
&& *buffer
>='0' && *buffer
<='9') {
94 drive
= (int)(*buffer
-'0');
96 if (length
&& *buffer
>='0' && *buffer
<='9') {
97 drive
= drive
*10 + (int)(*buffer
-'0');
100 printk("GDT: Flushing host drive %d .. ",drive
);
102 printk("GDT: Flushing all host drives .. ");
104 for (i
= 0; i
< MAX_HDRIVES
; ++i
) {
105 if (ha
->hdr
[i
].present
) {
106 if (drive
!= -1 && i
!= drive
)
109 gdtcmd
.Service
= CACHESERVICE
;
110 gdtcmd
.OpCode
= GDT_FLUSH
;
111 if (ha
->cache_feat
& GDT_64BIT
) {
112 gdtcmd
.u
.cache64
.DeviceNo
= i
;
113 gdtcmd
.u
.cache64
.BlockNo
= 1;
115 gdtcmd
.u
.cache
.DeviceNo
= i
;
116 gdtcmd
.u
.cache
.BlockNo
= 1;
119 gdth_execute(host
, &gdtcmd
, cmnd
, 30, NULL
);
123 printk("\nNo host drive found !\n");
129 if (length
>= 7 && strncmp(buffer
,"wbp_off",7)==0) {
132 printk("GDT: Disabling write back permanently .. ");
134 } else if (length
>= 6 && strncmp(buffer
,"wbp_on",6)==0) {
137 printk("GDT: Enabling write back permanently .. ");
139 } else if (length
>= 6 && strncmp(buffer
,"wb_off",6)==0) {
142 printk("GDT: Disabling write back commands .. ");
143 if (ha
->cache_feat
& GDT_WR_THROUGH
) {
144 gdth_write_through
= TRUE
;
147 printk("Not supported !\n");
150 } else if (length
>= 5 && strncmp(buffer
,"wb_on",5)==0) {
153 printk("GDT: Enabling write back commands .. ");
154 gdth_write_through
= FALSE
;
160 if (!gdth_ioctl_alloc(hanum
, sizeof(gdth_cpar_str
), TRUE
, &paddr
))
162 pcpar
= (gdth_cpar_str
*)ha
->pscratch
;
163 memcpy( pcpar
, &ha
->cpar
, sizeof(gdth_cpar_str
) );
164 gdtcmd
.Service
= CACHESERVICE
;
165 gdtcmd
.OpCode
= GDT_IOCTL
;
166 gdtcmd
.u
.ioctl
.p_param
= paddr
;
167 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_cpar_str
);
168 gdtcmd
.u
.ioctl
.subfunc
= CACHE_CONFIG
;
169 gdtcmd
.u
.ioctl
.channel
= INVALID_CHANNEL
;
170 pcpar
->write_back
= wb_mode
==1 ? 0:1;
172 gdth_execute(host
, &gdtcmd
, cmnd
, 30, NULL
);
174 gdth_ioctl_free(hanum
, GDTH_SCRATCH
, ha
->pscratch
, paddr
);
179 printk("GDT: Unknown command: %s Length: %d\n",buffer
,length
);
183 static int gdth_get_info(char *buffer
,char **start
,off_t offset
,int length
,
184 struct Scsi_Host
*host
,int hanum
,int busnum
)
186 int size
= 0,len
= 0;
187 off_t begin
= 0,pos
= 0;
189 int id
, i
, j
, k
, sec
, flag
;
190 int no_mdrv
= 0, drv_no
, is_mirr
;
195 gdth_cmd_str
*gdtcmd
;
201 gdth_dskstat_str
*pds
;
202 gdth_diskinfo_str
*pdi
;
203 gdth_arrayinf_str
*pai
;
204 gdth_defcnt_str
*pdef
;
205 gdth_cdrinfo_str
*pcdi
;
207 char cmnd
[MAX_COMMAND_SIZE
];
209 gdtcmd
= kmalloc(sizeof(*gdtcmd
), GFP_KERNEL
);
210 estr
= kmalloc(sizeof(*estr
), GFP_KERNEL
);
211 if (!gdtcmd
|| !estr
)
214 memset(cmnd
, 0xff, 12);
215 memset(gdtcmd
, 0, sizeof(gdth_cmd_str
));
217 TRACE2(("gdth_get_info() ha %d bus %d\n",hanum
,busnum
));
218 ha
= HADATA(gdth_ctr_tab
[hanum
]);
221 /* request is i.e. "cat /proc/scsi/gdth/0" */
222 /* format: %-15s\t%-10s\t%-15s\t%s */
223 /* driver parameters */
224 size
= sprintf(buffer
+len
,"Driver Parameters:\n");
225 len
+= size
; pos
= begin
+ len
;
226 if (reserve_list
[0] == 0xff)
229 sprintf(hrec
, "%d", reserve_list
[0]);
230 for (i
= 1; i
< MAX_RES_ARGS
; i
++) {
231 if (reserve_list
[i
] == 0xff)
233 sprintf(hrec
,"%s,%d", hrec
, reserve_list
[i
]);
236 size
= sprintf(buffer
+len
,
237 " reserve_mode: \t%d \treserve_list: \t%s\n",
239 len
+= size
; pos
= begin
+ len
;
240 size
= sprintf(buffer
+len
,
241 " max_ids: \t%-3d \thdr_channel: \t%d\n",
242 max_ids
, hdr_channel
);
243 len
+= size
; pos
= begin
+ len
;
245 /* controller information */
246 size
= sprintf(buffer
+len
,"\nDisk Array Controller Information:\n");
247 len
+= size
; pos
= begin
+ len
;
249 sprintf(hrec
, "%s (Bus %d)", ha
->binfo
.type_string
, busnum
);
251 strcpy(hrec
, ha
->binfo
.type_string
);
252 size
= sprintf(buffer
+len
,
253 " Number: \t%d \tName: \t%s\n",
255 len
+= size
; pos
= begin
+ len
;
258 sprintf(hrec
, "%d.%02d.%02d-%c%03X",
259 (unchar
)(ha
->binfo
.upd_fw_ver
>>24),
260 (unchar
)(ha
->binfo
.upd_fw_ver
>>16),
261 (unchar
)(ha
->binfo
.upd_fw_ver
),
262 ha
->bfeat
.raid
? 'R':'N',
263 ha
->binfo
.upd_revision
);
265 sprintf(hrec
, "%d.%02d", (unchar
)(ha
->cpar
.version
>>8),
266 (unchar
)(ha
->cpar
.version
));
268 size
= sprintf(buffer
+len
,
269 " Driver Ver.: \t%-10s\tFirmware Ver.: \t%s\n",
270 GDTH_VERSION_STR
, hrec
);
271 len
+= size
; pos
= begin
+ len
;
274 /* more information: 1. about controller */
275 size
= sprintf(buffer
+len
,
276 " Serial No.: \t0x%8X\tCache RAM size:\t%d KB\n",
277 ha
->binfo
.ser_no
, ha
->binfo
.memsize
/ 1024);
278 len
+= size
; pos
= begin
+ len
;
281 #ifdef GDTH_DMA_STATISTICS
282 /* controller statistics */
283 size
= sprintf(buffer
+len
,"\nController Statistics:\n");
284 len
+= size
; pos
= begin
+ len
;
285 size
= sprintf(buffer
+len
,
286 " 32-bit DMA buffer:\t%lu\t64-bit DMA buffer:\t%lu\n",
287 ha
->dma32_cnt
, ha
->dma64_cnt
);
288 len
+= size
; pos
= begin
+ len
;
295 if (pos
> offset
+ length
)
299 /* more information: 2. about physical devices */
300 size
= sprintf(buffer
+len
,"\nPhysical Devices:");
301 len
+= size
; pos
= begin
+ len
;
304 buf
= gdth_ioctl_alloc(hanum
, GDTH_SCRATCH
, FALSE
, &paddr
);
307 for (i
= 0; i
< ha
->bus_cnt
; ++i
) {
308 /* 2.a statistics (and retries/reassigns) */
309 TRACE2(("pdr_statistics() chn %d\n",i
));
310 pds
= (gdth_dskstat_str
*)(buf
+ GDTH_SCRATCH
/4);
311 gdtcmd
->Service
= CACHESERVICE
;
312 gdtcmd
->OpCode
= GDT_IOCTL
;
313 gdtcmd
->u
.ioctl
.p_param
= paddr
+ GDTH_SCRATCH
/4;
314 gdtcmd
->u
.ioctl
.param_size
= 3*GDTH_SCRATCH
/4;
315 gdtcmd
->u
.ioctl
.subfunc
= DSK_STATISTICS
| L_CTRL_PATTERN
;
316 gdtcmd
->u
.ioctl
.channel
= ha
->raw
[i
].address
| INVALID_CHANNEL
;
317 pds
->bid
= ha
->raw
[i
].local_no
;
319 pds
->entries
= ha
->raw
[i
].pdev_cnt
;
320 cnt
= (3*GDTH_SCRATCH
/4 - 5 * sizeof(ulong32
)) /
321 sizeof(pds
->list
[0]);
322 if (pds
->entries
> cnt
)
325 if (gdth_execute(host
, gdtcmd
, cmnd
, 30, NULL
) != S_OK
)
328 /* other IOCTLs must fit into area GDTH_SCRATCH/4 */
329 for (j
= 0; j
< ha
->raw
[i
].pdev_cnt
; ++j
) {
331 TRACE2(("scsi_drv_info() chn %d dev %d\n",
332 i
, ha
->raw
[i
].id_list
[j
]));
333 pdi
= (gdth_diskinfo_str
*)buf
;
334 gdtcmd
->Service
= CACHESERVICE
;
335 gdtcmd
->OpCode
= GDT_IOCTL
;
336 gdtcmd
->u
.ioctl
.p_param
= paddr
;
337 gdtcmd
->u
.ioctl
.param_size
= sizeof(gdth_diskinfo_str
);
338 gdtcmd
->u
.ioctl
.subfunc
= SCSI_DR_INFO
| L_CTRL_PATTERN
;
339 gdtcmd
->u
.ioctl
.channel
=
340 ha
->raw
[i
].address
| ha
->raw
[i
].id_list
[j
];
342 if (gdth_execute(host
, gdtcmd
, cmnd
, 30, NULL
) == S_OK
) {
343 strncpy(hrec
,pdi
->vendor
,8);
344 strncpy(hrec
+8,pdi
->product
,16);
345 strncpy(hrec
+24,pdi
->revision
,4);
347 size
= sprintf(buffer
+len
,
348 "\n Chn/ID/LUN: \t%c/%02d/%d \tName: \t%s\n",
349 'A'+i
,pdi
->target_id
,pdi
->lun
,hrec
);
350 len
+= size
; pos
= begin
+ len
;
352 pdi
->no_ldrive
&= 0xffff;
353 if (pdi
->no_ldrive
== 0xffff)
356 sprintf(hrec
,"%d",pdi
->no_ldrive
);
357 size
= sprintf(buffer
+len
,
358 " Capacity [MB]:\t%-6d \tTo Log. Drive: \t%s\n",
359 pdi
->blkcnt
/(1024*1024/pdi
->blksize
),
361 len
+= size
; pos
= begin
+ len
;
366 if (pdi
->devtype
== 0) {
367 /* search retries/reassigns */
368 for (k
= 0; k
< pds
->count
; ++k
) {
369 if (pds
->list
[k
].tid
== pdi
->target_id
&&
370 pds
->list
[k
].lun
== pdi
->lun
) {
371 size
= sprintf(buffer
+len
,
372 " Retries: \t%-6d \tReassigns: \t%d\n",
373 pds
->list
[k
].retries
,
374 pds
->list
[k
].reassigns
);
375 len
+= size
; pos
= begin
+ len
;
379 /* 2.c grown defects */
380 TRACE2(("scsi_drv_defcnt() chn %d dev %d\n",
381 i
, ha
->raw
[i
].id_list
[j
]));
382 pdef
= (gdth_defcnt_str
*)buf
;
383 gdtcmd
->Service
= CACHESERVICE
;
384 gdtcmd
->OpCode
= GDT_IOCTL
;
385 gdtcmd
->u
.ioctl
.p_param
= paddr
;
386 gdtcmd
->u
.ioctl
.param_size
= sizeof(gdth_defcnt_str
);
387 gdtcmd
->u
.ioctl
.subfunc
= SCSI_DEF_CNT
| L_CTRL_PATTERN
;
388 gdtcmd
->u
.ioctl
.channel
=
389 ha
->raw
[i
].address
| ha
->raw
[i
].id_list
[j
];
390 pdef
->sddc_type
= 0x08;
392 if (gdth_execute(host
, gdtcmd
, cmnd
, 30, NULL
) == S_OK
) {
393 size
= sprintf(buffer
+len
,
394 " Grown Defects:\t%d\n",
396 len
+= size
; pos
= begin
+ len
;
403 if (pos
> offset
+ length
)
407 gdth_ioctl_free(hanum
, GDTH_SCRATCH
, buf
, paddr
);
410 size
= sprintf(buffer
+len
, "\n --\n");
411 len
+= size
; pos
= begin
+ len
;
414 /* 3. about logical drives */
415 size
= sprintf(buffer
+len
,"\nLogical Drives:");
416 len
+= size
; pos
= begin
+ len
;
419 buf
= gdth_ioctl_alloc(hanum
, GDTH_SCRATCH
, FALSE
, &paddr
);
422 for (i
= 0; i
< MAX_LDRIVES
; ++i
) {
423 if (!ha
->hdr
[i
].is_logdrv
)
429 /* 3.a log. drive info */
430 TRACE2(("cache_drv_info() drive no %d\n",drv_no
));
431 pcdi
= (gdth_cdrinfo_str
*)buf
;
432 gdtcmd
->Service
= CACHESERVICE
;
433 gdtcmd
->OpCode
= GDT_IOCTL
;
434 gdtcmd
->u
.ioctl
.p_param
= paddr
;
435 gdtcmd
->u
.ioctl
.param_size
= sizeof(gdth_cdrinfo_str
);
436 gdtcmd
->u
.ioctl
.subfunc
= CACHE_DRV_INFO
;
437 gdtcmd
->u
.ioctl
.channel
= drv_no
;
438 if (gdth_execute(host
, gdtcmd
, cmnd
, 30, NULL
) != S_OK
)
440 pcdi
->ld_dtype
>>= 16;
442 if (pcdi
->ld_dtype
> 2) {
443 strcpy(hrec
, "missing");
444 } else if (pcdi
->ld_error
& 1) {
445 strcpy(hrec
, "fault");
446 } else if (pcdi
->ld_error
& 2) {
447 strcpy(hrec
, "invalid");
454 size
= sprintf(buffer
+len
,
455 "\n Number: \t%-2d \tStatus: \t%s\n",
457 len
+= size
; pos
= begin
+ len
;
459 no_mdrv
= pcdi
->cd_ldcnt
;
460 if (no_mdrv
> 1 || pcdi
->ld_slave
!= -1) {
462 strcpy(hrec
, "RAID-1");
463 } else if (pcdi
->ld_dtype
== 0) {
464 strcpy(hrec
, "Disk");
465 } else if (pcdi
->ld_dtype
== 1) {
466 strcpy(hrec
, "RAID-0");
467 } else if (pcdi
->ld_dtype
== 2) {
468 strcpy(hrec
, "Chain");
472 size
= sprintf(buffer
+len
,
473 " Capacity [MB]:\t%-6d \tType: \t%s\n",
474 pcdi
->ld_blkcnt
/(1024*1024/pcdi
->ld_blksize
),
476 len
+= size
; pos
= begin
+ len
;
478 size
= sprintf(buffer
+len
,
479 " Slave Number: \t%-2d \tStatus: \t%s\n",
480 drv_no
& 0x7fff, hrec
);
481 len
+= size
; pos
= begin
+ len
;
483 drv_no
= pcdi
->ld_slave
;
488 if (pos
> offset
+ length
)
490 } while (drv_no
!= -1);
493 size
= sprintf(buffer
+len
,
494 " Missing Drv.: \t%-2d \tInvalid Drv.: \t%d\n",
496 len
+= size
; pos
= begin
+ len
;
499 if (!ha
->hdr
[i
].is_arraydrv
)
502 sprintf(hrec
, "%d", ha
->hdr
[i
].master_no
);
503 size
= sprintf(buffer
+len
,
504 " To Array Drv.:\t%s\n", hrec
);
505 len
+= size
; pos
= begin
+ len
;
510 if (pos
> offset
+ length
)
513 gdth_ioctl_free(hanum
, GDTH_SCRATCH
, buf
, paddr
);
516 size
= sprintf(buffer
+len
, "\n --\n");
517 len
+= size
; pos
= begin
+ len
;
520 /* 4. about array drives */
521 size
= sprintf(buffer
+len
,"\nArray Drives:");
522 len
+= size
; pos
= begin
+ len
;
525 buf
= gdth_ioctl_alloc(hanum
, GDTH_SCRATCH
, FALSE
, &paddr
);
528 for (i
= 0; i
< MAX_LDRIVES
; ++i
) {
529 if (!(ha
->hdr
[i
].is_arraydrv
&& ha
->hdr
[i
].is_master
))
531 /* 4.a array drive info */
532 TRACE2(("array_info() drive no %d\n",i
));
533 pai
= (gdth_arrayinf_str
*)buf
;
534 gdtcmd
->Service
= CACHESERVICE
;
535 gdtcmd
->OpCode
= GDT_IOCTL
;
536 gdtcmd
->u
.ioctl
.p_param
= paddr
;
537 gdtcmd
->u
.ioctl
.param_size
= sizeof(gdth_arrayinf_str
);
538 gdtcmd
->u
.ioctl
.subfunc
= ARRAY_INFO
| LA_CTRL_PATTERN
;
539 gdtcmd
->u
.ioctl
.channel
= i
;
540 if (gdth_execute(host
, gdtcmd
, cmnd
, 30, NULL
) == S_OK
) {
541 if (pai
->ai_state
== 0)
542 strcpy(hrec
, "idle");
543 else if (pai
->ai_state
== 2)
544 strcpy(hrec
, "build");
545 else if (pai
->ai_state
== 4)
546 strcpy(hrec
, "ready");
547 else if (pai
->ai_state
== 6)
548 strcpy(hrec
, "fail");
549 else if (pai
->ai_state
== 8 || pai
->ai_state
== 10)
550 strcpy(hrec
, "rebuild");
552 strcpy(hrec
, "error");
553 if (pai
->ai_ext_state
& 0x10)
554 strcat(hrec
, "/expand");
555 else if (pai
->ai_ext_state
& 0x1)
556 strcat(hrec
, "/patch");
557 size
= sprintf(buffer
+len
,
558 "\n Number: \t%-2d \tStatus: \t%s\n",
560 len
+= size
; pos
= begin
+ len
;
563 if (pai
->ai_type
== 0)
564 strcpy(hrec
, "RAID-0");
565 else if (pai
->ai_type
== 4)
566 strcpy(hrec
, "RAID-4");
567 else if (pai
->ai_type
== 5)
568 strcpy(hrec
, "RAID-5");
570 strcpy(hrec
, "RAID-10");
571 size
= sprintf(buffer
+len
,
572 " Capacity [MB]:\t%-6d \tType: \t%s\n",
573 pai
->ai_size
/(1024*1024/pai
->ai_secsize
),
575 len
+= size
; pos
= begin
+ len
;
580 if (pos
> offset
+ length
)
584 gdth_ioctl_free(hanum
, GDTH_SCRATCH
, buf
, paddr
);
587 size
= sprintf(buffer
+len
, "\n --\n");
588 len
+= size
; pos
= begin
+ len
;
591 /* 5. about host drives */
592 size
= sprintf(buffer
+len
,"\nHost Drives:");
593 len
+= size
; pos
= begin
+ len
;
596 buf
= gdth_ioctl_alloc(hanum
, sizeof(gdth_hget_str
), FALSE
, &paddr
);
599 for (i
= 0; i
< MAX_LDRIVES
; ++i
) {
600 if (!ha
->hdr
[i
].is_logdrv
||
601 (ha
->hdr
[i
].is_arraydrv
&& !ha
->hdr
[i
].is_master
))
603 /* 5.a get host drive list */
604 TRACE2(("host_get() drv_no %d\n",i
));
605 phg
= (gdth_hget_str
*)buf
;
606 gdtcmd
->Service
= CACHESERVICE
;
607 gdtcmd
->OpCode
= GDT_IOCTL
;
608 gdtcmd
->u
.ioctl
.p_param
= paddr
;
609 gdtcmd
->u
.ioctl
.param_size
= sizeof(gdth_hget_str
);
610 gdtcmd
->u
.ioctl
.subfunc
= HOST_GET
| LA_CTRL_PATTERN
;
611 gdtcmd
->u
.ioctl
.channel
= i
;
612 phg
->entries
= MAX_HDRIVES
;
613 phg
->offset
= GDTOFFSOF(gdth_hget_str
, entry
[0]);
614 if (gdth_execute(host
, gdtcmd
, cmnd
, 30, NULL
) == S_OK
) {
615 ha
->hdr
[i
].ldr_no
= i
;
616 ha
->hdr
[i
].rw_attribs
= 0;
617 ha
->hdr
[i
].start_sec
= 0;
619 for (j
= 0; j
< phg
->entries
; ++j
) {
620 k
= phg
->entry
[j
].host_drive
;
621 if (k
>= MAX_LDRIVES
)
623 ha
->hdr
[k
].ldr_no
= phg
->entry
[j
].log_drive
;
624 ha
->hdr
[k
].rw_attribs
= phg
->entry
[j
].rw_attribs
;
625 ha
->hdr
[k
].start_sec
= phg
->entry
[j
].start_sec
;
629 gdth_ioctl_free(hanum
, sizeof(gdth_hget_str
), buf
, paddr
);
631 for (i
= 0; i
< MAX_HDRIVES
; ++i
) {
632 if (!(ha
->hdr
[i
].present
))
635 size
= sprintf(buffer
+len
,
636 "\n Number: \t%-2d \tArr/Log. Drive:\t%d\n",
637 i
, ha
->hdr
[i
].ldr_no
);
638 len
+= size
; pos
= begin
+ len
;
641 size
= sprintf(buffer
+len
,
642 " Capacity [MB]:\t%-6d \tStart Sector: \t%d\n",
643 (ulong32
)(ha
->hdr
[i
].size
/2048), ha
->hdr
[i
].start_sec
);
644 len
+= size
; pos
= begin
+ len
;
649 if (pos
> offset
+ length
)
654 size
= sprintf(buffer
+len
, "\n --\n");
655 len
+= size
; pos
= begin
+ len
;
659 /* controller events */
660 size
= sprintf(buffer
+len
,"\nController Events:\n");
661 len
+= size
; pos
= begin
+ len
;
664 id
= gdth_read_event(ha
, id
, estr
);
665 if (estr
->event_source
== 0)
667 if (estr
->event_data
.eu
.driver
.ionode
== hanum
&&
668 estr
->event_source
== ES_ASYNC
) {
669 gdth_log_event(&estr
->event_data
, hrec
);
670 do_gettimeofday(&tv
);
671 sec
= (int)(tv
.tv_sec
- estr
->first_stamp
);
672 if (sec
< 0) sec
= 0;
673 size
= sprintf(buffer
+len
," date- %02d:%02d:%02d\t%s\n",
674 sec
/3600, sec
%3600/60, sec
%60, hrec
);
675 len
+= size
; pos
= begin
+ len
;
680 if (pos
> offset
+ length
)
688 *start
= buffer
+(offset
-begin
);
689 len
-= (offset
-begin
);
692 TRACE2(("get_info() len %d pos %d begin %d offset %d length %d size %d\n",
693 len
,(int)pos
,(int)begin
,(int)offset
,length
,size
));
702 static char *gdth_ioctl_alloc(int hanum
, int size
, int scratch
,
712 ha
= HADATA(gdth_ctr_tab
[hanum
]);
713 spin_lock_irqsave(&ha
->smp_lock
, flags
);
715 if (!ha
->scratch_busy
&& size
<= GDTH_SCRATCH
) {
716 ha
->scratch_busy
= TRUE
;
717 ret_val
= ha
->pscratch
;
718 *paddr
= ha
->scratch_phys
;
719 } else if (scratch
) {
724 ret_val
= pci_alloc_consistent(ha
->pdev
, size
, &dma_addr
);
728 spin_unlock_irqrestore(&ha
->smp_lock
, flags
);
732 static void gdth_ioctl_free(int hanum
, int size
, char *buf
, ulong64 paddr
)
737 ha
= HADATA(gdth_ctr_tab
[hanum
]);
738 spin_lock_irqsave(&ha
->smp_lock
, flags
);
740 if (buf
== ha
->pscratch
) {
741 ha
->scratch_busy
= FALSE
;
743 pci_free_consistent(ha
->pdev
, size
, buf
, paddr
);
746 spin_unlock_irqrestore(&ha
->smp_lock
, flags
);
749 #ifdef GDTH_IOCTL_PROC
750 static int gdth_ioctl_check_bin(int hanum
, ushort size
)
756 ha
= HADATA(gdth_ctr_tab
[hanum
]);
757 spin_lock_irqsave(&ha
->smp_lock
, flags
);
760 if (ha
->scratch_busy
) {
761 if (((gdth_iord_str
*)ha
->pscratch
)->size
== (ulong32
)size
)
764 spin_unlock_irqrestore(&ha
->smp_lock
, flags
);
769 static void gdth_wait_completion(int hanum
, int busnum
, int id
)
777 ha
= HADATA(gdth_ctr_tab
[hanum
]);
778 spin_lock_irqsave(&ha
->smp_lock
, flags
);
780 for (i
= 0; i
< GDTH_MAXCMDS
; ++i
) {
781 scp
= ha
->cmd_tab
[i
].cmnd
;
783 b
= virt_ctr
? NUMDATA(scp
->device
->host
)->busnum
: scp
->device
->channel
;
785 if (!SPECIAL_SCP(scp
) && t
== (unchar
)id
&&
786 b
== (unchar
)busnum
) {
787 scp
->SCp
.have_data_in
= 0;
788 spin_unlock_irqrestore(&ha
->smp_lock
, flags
);
789 while (!scp
->SCp
.have_data_in
)
791 spin_lock_irqsave(&ha
->smp_lock
, flags
);
794 spin_unlock_irqrestore(&ha
->smp_lock
, flags
);
797 static void gdth_stop_timeout(int hanum
, int busnum
, int id
)
804 ha
= HADATA(gdth_ctr_tab
[hanum
]);
805 spin_lock_irqsave(&ha
->smp_lock
, flags
);
807 for (scp
= ha
->req_first
; scp
; scp
= (Scsi_Cmnd
*)scp
->SCp
.ptr
) {
808 if (scp
->done
!= gdth_scsi_done
) {
810 NUMDATA(scp
->device
->host
)->busnum
: scp
->device
->channel
;
812 if (t
== (unchar
)id
&& b
== (unchar
)busnum
) {
813 TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
814 scp
->SCp
.buffers_residual
= gdth_update_timeout(hanum
, scp
, 0);
818 spin_unlock_irqrestore(&ha
->smp_lock
, flags
);
821 static void gdth_start_timeout(int hanum
, int busnum
, int id
)
828 ha
= HADATA(gdth_ctr_tab
[hanum
]);
829 spin_lock_irqsave(&ha
->smp_lock
, flags
);
831 for (scp
= ha
->req_first
; scp
; scp
= (Scsi_Cmnd
*)scp
->SCp
.ptr
) {
832 if (scp
->done
!= gdth_scsi_done
) {
834 NUMDATA(scp
->device
->host
)->busnum
: scp
->device
->channel
;
836 if (t
== (unchar
)id
&& b
== (unchar
)busnum
) {
837 TRACE2(("gdth_start_timeout(): update_timeout()\n"));
838 gdth_update_timeout(hanum
, scp
, scp
->SCp
.buffers_residual
);
842 spin_unlock_irqrestore(&ha
->smp_lock
, flags
);
845 static int gdth_update_timeout(int hanum
, Scsi_Cmnd
*scp
, int timeout
)
849 oldto
= scp
->timeout_per_command
;
850 scp
->timeout_per_command
= timeout
;
853 del_timer(&scp
->eh_timeout
);
854 scp
->eh_timeout
.data
= (unsigned long) NULL
;
855 scp
->eh_timeout
.expires
= 0;
857 if (scp
->eh_timeout
.data
!= (unsigned long) NULL
)
858 del_timer(&scp
->eh_timeout
);
859 scp
->eh_timeout
.data
= (unsigned long) scp
;
860 scp
->eh_timeout
.expires
= jiffies
+ timeout
;
861 add_timer(&scp
->eh_timeout
);