2 * $Id: gdth_proc.c,v 1.37 2003/09/17 08:31:53 achim Exp $
5 #if LINUX_VERSION_CODE >= 0x020407
6 #include <linux/completion.h>
9 int gdth_proc_info(struct Scsi_Host
*host
, char *buffer
,char **start
,off_t offset
,int length
,
14 TRACE2(("gdth_proc_info() length %d ha %d offs %d inout %d\n",
15 length
,hostno
,(int)offset
,inout
));
17 hanum
= NUMDATA(host
)->hanum
;
18 busnum
= NUMDATA(host
)->busnum
;
21 return(gdth_set_info(buffer
,length
,hanum
,busnum
));
23 return(gdth_get_info(buffer
,start
,offset
,length
,hanum
,busnum
));
26 static int gdth_set_info(char *buffer
,int length
,int hanum
,int busnum
)
28 int ret_val
= -EINVAL
;
29 #if LINUX_VERSION_CODE >= 0x020503
32 #elif LINUX_VERSION_CODE >= 0x020322
39 #ifdef GDTH_IOCTL_PROC
41 piowr
= (gdth_iowr_str
*)buffer
;
43 TRACE2(("gdth_set_info() ha %d bus %d\n",hanum
,busnum
));
45 #if LINUX_VERSION_CODE >= 0x020503
46 sdev
= scsi_get_host_dev(gdth_ctr_tab
[hanum
]);
47 scp
= scsi_allocate_request(sdev
, GFP_KERNEL
);
52 #elif LINUX_VERSION_CODE >= 0x020322
53 sdev
= scsi_get_host_dev(gdth_ctr_tab
[hanum
]);
54 scp
= scsi_allocate_device(sdev
, 1, FALSE
);
60 memset(&sdev
,0,sizeof(Scsi_Device
));
61 memset(&scp
, 0,sizeof(Scsi_Cmnd
));
62 sdev
.host
= scp
.host
= gdth_ctr_tab
[hanum
];
63 sdev
.id
= scp
.target
= sdev
.host
->this_id
;
68 if (strncmp(buffer
,"gdth",4) == 0) {
71 ret_val
= gdth_set_asc_info( buffer
, length
, hanum
, scp
);
72 #ifdef GDTH_IOCTL_PROC
73 } else if (piowr
->magic
== GDTIOCTL_MAGIC
) {
74 ret_val
= gdth_set_bin_info( buffer
, length
, hanum
, scp
);
76 printk("GDT: Wrong signature %x (%x required)!\n",
77 piowr
->magic
, GDTIOCTL_MAGIC
);
78 if (piowr
->magic
> GDTIOCTL_MAGIC
)
79 printk("GDT: Please update your driver.\n");
81 printk("GDT: Please update your tool.\n");
85 #if LINUX_VERSION_CODE >= 0x020503
86 scsi_release_request(scp
);
87 scsi_free_host_dev(sdev
);
88 #elif LINUX_VERSION_CODE >= 0x020322
89 scsi_release_command(scp
);
90 scsi_free_host_dev(sdev
);
95 #if LINUX_VERSION_CODE >= 0x020503
96 static int gdth_set_asc_info(char *buffer
,int length
,int hanum
,Scsi_Request
*scp
)
97 #elif LINUX_VERSION_CODE >= 0x020322
98 static int gdth_set_asc_info(char *buffer
,int length
,int hanum
,Scsi_Cmnd
*scp
)
100 static int gdth_set_asc_info(char *buffer
,int length
,int hanum
,Scsi_Cmnd scp
)
103 int orig_length
, drive
, wb_mode
;
107 gdth_cpar_str
*pcpar
;
110 char cmnd
[MAX_COMMAND_SIZE
];
111 memset(cmnd
, 0xff, 12);
112 memset(&gdtcmd
, 0, sizeof(gdth_cmd_str
));
114 TRACE2(("gdth_set_asc_info() ha %d\n",hanum
));
115 ha
= HADATA(gdth_ctr_tab
[hanum
]);
116 orig_length
= length
+ 5;
121 if (length
>= 5 && strncmp(buffer
,"flush",5)==0) {
124 if (length
&& *buffer
>='0' && *buffer
<='9') {
125 drive
= (int)(*buffer
-'0');
127 if (length
&& *buffer
>='0' && *buffer
<='9') {
128 drive
= drive
*10 + (int)(*buffer
-'0');
131 printk("GDT: Flushing host drive %d .. ",drive
);
133 printk("GDT: Flushing all host drives .. ");
135 for (i
= 0; i
< MAX_HDRIVES
; ++i
) {
136 if (ha
->hdr
[i
].present
) {
137 if (drive
!= -1 && i
!= drive
)
140 gdtcmd
.Service
= CACHESERVICE
;
141 gdtcmd
.OpCode
= GDT_FLUSH
;
142 gdtcmd
.u
.cache
.DeviceNo
= i
;
143 gdtcmd
.u
.cache
.BlockNo
= 1;
144 #if LINUX_VERSION_CODE >= 0x020503
145 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
146 #elif LINUX_VERSION_CODE >= 0x020322
147 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
149 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
154 printk("\nNo host drive found !\n");
160 if (length
>= 7 && strncmp(buffer
,"wbp_off",7)==0) {
163 printk("GDT: Disabling write back permanently .. ");
165 } else if (length
>= 6 && strncmp(buffer
,"wbp_on",6)==0) {
168 printk("GDT: Enabling write back permanently .. ");
170 } else if (length
>= 6 && strncmp(buffer
,"wb_off",6)==0) {
173 printk("GDT: Disabling write back commands .. ");
174 if (ha
->cache_feat
& GDT_WR_THROUGH
) {
175 gdth_write_through
= TRUE
;
178 printk("Not supported !\n");
181 } else if (length
>= 5 && strncmp(buffer
,"wb_on",5)==0) {
184 printk("GDT: Enabling write back commands .. ");
185 gdth_write_through
= FALSE
;
191 if (!gdth_ioctl_alloc(hanum
, sizeof(gdth_cpar_str
), TRUE
, &paddr
))
193 pcpar
= (gdth_cpar_str
*)ha
->pscratch
;
194 memcpy( pcpar
, &ha
->cpar
, sizeof(gdth_cpar_str
) );
195 gdtcmd
.Service
= CACHESERVICE
;
196 gdtcmd
.OpCode
= GDT_IOCTL
;
197 gdtcmd
.u
.ioctl
.p_param
= paddr
;
198 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_cpar_str
);
199 gdtcmd
.u
.ioctl
.subfunc
= CACHE_CONFIG
;
200 gdtcmd
.u
.ioctl
.channel
= INVALID_CHANNEL
;
201 pcpar
->write_back
= wb_mode
==1 ? 0:1;
202 #if LINUX_VERSION_CODE >= 0x020503
203 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
204 #elif LINUX_VERSION_CODE >= 0x020322
205 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
207 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
209 gdth_ioctl_free(hanum
, GDTH_SCRATCH
, ha
->pscratch
, paddr
);
214 printk("GDT: Unknown command: %s Length: %d\n",buffer
,length
);
218 #ifdef GDTH_IOCTL_PROC
219 #if LINUX_VERSION_CODE >= 0x020503
220 static int gdth_set_bin_info(char *buffer
,int length
,int hanum
,Scsi_Request
*scp
)
221 #elif LINUX_VERSION_CODE >= 0x020322
222 static int gdth_set_bin_info(char *buffer
,int length
,int hanum
,Scsi_Cmnd
*scp
)
224 static int gdth_set_bin_info(char *buffer
,int length
,int hanum
,Scsi_Cmnd scp
)
228 ushort k
, hdr_cnt
, status
;
230 gdth_iowr_str
*piowr
;
231 gdth_iord_str
*piord
;
234 ulong32
*ppadd
, add_size
, *ppadd2
, add_size2
, info
, paddr
;
237 int drv_cyls
, drv_hds
, drv_secs
;
239 char cmnd
[MAX_COMMAND_SIZE
];
240 memset(cmnd
, 0xff, 12);
241 memset(&gdtcmd
, 0, sizeof(gdth_cmd_str
));
243 TRACE2(("gdth_set_bin_info() ha %d\n",hanum
));
244 ha
= HADATA(gdth_ctr_tab
[hanum
]);
245 piowr
= (gdth_iowr_str
*)buffer
;
248 ppadd
= ppadd2
= NULL
;
249 add_size
= add_size2
= 0;
251 if (length
< GDTOFFSOF(gdth_iowr_str
,iu
))
254 switch (piowr
->ioctl
) {
255 case GDTIOCTL_GENERAL
:
256 if (length
< GDTOFFSOF(gdth_iowr_str
,iu
.general
.data
[0]))
258 pcmd
= (gdth_cmd_str
*)piowr
->iu
.general
.command
;
259 pcmd
->Service
= piowr
->service
;
260 if (pcmd
->OpCode
== GDT_IOCTL
) {
261 ppadd
= &pcmd
->u
.ioctl
.p_param
;
262 add_size
= pcmd
->u
.ioctl
.param_size
;
263 } else if (piowr
->service
== CACHESERVICE
) {
264 add_size
= pcmd
->u
.cache
.BlockCnt
* SECTOR_SIZE
;
265 if (ha
->cache_feat
& SCATTER_GATHER
) {
266 ppadd
= &pcmd
->u
.cache
.sg_lst
[0].sg_ptr
;
267 pcmd
->u
.cache
.DestAddr
= 0xffffffff;
268 pcmd
->u
.cache
.sg_lst
[0].sg_len
= add_size
;
269 pcmd
->u
.cache
.sg_canz
= 1;
271 ppadd
= &pcmd
->u
.cache
.DestAddr
;
272 pcmd
->u
.cache
.sg_canz
= 0;
274 } else if (piowr
->service
== SCSIRAWSERVICE
) {
275 add_size
= pcmd
->u
.raw
.sdlen
;
276 add_size2
= pcmd
->u
.raw
.sense_len
;
277 if (ha
->raw_feat
& SCATTER_GATHER
) {
278 ppadd
= &pcmd
->u
.raw
.sg_lst
[0].sg_ptr
;
279 pcmd
->u
.raw
.sdata
= 0xffffffff;
280 pcmd
->u
.raw
.sg_lst
[0].sg_len
= add_size
;
281 pcmd
->u
.raw
.sg_ranz
= 1;
283 ppadd
= &pcmd
->u
.raw
.sdata
;
284 pcmd
->u
.raw
.sg_ranz
= 0;
286 ppadd2
= &pcmd
->u
.raw
.sense_data
;
290 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
)+add_size
+add_size2
,
293 piord
= (gdth_iord_str
*)ha
->pscratch
;
294 piord
->size
= sizeof(gdth_iord_str
) + add_size
+ add_size2
;
296 memcpy(piord
->iu
.general
.data
, piowr
->iu
.general
.data
, add_size
);
297 *ppadd
= paddr
+ GDTOFFSOF(gdth_iord_str
, iu
.general
.data
[0]);
300 memcpy(piord
->iu
.general
.data
+add_size
, piowr
->iu
.general
.data
, add_size2
);
301 *ppadd2
= paddr
+ GDTOFFSOF(gdth_iord_str
, iu
.general
.data
[0]) + add_size2
;
305 #if LINUX_VERSION_CODE >= 0x020503
306 gdth_do_req(scp
, pcmd
, cmnd
, piowr
->timeout
);
307 piord
->status
= (scp
->sr_command
->SCp
.Message
<< 16) |
308 scp
->sr_command
->SCp
.Status
;
309 #elif LINUX_VERSION_CODE >= 0x020322
310 gdth_do_cmd(scp
, pcmd
, cmnd
, piowr
->timeout
);
311 piord
->status
= (scp
->SCp
.Message
<<16)|scp
->SCp
.Status
;
313 gdth_do_cmd(&scp
, pcmd
, cmnd
, piowr
->timeout
);
314 piord
->status
= (scp
.SCp
.Message
<<16)|scp
.SCp
.Status
;
318 case GDTIOCTL_DRVERS
:
319 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
), TRUE
, &paddr
))
321 piord
= (gdth_iord_str
*)ha
->pscratch
;
322 piord
->size
= sizeof(gdth_iord_str
);
323 piord
->status
= S_OK
;
324 piord
->iu
.drvers
.version
= (GDTH_VERSION
<<8) | GDTH_SUBVERSION
;
327 case GDTIOCTL_CTRTYPE
:
328 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
), TRUE
, &paddr
))
330 piord
= (gdth_iord_str
*)ha
->pscratch
;
331 piord
->size
= sizeof(gdth_iord_str
);
332 piord
->status
= S_OK
;
333 if (ha
->type
== GDT_ISA
|| ha
->type
== GDT_EISA
) {
334 piord
->iu
.ctrtype
.type
= (unchar
)((ha
->stype
>>20) - 0x10);
336 if (ha
->type
!= GDT_PCIMPR
) {
337 piord
->iu
.ctrtype
.type
= (unchar
)((ha
->stype
<<4) + 6);
339 piord
->iu
.ctrtype
.type
=
340 (ha
->oem_id
== OEM_ID_INTEL
? 0xfd : 0xfe);
341 if (ha
->stype
>= 0x300)
342 piord
->iu
.ctrtype
.ext_type
= 0x6000 | ha
->subdevice_id
;
344 piord
->iu
.ctrtype
.ext_type
= 0x6000 | ha
->stype
;
346 piord
->iu
.ctrtype
.device_id
= ha
->stype
;
347 piord
->iu
.ctrtype
.sub_device_id
= ha
->subdevice_id
;
349 piord
->iu
.ctrtype
.info
= ha
->brd_phys
;
350 piord
->iu
.ctrtype
.oem_id
= ha
->oem_id
;
353 case GDTIOCTL_CTRCNT
:
354 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
), TRUE
, &paddr
))
356 piord
= (gdth_iord_str
*)ha
->pscratch
;
357 piord
->size
= sizeof(gdth_iord_str
);
358 piord
->status
= S_OK
;
359 piord
->iu
.ctrcnt
.count
= (ushort
)gdth_ctr_count
;
362 case GDTIOCTL_OSVERS
:
363 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
), TRUE
, &paddr
))
365 piord
= (gdth_iord_str
*)ha
->pscratch
;
366 piord
->size
= sizeof(gdth_iord_str
);
367 piord
->status
= S_OK
;
368 piord
->iu
.osvers
.version
= (unchar
)(LINUX_VERSION_CODE
>> 16);
369 piord
->iu
.osvers
.subversion
= (unchar
)(LINUX_VERSION_CODE
>> 8);
370 piord
->iu
.osvers
.revision
= (ushort
)(LINUX_VERSION_CODE
& 0xff);
373 case GDTIOCTL_LOCKDRV
:
374 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
), TRUE
, &paddr
))
376 piord
= (gdth_iord_str
*)ha
->pscratch
;
377 for (i
= 0; i
< piowr
->iu
.lockdrv
.drive_cnt
; ++i
) {
378 j
= piowr
->iu
.lockdrv
.drives
[i
];
379 if (j
>= MAX_HDRIVES
|| !ha
->hdr
[j
].present
)
381 if (piowr
->iu
.lockdrv
.lock
) {
382 GDTH_LOCK_HA(ha
, flags
);
384 GDTH_UNLOCK_HA(ha
, flags
);
385 gdth_wait_completion( hanum
, ha
->bus_cnt
, j
);
386 gdth_stop_timeout( hanum
, ha
->bus_cnt
, j
);
388 GDTH_LOCK_HA(ha
, flags
);
390 GDTH_UNLOCK_HA(ha
, flags
);
391 gdth_start_timeout( hanum
, ha
->bus_cnt
, j
);
395 piord
->size
= sizeof(gdth_iord_str
);
396 piord
->status
= S_OK
;
399 case GDTIOCTL_LOCKCHN
:
400 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
), TRUE
, &paddr
))
402 i
= piowr
->iu
.lockchn
.channel
;
403 if (i
< ha
->bus_cnt
) {
404 if (piowr
->iu
.lockchn
.lock
) {
405 GDTH_LOCK_HA(ha
, flags
);
407 GDTH_UNLOCK_HA(ha
, flags
);
408 for (j
= 0; j
< ha
->tid_cnt
; ++j
) {
409 gdth_wait_completion( hanum
, i
, j
);
410 gdth_stop_timeout( hanum
, i
, j
);
413 GDTH_LOCK_HA(ha
, flags
);
415 GDTH_UNLOCK_HA(ha
, flags
);
416 for (j
= 0; j
< ha
->tid_cnt
; ++j
) {
417 gdth_start_timeout( hanum
, i
, j
);
422 piord
= (gdth_iord_str
*)ha
->pscratch
;
423 piord
->size
= sizeof(gdth_iord_str
);
424 piord
->status
= S_OK
;
428 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
), TRUE
, &paddr
))
430 piord
= (gdth_iord_str
*)ha
->pscratch
;
431 if (piowr
->iu
.event
.erase
== 0xff) {
432 pevt
= (gdth_evt_str
*)piowr
->iu
.event
.evt
;
433 if (pevt
->event_source
== ES_TEST
)
434 pevt
->event_data
.size
= sizeof(pevt
->event_data
.eu
.test
);
435 else if (pevt
->event_source
== ES_DRIVER
)
436 pevt
->event_data
.size
= sizeof(pevt
->event_data
.eu
.driver
);
437 else if (pevt
->event_source
== ES_SYNC
)
438 pevt
->event_data
.size
= sizeof(pevt
->event_data
.eu
.sync
);
440 pevt
->event_data
.size
= sizeof(pevt
->event_data
.eu
.async
);
441 gdth_log_event(&pevt
->event_data
, NULL
);
443 GDTH_LOCK_HA(ha
, flags
);
444 gdth_store_event(ha
, pevt
->event_source
, pevt
->event_idx
,
446 GDTH_UNLOCK_HA(ha
, flags
);
447 } else if (piowr
->iu
.event
.erase
== 0xfe) {
449 } else if (piowr
->iu
.event
.erase
== 0) {
450 piord
->iu
.event
.handle
=
451 gdth_read_event(ha
,piowr
->iu
.event
.handle
,
452 (gdth_evt_str
*)piord
->iu
.event
.evt
);
454 piord
->iu
.event
.handle
= piowr
->iu
.event
.handle
;
455 gdth_readapp_event(ha
, (unchar
)piowr
->iu
.event
.erase
,
456 (gdth_evt_str
*)piord
->iu
.event
.evt
);
458 piord
->size
= sizeof(gdth_iord_str
);
459 piord
->status
= S_OK
;
463 #if LINUX_VERSION_CODE >= 0x020503
466 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
), TRUE
, &paddr
))
468 piord
= (gdth_iord_str
*)ha
->pscratch
;
469 piord
->size
= sizeof(gdth_iord_str
);
470 memcpy(cmnd
, piowr
->iu
.scsi
.cmd
, 12);
471 #if LINUX_VERSION_CODE >= 0x020322
472 scp
->target
= piowr
->iu
.scsi
.target
;
473 scp
->channel
= virt_ctr
? 0 : piowr
->iu
.scsi
.bus
;
474 scp
->cmd_len
= piowr
->iu
.scsi
.cmd_len
;
475 gdth_do_cmd(scp
, pcmd
, cmnd
, piowr
->timeout
);
476 piord
->status
= (scp
->SCp
.Message
<<16)|scp
->SCp
.Status
;
478 scp
.target
= piowr
->iu
.scsi
.target
;
479 scp
.channel
= virt_ctr
? 0 : piowr
->iu
.scsi
.bus
;
480 scp
.cmd_len
= piowr
->iu
.scsi
.cmd_len
;
481 gdth_do_cmd(&scp
, pcmd
, cmnd
, piowr
->timeout
);
482 piord
->status
= (scp
.SCp
.Message
<<16)|scp
.SCp
.Status
;
487 case GDTIOCTL_RESET_BUS
:
488 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
), TRUE
, &paddr
))
490 piord
= (gdth_iord_str
*)ha
->pscratch
;
491 piord
->size
= sizeof(gdth_iord_str
);
492 #if LINUX_VERSION_CODE >= 0x02053C
497 sdev
= scsi_get_host_dev(gdth_ctr_tab
[hanum
]);
498 scmnd
= scsi_get_command(sdev
, GFP_KERNEL
);
501 scmnd
->device
->host
= scp
->sr_host
;
502 scmnd
->device
->channel
= virt_ctr
? 0 : piowr
->iu
.scsi
.bus
;
503 piord
->status
= (ulong32
)gdth_eh_bus_reset( scmnd
);
504 if (piord
->status
== SUCCESS
)
505 piord
->status
= S_OK
;
507 piord
->status
= S_GENERR
;
508 scsi_put_command(scmnd
);
509 scsi_free_host_dev(sdev
);
511 #elif LINUX_VERSION_CODE >= 0x020503
515 scmnd
.host
= scp
->sr_host
;
516 scmnd
.channel
= virt_ctr
? 0 : piowr
->iu
.scsi
.bus
;
517 piord
->status
= (ulong32
)gdth_eh_bus_reset( &scmnd
);
518 if (piord
->status
== SUCCESS
)
519 piord
->status
= S_OK
;
521 piord
->status
= S_GENERR
;
523 #elif LINUX_VERSION_CODE >= 0x020322
524 scp
->channel
= virt_ctr
? 0 : piowr
->iu
.scsi
.bus
;
525 piord
->status
= (ulong32
)gdth_eh_bus_reset( scp
);
526 if (piord
->status
== SUCCESS
)
527 piord
->status
= S_OK
;
529 piord
->status
= S_GENERR
;
530 #elif LINUX_VERSION_CODE >= 0x02015F
531 scp
.channel
= virt_ctr
? 0 : piowr
->iu
.scsi
.bus
;
532 piord
->status
= (ulong32
)gdth_eh_bus_reset( &scp
);
533 if (piord
->status
== SUCCESS
)
534 piord
->status
= S_OK
;
536 piord
->status
= S_GENERR
;
538 piord
->status
= S_OK
;
542 case GDTIOCTL_HDRLIST
:
543 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
), TRUE
, &paddr
))
545 piord
= (gdth_iord_str
*)ha
->pscratch
;
546 piord
->size
= sizeof(gdth_iord_str
);
547 piord
->status
= S_OK
;
548 for (i
= 0; i
< MAX_HDRIVES
; ++i
) {
549 if (ha
->hdr
[i
].present
) {
550 piord
->iu
.hdr_list
[i
].bus
= ha
->virt_bus
;
551 piord
->iu
.hdr_list
[i
].target
= i
;
552 piord
->iu
.hdr_list
[i
].lun
= 0;
553 piord
->iu
.hdr_list
[i
].cluster_type
= ha
->hdr
[i
].cluster_type
;
554 if (ha
->hdr
[i
].cluster_type
& CLUSTER_DRIVE
) {
555 gdtcmd
.Service
= CACHESERVICE
;
556 gdtcmd
.OpCode
= GDT_CLUST_INFO
;
557 gdtcmd
.u
.cache
.DeviceNo
= i
;
558 #if LINUX_VERSION_CODE >= 0x020503
559 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
560 if (scp
->sr_command
->SCp
.Status
== S_OK
)
561 piord
->iu
.hdr_list
[i
].cluster_type
=
562 (unchar
)scp
->sr_command
->SCp
.Message
;
563 #elif LINUX_VERSION_CODE >= 0x020322
564 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
565 if (scp
->SCp
.Status
== S_OK
)
566 piord
->iu
.hdr_list
[i
].cluster_type
=
567 (unchar
)scp
->SCp
.Message
;
569 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
570 if (scp
.SCp
.Status
== S_OK
)
571 piord
->iu
.hdr_list
[i
].cluster_type
=
572 (unchar
)scp
.SCp
.Message
;
576 piord
->iu
.hdr_list
[i
].bus
= 0xff;
581 case GDTIOCTL_RESCAN
:
582 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
), TRUE
, &paddr
))
584 piord
= (gdth_iord_str
*)ha
->pscratch
;
585 piord
->size
= sizeof(gdth_iord_str
);
586 piord
->status
= S_OK
;
587 if (piowr
->iu
.rescan
.flag
== 0) {
588 /* old method: scan all host drives
589 re-initialize cache service to get host drive count
591 gdtcmd
.Service
= CACHESERVICE
;
592 gdtcmd
.OpCode
= GDT_INIT
;
593 gdtcmd
.u
.cache
.DeviceNo
= LINUX_OS
;
594 #if LINUX_VERSION_CODE >= 0x020503
595 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
596 status
= (ushort
)scp
->sr_command
->SCp
.Status
;
597 info
= (ulong32
)scp
->sr_command
->SCp
.Message
;
598 #elif LINUX_VERSION_CODE >= 0x020322
599 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
600 status
= (ushort
)scp
->SCp
.Status
;
601 info
= (ulong32
)scp
->SCp
.Message
;
603 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
604 status
= (ushort
)scp
.SCp
.Status
;
605 info
= (ulong32
)scp
.SCp
.Message
;
610 hdr_cnt
= (ushort
)info
;
612 k
= piowr
->iu
.rescan
.hdr_no
;
615 if (hdr_cnt
> MAX_HDRIVES
)
616 hdr_cnt
= MAX_HDRIVES
;
617 /* scanning for host drives */
618 for (; k
< hdr_cnt
; ++k
) {
619 /* info about host drive */
620 gdtcmd
.Service
= CACHESERVICE
;
621 gdtcmd
.OpCode
= GDT_INFO
;
622 gdtcmd
.u
.cache
.DeviceNo
= k
;
623 #if LINUX_VERSION_CODE >= 0x020503
624 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
625 status
= (ushort
)scp
->sr_command
->SCp
.Status
;
626 info
= (ulong32
)scp
->sr_command
->SCp
.Message
;
627 #elif LINUX_VERSION_CODE >= 0x020322
628 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
629 status
= (ushort
)scp
->SCp
.Status
;
630 info
= (ulong32
)scp
->SCp
.Message
;
632 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
633 status
= (ushort
)scp
.SCp
.Status
;
634 info
= (ulong32
)scp
.SCp
.Message
;
636 GDTH_LOCK_HA(ha
, flags
);
637 piord
->iu
.hdr_list
[k
].bus
= ha
->virt_bus
;
638 piord
->iu
.hdr_list
[k
].target
= k
;
639 piord
->iu
.hdr_list
[k
].lun
= 0;
640 if (status
!= S_OK
) {
641 ha
->hdr
[k
].present
= FALSE
;
643 ha
->hdr
[k
].present
= TRUE
;
644 ha
->hdr
[k
].size
= info
;
645 /* evaluate mapping (sectors per head, heads per cylinder) */
646 ha
->hdr
[k
].size
&= ~SECS32
;
647 gdth_eval_mapping(ha
->hdr
[k
].size
,&drv_cyls
,&drv_hds
,&drv_secs
);
648 ha
->hdr
[k
].heads
= (unchar
)drv_hds
;
649 ha
->hdr
[k
].secs
= (unchar
)drv_secs
;
651 ha
->hdr
[k
].size
= drv_cyls
* drv_hds
* drv_secs
;
653 GDTH_UNLOCK_HA(ha
, flags
);
655 continue; /* next host drive */
657 /* devtype, cluster info, R/W attributes */
658 gdtcmd
.Service
= CACHESERVICE
;
659 gdtcmd
.OpCode
= GDT_DEVTYPE
;
660 gdtcmd
.u
.cache
.DeviceNo
= k
;
661 #if LINUX_VERSION_CODE >= 0x020503
662 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
663 status
= (ushort
)scp
->sr_command
->SCp
.Status
;
664 info
= (ulong32
)scp
->sr_command
->SCp
.Message
;
665 #elif LINUX_VERSION_CODE >= 0x020322
666 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
667 status
= (ushort
)scp
->SCp
.Status
;
668 info
= (ulong32
)scp
->SCp
.Message
;
670 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
671 status
= (ushort
)scp
.SCp
.Status
;
672 info
= (ulong32
)scp
.SCp
.Message
;
674 GDTH_LOCK_HA(ha
, flags
);
675 ha
->hdr
[k
].devtype
= 0;
677 ha
->hdr
[k
].devtype
= (ushort
)info
;
678 GDTH_UNLOCK_HA(ha
, flags
);
680 gdtcmd
.Service
= CACHESERVICE
;
681 gdtcmd
.OpCode
= GDT_CLUST_INFO
;
682 gdtcmd
.u
.cache
.DeviceNo
= k
;
683 #if LINUX_VERSION_CODE >= 0x020503
684 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
685 status
= (ushort
)scp
->sr_command
->SCp
.Status
;
686 info
= (ulong32
)scp
->sr_command
->SCp
.Message
;
687 #elif LINUX_VERSION_CODE >= 0x020322
688 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
689 status
= (ushort
)scp
->SCp
.Status
;
690 info
= (ulong32
)scp
->SCp
.Message
;
692 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
693 status
= (ushort
)scp
.SCp
.Status
;
694 info
= (ulong32
)scp
.SCp
.Message
;
696 GDTH_LOCK_HA(ha
, flags
);
697 ha
->hdr
[k
].cluster_type
= 0;
698 if (status
== S_OK
&& !shared_access
)
699 ha
->hdr
[k
].cluster_type
= (ushort
)info
;
700 GDTH_UNLOCK_HA(ha
, flags
);
701 piord
->iu
.hdr_list
[k
].cluster_type
= ha
->hdr
[k
].cluster_type
;
703 gdtcmd
.Service
= CACHESERVICE
;
704 gdtcmd
.OpCode
= GDT_RW_ATTRIBS
;
705 gdtcmd
.u
.cache
.DeviceNo
= k
;
706 #if LINUX_VERSION_CODE >= 0x020503
707 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
708 status
= (ushort
)scp
->sr_command
->SCp
.Status
;
709 info
= (ulong32
)scp
->sr_command
->SCp
.Message
;
710 #elif LINUX_VERSION_CODE >= 0x020322
711 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
712 status
= (ushort
)scp
->SCp
.Status
;
713 info
= (ulong32
)scp
->SCp
.Message
;
715 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
716 status
= (ushort
)scp
.SCp
.Status
;
717 info
= (ulong32
)scp
.SCp
.Message
;
719 GDTH_LOCK_HA(ha
, flags
);
720 ha
->hdr
[k
].rw_attribs
= 0;
722 ha
->hdr
[k
].rw_attribs
= (ushort
)info
;
723 GDTH_UNLOCK_HA(ha
, flags
);
727 case GDTIOCTL_RESET_DRV
:
728 if (!gdth_ioctl_alloc( hanum
, sizeof(gdth_iord_str
), TRUE
, &paddr
))
730 piord
= (gdth_iord_str
*)ha
->pscratch
;
731 piord
->size
= sizeof(gdth_iord_str
);
732 piord
->status
= S_OK
;
733 i
= piowr
->iu
.scsi
.target
;
734 if (ha
->hdr
[i
].present
) {
735 gdtcmd
.Service
= CACHESERVICE
;
736 gdtcmd
.OpCode
= GDT_CLUST_RESET
;
737 gdtcmd
.u
.cache
.DeviceNo
= i
;
738 #if LINUX_VERSION_CODE >= 0x020503
739 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
740 piord
->status
= (ushort
)scp
->sr_command
->SCp
.Status
;
741 #elif LINUX_VERSION_CODE >= 0x020322
742 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
743 piord
->status
= (scp
->SCp
.Message
<<16)|scp
->SCp
.Status
;
745 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
746 piord
->status
= (scp
.SCp
.Message
<<16)|scp
.SCp
.Status
;
758 static int gdth_get_info(char *buffer
,char **start
,off_t offset
,
759 int length
,int hanum
,int busnum
)
761 int size
= 0,len
= 0;
762 off_t begin
= 0,pos
= 0;
764 int id
, i
, j
, k
, sec
, flag
;
765 int no_mdrv
= 0, drv_no
, is_mirr
;
770 #if LINUX_VERSION_CODE >= 0x020503
773 #elif LINUX_VERSION_CODE >= 0x020322
784 gdth_dskstat_str
*pds
;
785 gdth_diskinfo_str
*pdi
;
786 gdth_arrayinf_str
*pai
;
787 gdth_defcnt_str
*pdef
;
788 gdth_cdrinfo_str
*pcdi
;
791 char cmnd
[MAX_COMMAND_SIZE
];
792 memset(cmnd
, 0xff, 12);
793 memset(&gdtcmd
, 0, sizeof(gdth_cmd_str
));
795 TRACE2(("gdth_get_info() ha %d bus %d\n",hanum
,busnum
));
796 ha
= HADATA(gdth_ctr_tab
[hanum
]);
798 #if LINUX_VERSION_CODE >= 0x020503
799 sdev
= scsi_get_host_dev(gdth_ctr_tab
[hanum
]);
800 scp
= scsi_allocate_request(sdev
, GFP_KERNEL
);
803 scp
->sr_cmd_len
= 12;
805 #elif LINUX_VERSION_CODE >= 0x020322
806 sdev
= scsi_get_host_dev(gdth_ctr_tab
[hanum
]);
807 scp
= scsi_allocate_device(sdev
, 1, FALSE
);
813 memset(&sdev
,0,sizeof(Scsi_Device
));
814 memset(&scp
, 0,sizeof(Scsi_Cmnd
));
815 sdev
.host
= scp
.host
= gdth_ctr_tab
[hanum
];
816 sdev
.id
= scp
.target
= sdev
.host
->this_id
;
820 #ifdef GDTH_IOCTL_PROC
821 /* ioctl from tool? */
822 if (!gdth_ioctl_check_bin(hanum
, (ushort
)length
)) {
824 /* request is i.e. "cat /proc/scsi/gdth/0" */
825 /* format: %-15s\t%-10s\t%-15s\t%s */
826 /* driver parameters */
827 size
= sprintf(buffer
+len
,"Driver Parameters:\n");
828 len
+= size
; pos
= begin
+ len
;
829 if (reserve_list
[0] == 0xff)
832 sprintf(hrec
, "%d", reserve_list
[0]);
833 for (i
= 1; i
< MAX_RES_ARGS
; i
++) {
834 if (reserve_list
[i
] == 0xff)
836 sprintf(hrec
,"%s,%d", hrec
, reserve_list
[i
]);
839 size
= sprintf(buffer
+len
,
840 " reserve_mode: \t%d \treserve_list: \t%s\n",
842 len
+= size
; pos
= begin
+ len
;
843 size
= sprintf(buffer
+len
,
844 " max_ids: \t%-3d \thdr_channel: \t%d\n",
845 max_ids
, hdr_channel
);
846 len
+= size
; pos
= begin
+ len
;
848 /* controller information */
849 size
= sprintf(buffer
+len
,"\nDisk Array Controller Information:\n");
850 len
+= size
; pos
= begin
+ len
;
852 sprintf(hrec
, "%s (Bus %d)", ha
->binfo
.type_string
, busnum
);
854 strcpy(hrec
, ha
->binfo
.type_string
);
855 size
= sprintf(buffer
+len
,
856 " Number: \t%d \tName: \t%s\n",
858 len
+= size
; pos
= begin
+ len
;
861 sprintf(hrec
, "%d.%02d.%02d-%c%03X",
862 (unchar
)(ha
->binfo
.upd_fw_ver
>>24),
863 (unchar
)(ha
->binfo
.upd_fw_ver
>>16),
864 (unchar
)(ha
->binfo
.upd_fw_ver
),
865 ha
->bfeat
.raid
? 'R':'N',
866 ha
->binfo
.upd_revision
);
868 sprintf(hrec
, "%d.%02d", (unchar
)(ha
->cpar
.version
>>8),
869 (unchar
)(ha
->cpar
.version
));
871 size
= sprintf(buffer
+len
,
872 " Driver Ver.: \t%-10s\tFirmware Ver.: \t%s\n",
873 GDTH_VERSION_STR
, hrec
);
874 len
+= size
; pos
= begin
+ len
;
880 if (pos
> offset
+ length
)
884 /* more information: 1. about controller */
885 size
= sprintf(buffer
+len
,
886 " Serial No.: \t0x%8X\tCache RAM size:\t%d KB\n",
887 ha
->binfo
.ser_no
, ha
->binfo
.memsize
/ 1024);
888 len
+= size
; pos
= begin
+ len
;
890 /* 2. about physical devices */
891 size
= sprintf(buffer
+len
,"\nPhysical Devices:");
892 len
+= size
; pos
= begin
+ len
;
895 buf
= gdth_ioctl_alloc(hanum
, GDTH_SCRATCH
, FALSE
, &paddr
);
898 for (i
= 0; i
< ha
->bus_cnt
; ++i
) {
899 /* 2.a statistics (and retries/reassigns) */
900 TRACE2(("pdr_statistics() chn %d\n",i
));
901 pds
= (gdth_dskstat_str
*)(buf
+ GDTH_SCRATCH
/4);
902 gdtcmd
.Service
= CACHESERVICE
;
903 gdtcmd
.OpCode
= GDT_IOCTL
;
904 gdtcmd
.u
.ioctl
.p_param
= paddr
+ GDTH_SCRATCH
/4;
905 gdtcmd
.u
.ioctl
.param_size
= 3*GDTH_SCRATCH
/4;
906 gdtcmd
.u
.ioctl
.subfunc
= DSK_STATISTICS
| L_CTRL_PATTERN
;
907 gdtcmd
.u
.ioctl
.channel
= ha
->raw
[i
].address
| INVALID_CHANNEL
;
908 pds
->bid
= ha
->raw
[i
].local_no
;
910 pds
->entries
= ha
->raw
[i
].pdev_cnt
;
911 cnt
= (3*GDTH_SCRATCH
/4 - 5 * sizeof(ulong32
)) /
912 sizeof(pds
->list
[0]);
913 if (pds
->entries
> cnt
)
915 #if LINUX_VERSION_CODE >= 0x020503
916 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
917 if (scp
->sr_command
->SCp
.Status
!= S_OK
)
918 #elif LINUX_VERSION_CODE >= 0x020322
919 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
920 if (scp
->SCp
.Status
!= S_OK
)
922 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
923 if (scp
.SCp
.Status
!= S_OK
)
929 /* other IOCTLs must fit into area GDTH_SCRATCH/4 */
930 for (j
= 0; j
< ha
->raw
[i
].pdev_cnt
; ++j
) {
932 TRACE2(("scsi_drv_info() chn %d dev %d\n",
933 i
, ha
->raw
[i
].id_list
[j
]));
934 pdi
= (gdth_diskinfo_str
*)buf
;
935 gdtcmd
.Service
= CACHESERVICE
;
936 gdtcmd
.OpCode
= GDT_IOCTL
;
937 gdtcmd
.u
.ioctl
.p_param
= paddr
;
938 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_diskinfo_str
);
939 gdtcmd
.u
.ioctl
.subfunc
= SCSI_DR_INFO
| L_CTRL_PATTERN
;
940 gdtcmd
.u
.ioctl
.channel
=
941 ha
->raw
[i
].address
| ha
->raw
[i
].id_list
[j
];
942 #if LINUX_VERSION_CODE >= 0x020503
943 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
944 if (scp
->sr_command
->SCp
.Status
== S_OK
)
945 #elif LINUX_VERSION_CODE >= 0x020322
946 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
947 if (scp
->SCp
.Status
== S_OK
)
949 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
950 if (scp
.SCp
.Status
== S_OK
)
953 strncpy(hrec
,pdi
->vendor
,8);
954 strncpy(hrec
+8,pdi
->product
,16);
955 strncpy(hrec
+24,pdi
->revision
,4);
957 size
= sprintf(buffer
+len
,
958 "\n Chn/ID/LUN: \t%c/%02d/%d \tName: \t%s\n",
959 'A'+i
,pdi
->target_id
,pdi
->lun
,hrec
);
960 len
+= size
; pos
= begin
+ len
;
962 pdi
->no_ldrive
&= 0xffff;
963 if (pdi
->no_ldrive
== 0xffff)
966 sprintf(hrec
,"%d",pdi
->no_ldrive
);
967 size
= sprintf(buffer
+len
,
968 " Capacity [MB]:\t%-6d \tTo Log. Drive: \t%s\n",
969 pdi
->blkcnt
/(1024*1024/pdi
->blksize
),
971 len
+= size
; pos
= begin
+ len
;
976 if (pdi
->devtype
== 0) {
977 /* search retries/reassigns */
978 for (k
= 0; k
< pds
->count
; ++k
) {
979 if (pds
->list
[k
].tid
== pdi
->target_id
&&
980 pds
->list
[k
].lun
== pdi
->lun
) {
981 size
= sprintf(buffer
+len
,
982 " Retries: \t%-6d \tReassigns: \t%d\n",
983 pds
->list
[k
].retries
,
984 pds
->list
[k
].reassigns
);
985 len
+= size
; pos
= begin
+ len
;
989 /* 2.c grown defects */
990 TRACE2(("scsi_drv_defcnt() chn %d dev %d\n",
991 i
, ha
->raw
[i
].id_list
[j
]));
992 pdef
= (gdth_defcnt_str
*)buf
;
993 gdtcmd
.Service
= CACHESERVICE
;
994 gdtcmd
.OpCode
= GDT_IOCTL
;
995 gdtcmd
.u
.ioctl
.p_param
= paddr
;
996 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_defcnt_str
);
997 gdtcmd
.u
.ioctl
.subfunc
= SCSI_DEF_CNT
| L_CTRL_PATTERN
;
998 gdtcmd
.u
.ioctl
.channel
=
999 ha
->raw
[i
].address
| ha
->raw
[i
].id_list
[j
];
1000 pdef
->sddc_type
= 0x08;
1001 #if LINUX_VERSION_CODE >= 0x020503
1002 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
1003 if (scp
->sr_command
->SCp
.Status
== S_OK
)
1004 #elif LINUX_VERSION_CODE >= 0x020322
1005 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
1006 if (scp
->SCp
.Status
== S_OK
)
1008 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
1009 if (scp
.SCp
.Status
== S_OK
)
1012 size
= sprintf(buffer
+len
,
1013 " Grown Defects:\t%d\n",
1015 len
+= size
; pos
= begin
+ len
;
1022 if (pos
> offset
+ length
)
1026 gdth_ioctl_free(hanum
, GDTH_SCRATCH
, buf
, paddr
);
1029 size
= sprintf(buffer
+len
, "\n --\n");
1030 len
+= size
; pos
= begin
+ len
;
1033 /* 3. about logical drives */
1034 size
= sprintf(buffer
+len
,"\nLogical Drives:");
1035 len
+= size
; pos
= begin
+ len
;
1038 buf
= gdth_ioctl_alloc(hanum
, GDTH_SCRATCH
, FALSE
, &paddr
);
1041 for (i
= 0; i
< MAX_LDRIVES
; ++i
) {
1042 if (!ha
->hdr
[i
].is_logdrv
)
1048 /* 3.a log. drive info */
1049 TRACE2(("cache_drv_info() drive no %d\n",drv_no
));
1050 pcdi
= (gdth_cdrinfo_str
*)buf
;
1051 gdtcmd
.Service
= CACHESERVICE
;
1052 gdtcmd
.OpCode
= GDT_IOCTL
;
1053 gdtcmd
.u
.ioctl
.p_param
= paddr
;
1054 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_cdrinfo_str
);
1055 gdtcmd
.u
.ioctl
.subfunc
= CACHE_DRV_INFO
;
1056 gdtcmd
.u
.ioctl
.channel
= drv_no
;
1057 #if LINUX_VERSION_CODE >= 0x020503
1058 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
1059 if (scp
->sr_command
->SCp
.Status
!= S_OK
)
1060 #elif LINUX_VERSION_CODE >= 0x020322
1061 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
1062 if (scp
->SCp
.Status
!= S_OK
)
1064 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
1065 if (scp
.SCp
.Status
!= S_OK
)
1070 pcdi
->ld_dtype
>>= 16;
1072 if (pcdi
->ld_dtype
> 2) {
1073 strcpy(hrec
, "missing");
1074 } else if (pcdi
->ld_error
& 1) {
1075 strcpy(hrec
, "fault");
1076 } else if (pcdi
->ld_error
& 2) {
1077 strcpy(hrec
, "invalid");
1084 size
= sprintf(buffer
+len
,
1085 "\n Number: \t%-2d \tStatus: \t%s\n",
1087 len
+= size
; pos
= begin
+ len
;
1089 no_mdrv
= pcdi
->cd_ldcnt
;
1090 if (no_mdrv
> 1 || pcdi
->ld_slave
!= -1) {
1092 strcpy(hrec
, "RAID-1");
1093 } else if (pcdi
->ld_dtype
== 0) {
1094 strcpy(hrec
, "Disk");
1095 } else if (pcdi
->ld_dtype
== 1) {
1096 strcpy(hrec
, "RAID-0");
1097 } else if (pcdi
->ld_dtype
== 2) {
1098 strcpy(hrec
, "Chain");
1100 strcpy(hrec
, "???");
1102 size
= sprintf(buffer
+len
,
1103 " Capacity [MB]:\t%-6d \tType: \t%s\n",
1104 pcdi
->ld_blkcnt
/(1024*1024/pcdi
->ld_blksize
),
1106 len
+= size
; pos
= begin
+ len
;
1108 size
= sprintf(buffer
+len
,
1109 " Slave Number: \t%-2d \tStatus: \t%s\n",
1110 drv_no
& 0x7fff, hrec
);
1111 len
+= size
; pos
= begin
+ len
;
1113 drv_no
= pcdi
->ld_slave
;
1118 if (pos
> offset
+ length
)
1120 } while (drv_no
!= -1);
1123 size
= sprintf(buffer
+len
,
1124 " Missing Drv.: \t%-2d \tInvalid Drv.: \t%d\n",
1125 no_mdrv
- j
- k
, k
);
1126 len
+= size
; pos
= begin
+ len
;
1129 if (!ha
->hdr
[i
].is_arraydrv
)
1132 sprintf(hrec
, "%d", ha
->hdr
[i
].master_no
);
1133 size
= sprintf(buffer
+len
,
1134 " To Array Drv.:\t%s\n", hrec
);
1135 len
+= size
; pos
= begin
+ len
;
1140 if (pos
> offset
+ length
)
1143 gdth_ioctl_free(hanum
, GDTH_SCRATCH
, buf
, paddr
);
1146 size
= sprintf(buffer
+len
, "\n --\n");
1147 len
+= size
; pos
= begin
+ len
;
1150 /* 4. about array drives */
1151 size
= sprintf(buffer
+len
,"\nArray Drives:");
1152 len
+= size
; pos
= begin
+ len
;
1155 buf
= gdth_ioctl_alloc(hanum
, GDTH_SCRATCH
, FALSE
, &paddr
);
1158 for (i
= 0; i
< MAX_LDRIVES
; ++i
) {
1159 if (!(ha
->hdr
[i
].is_arraydrv
&& ha
->hdr
[i
].is_master
))
1161 /* 4.a array drive info */
1162 TRACE2(("array_info() drive no %d\n",i
));
1163 pai
= (gdth_arrayinf_str
*)buf
;
1164 gdtcmd
.Service
= CACHESERVICE
;
1165 gdtcmd
.OpCode
= GDT_IOCTL
;
1166 gdtcmd
.u
.ioctl
.p_param
= paddr
;
1167 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_arrayinf_str
);
1168 gdtcmd
.u
.ioctl
.subfunc
= ARRAY_INFO
| LA_CTRL_PATTERN
;
1169 gdtcmd
.u
.ioctl
.channel
= i
;
1170 #if LINUX_VERSION_CODE >= 0x020503
1171 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
1172 if (scp
->sr_command
->SCp
.Status
== S_OK
)
1173 #elif LINUX_VERSION_CODE >= 0x020322
1174 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
1175 if (scp
->SCp
.Status
== S_OK
)
1177 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
1178 if (scp
.SCp
.Status
== S_OK
)
1181 if (pai
->ai_state
== 0)
1182 strcpy(hrec
, "idle");
1183 else if (pai
->ai_state
== 2)
1184 strcpy(hrec
, "build");
1185 else if (pai
->ai_state
== 4)
1186 strcpy(hrec
, "ready");
1187 else if (pai
->ai_state
== 6)
1188 strcpy(hrec
, "fail");
1189 else if (pai
->ai_state
== 8 || pai
->ai_state
== 10)
1190 strcpy(hrec
, "rebuild");
1192 strcpy(hrec
, "error");
1193 if (pai
->ai_ext_state
& 0x10)
1194 strcat(hrec
, "/expand");
1195 else if (pai
->ai_ext_state
& 0x1)
1196 strcat(hrec
, "/patch");
1197 size
= sprintf(buffer
+len
,
1198 "\n Number: \t%-2d \tStatus: \t%s\n",
1200 len
+= size
; pos
= begin
+ len
;
1203 if (pai
->ai_type
== 0)
1204 strcpy(hrec
, "RAID-0");
1205 else if (pai
->ai_type
== 4)
1206 strcpy(hrec
, "RAID-4");
1207 else if (pai
->ai_type
== 5)
1208 strcpy(hrec
, "RAID-5");
1210 strcpy(hrec
, "RAID-10");
1211 size
= sprintf(buffer
+len
,
1212 " Capacity [MB]:\t%-6d \tType: \t%s\n",
1213 pai
->ai_size
/(1024*1024/pai
->ai_secsize
),
1215 len
+= size
; pos
= begin
+ len
;
1220 if (pos
> offset
+ length
)
1224 gdth_ioctl_free(hanum
, GDTH_SCRATCH
, buf
, paddr
);
1227 size
= sprintf(buffer
+len
, "\n --\n");
1228 len
+= size
; pos
= begin
+ len
;
1231 /* 5. about host drives */
1232 size
= sprintf(buffer
+len
,"\nHost Drives:");
1233 len
+= size
; pos
= begin
+ len
;
1236 buf
= gdth_ioctl_alloc(hanum
, sizeof(gdth_hget_str
), FALSE
, &paddr
);
1239 for (i
= 0; i
< MAX_LDRIVES
; ++i
) {
1240 if (!ha
->hdr
[i
].is_logdrv
||
1241 (ha
->hdr
[i
].is_arraydrv
&& !ha
->hdr
[i
].is_master
))
1243 /* 5.a get host drive list */
1244 TRACE2(("host_get() drv_no %d\n",i
));
1245 phg
= (gdth_hget_str
*)buf
;
1246 gdtcmd
.Service
= CACHESERVICE
;
1247 gdtcmd
.OpCode
= GDT_IOCTL
;
1248 gdtcmd
.u
.ioctl
.p_param
= paddr
;
1249 gdtcmd
.u
.ioctl
.param_size
= sizeof(gdth_hget_str
);
1250 gdtcmd
.u
.ioctl
.subfunc
= HOST_GET
| LA_CTRL_PATTERN
;
1251 gdtcmd
.u
.ioctl
.channel
= i
;
1252 phg
->entries
= MAX_HDRIVES
;
1253 phg
->offset
= GDTOFFSOF(gdth_hget_str
, entry
[0]);
1254 #if LINUX_VERSION_CODE >= 0x020503
1255 gdth_do_req(scp
, &gdtcmd
, cmnd
, 30);
1256 if (scp
->sr_command
->SCp
.Status
!= S_OK
)
1257 #elif LINUX_VERSION_CODE >= 0x020322
1258 gdth_do_cmd(scp
, &gdtcmd
, cmnd
, 30);
1259 if (scp
->SCp
.Status
!= S_OK
)
1261 gdth_do_cmd(&scp
, &gdtcmd
, cmnd
, 30);
1262 if (scp
.SCp
.Status
!= S_OK
)
1265 ha
->hdr
[i
].ldr_no
= i
;
1266 ha
->hdr
[i
].rw_attribs
= 0;
1267 ha
->hdr
[i
].start_sec
= 0;
1269 for (j
= 0; j
< phg
->entries
; ++j
) {
1270 k
= phg
->entry
[j
].host_drive
;
1271 if (k
>= MAX_LDRIVES
)
1273 ha
->hdr
[k
].ldr_no
= phg
->entry
[j
].log_drive
;
1274 ha
->hdr
[k
].rw_attribs
= phg
->entry
[j
].rw_attribs
;
1275 ha
->hdr
[k
].start_sec
= phg
->entry
[j
].start_sec
;
1279 gdth_ioctl_free(hanum
, sizeof(gdth_hget_str
), buf
, paddr
);
1281 for (i
= 0; i
< MAX_HDRIVES
; ++i
) {
1282 if (!(ha
->hdr
[i
].present
))
1285 size
= sprintf(buffer
+len
,
1286 "\n Number: \t%-2d \tArr/Log. Drive:\t%d\n",
1287 i
, ha
->hdr
[i
].ldr_no
);
1288 len
+= size
; pos
= begin
+ len
;
1291 size
= sprintf(buffer
+len
,
1292 " Capacity [MB]:\t%-6d \tStart Sector: \t%d\n",
1293 ha
->hdr
[i
].size
/2048, ha
->hdr
[i
].start_sec
);
1294 len
+= size
; pos
= begin
+ len
;
1299 if (pos
> offset
+ length
)
1304 size
= sprintf(buffer
+len
, "\n --\n");
1305 len
+= size
; pos
= begin
+ len
;
1309 /* controller events */
1310 size
= sprintf(buffer
+len
,"\nController Events:\n");
1311 len
+= size
; pos
= begin
+ len
;
1314 id
= gdth_read_event(ha
, id
, &estr
);
1315 if (estr
.event_source
== 0)
1317 if (estr
.event_data
.eu
.driver
.ionode
== hanum
&&
1318 estr
.event_source
== ES_ASYNC
) {
1319 gdth_log_event(&estr
.event_data
, hrec
);
1320 do_gettimeofday(&tv
);
1321 sec
= (int)(tv
.tv_sec
- estr
.first_stamp
);
1322 if (sec
< 0) sec
= 0;
1323 size
= sprintf(buffer
+len
," date- %02d:%02d:%02d\t%s\n",
1324 sec
/3600, sec
%3600/60, sec
%60, hrec
);
1325 len
+= size
; pos
= begin
+ len
;
1330 if (pos
> offset
+ length
)
1336 #ifdef GDTH_IOCTL_PROC
1338 gdth_iord_str
*piord
;
1340 /* request from tool (GDTMON,..) */
1341 piord
= (gdth_iord_str
*)ha
->pscratch
;
1344 length
= piord
->size
;
1345 memcpy(buffer
+len
, (char *)piord
, length
);
1346 gdth_ioctl_free(hanum
, GDTH_SCRATCH
, ha
->pscratch
, paddr
);
1352 #if LINUX_VERSION_CODE >= 0x020503
1353 scsi_release_request(scp
);
1354 scsi_free_host_dev(sdev
);
1355 #elif LINUX_VERSION_CODE >= 0x020322
1356 scsi_release_command(scp
);
1357 scsi_free_host_dev(sdev
);
1359 *start
= buffer
+(offset
-begin
);
1360 len
-= (offset
-begin
);
1363 TRACE2(("get_info() len %d pos %d begin %d offset %d length %d size %d\n",
1364 len
,(int)pos
,(int)begin
,(int)offset
,length
,size
));
1368 #if LINUX_VERSION_CODE >= 0x020503
1369 static void gdth_do_req(Scsi_Request
*scp
, gdth_cmd_str
*gdtcmd
,
1370 char *cmnd
, int timeout
)
1373 DECLARE_COMPLETION(wait
);
1375 TRACE2(("gdth_do_req()\n"));
1376 if (gdtcmd
!= NULL
) {
1377 bufflen
= sizeof(gdth_cmd_str
);
1381 scp
->sr_request
->rq_status
= RQ_SCSI_BUSY
;
1382 scp
->sr_request
->waiting
= &wait
;
1383 scsi_do_req(scp
, cmnd
, gdtcmd
, bufflen
, gdth_scsi_done
, timeout
*HZ
, 1);
1384 wait_for_completion(&wait
);
1388 static void gdth_do_cmd(Scsi_Cmnd
*scp
, gdth_cmd_str
*gdtcmd
,
1389 char *cmnd
, int timeout
)
1392 #if LINUX_VERSION_CODE >= 0x020407
1393 DECLARE_COMPLETION(wait
);
1394 #elif LINUX_VERSION_CODE >= 0x020322
1395 DECLARE_MUTEX_LOCKED(sem
);
1397 struct semaphore sem
= MUTEX_LOCKED
;
1400 TRACE2(("gdth_do_cmd()\n"));
1401 if (gdtcmd
!= NULL
) {
1402 scp
->SCp
.this_residual
= IOCTL_PRI
;
1403 bufflen
= sizeof(gdth_cmd_str
);
1405 scp
->SCp
.this_residual
= DEFAULT_PRI
;
1408 #if LINUX_VERSION_CODE >= 0x020407
1409 scp
->request
.rq_status
= RQ_SCSI_BUSY
;
1410 scp
->request
.waiting
= &wait
;
1411 scsi_do_cmd(scp
, cmnd
, gdtcmd
, bufflen
, gdth_scsi_done
, timeout
*HZ
, 1);
1412 wait_for_completion(&wait
);
1414 scp
->request
.sem
= &sem
;
1415 #if LINUX_VERSION_CODE >= 0x020322
1416 scsi_do_cmd(scp
, cmnd
, gdtcmd
, bufflen
, gdth_scsi_done
, timeout
*HZ
, 1);
1418 GDTH_LOCK_SCSI_DOCMD();
1419 scsi_do_cmd(scp
, cmnd
, gdtcmd
, bufflen
, gdth_scsi_done
, timeout
*HZ
, 1);
1420 GDTH_UNLOCK_SCSI_DOCMD();
1427 void gdth_scsi_done(Scsi_Cmnd
*scp
)
1429 TRACE2(("gdth_scsi_done()\n"));
1431 #if LINUX_VERSION_CODE >= 0x020503
1432 scp
->request
->rq_status
= RQ_SCSI_DONE
;
1433 if (scp
->request
->waiting
!= NULL
)
1434 complete(scp
->request
->waiting
);
1435 #elif LINUX_VERSION_CODE >= 0x020407
1436 scp
->request
.rq_status
= RQ_SCSI_DONE
;
1437 if (scp
->request
.waiting
!= NULL
)
1438 complete(scp
->request
.waiting
);
1440 scp
->request
.rq_status
= RQ_SCSI_DONE
;
1441 if (scp
->request
.sem
!= NULL
)
1442 up(scp
->request
.sem
);
1446 static char *gdth_ioctl_alloc(int hanum
, int size
, int scratch
,
1456 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1457 GDTH_LOCK_HA(ha
, flags
);
1459 if (!ha
->scratch_busy
&& size
<= GDTH_SCRATCH
) {
1460 ha
->scratch_busy
= TRUE
;
1461 ret_val
= ha
->pscratch
;
1462 *paddr
= ha
->scratch_phys
;
1463 } else if (scratch
) {
1466 #if LINUX_VERSION_CODE >= 0x020400
1467 dma_addr_t dma_addr
;
1469 ret_val
= pci_alloc_consistent(ha
->pdev
, size
, &dma_addr
);
1470 *paddr
= (ulong32
)dma_addr
;
1472 ret_val
= scsi_init_malloc(size
, GFP_ATOMIC
| GFP_DMA
);
1474 *paddr
= virt_to_bus(ret_val
);
1478 GDTH_UNLOCK_HA(ha
, flags
);
1482 static void gdth_ioctl_free(int hanum
, int size
, char *buf
, ulong32 paddr
)
1487 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1488 GDTH_LOCK_HA(ha
, flags
);
1490 if (buf
== ha
->pscratch
) {
1491 ha
->scratch_busy
= FALSE
;
1493 #if LINUX_VERSION_CODE >= 0x020400
1494 pci_free_consistent(ha
->pdev
, size
, buf
, paddr
);
1496 scsi_init_free((void *)buf
, size
);
1500 GDTH_UNLOCK_HA(ha
, flags
);
1503 #ifdef GDTH_IOCTL_PROC
1504 static int gdth_ioctl_check_bin(int hanum
, ushort size
)
1510 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1511 GDTH_LOCK_HA(ha
, flags
);
1514 if (ha
->scratch_busy
) {
1515 if (((gdth_iord_str
*)ha
->pscratch
)->size
== (ulong32
)size
)
1518 GDTH_UNLOCK_HA(ha
, flags
);
1523 static void gdth_wait_completion(int hanum
, int busnum
, int id
)
1531 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1532 GDTH_LOCK_HA(ha
, flags
);
1534 for (i
= 0; i
< GDTH_MAXCMDS
; ++i
) {
1535 scp
= ha
->cmd_tab
[i
].cmnd
;
1536 #if LINUX_VERSION_CODE >= 0x02053C
1537 b
= virt_ctr
? NUMDATA(scp
->device
->host
)->busnum
: scp
->device
->channel
;
1538 t
= scp
->device
->id
;
1540 b
= virt_ctr
? NUMDATA(scp
->host
)->busnum
: scp
->channel
;
1543 if (!SPECIAL_SCP(scp
) && t
== (unchar
)id
&&
1544 b
== (unchar
)busnum
) {
1545 scp
->SCp
.have_data_in
= 0;
1546 GDTH_UNLOCK_HA(ha
, flags
);
1547 while (!scp
->SCp
.have_data_in
)
1549 #if LINUX_VERSION_CODE >= 0x02053C
1550 GDTH_LOCK_SCSI_DONE(scp
->device
->host
, flags
);
1551 scp
->scsi_done(scp
);
1552 GDTH_UNLOCK_SCSI_DONE(scp
->device
->host
, flags
);
1553 #elif LINUX_VERSION_CODE >= 0x020503
1554 GDTH_LOCK_SCSI_DONE(scp
->host
, flags
);
1555 scp
->scsi_done(scp
);
1556 GDTH_UNLOCK_SCSI_DONE(scp
->host
, flags
);
1558 GDTH_LOCK_SCSI_DONE(flags
);
1559 scp
->scsi_done(scp
);
1560 GDTH_UNLOCK_SCSI_DONE(flags
);
1562 GDTH_LOCK_HA(ha
, flags
);
1565 GDTH_UNLOCK_HA(ha
, flags
);
1568 static void gdth_stop_timeout(int hanum
, int busnum
, int id
)
1575 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1576 GDTH_LOCK_HA(ha
, flags
);
1578 for (scp
= ha
->req_first
; scp
; scp
= (Scsi_Cmnd
*)scp
->SCp
.ptr
) {
1579 #if LINUX_VERSION_CODE >= 0x02053C
1580 b
= virt_ctr
? NUMDATA(scp
->device
->host
)->busnum
: scp
->device
->channel
;
1581 t
= scp
->device
->id
;
1583 b
= virt_ctr
? NUMDATA(scp
->host
)->busnum
: scp
->channel
;
1586 if (t
== (unchar
)id
&& b
== (unchar
)busnum
) {
1587 TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
1588 scp
->SCp
.buffers_residual
= gdth_update_timeout(hanum
, scp
, 0);
1591 GDTH_UNLOCK_HA(ha
, flags
);
1594 static void gdth_start_timeout(int hanum
, int busnum
, int id
)
1601 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1602 GDTH_LOCK_HA(ha
, flags
);
1604 for (scp
= ha
->req_first
; scp
; scp
= (Scsi_Cmnd
*)scp
->SCp
.ptr
) {
1605 #if LINUX_VERSION_CODE >= 0x02053C
1606 b
= virt_ctr
? NUMDATA(scp
->device
->host
)->busnum
: scp
->device
->channel
;
1607 t
= scp
->device
->id
;
1609 b
= virt_ctr
? NUMDATA(scp
->host
)->busnum
: scp
->channel
;
1612 if (t
== (unchar
)id
&& b
== (unchar
)busnum
) {
1613 TRACE2(("gdth_start_timeout(): update_timeout()\n"));
1614 gdth_update_timeout(hanum
, scp
, scp
->SCp
.buffers_residual
);
1617 GDTH_UNLOCK_HA(ha
, flags
);
1620 static int gdth_update_timeout(int hanum
, Scsi_Cmnd
*scp
, int timeout
)
1624 oldto
= scp
->timeout_per_command
;
1625 scp
->timeout_per_command
= timeout
;
1627 #if LINUX_VERSION_CODE >= 0x02014B
1629 del_timer(&scp
->eh_timeout
);
1630 scp
->eh_timeout
.data
= (unsigned long) NULL
;
1631 scp
->eh_timeout
.expires
= 0;
1633 if (scp
->eh_timeout
.data
!= (unsigned long) NULL
)
1634 del_timer(&scp
->eh_timeout
);
1635 scp
->eh_timeout
.data
= (unsigned long) scp
;
1636 scp
->eh_timeout
.expires
= jiffies
+ timeout
;
1637 add_timer(&scp
->eh_timeout
);
1641 if (timer_table
[SCSI_TIMER
].expires
== 0) {
1642 timer_table
[SCSI_TIMER
].expires
= jiffies
+ timeout
;
1643 timer_active
|= 1 << SCSI_TIMER
;
1645 if (jiffies
+ timeout
< timer_table
[SCSI_TIMER
].expires
)
1646 timer_table
[SCSI_TIMER
].expires
= jiffies
+ timeout
;