2 * $Id: gdth_proc.c,v 1.13 1999/03/22 16:12:53 achim Exp $
5 #include "gdth_ioctl.h"
7 int gdth_proc_info(char *buffer
,char **start
,off_t offset
,int length
,
12 TRACE2(("gdth_proc_info() length %d ha %d offs %d inout %d\n",
13 length
,hostno
,(int)offset
,inout
));
15 for (i
=0; i
<gdth_ctr_vcount
; ++i
) {
16 if (gdth_ctr_vtab
[i
]->host_no
== hostno
)
19 if (i
==gdth_ctr_vcount
)
22 hanum
= NUMDATA(gdth_ctr_vtab
[i
])->hanum
;
23 busnum
= NUMDATA(gdth_ctr_vtab
[i
])->busnum
;
26 return(gdth_set_info(buffer
,length
,i
,hanum
,busnum
));
28 return(gdth_get_info(buffer
,start
,offset
,length
,i
,hanum
,busnum
));
31 static int gdth_set_info(char *buffer
,int length
,int vh
,int hanum
,int busnum
)
38 TRACE2(("gdth_set_info() ha %d bus %d\n",hanum
,busnum
));
39 piowr
= (gdth_iowr_str
*)buffer
;
41 memset(&sdev
,0,sizeof(Scsi_Device
));
42 memset(&scp
, 0,sizeof(Scsi_Cmnd
));
43 sdev
.host
= gdth_ctr_vtab
[vh
];
44 sdev
.id
= sdev
.host
->this_id
;
46 scp
.host
= gdth_ctr_vtab
[vh
];
47 scp
.target
= sdev
.host
->this_id
;
52 if (strncmp(buffer
,"gdth",4) == 0) {
55 ret_val
= gdth_set_asc_info( buffer
, length
, hanum
, scp
);
56 } else if (piowr
->magic
== GDTIOCTL_MAGIC
) {
57 ret_val
= gdth_set_bin_info( buffer
, length
, hanum
, scp
);
59 printk("GDT: Wrong signature: %6s\n",buffer
);
68 static int gdth_set_asc_info(char *buffer
,int length
,int hanum
,Scsi_Cmnd scp
)
70 int orig_length
, drive
, wb_mode
;
76 TRACE2(("gdth_set_asc_info() ha %d\n",hanum
));
77 ha
= HADATA(gdth_ctr_tab
[hanum
]);
78 orig_length
= length
+ 5;
83 if (length
>= 5 && strncmp(buffer
,"flush",5)==0) {
86 if (length
&& *buffer
>='0' && *buffer
<='9') {
87 drive
= (int)(*buffer
-'0');
89 if (length
&& *buffer
>='0' && *buffer
<='9') {
90 drive
= drive
*10 + (int)(*buffer
-'0');
93 printk("GDT: Flushing host drive %d .. ",drive
);
95 printk("GDT: Flushing all host drives .. ");
97 for (i
= 0; i
< MAX_HDRIVES
; ++i
) {
98 if (ha
->hdr
[i
].present
) {
99 if (drive
!= -1 && i
!= drive
)
102 gdtcmd
.BoardNode
= LOCALBOARD
;
103 gdtcmd
.Service
= CACHESERVICE
;
104 gdtcmd
.OpCode
= GDT_FLUSH
;
105 gdtcmd
.u
.cache
.DeviceNo
= i
;
106 gdtcmd
.u
.cache
.BlockNo
= 1;
107 gdtcmd
.u
.cache
.sg_canz
= 0;
108 gdth_do_cmd(&scp
, &gdtcmd
, 30);
112 printk("\nNo host drive found !\n");
118 if (length
>= 7 && strncmp(buffer
,"wbp_off",7)==0) {
121 printk("GDT: Disabling write back permanently .. ");
123 } else if (length
>= 6 && strncmp(buffer
,"wbp_on",6)==0) {
126 printk("GDT: Enabling write back permanently .. ");
128 } else if (length
>= 6 && strncmp(buffer
,"wb_off",6)==0) {
131 printk("GDT: Disabling write back commands .. ");
132 if (ha
->cache_feat
& GDT_WR_THROUGH
) {
133 gdth_write_through
= TRUE
;
136 printk("Not supported !\n");
139 } else if (length
>= 5 && strncmp(buffer
,"wb_on",5)==0) {
142 printk("GDT: Enabling write back commands .. ");
143 gdth_write_through
= FALSE
;
149 if (!gdth_ioctl_alloc(hanum
, sizeof(gdth_cpar_str
)))
151 pcpar
= (gdth_cpar_str
*)ha
->pscratch
;
152 memcpy( pcpar
, &ha
->cpar
, sizeof(gdth_cpar_str
) );
153 gdtcmd
.BoardNode
= LOCALBOARD
;
154 gdtcmd
.Service
= CACHESERVICE
;
155 gdtcmd
.OpCode
= GDT_IOCTL
;
156 gdtcmd
.u
.ioctl
.p_param
= virt_to_bus(pcpar
);
157 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_cpar_str
);
158 gdtcmd
.u
.ioctl
.subfunc
= CACHE_CONFIG
;
159 gdtcmd
.u
.ioctl
.channel
= INVALID_CHANNEL
;
160 pcpar
->write_back
= wb_mode
==1 ? 0:1;
161 gdth_do_cmd(&scp
, &gdtcmd
, 30);
162 gdth_ioctl_free(hanum
);
167 printk("GDT: Unknown command: %s Length: %d\n",buffer
,length
);
171 static int gdth_set_bin_info(char *buffer
,int length
,int hanum
,Scsi_Cmnd scp
)
175 gdth_iowr_str
*piowr
;
176 gdth_iord_str
*piord
;
179 ulong32
*ppadd
, add_size
;
180 ulong32
*ppadd2
, add_size2
;
183 TRACE2(("gdth_set_bin_info() ha %d\n",hanum
));
184 ha
= HADATA(gdth_ctr_tab
[hanum
]);
185 piowr
= (gdth_iowr_str
*)buffer
;
188 ppadd
= ppadd2
= NULL
;
189 add_size
= add_size2
= 0;
191 if (length
< GDTOFFSOF(gdth_iowr_str
,iu
))
194 switch (piowr
->ioctl
) {
195 case GDTIOCTL_GENERAL
:
196 if (length
< GDTOFFSOF(gdth_iowr_str
,iu
.general
.data
[0]))
198 pcmd
= (gdth_cmd_str
*)piowr
->iu
.general
.command
;
199 pcmd
->Service
= piowr
->service
;
200 if (pcmd
->OpCode
== GDT_IOCTL
) {
201 ppadd
= &pcmd
->u
.ioctl
.p_param
;
202 add_size
= pcmd
->u
.ioctl
.param_size
;
203 } else if (piowr
->service
== CACHESERVICE
) {
204 add_size
= pcmd
->u
.cache
.BlockCnt
* SECTOR_SIZE
;
205 if (ha
->cache_feat
& SCATTER_GATHER
) {
206 ppadd
= &pcmd
->u
.cache
.sg_lst
[0].sg_ptr
;
207 pcmd
->u
.cache
.DestAddr
= 0xffffffff;
208 pcmd
->u
.cache
.sg_lst
[0].sg_len
= add_size
;
209 pcmd
->u
.cache
.sg_canz
= 1;
211 ppadd
= &pcmd
->u
.cache
.DestAddr
;
212 pcmd
->u
.cache
.sg_canz
= 0;
214 } else if (piowr
->service
== SCSIRAWSERVICE
) {
215 add_size
= pcmd
->u
.raw
.sdlen
;
216 add_size2
= pcmd
->u
.raw
.sense_len
;
217 if (ha
->raw_feat
& SCATTER_GATHER
) {
218 ppadd
= &pcmd
->u
.raw
.sg_lst
[0].sg_ptr
;
219 pcmd
->u
.raw
.sdata
= 0xffffffff;
220 pcmd
->u
.raw
.sg_lst
[0].sg_len
= add_size
;
221 pcmd
->u
.raw
.sg_ranz
= 1;
223 ppadd
= &pcmd
->u
.raw
.sdata
;
224 pcmd
->u
.raw
.sg_ranz
= 0;
226 ppadd2
= &pcmd
->u
.raw
.sense_data
;
230 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
)+add_size
+add_size2
))
232 piord
= (gdth_iord_str
*)ha
->pscratch
;
234 piord
->size
= sizeof(gdth_iord_str
) + add_size
+ add_size2
;
236 memcpy(piord
->iu
.general
.data
, piowr
->iu
.general
.data
, add_size
);
237 *ppadd
= virt_to_bus(piord
->iu
.general
.data
);
240 memcpy(piord
->iu
.general
.data
+add_size
, piowr
->iu
.general
.data
, add_size2
);
241 *ppadd2
= virt_to_bus(piord
->iu
.general
.data
+add_size
);
244 gdth_do_cmd(&scp
, pcmd
, piowr
->timeout
);
245 piord
->status
= (ulong32
)scp
.SCp
.Message
;
248 case GDTIOCTL_DRVERS
:
249 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
) ))
251 piord
= (gdth_iord_str
*)ha
->pscratch
;
252 piord
->size
= sizeof(gdth_iord_str
);
253 piord
->status
= S_OK
;
254 piord
->iu
.drvers
.version
= (GDTH_VERSION
<<8) | GDTH_SUBVERSION
;
257 case GDTIOCTL_CTRTYPE
:
258 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
) ))
260 piord
= (gdth_iord_str
*)ha
->pscratch
;
261 piord
->size
= sizeof(gdth_iord_str
);
262 piord
->status
= S_OK
;
263 if (ha
->type
== GDT_ISA
|| ha
->type
== GDT_EISA
) {
264 piord
->iu
.ctrtype
.type
= (unchar
)((ha
->stype
>>20) - 0x10);
265 } else if (ha
->type
!= GDT_PCIMPR
) {
266 piord
->iu
.ctrtype
.type
= (unchar
)((ha
->stype
<<8) + 6);
268 piord
->iu
.ctrtype
.type
= 0xfe;
269 piord
->iu
.ctrtype
.ext_type
= 0x6000 | ha
->stype
;
271 piord
->iu
.ctrtype
.info
= ha
->brd_phys
;
272 piord
->iu
.ctrtype
.oem_id
= (ushort
)GDT3_ID
;
275 case GDTIOCTL_CTRCNT
:
276 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
) ))
278 piord
= (gdth_iord_str
*)ha
->pscratch
;
279 piord
->size
= sizeof(gdth_iord_str
);
280 piord
->status
= S_OK
;
281 piord
->iu
.ctrcnt
.count
= (ushort
)gdth_ctr_count
;
284 case GDTIOCTL_OSVERS
:
285 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
) ))
287 piord
= (gdth_iord_str
*)ha
->pscratch
;
288 piord
->size
= sizeof(gdth_iord_str
);
289 piord
->status
= S_OK
;
290 piord
->iu
.osvers
.version
= (unchar
)(LINUX_VERSION_CODE
>> 16);
291 piord
->iu
.osvers
.subversion
= (unchar
)(LINUX_VERSION_CODE
>> 8);
292 piord
->iu
.osvers
.revision
= (ushort
)(LINUX_VERSION_CODE
& 0xff);
295 case GDTIOCTL_LOCKDRV
:
296 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
) ))
298 piord
= (gdth_iord_str
*)ha
->pscratch
;
299 for (i
= 0; i
< piowr
->iu
.lockdrv
.drive_cnt
; ++i
) {
300 j
= piowr
->iu
.lockdrv
.drives
[i
];
301 if (j
>= MAX_HDRIVES
|| !ha
->hdr
[j
].present
)
303 if (piowr
->iu
.lockdrv
.lock
) {
304 GDTH_LOCK_HA(ha
, flags
);
306 GDTH_UNLOCK_HA(ha
, flags
);
307 gdth_wait_completion( hanum
, ha
->bus_cnt
, j
);
308 gdth_stop_timeout( hanum
, ha
->bus_cnt
, j
);
310 GDTH_LOCK_HA(ha
, flags
);
312 GDTH_UNLOCK_HA(ha
, flags
);
313 gdth_start_timeout( hanum
, ha
->bus_cnt
, j
);
317 piord
->size
= sizeof(gdth_iord_str
);
318 piord
->status
= S_OK
;
321 case GDTIOCTL_LOCKCHN
:
322 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
) ))
324 i
= piowr
->iu
.lockchn
.channel
;
325 if (i
< ha
->bus_cnt
) {
326 if (piowr
->iu
.lockchn
.lock
) {
327 GDTH_LOCK_HA(ha
, flags
);
329 GDTH_UNLOCK_HA(ha
, flags
);
330 for (j
= 0; j
< ha
->tid_cnt
; ++j
) {
331 gdth_wait_completion( hanum
, i
, j
);
332 gdth_stop_timeout( hanum
, i
, j
);
335 GDTH_LOCK_HA(ha
, flags
);
337 GDTH_UNLOCK_HA(ha
, flags
);
338 for (j
= 0; j
< ha
->tid_cnt
; ++j
) {
339 gdth_start_timeout( hanum
, i
, j
);
344 piord
= (gdth_iord_str
*)ha
->pscratch
;
345 piord
->size
= sizeof(gdth_iord_str
);
346 piord
->status
= S_OK
;
350 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
) ))
352 piord
= (gdth_iord_str
*)ha
->pscratch
;
353 if (piowr
->iu
.event
.erase
== 0xff) {
354 pevt
= (gdth_evt_str
*)piowr
->iu
.event
.evt
;
355 if (pevt
->event_source
== ES_TEST
)
356 pevt
->event_data
.size
= sizeof(pevt
->event_data
.eu
.test
);
357 else if (pevt
->event_source
== ES_DRIVER
)
358 pevt
->event_data
.size
= sizeof(pevt
->event_data
.eu
.driver
);
359 else if (pevt
->event_source
== ES_SYNC
)
360 pevt
->event_data
.size
= sizeof(pevt
->event_data
.eu
.sync
);
362 pevt
->event_data
.size
= sizeof(pevt
->event_data
.eu
.async
);
363 gdth_log_event(&pevt
->event_data
, NULL
);
365 GDTH_LOCK_HA(ha
, flags
);
366 gdth_store_event(ha
, pevt
->event_source
, pevt
->event_idx
,
368 GDTH_UNLOCK_HA(ha
, flags
);
369 } else if (piowr
->iu
.event
.erase
== 0xfe) {
371 } else if (piowr
->iu
.event
.erase
== 0) {
372 piord
->iu
.event
.handle
=
373 gdth_read_event(ha
,piowr
->iu
.event
.handle
,
374 (gdth_evt_str
*)piord
->iu
.event
.evt
);
376 piord
->iu
.event
.handle
= piowr
->iu
.event
.handle
;
377 gdth_readapp_event(ha
, (unchar
)piowr
->iu
.event
.erase
,
378 (gdth_evt_str
*)piord
->iu
.event
.evt
);
380 piord
->size
= sizeof(gdth_iord_str
);
381 piord
->status
= S_OK
;
387 /* we return a buffer ID to detect the right buffer during READ-IOCTL */
391 static int gdth_get_info(char *buffer
,char **start
,off_t offset
,
392 int length
,int vh
,int hanum
,int busnum
)
394 int size
= 0,len
= 0;
395 off_t begin
= 0,pos
= 0;
397 gdth_iord_str
*piord
;
398 int id
, i
, j
, k
, sec
, flag
;
399 int no_mdrv
= 0, drv_no
, is_mirr
;
409 gdth_dskstat_str
*pds
;
410 gdth_diskinfo_str
*pdi
;
411 gdth_arrayinf_str
*pai
;
412 gdth_defcnt_str
*pdef
;
413 gdth_cdrinfo_str
*pcdi
;
416 TRACE2(("gdth_get_info() ha %d bus %d\n",hanum
,busnum
));
417 ha
= HADATA(gdth_ctr_tab
[hanum
]);
420 memset(&sdev
,0,sizeof(Scsi_Device
));
421 memset(&scp
, 0,sizeof(Scsi_Cmnd
));
422 sdev
.host
= gdth_ctr_vtab
[vh
];
423 sdev
.id
= sdev
.host
->this_id
;
425 scp
.host
= gdth_ctr_vtab
[vh
];
426 scp
.target
= sdev
.host
->this_id
;
430 /* look for buffer ID in length */
432 /* request is i.e. "cat /proc/scsi/gdth/0" */
433 /* format: %-15s\t%-10s\t%-15s\t%s */
434 /* driver parameters */
435 size
= sprintf(buffer
+len
,"Driver Parameters:\n");
436 len
+= size
; pos
= begin
+ len
;
437 if (reserve_list
[0] == 0xff)
440 sprintf(hrec
, "%d", reserve_list
[0]);
441 for (i
= 1; i
< MAX_RES_ARGS
; i
++) {
442 if (reserve_list
[i
] == 0xff)
444 sprintf(hrec
,"%s,%d", hrec
, reserve_list
[i
]);
447 size
= sprintf(buffer
+len
,
448 " reserve_mode: \t%d \treserve_list: \t%s\n",
450 len
+= size
; pos
= begin
+ len
;
451 size
= sprintf(buffer
+len
,
452 " max_ids: \t%-3d \thdr_channel: \t%d\n",
453 max_ids
, hdr_channel
);
454 len
+= size
; pos
= begin
+ len
;
460 if (pos
> offset
+ length
)
463 /* controller information */
464 size
= sprintf(buffer
+len
,"\nDisk Array Controller Information:\n");
465 len
+= size
; pos
= begin
+ len
;
466 #if LINUX_VERSION_CODE >= 0x020000
467 strcpy(hrec
, ha
->binfo
.type_string
);
469 sprintf(hrec
, "%s (Bus %d)", ha
->binfo
.type_string
, busnum
);
471 size
= sprintf(buffer
+len
,
472 " Number: \t%d \tName: \t%s\n",
474 len
+= size
; pos
= begin
+ len
;
477 sprintf(hrec
, "%d.%02d.%02d-%c%03X",
478 (unchar
)(ha
->binfo
.upd_fw_ver
>>24),
479 (unchar
)(ha
->binfo
.upd_fw_ver
>>16),
480 (unchar
)(ha
->binfo
.upd_fw_ver
),
481 ha
->bfeat
.raid
? 'R':'N',
482 ha
->binfo
.upd_revision
);
484 sprintf(hrec
, "%d.%02d", (unchar
)(ha
->cpar
.version
>>8),
485 (unchar
)(ha
->cpar
.version
));
487 size
= sprintf(buffer
+len
,
488 " Driver Ver.: \t%-10s\tFirmware Ver.: \t%s\n",
489 GDTH_VERSION_STR
, hrec
);
490 len
+= size
; pos
= begin
+ len
;
496 if (pos
> offset
+ length
)
500 /* more information: 1. about controller */
501 size
= sprintf(buffer
+len
,
502 " Serial No.: \t0x%8X\tCache RAM size:\t%d KB\n",
503 ha
->binfo
.ser_no
, ha
->binfo
.memsize
/ 1024);
504 len
+= size
; pos
= begin
+ len
;
510 if (pos
> offset
+ length
)
513 /* 2. about physical devices */
514 size
= sprintf(buffer
+len
,"\nPhysical Devices:");
515 len
+= size
; pos
= begin
+ len
;
518 if (!gdth_ioctl_alloc(hanum
, GDTH_SCRATCH
))
520 for (i
= 0; i
< ha
->bus_cnt
; ++i
) {
521 /* 2.a statistics (and retries/reassigns) */
522 TRACE2(("pdr_statistics() chn %d\n",i
));
523 pds
= (gdth_dskstat_str
*)(ha
->pscratch
+ GDTH_SCRATCH
/4);
524 gdtcmd
.BoardNode
= LOCALBOARD
;
525 gdtcmd
.Service
= CACHESERVICE
;
526 gdtcmd
.OpCode
= GDT_IOCTL
;
527 gdtcmd
.u
.ioctl
.p_param
= virt_to_bus(pds
);
528 gdtcmd
.u
.ioctl
.param_size
= 3*GDTH_SCRATCH
/4;
529 gdtcmd
.u
.ioctl
.subfunc
= DSK_STATISTICS
| L_CTRL_PATTERN
;
530 gdtcmd
.u
.ioctl
.channel
= ha
->raw
[i
].address
| INVALID_CHANNEL
;
531 pds
->bid
= ha
->raw
[i
].local_no
;
533 pds
->entries
= ha
->raw
[i
].pdev_cnt
;
534 cnt
= (3*GDTH_SCRATCH
/4 - 5 * sizeof(ulong32
)) /
535 sizeof(pds
->list
[0]);
536 if (pds
->entries
> cnt
)
538 gdth_do_cmd(&scp
, &gdtcmd
, 30);
539 if (scp
.SCp
.Message
!= S_OK
)
541 TRACE2(("pdr_statistics() entries %d status %d\n",
542 pds
->count
, scp
.SCp
.Message
));
544 /* other IOCTLs must fit into area GDTH_SCRATCH/4 */
545 for (j
= 0; j
< ha
->raw
[i
].pdev_cnt
; ++j
) {
547 TRACE2(("scsi_drv_info() chn %d dev %d\n",
548 i
, ha
->raw
[i
].id_list
[j
]));
549 pdi
= (gdth_diskinfo_str
*)ha
->pscratch
;
550 gdtcmd
.BoardNode
= LOCALBOARD
;
551 gdtcmd
.Service
= CACHESERVICE
;
552 gdtcmd
.OpCode
= GDT_IOCTL
;
553 gdtcmd
.u
.ioctl
.p_param
= virt_to_bus(pdi
);
554 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_diskinfo_str
);
555 gdtcmd
.u
.ioctl
.subfunc
= SCSI_DR_INFO
| L_CTRL_PATTERN
;
556 gdtcmd
.u
.ioctl
.channel
=
557 ha
->raw
[i
].address
| ha
->raw
[i
].id_list
[j
];
558 gdth_do_cmd(&scp
, &gdtcmd
, 30);
559 if (scp
.SCp
.Message
== S_OK
) {
560 strncpy(hrec
,pdi
->vendor
,8);
561 strncpy(hrec
+8,pdi
->product
,16);
562 strncpy(hrec
+24,pdi
->revision
,4);
564 size
= sprintf(buffer
+len
,
565 "\n Chn/ID/LUN: \t%c/%02d/%d \tName: \t%s\n",
566 'A'+i
,pdi
->target_id
,pdi
->lun
,hrec
);
567 len
+= size
; pos
= begin
+ len
;
569 pdi
->no_ldrive
&= 0xffff;
570 if (pdi
->no_ldrive
== 0xffff)
573 sprintf(hrec
,"%d",pdi
->no_ldrive
);
574 size
= sprintf(buffer
+len
,
575 " Capacity [MB]:\t%-6d \tTo Log. Drive: \t%s\n",
576 pdi
->blkcnt
/(1024*1024/pdi
->blksize
),
578 len
+= size
; pos
= begin
+ len
;
583 if (pdi
->devtype
== 0) {
584 /* search retries/reassigns */
585 for (k
= 0; k
< pds
->count
; ++k
) {
586 if (pds
->list
[k
].tid
== pdi
->target_id
&&
587 pds
->list
[k
].lun
== pdi
->lun
) {
588 size
= sprintf(buffer
+len
,
589 " Retries: \t%-6d \tReassigns: \t%d\n",
590 pds
->list
[k
].retries
,
591 pds
->list
[k
].reassigns
);
592 len
+= size
; pos
= begin
+ len
;
596 /* 2.c grown defects */
597 TRACE2(("scsi_drv_defcnt() chn %d dev %d\n",
598 i
, ha
->raw
[i
].id_list
[j
]));
599 pdef
= (gdth_defcnt_str
*)ha
->pscratch
;
600 gdtcmd
.BoardNode
= LOCALBOARD
;
601 gdtcmd
.Service
= CACHESERVICE
;
602 gdtcmd
.OpCode
= GDT_IOCTL
;
603 gdtcmd
.u
.ioctl
.p_param
= virt_to_bus(pdef
);
604 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_defcnt_str
);
605 gdtcmd
.u
.ioctl
.subfunc
= SCSI_DEF_CNT
| L_CTRL_PATTERN
;
606 gdtcmd
.u
.ioctl
.channel
=
607 ha
->raw
[i
].address
| ha
->raw
[i
].id_list
[j
];
608 pdef
->sddc_type
= 0x08;
609 gdth_do_cmd(&scp
, &gdtcmd
, 30);
610 if (scp
.SCp
.Message
== S_OK
) {
611 size
= sprintf(buffer
+len
,
612 " Grown Defects:\t%d\n",
614 len
+= size
; pos
= begin
+ len
;
619 gdth_ioctl_free(hanum
);
622 size
= sprintf(buffer
+len
, "\n --\n");
623 len
+= size
; pos
= begin
+ len
;
629 if (pos
> offset
+ length
)
632 /* 3. about logical drives */
633 size
= sprintf(buffer
+len
,"\nLogical Drives:");
634 len
+= size
; pos
= begin
+ len
;
637 if (!gdth_ioctl_alloc(hanum
, GDTH_SCRATCH
))
639 for (i
= 0; i
< MAX_HDRIVES
; ++i
) {
640 if (!ha
->hdr
[i
].is_logdrv
)
646 /* 3.a log. drive info */
647 TRACE2(("cache_drv_info() drive no %d\n",drv_no
));
648 pcdi
= (gdth_cdrinfo_str
*)ha
->pscratch
;
649 gdtcmd
.BoardNode
= LOCALBOARD
;
650 gdtcmd
.Service
= CACHESERVICE
;
651 gdtcmd
.OpCode
= GDT_IOCTL
;
652 gdtcmd
.u
.ioctl
.p_param
= virt_to_bus(pcdi
);
653 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_cdrinfo_str
);
654 gdtcmd
.u
.ioctl
.subfunc
= CACHE_DRV_INFO
;
655 gdtcmd
.u
.ioctl
.channel
= drv_no
;
656 gdth_do_cmd(&scp
, &gdtcmd
, 30);
657 if (scp
.SCp
.Message
!= S_OK
)
659 pcdi
->ld_dtype
>>= 16;
661 if (pcdi
->ld_dtype
> 2) {
662 strcpy(hrec
, "missing");
663 } else if (pcdi
->ld_error
& 1) {
664 strcpy(hrec
, "fault");
665 } else if (pcdi
->ld_error
& 2) {
666 strcpy(hrec
, "invalid");
673 size
= sprintf(buffer
+len
,
674 "\n Number: \t%-2d \tStatus: \t%s\n",
676 len
+= size
; pos
= begin
+ len
;
678 no_mdrv
= pcdi
->cd_ldcnt
;
679 if (no_mdrv
> 1 || pcdi
->ld_slave
!= -1) {
681 strcpy(hrec
, "RAID-1");
682 } else if (pcdi
->ld_dtype
== 0) {
683 strcpy(hrec
, "Disk");
684 } else if (pcdi
->ld_dtype
== 1) {
685 strcpy(hrec
, "RAID-0");
686 } else if (pcdi
->ld_dtype
== 2) {
687 strcpy(hrec
, "Chain");
691 size
= sprintf(buffer
+len
,
692 " Capacity [MB]:\t%-6d \tType: \t%s\n",
693 pcdi
->ld_blkcnt
/(1024*1024/pcdi
->ld_blksize
),
695 len
+= size
; pos
= begin
+ len
;
697 size
= sprintf(buffer
+len
,
698 " Slave Number: \t%-2d \tStatus: \t%s\n",
699 drv_no
& 0x7fff, hrec
);
700 len
+= size
; pos
= begin
+ len
;
702 drv_no
= pcdi
->ld_slave
;
703 } while (drv_no
!= -1);
706 size
= sprintf(buffer
+len
,
707 " Missing Drv.: \t%-2d \tInvalid Drv.: \t%d\n",
709 len
+= size
; pos
= begin
+ len
;
712 if (!ha
->hdr
[i
].is_arraydrv
)
715 sprintf(hrec
, "%d", ha
->hdr
[i
].master_no
);
716 size
= sprintf(buffer
+len
,
717 " To Array Drv.:\t%s\n", hrec
);
718 len
+= size
; pos
= begin
+ len
;
720 gdth_ioctl_free(hanum
);
723 size
= sprintf(buffer
+len
, "\n --\n");
724 len
+= size
; pos
= begin
+ len
;
730 if (pos
> offset
+ length
)
733 /* 4. about array drives */
734 size
= sprintf(buffer
+len
,"\nArray Drives:");
735 len
+= size
; pos
= begin
+ len
;
738 if (!gdth_ioctl_alloc(hanum
, GDTH_SCRATCH
))
740 for (i
= 0; i
< MAX_HDRIVES
; ++i
) {
741 if (!(ha
->hdr
[i
].is_arraydrv
&& ha
->hdr
[i
].is_master
))
743 /* 4.a array drive info */
744 TRACE2(("array_info() drive no %d\n",i
));
745 pai
= (gdth_arrayinf_str
*)ha
->pscratch
;
746 gdtcmd
.BoardNode
= LOCALBOARD
;
747 gdtcmd
.Service
= CACHESERVICE
;
748 gdtcmd
.OpCode
= GDT_IOCTL
;
749 gdtcmd
.u
.ioctl
.p_param
= virt_to_bus(pai
);
750 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_arrayinf_str
);
751 gdtcmd
.u
.ioctl
.subfunc
= ARRAY_INFO
| LA_CTRL_PATTERN
;
752 gdtcmd
.u
.ioctl
.channel
= i
;
753 gdth_do_cmd(&scp
, &gdtcmd
, 30);
754 if (scp
.SCp
.Message
== S_OK
) {
755 if (pai
->ai_state
== 0)
756 strcpy(hrec
, "idle");
757 else if (pai
->ai_state
== 2)
758 strcpy(hrec
, "build");
759 else if (pai
->ai_state
== 4)
760 strcpy(hrec
, "ready");
761 else if (pai
->ai_state
== 6)
762 strcpy(hrec
, "fail");
763 else if (pai
->ai_state
== 8 || pai
->ai_state
== 10)
764 strcpy(hrec
, "rebuild");
766 strcpy(hrec
, "error");
767 if (pai
->ai_ext_state
& 0x10)
768 strcat(hrec
, "/expand");
769 else if (pai
->ai_ext_state
& 0x1)
770 strcat(hrec
, "/patch");
771 size
= sprintf(buffer
+len
,
772 "\n Number: \t%-2d \tStatus: \t%s\n",
774 len
+= size
; pos
= begin
+ len
;
777 if (pai
->ai_type
== 0)
778 strcpy(hrec
, "RAID-0");
779 else if (pai
->ai_type
== 4)
780 strcpy(hrec
, "RAID-4");
781 else if (pai
->ai_type
== 5)
782 strcpy(hrec
, "RAID-5");
784 strcpy(hrec
, "RAID-10");
785 size
= sprintf(buffer
+len
,
786 " Capacity [MB]:\t%-6d \tType: \t%s\n",
787 pai
->ai_size
/(1024*1024/pai
->ai_secsize
),
789 len
+= size
; pos
= begin
+ len
;
792 gdth_ioctl_free(hanum
);
795 size
= sprintf(buffer
+len
, "\n --\n");
796 len
+= size
; pos
= begin
+ len
;
802 if (pos
> offset
+ length
)
805 /* 5. about host drives */
806 size
= sprintf(buffer
+len
,"\nHost Drives:");
807 len
+= size
; pos
= begin
+ len
;
810 if (!gdth_ioctl_alloc(hanum
, GDTH_SCRATCH
))
812 for (i
= 0; i
< MAX_HDRIVES
; ++i
) {
813 if (!ha
->hdr
[i
].is_logdrv
||
814 (ha
->hdr
[i
].is_arraydrv
&& !ha
->hdr
[i
].is_master
))
816 /* 5.a get host drive list */
817 TRACE2(("host_get() drv_no %d\n",i
));
818 phg
= (gdth_hget_str
*)ha
->pscratch
;
819 gdtcmd
.BoardNode
= LOCALBOARD
;
820 gdtcmd
.Service
= CACHESERVICE
;
821 gdtcmd
.OpCode
= GDT_IOCTL
;
822 gdtcmd
.u
.ioctl
.p_param
= virt_to_bus(phg
);
823 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_hget_str
);
824 gdtcmd
.u
.ioctl
.subfunc
= HOST_GET
| LA_CTRL_PATTERN
;
825 gdtcmd
.u
.ioctl
.channel
= i
;
826 phg
->entries
= MAX_HDRIVES
;
827 phg
->offset
= GDTOFFSOF(gdth_hget_str
, entry
[0]);
828 gdth_do_cmd(&scp
, &gdtcmd
, 30);
829 if (scp
.SCp
.Message
!= S_OK
) {
830 ha
->hdr
[i
].ldr_no
= i
;
831 ha
->hdr
[i
].rw_attribs
= 0;
832 ha
->hdr
[i
].start_sec
= 0;
834 for (j
= 0; j
< phg
->entries
; ++j
) {
835 k
= phg
->entry
[j
].host_drive
;
836 if (k
>= MAX_HDRIVES
)
838 ha
->hdr
[k
].ldr_no
= phg
->entry
[j
].log_drive
;
839 ha
->hdr
[k
].rw_attribs
= phg
->entry
[j
].rw_attribs
;
840 ha
->hdr
[k
].start_sec
= phg
->entry
[j
].start_sec
;
843 TRACE2(("host_get entries %d status %d\n",
844 phg
->entries
, scp
.SCp
.Message
));
846 gdth_ioctl_free(hanum
);
848 for (i
= 0; i
< MAX_HDRIVES
; ++i
) {
849 if (!(ha
->hdr
[i
].present
))
852 size
= sprintf(buffer
+len
,
853 "\n Number: \t%-2d \tArr/Log. Drive:\t%d\n",
854 i
, ha
->hdr
[i
].ldr_no
);
855 len
+= size
; pos
= begin
+ len
;
858 size
= sprintf(buffer
+len
,
859 " Capacity [MB]:\t%-6d \tStart Sector: \t%d\n",
860 ha
->hdr
[i
].size
/2048, ha
->hdr
[i
].start_sec
);
861 len
+= size
; pos
= begin
+ len
;
865 size
= sprintf(buffer
+len
, "\n --\n");
866 len
+= size
; pos
= begin
+ len
;
872 if (pos
> offset
+ length
)
876 /* controller events */
877 size
= sprintf(buffer
+len
,"\nController Events:\n");
878 len
+= size
; pos
= begin
+ len
;
881 id
= gdth_read_event(ha
, id
, &estr
);
882 if (estr
.event_source
== 0)
884 if (estr
.event_data
.eu
.driver
.ionode
== hanum
&&
885 estr
.event_source
== ES_ASYNC
) {
886 gdth_log_event(&estr
.event_data
, hrec
);
887 do_gettimeofday(&tv
);
888 sec
= (int)(tv
.tv_sec
- estr
.first_stamp
);
889 if (sec
< 0) sec
= 0;
890 size
= sprintf(buffer
+len
," date- %02d:%02d:%02d\t%s\n",
891 sec
/3600, sec
%3600/60, sec
%60, hrec
);
892 len
+= size
; pos
= begin
+ len
;
897 if (pos
> offset
+ length
)
904 /* request from tool (GDTMON,..) */
905 piord
= (gdth_iord_str
*)ha
->pscratch
;
908 length
= piord
->size
;
909 memcpy(buffer
+len
, (char *)piord
, length
);
910 gdth_ioctl_free(hanum
);
911 len
+= length
; pos
= begin
+ len
;
917 if (pos
> offset
+ length
)
922 *start
= buffer
+(offset
-begin
);
923 len
-= (offset
-begin
);
926 TRACE2(("get_info() len %d pos %d begin %d offset %d length %d size %d\n",
927 len
,(int)pos
,(int)begin
,(int)offset
,length
,size
));
931 static void gdth_do_cmd(Scsi_Cmnd
*scp
,gdth_cmd_str
*gdtcmd
,int timeout
)
934 DECLARE_MUTEX_LOCKED(sem
);
936 TRACE2(("gdth_do_cmd()\n"));
938 scp
->request
.rq_status
= RQ_SCSI_BUSY
;
939 scp
->request
.sem
= &sem
;
940 scp
->SCp
.this_residual
= IOCTL_PRI
;
941 GDTH_LOCK_SCSI_DOCMD();
942 scsi_do_cmd(scp
, cmnd
, gdtcmd
, sizeof(gdth_cmd_str
),
943 gdth_scsi_done
, timeout
*HZ
, 1);
944 GDTH_UNLOCK_SCSI_DOCMD();
948 void gdth_scsi_done(Scsi_Cmnd
*scp
)
950 TRACE2(("gdth_scsi_done()\n"));
952 scp
->request
.rq_status
= RQ_SCSI_DONE
;
954 if (scp
->request
.sem
!= NULL
)
955 up(scp
->request
.sem
);
958 static int gdth_ioctl_alloc(int hanum
, ushort size
)
964 if (size
== 0 || size
> GDTH_SCRATCH
)
967 ha
= HADATA(gdth_ctr_tab
[hanum
]);
968 GDTH_LOCK_HA(ha
, flags
);
970 if (!ha
->scratch_busy
) {
971 ha
->scratch_busy
= TRUE
;
976 GDTH_UNLOCK_HA(ha
, flags
);
980 static void gdth_ioctl_free(int hanum
)
985 ha
= HADATA(gdth_ctr_tab
[hanum
]);
986 GDTH_LOCK_HA(ha
, flags
);
988 ha
->scratch_busy
= FALSE
;
990 GDTH_UNLOCK_HA(ha
, flags
);
993 static void gdth_wait_completion(int hanum
, int busnum
, int id
)
1000 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1001 GDTH_LOCK_HA(ha
, flags
);
1003 for (i
= 0; i
< GDTH_MAXCMDS
; ++i
) {
1004 scp
= ha
->cmd_tab
[i
].cmnd
;
1005 #if LINUX_VERSION_CODE >= 0x020000
1006 if (!SPECIAL_SCP(scp
) && scp
->target
== (unchar
)id
&&
1007 scp
->channel
== (unchar
)busnum
)
1009 if (!SPECIAL_SCP(scp
) && scp
->target
== (unchar
)id
&&
1010 NUMDATA(scp
->host
)->busnum
== (unchar
)busnum
)
1013 scp
->SCp
.have_data_in
= 0;
1014 GDTH_UNLOCK_HA(ha
, flags
);
1015 while (!scp
->SCp
.have_data_in
)
1017 GDTH_LOCK_SCSI_DONE(flags
);
1018 scp
->scsi_done(scp
);
1019 GDTH_UNLOCK_SCSI_DONE(flags
);
1020 GDTH_LOCK_HA(ha
, flags
);
1023 GDTH_UNLOCK_HA(ha
, flags
);
1026 static void gdth_stop_timeout(int hanum
, int busnum
, int id
)
1032 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1033 GDTH_LOCK_HA(ha
, flags
);
1035 for (scp
= ha
->req_first
; scp
; scp
= (Scsi_Cmnd
*)scp
->SCp
.ptr
) {
1036 #if LINUX_VERSION_CODE >= 0x020000
1037 if (scp
->target
== (unchar
)id
&&
1038 scp
->channel
== (unchar
)busnum
)
1040 if (scp
->target
== (unchar
)id
&&
1041 NUMDATA(scp
->host
)->busnum
== (unchar
)busnum
)
1044 TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
1045 scp
->SCp
.buffers_residual
= gdth_update_timeout(hanum
, scp
, 0);
1048 GDTH_UNLOCK_HA(ha
, flags
);
1051 static void gdth_start_timeout(int hanum
, int busnum
, int id
)
1057 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1058 GDTH_LOCK_HA(ha
, flags
);
1060 for (scp
= ha
->req_first
; scp
; scp
= (Scsi_Cmnd
*)scp
->SCp
.ptr
) {
1061 #if LINUX_VERSION_CODE >= 0x020000
1062 if (scp
->target
== (unchar
)id
&&
1063 scp
->channel
== (unchar
)busnum
)
1065 if (scp
->target
== (unchar
)id
&&
1066 NUMDATA(scp
->host
)->busnum
== (unchar
)busnum
)
1069 TRACE2(("gdth_start_timeout(): update_timeout()\n"));
1070 gdth_update_timeout(hanum
, scp
, scp
->SCp
.buffers_residual
);
1073 GDTH_UNLOCK_HA(ha
, flags
);
1076 static int gdth_update_timeout(int hanum
, Scsi_Cmnd
*scp
, int timeout
)
1080 oldto
= scp
->timeout_per_command
;
1081 scp
->timeout_per_command
= timeout
;
1083 #if LINUX_VERSION_CODE >= 0x02014B
1085 del_timer(&scp
->eh_timeout
);
1086 scp
->eh_timeout
.data
= (unsigned long) NULL
;
1087 scp
->eh_timeout
.expires
= 0;
1089 if (scp
->eh_timeout
.data
!= (unsigned long) NULL
)
1090 del_timer(&scp
->eh_timeout
);
1091 scp
->eh_timeout
.data
= (unsigned long) scp
;
1092 scp
->eh_timeout
.expires
= jiffies
+ timeout
;
1093 add_timer(&scp
->eh_timeout
);
1097 if (timer_table
[SCSI_TIMER
].expires
== 0) {
1098 timer_table
[SCSI_TIMER
].expires
= jiffies
+ timeout
;
1099 timer_active
|= 1 << SCSI_TIMER
;
1101 if (jiffies
+ timeout
< timer_table
[SCSI_TIMER
].expires
)
1102 timer_table
[SCSI_TIMER
].expires
= jiffies
+ timeout
;