2 * $Id: gdth_proc.c,v 1.42 2004/03/05 15:50:20 achim Exp $
5 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
6 #include <linux/completion.h>
9 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
10 int gdth_proc_info(struct Scsi_Host
*host
, char *buffer
,char **start
,off_t offset
,int length
,
15 TRACE2(("gdth_proc_info() length %d offs %d inout %d\n",
16 length
,(int)offset
,inout
));
18 hanum
= NUMDATA(host
)->hanum
;
19 busnum
= NUMDATA(host
)->busnum
;
22 return(gdth_set_info(buffer
,length
,host
,hanum
,busnum
));
24 return(gdth_get_info(buffer
,start
,offset
,length
,host
,hanum
,busnum
));
27 int gdth_proc_info(char *buffer
,char **start
,off_t offset
,int length
,int hostno
,
32 TRACE2(("gdth_proc_info() length %d offs %d inout %d\n",
33 length
,(int)offset
,inout
));
35 for (i
= 0; i
< gdth_ctr_vcount
; ++i
) {
36 if (gdth_ctr_vtab
[i
]->host_no
== hostno
)
39 if (i
== gdth_ctr_vcount
)
42 hanum
= NUMDATA(gdth_ctr_vtab
[i
])->hanum
;
43 busnum
= NUMDATA(gdth_ctr_vtab
[i
])->busnum
;
46 return(gdth_set_info(buffer
,length
,gdth_ctr_vtab
[i
],hanum
,busnum
));
48 return(gdth_get_info(buffer
,start
,offset
,length
,
49 gdth_ctr_vtab
[i
],hanum
,busnum
));
53 static int gdth_set_info(char *buffer
,int length
,struct Scsi_Host
*host
,
56 int ret_val
= -EINVAL
;
57 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
60 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
67 TRACE2(("gdth_set_info() ha %d bus %d\n",hanum
,busnum
));
69 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
70 sdev
= scsi_get_host_dev(host
);
71 scp
= scsi_allocate_request(sdev
, GFP_KERNEL
);
76 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
77 sdev
= scsi_get_host_dev(host
);
78 scp
= scsi_allocate_device(sdev
, 1, FALSE
);
84 memset(&sdev
,0,sizeof(Scsi_Device
));
85 memset(&scp
, 0,sizeof(Scsi_Cmnd
));
86 sdev
.host
= scp
.host
= host
;
87 sdev
.id
= scp
.target
= sdev
.host
->this_id
;
92 if (strncmp(buffer
,"gdth",4) == 0) {
95 ret_val
= gdth_set_asc_info( buffer
, length
, hanum
, scp
);
98 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
99 scsi_release_request(scp
);
100 scsi_free_host_dev(sdev
);
101 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
102 scsi_release_command(scp
);
103 scsi_free_host_dev(sdev
);
108 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
109 static int gdth_set_asc_info(char *buffer
,int length
,int hanum
,Scsi_Request
*scp
)
110 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
111 static int gdth_set_asc_info(char *buffer
,int length
,int hanum
,Scsi_Cmnd
*scp
)
113 static int gdth_set_asc_info(char *buffer
,int length
,int hanum
,Scsi_Cmnd scp
)
116 int orig_length
, drive
, wb_mode
;
120 gdth_cpar_str
*pcpar
;
123 char cmnd
[MAX_COMMAND_SIZE
];
124 memset(cmnd
, 0xff, 12);
125 memset(&gdtcmd
, 0, sizeof(gdth_cmd_str
));
127 TRACE2(("gdth_set_asc_info() ha %d\n",hanum
));
128 ha
= HADATA(gdth_ctr_tab
[hanum
]);
129 orig_length
= length
+ 5;
134 if (length
>= 5 && strncmp(buffer
,"flush",5)==0) {
137 if (length
&& *buffer
>='0' && *buffer
<='9') {
138 drive
= (int)(*buffer
-'0');
140 if (length
&& *buffer
>='0' && *buffer
<='9') {
141 drive
= drive
*10 + (int)(*buffer
-'0');
144 printk("GDT: Flushing host drive %d .. ",drive
);
146 printk("GDT: Flushing all host drives .. ");
148 for (i
= 0; i
< MAX_HDRIVES
; ++i
) {
149 if (ha
->hdr
[i
].present
) {
150 if (drive
!= -1 && i
!= drive
)
153 gdtcmd
.Service
= CACHESERVICE
;
154 gdtcmd
.OpCode
= GDT_FLUSH
;
155 if (ha
->cache_feat
& GDT_64BIT
) {
156 gdtcmd
.u
.cache64
.DeviceNo
= i
;
157 gdtcmd
.u
.cache64
.BlockNo
= 1;
159 gdtcmd
.u
.cache
.DeviceNo
= i
;
160 gdtcmd
.u
.cache
.BlockNo
= 1;
162 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
163 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
164 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
165 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
167 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
172 printk("\nNo host drive found !\n");
178 if (length
>= 7 && strncmp(buffer
,"wbp_off",7)==0) {
181 printk("GDT: Disabling write back permanently .. ");
183 } else if (length
>= 6 && strncmp(buffer
,"wbp_on",6)==0) {
186 printk("GDT: Enabling write back permanently .. ");
188 } else if (length
>= 6 && strncmp(buffer
,"wb_off",6)==0) {
191 printk("GDT: Disabling write back commands .. ");
192 if (ha
->cache_feat
& GDT_WR_THROUGH
) {
193 gdth_write_through
= TRUE
;
196 printk("Not supported !\n");
199 } else if (length
>= 5 && strncmp(buffer
,"wb_on",5)==0) {
202 printk("GDT: Enabling write back commands .. ");
203 gdth_write_through
= FALSE
;
209 if (!gdth_ioctl_alloc(hanum
, sizeof(gdth_cpar_str
), TRUE
, &paddr
))
211 pcpar
= (gdth_cpar_str
*)ha
->pscratch
;
212 memcpy( pcpar
, &ha
->cpar
, sizeof(gdth_cpar_str
) );
213 gdtcmd
.Service
= CACHESERVICE
;
214 gdtcmd
.OpCode
= GDT_IOCTL
;
215 gdtcmd
.u
.ioctl
.p_param
= paddr
;
216 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_cpar_str
);
217 gdtcmd
.u
.ioctl
.subfunc
= CACHE_CONFIG
;
218 gdtcmd
.u
.ioctl
.channel
= INVALID_CHANNEL
;
219 pcpar
->write_back
= wb_mode
==1 ? 0:1;
220 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
221 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
222 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
223 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
225 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
227 gdth_ioctl_free(hanum
, GDTH_SCRATCH
, ha
->pscratch
, paddr
);
232 printk("GDT: Unknown command: %s Length: %d\n",buffer
,length
);
236 static int gdth_get_info(char *buffer
,char **start
,off_t offset
,int length
,
237 struct Scsi_Host
*host
,int hanum
,int busnum
)
239 int size
= 0,len
= 0;
240 off_t begin
= 0,pos
= 0;
242 int id
, i
, j
, k
, sec
, flag
;
243 int no_mdrv
= 0, drv_no
, is_mirr
;
249 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
252 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
263 gdth_dskstat_str
*pds
;
264 gdth_diskinfo_str
*pdi
;
265 gdth_arrayinf_str
*pai
;
266 gdth_defcnt_str
*pdef
;
267 gdth_cdrinfo_str
*pcdi
;
270 char cmnd
[MAX_COMMAND_SIZE
];
271 memset(cmnd
, 0xff, 12);
272 memset(&gdtcmd
, 0, sizeof(gdth_cmd_str
));
274 TRACE2(("gdth_get_info() ha %d bus %d\n",hanum
,busnum
));
275 ha
= HADATA(gdth_ctr_tab
[hanum
]);
277 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
278 sdev
= scsi_get_host_dev(host
);
279 scp
= scsi_allocate_request(sdev
, GFP_KERNEL
);
282 scp
->sr_cmd_len
= 12;
284 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
285 sdev
= scsi_get_host_dev(host
);
286 scp
= scsi_allocate_device(sdev
, 1, FALSE
);
292 memset(&sdev
,0,sizeof(Scsi_Device
));
293 memset(&scp
, 0,sizeof(Scsi_Cmnd
));
294 sdev
.host
= scp
.host
= host
;
295 sdev
.id
= scp
.target
= sdev
.host
->this_id
;
300 /* request is i.e. "cat /proc/scsi/gdth/0" */
301 /* format: %-15s\t%-10s\t%-15s\t%s */
302 /* driver parameters */
303 size
= sprintf(buffer
+len
,"Driver Parameters:\n");
304 len
+= size
; pos
= begin
+ len
;
305 if (reserve_list
[0] == 0xff)
308 sprintf(hrec
, "%d", reserve_list
[0]);
309 for (i
= 1; i
< MAX_RES_ARGS
; i
++) {
310 if (reserve_list
[i
] == 0xff)
312 sprintf(hrec
,"%s,%d", hrec
, reserve_list
[i
]);
315 size
= sprintf(buffer
+len
,
316 " reserve_mode: \t%d \treserve_list: \t%s\n",
318 len
+= size
; pos
= begin
+ len
;
319 size
= sprintf(buffer
+len
,
320 " max_ids: \t%-3d \thdr_channel: \t%d\n",
321 max_ids
, hdr_channel
);
322 len
+= size
; pos
= begin
+ len
;
324 /* controller information */
325 size
= sprintf(buffer
+len
,"\nDisk Array Controller Information:\n");
326 len
+= size
; pos
= begin
+ len
;
328 sprintf(hrec
, "%s (Bus %d)", ha
->binfo
.type_string
, busnum
);
330 strcpy(hrec
, ha
->binfo
.type_string
);
331 size
= sprintf(buffer
+len
,
332 " Number: \t%d \tName: \t%s\n",
334 len
+= size
; pos
= begin
+ len
;
337 sprintf(hrec
, "%d.%02d.%02d-%c%03X",
338 (unchar
)(ha
->binfo
.upd_fw_ver
>>24),
339 (unchar
)(ha
->binfo
.upd_fw_ver
>>16),
340 (unchar
)(ha
->binfo
.upd_fw_ver
),
341 ha
->bfeat
.raid
? 'R':'N',
342 ha
->binfo
.upd_revision
);
344 sprintf(hrec
, "%d.%02d", (unchar
)(ha
->cpar
.version
>>8),
345 (unchar
)(ha
->cpar
.version
));
347 size
= sprintf(buffer
+len
,
348 " Driver Ver.: \t%-10s\tFirmware Ver.: \t%s\n",
349 GDTH_VERSION_STR
, hrec
);
350 len
+= size
; pos
= begin
+ len
;
353 /* more information: 1. about controller */
354 size
= sprintf(buffer
+len
,
355 " Serial No.: \t0x%8X\tCache RAM size:\t%d KB\n",
356 ha
->binfo
.ser_no
, ha
->binfo
.memsize
/ 1024);
357 len
+= size
; pos
= begin
+ len
;
360 #ifdef GDTH_DMA_STATISTICS
361 /* controller statistics */
362 size
= sprintf(buffer
+len
,"\nController Statistics:\n");
363 len
+= size
; pos
= begin
+ len
;
364 size
= sprintf(buffer
+len
,
365 " 32-bit DMA buffer:\t%lu\t64-bit DMA buffer:\t%lu\n",
366 ha
->dma32_cnt
, ha
->dma64_cnt
);
367 len
+= size
; pos
= begin
+ len
;
374 if (pos
> offset
+ length
)
378 /* more information: 2. about physical devices */
379 size
= sprintf(buffer
+len
,"\nPhysical Devices:");
380 len
+= size
; pos
= begin
+ len
;
383 buf
= gdth_ioctl_alloc(hanum
, GDTH_SCRATCH
, FALSE
, &paddr
);
386 for (i
= 0; i
< ha
->bus_cnt
; ++i
) {
387 /* 2.a statistics (and retries/reassigns) */
388 TRACE2(("pdr_statistics() chn %d\n",i
));
389 pds
= (gdth_dskstat_str
*)(buf
+ GDTH_SCRATCH
/4);
390 gdtcmd
.Service
= CACHESERVICE
;
391 gdtcmd
.OpCode
= GDT_IOCTL
;
392 gdtcmd
.u
.ioctl
.p_param
= paddr
+ GDTH_SCRATCH
/4;
393 gdtcmd
.u
.ioctl
.param_size
= 3*GDTH_SCRATCH
/4;
394 gdtcmd
.u
.ioctl
.subfunc
= DSK_STATISTICS
| L_CTRL_PATTERN
;
395 gdtcmd
.u
.ioctl
.channel
= ha
->raw
[i
].address
| INVALID_CHANNEL
;
396 pds
->bid
= ha
->raw
[i
].local_no
;
398 pds
->entries
= ha
->raw
[i
].pdev_cnt
;
399 cnt
= (3*GDTH_SCRATCH
/4 - 5 * sizeof(ulong32
)) /
400 sizeof(pds
->list
[0]);
401 if (pds
->entries
> cnt
)
403 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
404 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
405 if (scp
->sr_command
->SCp
.Status
!= S_OK
)
406 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
407 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
408 if (scp
->SCp
.Status
!= S_OK
)
410 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
411 if (scp
.SCp
.Status
!= S_OK
)
417 /* other IOCTLs must fit into area GDTH_SCRATCH/4 */
418 for (j
= 0; j
< ha
->raw
[i
].pdev_cnt
; ++j
) {
420 TRACE2(("scsi_drv_info() chn %d dev %d\n",
421 i
, ha
->raw
[i
].id_list
[j
]));
422 pdi
= (gdth_diskinfo_str
*)buf
;
423 gdtcmd
.Service
= CACHESERVICE
;
424 gdtcmd
.OpCode
= GDT_IOCTL
;
425 gdtcmd
.u
.ioctl
.p_param
= paddr
;
426 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_diskinfo_str
);
427 gdtcmd
.u
.ioctl
.subfunc
= SCSI_DR_INFO
| L_CTRL_PATTERN
;
428 gdtcmd
.u
.ioctl
.channel
=
429 ha
->raw
[i
].address
| ha
->raw
[i
].id_list
[j
];
430 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
431 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
432 if (scp
->sr_command
->SCp
.Status
== S_OK
)
433 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
434 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
435 if (scp
->SCp
.Status
== S_OK
)
437 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
438 if (scp
.SCp
.Status
== S_OK
)
441 strncpy(hrec
,pdi
->vendor
,8);
442 strncpy(hrec
+8,pdi
->product
,16);
443 strncpy(hrec
+24,pdi
->revision
,4);
445 size
= sprintf(buffer
+len
,
446 "\n Chn/ID/LUN: \t%c/%02d/%d \tName: \t%s\n",
447 'A'+i
,pdi
->target_id
,pdi
->lun
,hrec
);
448 len
+= size
; pos
= begin
+ len
;
450 pdi
->no_ldrive
&= 0xffff;
451 if (pdi
->no_ldrive
== 0xffff)
454 sprintf(hrec
,"%d",pdi
->no_ldrive
);
455 size
= sprintf(buffer
+len
,
456 " Capacity [MB]:\t%-6d \tTo Log. Drive: \t%s\n",
457 pdi
->blkcnt
/(1024*1024/pdi
->blksize
),
459 len
+= size
; pos
= begin
+ len
;
464 if (pdi
->devtype
== 0) {
465 /* search retries/reassigns */
466 for (k
= 0; k
< pds
->count
; ++k
) {
467 if (pds
->list
[k
].tid
== pdi
->target_id
&&
468 pds
->list
[k
].lun
== pdi
->lun
) {
469 size
= sprintf(buffer
+len
,
470 " Retries: \t%-6d \tReassigns: \t%d\n",
471 pds
->list
[k
].retries
,
472 pds
->list
[k
].reassigns
);
473 len
+= size
; pos
= begin
+ len
;
477 /* 2.c grown defects */
478 TRACE2(("scsi_drv_defcnt() chn %d dev %d\n",
479 i
, ha
->raw
[i
].id_list
[j
]));
480 pdef
= (gdth_defcnt_str
*)buf
;
481 gdtcmd
.Service
= CACHESERVICE
;
482 gdtcmd
.OpCode
= GDT_IOCTL
;
483 gdtcmd
.u
.ioctl
.p_param
= paddr
;
484 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_defcnt_str
);
485 gdtcmd
.u
.ioctl
.subfunc
= SCSI_DEF_CNT
| L_CTRL_PATTERN
;
486 gdtcmd
.u
.ioctl
.channel
=
487 ha
->raw
[i
].address
| ha
->raw
[i
].id_list
[j
];
488 pdef
->sddc_type
= 0x08;
489 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
490 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
491 if (scp
->sr_command
->SCp
.Status
== S_OK
)
492 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
493 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
494 if (scp
->SCp
.Status
== S_OK
)
496 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
497 if (scp
.SCp
.Status
== S_OK
)
500 size
= sprintf(buffer
+len
,
501 " Grown Defects:\t%d\n",
503 len
+= size
; pos
= begin
+ len
;
510 if (pos
> offset
+ length
)
514 gdth_ioctl_free(hanum
, GDTH_SCRATCH
, buf
, paddr
);
517 size
= sprintf(buffer
+len
, "\n --\n");
518 len
+= size
; pos
= begin
+ len
;
521 /* 3. about logical drives */
522 size
= sprintf(buffer
+len
,"\nLogical Drives:");
523 len
+= size
; pos
= begin
+ len
;
526 buf
= gdth_ioctl_alloc(hanum
, GDTH_SCRATCH
, FALSE
, &paddr
);
529 for (i
= 0; i
< MAX_LDRIVES
; ++i
) {
530 if (!ha
->hdr
[i
].is_logdrv
)
536 /* 3.a log. drive info */
537 TRACE2(("cache_drv_info() drive no %d\n",drv_no
));
538 pcdi
= (gdth_cdrinfo_str
*)buf
;
539 gdtcmd
.Service
= CACHESERVICE
;
540 gdtcmd
.OpCode
= GDT_IOCTL
;
541 gdtcmd
.u
.ioctl
.p_param
= paddr
;
542 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_cdrinfo_str
);
543 gdtcmd
.u
.ioctl
.subfunc
= CACHE_DRV_INFO
;
544 gdtcmd
.u
.ioctl
.channel
= drv_no
;
545 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
546 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
547 if (scp
->sr_command
->SCp
.Status
!= S_OK
)
548 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
549 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
550 if (scp
->SCp
.Status
!= S_OK
)
552 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
553 if (scp
.SCp
.Status
!= S_OK
)
558 pcdi
->ld_dtype
>>= 16;
560 if (pcdi
->ld_dtype
> 2) {
561 strcpy(hrec
, "missing");
562 } else if (pcdi
->ld_error
& 1) {
563 strcpy(hrec
, "fault");
564 } else if (pcdi
->ld_error
& 2) {
565 strcpy(hrec
, "invalid");
572 size
= sprintf(buffer
+len
,
573 "\n Number: \t%-2d \tStatus: \t%s\n",
575 len
+= size
; pos
= begin
+ len
;
577 no_mdrv
= pcdi
->cd_ldcnt
;
578 if (no_mdrv
> 1 || pcdi
->ld_slave
!= -1) {
580 strcpy(hrec
, "RAID-1");
581 } else if (pcdi
->ld_dtype
== 0) {
582 strcpy(hrec
, "Disk");
583 } else if (pcdi
->ld_dtype
== 1) {
584 strcpy(hrec
, "RAID-0");
585 } else if (pcdi
->ld_dtype
== 2) {
586 strcpy(hrec
, "Chain");
590 size
= sprintf(buffer
+len
,
591 " Capacity [MB]:\t%-6d \tType: \t%s\n",
592 pcdi
->ld_blkcnt
/(1024*1024/pcdi
->ld_blksize
),
594 len
+= size
; pos
= begin
+ len
;
596 size
= sprintf(buffer
+len
,
597 " Slave Number: \t%-2d \tStatus: \t%s\n",
598 drv_no
& 0x7fff, hrec
);
599 len
+= size
; pos
= begin
+ len
;
601 drv_no
= pcdi
->ld_slave
;
606 if (pos
> offset
+ length
)
608 } while (drv_no
!= -1);
611 size
= sprintf(buffer
+len
,
612 " Missing Drv.: \t%-2d \tInvalid Drv.: \t%d\n",
614 len
+= size
; pos
= begin
+ len
;
617 if (!ha
->hdr
[i
].is_arraydrv
)
620 sprintf(hrec
, "%d", ha
->hdr
[i
].master_no
);
621 size
= sprintf(buffer
+len
,
622 " To Array Drv.:\t%s\n", hrec
);
623 len
+= size
; pos
= begin
+ len
;
628 if (pos
> offset
+ length
)
631 gdth_ioctl_free(hanum
, GDTH_SCRATCH
, buf
, paddr
);
634 size
= sprintf(buffer
+len
, "\n --\n");
635 len
+= size
; pos
= begin
+ len
;
638 /* 4. about array drives */
639 size
= sprintf(buffer
+len
,"\nArray Drives:");
640 len
+= size
; pos
= begin
+ len
;
643 buf
= gdth_ioctl_alloc(hanum
, GDTH_SCRATCH
, FALSE
, &paddr
);
646 for (i
= 0; i
< MAX_LDRIVES
; ++i
) {
647 if (!(ha
->hdr
[i
].is_arraydrv
&& ha
->hdr
[i
].is_master
))
649 /* 4.a array drive info */
650 TRACE2(("array_info() drive no %d\n",i
));
651 pai
= (gdth_arrayinf_str
*)buf
;
652 gdtcmd
.Service
= CACHESERVICE
;
653 gdtcmd
.OpCode
= GDT_IOCTL
;
654 gdtcmd
.u
.ioctl
.p_param
= paddr
;
655 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_arrayinf_str
);
656 gdtcmd
.u
.ioctl
.subfunc
= ARRAY_INFO
| LA_CTRL_PATTERN
;
657 gdtcmd
.u
.ioctl
.channel
= i
;
658 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
659 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
660 if (scp
->sr_command
->SCp
.Status
== S_OK
)
661 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
662 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
663 if (scp
->SCp
.Status
== S_OK
)
665 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
666 if (scp
.SCp
.Status
== S_OK
)
669 if (pai
->ai_state
== 0)
670 strcpy(hrec
, "idle");
671 else if (pai
->ai_state
== 2)
672 strcpy(hrec
, "build");
673 else if (pai
->ai_state
== 4)
674 strcpy(hrec
, "ready");
675 else if (pai
->ai_state
== 6)
676 strcpy(hrec
, "fail");
677 else if (pai
->ai_state
== 8 || pai
->ai_state
== 10)
678 strcpy(hrec
, "rebuild");
680 strcpy(hrec
, "error");
681 if (pai
->ai_ext_state
& 0x10)
682 strcat(hrec
, "/expand");
683 else if (pai
->ai_ext_state
& 0x1)
684 strcat(hrec
, "/patch");
685 size
= sprintf(buffer
+len
,
686 "\n Number: \t%-2d \tStatus: \t%s\n",
688 len
+= size
; pos
= begin
+ len
;
691 if (pai
->ai_type
== 0)
692 strcpy(hrec
, "RAID-0");
693 else if (pai
->ai_type
== 4)
694 strcpy(hrec
, "RAID-4");
695 else if (pai
->ai_type
== 5)
696 strcpy(hrec
, "RAID-5");
698 strcpy(hrec
, "RAID-10");
699 size
= sprintf(buffer
+len
,
700 " Capacity [MB]:\t%-6d \tType: \t%s\n",
701 pai
->ai_size
/(1024*1024/pai
->ai_secsize
),
703 len
+= size
; pos
= begin
+ len
;
708 if (pos
> offset
+ length
)
712 gdth_ioctl_free(hanum
, GDTH_SCRATCH
, buf
, paddr
);
715 size
= sprintf(buffer
+len
, "\n --\n");
716 len
+= size
; pos
= begin
+ len
;
719 /* 5. about host drives */
720 size
= sprintf(buffer
+len
,"\nHost Drives:");
721 len
+= size
; pos
= begin
+ len
;
724 buf
= gdth_ioctl_alloc(hanum
, sizeof(gdth_hget_str
), FALSE
, &paddr
);
727 for (i
= 0; i
< MAX_LDRIVES
; ++i
) {
728 if (!ha
->hdr
[i
].is_logdrv
||
729 (ha
->hdr
[i
].is_arraydrv
&& !ha
->hdr
[i
].is_master
))
731 /* 5.a get host drive list */
732 TRACE2(("host_get() drv_no %d\n",i
));
733 phg
= (gdth_hget_str
*)buf
;
734 gdtcmd
.Service
= CACHESERVICE
;
735 gdtcmd
.OpCode
= GDT_IOCTL
;
736 gdtcmd
.u
.ioctl
.p_param
= paddr
;
737 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_hget_str
);
738 gdtcmd
.u
.ioctl
.subfunc
= HOST_GET
| LA_CTRL_PATTERN
;
739 gdtcmd
.u
.ioctl
.channel
= i
;
740 phg
->entries
= MAX_HDRIVES
;
741 phg
->offset
= GDTOFFSOF(gdth_hget_str
, entry
[0]);
742 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
743 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
744 if (scp
->sr_command
->SCp
.Status
!= S_OK
)
745 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
746 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
747 if (scp
->SCp
.Status
!= S_OK
)
749 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
750 if (scp
.SCp
.Status
!= S_OK
)
753 ha
->hdr
[i
].ldr_no
= i
;
754 ha
->hdr
[i
].rw_attribs
= 0;
755 ha
->hdr
[i
].start_sec
= 0;
757 for (j
= 0; j
< phg
->entries
; ++j
) {
758 k
= phg
->entry
[j
].host_drive
;
759 if (k
>= MAX_LDRIVES
)
761 ha
->hdr
[k
].ldr_no
= phg
->entry
[j
].log_drive
;
762 ha
->hdr
[k
].rw_attribs
= phg
->entry
[j
].rw_attribs
;
763 ha
->hdr
[k
].start_sec
= phg
->entry
[j
].start_sec
;
767 gdth_ioctl_free(hanum
, sizeof(gdth_hget_str
), buf
, paddr
);
769 for (i
= 0; i
< MAX_HDRIVES
; ++i
) {
770 if (!(ha
->hdr
[i
].present
))
773 size
= sprintf(buffer
+len
,
774 "\n Number: \t%-2d \tArr/Log. Drive:\t%d\n",
775 i
, ha
->hdr
[i
].ldr_no
);
776 len
+= size
; pos
= begin
+ len
;
779 size
= sprintf(buffer
+len
,
780 " Capacity [MB]:\t%-6d \tStart Sector: \t%d\n",
781 (ulong32
)(ha
->hdr
[i
].size
/2048), ha
->hdr
[i
].start_sec
);
782 len
+= size
; pos
= begin
+ len
;
787 if (pos
> offset
+ length
)
792 size
= sprintf(buffer
+len
, "\n --\n");
793 len
+= size
; pos
= begin
+ len
;
797 /* controller events */
798 size
= sprintf(buffer
+len
,"\nController Events:\n");
799 len
+= size
; pos
= begin
+ len
;
802 id
= gdth_read_event(ha
, id
, &estr
);
803 if (estr
.event_source
== 0)
805 if (estr
.event_data
.eu
.driver
.ionode
== hanum
&&
806 estr
.event_source
== ES_ASYNC
) {
807 gdth_log_event(&estr
.event_data
, hrec
);
808 do_gettimeofday(&tv
);
809 sec
= (int)(tv
.tv_sec
- estr
.first_stamp
);
810 if (sec
< 0) sec
= 0;
811 size
= sprintf(buffer
+len
," date- %02d:%02d:%02d\t%s\n",
812 sec
/3600, sec
%3600/60, sec
%60, hrec
);
813 len
+= size
; pos
= begin
+ len
;
818 if (pos
> offset
+ length
)
826 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
827 scsi_release_request(scp
);
828 scsi_free_host_dev(sdev
);
829 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
830 scsi_release_command(scp
);
831 scsi_free_host_dev(sdev
);
833 *start
= buffer
+(offset
-begin
);
834 len
-= (offset
-begin
);
837 TRACE2(("get_info() len %d pos %d begin %d offset %d length %d size %d\n",
838 len
,(int)pos
,(int)begin
,(int)offset
,length
,size
));
843 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
844 static void gdth_do_req(Scsi_Request
*scp
, gdth_cmd_str
*gdtcmd
,
845 char *cmnd
, int timeout
)
848 DECLARE_COMPLETION(wait
);
850 TRACE2(("gdth_do_req()\n"));
851 if (gdtcmd
!= NULL
) {
852 bufflen
= sizeof(gdth_cmd_str
);
856 scp
->sr_request
->rq_status
= RQ_SCSI_BUSY
;
857 scp
->sr_request
->waiting
= &wait
;
858 scsi_do_req(scp
, cmnd
, gdtcmd
, bufflen
, gdth_scsi_done
, timeout
*HZ
, 1);
859 wait_for_completion(&wait
);
863 static void gdth_do_cmd(Scsi_Cmnd
*scp
, gdth_cmd_str
*gdtcmd
,
864 char *cmnd
, int timeout
)
867 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
868 DECLARE_COMPLETION(wait
);
869 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
870 DECLARE_MUTEX_LOCKED(sem
);
872 struct semaphore sem
= MUTEX_LOCKED
;
875 TRACE2(("gdth_do_cmd()\n"));
876 if (gdtcmd
!= NULL
) {
877 scp
->SCp
.this_residual
= IOCTL_PRI
;
878 bufflen
= sizeof(gdth_cmd_str
);
880 scp
->SCp
.this_residual
= DEFAULT_PRI
;
883 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
884 scp
->request
.rq_status
= RQ_SCSI_BUSY
;
885 scp
->request
.waiting
= &wait
;
886 scsi_do_cmd(scp
, cmnd
, gdtcmd
, bufflen
, gdth_scsi_done
, timeout
*HZ
, 1);
887 wait_for_completion(&wait
);
889 scp
->request
.sem
= &sem
;
890 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
891 scsi_do_cmd(scp
, cmnd
, gdtcmd
, bufflen
, gdth_scsi_done
, timeout
*HZ
, 1);
893 spin_lock_irq(&io_request_lock
);
894 scsi_do_cmd(scp
, cmnd
, gdtcmd
, bufflen
, gdth_scsi_done
, timeout
*HZ
, 1);
895 spin_unlock_irq(&io_request_lock
);
902 void gdth_scsi_done(Scsi_Cmnd
*scp
)
904 TRACE2(("gdth_scsi_done()\n"));
906 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
907 scp
->request
->rq_status
= RQ_SCSI_DONE
;
908 if (scp
->request
->waiting
!= NULL
)
909 complete(scp
->request
->waiting
);
910 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
911 scp
->request
.rq_status
= RQ_SCSI_DONE
;
912 if (scp
->request
.waiting
!= NULL
)
913 complete(scp
->request
.waiting
);
915 scp
->request
.rq_status
= RQ_SCSI_DONE
;
916 if (scp
->request
.sem
!= NULL
)
917 up(scp
->request
.sem
);
921 static char *gdth_ioctl_alloc(int hanum
, int size
, int scratch
,
931 ha
= HADATA(gdth_ctr_tab
[hanum
]);
932 GDTH_LOCK_HA(ha
, flags
);
934 if (!ha
->scratch_busy
&& size
<= GDTH_SCRATCH
) {
935 ha
->scratch_busy
= TRUE
;
936 ret_val
= ha
->pscratch
;
937 *paddr
= ha
->scratch_phys
;
938 } else if (scratch
) {
941 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
944 ret_val
= pci_alloc_consistent(ha
->pdev
, size
, &dma_addr
);
947 ret_val
= scsi_init_malloc(size
, GFP_ATOMIC
| GFP_DMA
);
949 *paddr
= virt_to_bus(ret_val
);
953 GDTH_UNLOCK_HA(ha
, flags
);
957 static void gdth_ioctl_free(int hanum
, int size
, char *buf
, ulong64 paddr
)
962 ha
= HADATA(gdth_ctr_tab
[hanum
]);
963 GDTH_LOCK_HA(ha
, flags
);
965 if (buf
== ha
->pscratch
) {
966 ha
->scratch_busy
= FALSE
;
968 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
969 pci_free_consistent(ha
->pdev
, size
, buf
, paddr
);
971 scsi_init_free((void *)buf
, size
);
975 GDTH_UNLOCK_HA(ha
, flags
);
978 #ifdef GDTH_IOCTL_PROC
979 static int gdth_ioctl_check_bin(int hanum
, ushort size
)
985 ha
= HADATA(gdth_ctr_tab
[hanum
]);
986 GDTH_LOCK_HA(ha
, flags
);
989 if (ha
->scratch_busy
) {
990 if (((gdth_iord_str
*)ha
->pscratch
)->size
== (ulong32
)size
)
993 GDTH_UNLOCK_HA(ha
, flags
);
998 static void gdth_wait_completion(int hanum
, int busnum
, int id
)
1006 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1007 GDTH_LOCK_HA(ha
, flags
);
1009 for (i
= 0; i
< GDTH_MAXCMDS
; ++i
) {
1010 scp
= ha
->cmd_tab
[i
].cmnd
;
1011 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
1012 b
= virt_ctr
? NUMDATA(scp
->device
->host
)->busnum
: scp
->device
->channel
;
1013 t
= scp
->device
->id
;
1015 b
= virt_ctr
? NUMDATA(scp
->host
)->busnum
: scp
->channel
;
1018 if (!SPECIAL_SCP(scp
) && t
== (unchar
)id
&&
1019 b
== (unchar
)busnum
) {
1020 scp
->SCp
.have_data_in
= 0;
1021 GDTH_UNLOCK_HA(ha
, flags
);
1022 while (!scp
->SCp
.have_data_in
)
1024 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
1025 GDTH_LOCK_SCSI_DONE(scp
->device
->host
, flags
);
1026 scp
->scsi_done(scp
);
1027 GDTH_UNLOCK_SCSI_DONE(scp
->device
->host
, flags
);
1029 GDTH_LOCK_SCSI_DONE(flags
);
1030 scp
->scsi_done(scp
);
1031 GDTH_UNLOCK_SCSI_DONE(flags
);
1033 GDTH_LOCK_HA(ha
, flags
);
1036 GDTH_UNLOCK_HA(ha
, flags
);
1039 static void gdth_stop_timeout(int hanum
, int busnum
, int id
)
1046 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1047 GDTH_LOCK_HA(ha
, flags
);
1049 for (scp
= ha
->req_first
; scp
; scp
= (Scsi_Cmnd
*)scp
->SCp
.ptr
) {
1050 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
1051 b
= virt_ctr
? NUMDATA(scp
->device
->host
)->busnum
: scp
->device
->channel
;
1052 t
= scp
->device
->id
;
1054 b
= virt_ctr
? NUMDATA(scp
->host
)->busnum
: scp
->channel
;
1057 if (t
== (unchar
)id
&& b
== (unchar
)busnum
) {
1058 TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
1059 scp
->SCp
.buffers_residual
= gdth_update_timeout(hanum
, scp
, 0);
1062 GDTH_UNLOCK_HA(ha
, flags
);
1065 static void gdth_start_timeout(int hanum
, int busnum
, int id
)
1072 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1073 GDTH_LOCK_HA(ha
, flags
);
1075 for (scp
= ha
->req_first
; scp
; scp
= (Scsi_Cmnd
*)scp
->SCp
.ptr
) {
1076 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
1077 b
= virt_ctr
? NUMDATA(scp
->device
->host
)->busnum
: scp
->device
->channel
;
1078 t
= scp
->device
->id
;
1080 b
= virt_ctr
? NUMDATA(scp
->host
)->busnum
: scp
->channel
;
1083 if (t
== (unchar
)id
&& b
== (unchar
)busnum
) {
1084 TRACE2(("gdth_start_timeout(): update_timeout()\n"));
1085 gdth_update_timeout(hanum
, scp
, scp
->SCp
.buffers_residual
);
1088 GDTH_UNLOCK_HA(ha
, flags
);
1091 static int gdth_update_timeout(int hanum
, Scsi_Cmnd
*scp
, int timeout
)
1095 oldto
= scp
->timeout_per_command
;
1096 scp
->timeout_per_command
= timeout
;
1099 del_timer(&scp
->eh_timeout
);
1100 scp
->eh_timeout
.data
= (unsigned long) NULL
;
1101 scp
->eh_timeout
.expires
= 0;
1103 if (scp
->eh_timeout
.data
!= (unsigned long) NULL
)
1104 del_timer(&scp
->eh_timeout
);
1105 scp
->eh_timeout
.data
= (unsigned long) scp
;
1106 scp
->eh_timeout
.expires
= jiffies
+ timeout
;
1107 add_timer(&scp
->eh_timeout
);