2 * $Id: gdth_proc.c,v 1.13 1999/03/22 16:12:53 achim Exp $ 7 intgdth_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 intgdth_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 intgdth_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 intgdth_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 intgdth_get_info(char*buffer
,char**start
,off_t offset
, 392 int length
,int vh
,int hanum
,int busnum
) 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 "\nChn/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 "\nNumber:\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) { 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) 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) 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 "\nNumber:\t%-2d\tStatus:\t%s\n", 774 len
+= size
; pos
= begin
+ len
; 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
; 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 "\nNumber:\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
); 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 voidgdth_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 voidgdth_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 intgdth_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 voidgdth_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 voidgdth_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 voidgdth_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 voidgdth_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 intgdth_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
;