2 * $Id: gdth_proc.c,v 1.42 2004/03/05 15:50:20 achim Exp $
5 #include <linux/completion.h>
7 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
8 int gdth_proc_info(struct Scsi_Host *host, char *buffer,char **start,off_t offset,int length,
13 TRACE2(("gdth_proc_info() length %d offs %d inout %d\n",
14 length,(int)offset,inout));
16 hanum = NUMDATA(host)->hanum;
17 busnum= NUMDATA(host)->busnum;
20 return(gdth_set_info(buffer,length,host,hanum,busnum));
22 return(gdth_get_info(buffer,start,offset,length,host,hanum,busnum));
25 int gdth_proc_info(char *buffer,char **start,off_t offset,int length,int hostno,
30 TRACE2(("gdth_proc_info() length %d offs %d inout %d\n",
31 length,(int)offset,inout));
33 for (i = 0; i < gdth_ctr_vcount; ++i) {
34 if (gdth_ctr_vtab[i]->host_no == hostno)
37 if (i == gdth_ctr_vcount)
40 hanum = NUMDATA(gdth_ctr_vtab[i])->hanum;
41 busnum= NUMDATA(gdth_ctr_vtab[i])->busnum;
44 return(gdth_set_info(buffer,length,gdth_ctr_vtab[i],hanum,busnum));
46 return(gdth_get_info(buffer,start,offset,length,
47 gdth_ctr_vtab[i],hanum,busnum));
51 static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
54 int ret_val = -EINVAL;
55 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
62 TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum));
64 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
65 sdev = scsi_get_host_dev(host);
66 scp = scsi_allocate_request(sdev, GFP_KERNEL);
72 sdev = scsi_get_host_dev(host);
73 scp = scsi_allocate_device(sdev, 1, FALSE);
81 if (strncmp(buffer,"gdth",4) == 0) {
84 ret_val = gdth_set_asc_info( buffer, length, hanum, scp );
87 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
88 scsi_release_request(scp);
89 scsi_free_host_dev(sdev);
91 scsi_release_command(scp);
92 scsi_free_host_dev(sdev);
97 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
98 static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *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 if (ha->cache_feat & GDT_64BIT) {
143 gdtcmd.u.cache64.DeviceNo = i;
144 gdtcmd.u.cache64.BlockNo = 1;
146 gdtcmd.u.cache.DeviceNo = i;
147 gdtcmd.u.cache.BlockNo = 1;
149 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
150 gdth_do_req(scp, &gdtcmd, cmnd, 30);
152 gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
157 printk("\nNo host drive found !\n");
163 if (length >= 7 && strncmp(buffer,"wbp_off",7)==0) {
166 printk("GDT: Disabling write back permanently .. ");
168 } else if (length >= 6 && strncmp(buffer,"wbp_on",6)==0) {
171 printk("GDT: Enabling write back permanently .. ");
173 } else if (length >= 6 && strncmp(buffer,"wb_off",6)==0) {
176 printk("GDT: Disabling write back commands .. ");
177 if (ha->cache_feat & GDT_WR_THROUGH) {
178 gdth_write_through = TRUE;
181 printk("Not supported !\n");
184 } else if (length >= 5 && strncmp(buffer,"wb_on",5)==0) {
187 printk("GDT: Enabling write back commands .. ");
188 gdth_write_through = FALSE;
194 if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str), TRUE, &paddr))
196 pcpar = (gdth_cpar_str *)ha->pscratch;
197 memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) );
198 gdtcmd.Service = CACHESERVICE;
199 gdtcmd.OpCode = GDT_IOCTL;
200 gdtcmd.u.ioctl.p_param = paddr;
201 gdtcmd.u.ioctl.param_size = sizeof(gdth_cpar_str);
202 gdtcmd.u.ioctl.subfunc = CACHE_CONFIG;
203 gdtcmd.u.ioctl.channel = INVALID_CHANNEL;
204 pcpar->write_back = wb_mode==1 ? 0:1;
205 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
206 gdth_do_req(scp, &gdtcmd, cmnd, 30);
208 gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
210 gdth_ioctl_free(hanum, GDTH_SCRATCH, ha->pscratch, paddr);
215 printk("GDT: Unknown command: %s Length: %d\n",buffer,length);
219 static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
220 struct Scsi_Host *host,int hanum,int busnum)
222 int size = 0,len = 0;
223 off_t begin = 0,pos = 0;
225 int id, i, j, k, sec, flag;
226 int no_mdrv = 0, drv_no, is_mirr;
231 gdth_cmd_str *gdtcmd;
233 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
244 gdth_dskstat_str *pds;
245 gdth_diskinfo_str *pdi;
246 gdth_arrayinf_str *pai;
247 gdth_defcnt_str *pdef;
248 gdth_cdrinfo_str *pcdi;
250 char cmnd[MAX_COMMAND_SIZE];
252 gdtcmd = kmalloc(sizeof(*gdtcmd), GFP_KERNEL);
253 estr = kmalloc(sizeof(*estr), GFP_KERNEL);
254 if (!gdtcmd || !estr)
257 memset(cmnd, 0xff, 12);
258 memset(gdtcmd, 0, sizeof(gdth_cmd_str));
260 TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum));
261 ha = HADATA(gdth_ctr_tab[hanum]);
263 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
264 sdev = scsi_get_host_dev(host);
265 scp = scsi_allocate_request(sdev, GFP_KERNEL);
268 scp->sr_cmd_len = 12;
270 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
271 sdev = scsi_get_host_dev(host);
272 scp = scsi_allocate_device(sdev, 1, FALSE);
278 memset(&sdev,0,sizeof(Scsi_Device));
279 memset(&scp, 0,sizeof(Scsi_Cmnd));
280 sdev.host = scp.host = host;
281 sdev.id = scp.target = sdev.host->this_id;
286 /* request is i.e. "cat /proc/scsi/gdth/0" */
287 /* format: %-15s\t%-10s\t%-15s\t%s */
288 /* driver parameters */
289 size = sprintf(buffer+len,"Driver Parameters:\n");
290 len += size; pos = begin + len;
291 if (reserve_list[0] == 0xff)
294 sprintf(hrec, "%d", reserve_list[0]);
295 for (i = 1; i < MAX_RES_ARGS; i++) {
296 if (reserve_list[i] == 0xff)
298 sprintf(hrec,"%s,%d", hrec, reserve_list[i]);
301 size = sprintf(buffer+len,
302 " reserve_mode: \t%d \treserve_list: \t%s\n",
304 len += size; pos = begin + len;
305 size = sprintf(buffer+len,
306 " max_ids: \t%-3d \thdr_channel: \t%d\n",
307 max_ids, hdr_channel);
308 len += size; pos = begin + len;
310 /* controller information */
311 size = sprintf(buffer+len,"\nDisk Array Controller Information:\n");
312 len += size; pos = begin + len;
314 sprintf(hrec, "%s (Bus %d)", ha->binfo.type_string, busnum);
316 strcpy(hrec, ha->binfo.type_string);
317 size = sprintf(buffer+len,
318 " Number: \t%d \tName: \t%s\n",
320 len += size; pos = begin + len;
323 sprintf(hrec, "%d.%02d.%02d-%c%03X",
324 (unchar)(ha->binfo.upd_fw_ver>>24),
325 (unchar)(ha->binfo.upd_fw_ver>>16),
326 (unchar)(ha->binfo.upd_fw_ver),
327 ha->bfeat.raid ? 'R':'N',
328 ha->binfo.upd_revision);
330 sprintf(hrec, "%d.%02d", (unchar)(ha->cpar.version>>8),
331 (unchar)(ha->cpar.version));
333 size = sprintf(buffer+len,
334 " Driver Ver.: \t%-10s\tFirmware Ver.: \t%s\n",
335 GDTH_VERSION_STR, hrec);
336 len += size; pos = begin + len;
339 /* more information: 1. about controller */
340 size = sprintf(buffer+len,
341 " Serial No.: \t0x%8X\tCache RAM size:\t%d KB\n",
342 ha->binfo.ser_no, ha->binfo.memsize / 1024);
343 len += size; pos = begin + len;
346 #ifdef GDTH_DMA_STATISTICS
347 /* controller statistics */
348 size = sprintf(buffer+len,"\nController Statistics:\n");
349 len += size; pos = begin + len;
350 size = sprintf(buffer+len,
351 " 32-bit DMA buffer:\t%lu\t64-bit DMA buffer:\t%lu\n",
352 ha->dma32_cnt, ha->dma64_cnt);
353 len += size; pos = begin + len;
360 if (pos > offset + length)
364 /* more information: 2. about physical devices */
365 size = sprintf(buffer+len,"\nPhysical Devices:");
366 len += size; pos = begin + len;
369 buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr);
372 for (i = 0; i < ha->bus_cnt; ++i) {
373 /* 2.a statistics (and retries/reassigns) */
374 TRACE2(("pdr_statistics() chn %d\n",i));
375 pds = (gdth_dskstat_str *)(buf + GDTH_SCRATCH/4);
376 gdtcmd->Service = CACHESERVICE;
377 gdtcmd->OpCode = GDT_IOCTL;
378 gdtcmd->u.ioctl.p_param = paddr + GDTH_SCRATCH/4;
379 gdtcmd->u.ioctl.param_size = 3*GDTH_SCRATCH/4;
380 gdtcmd->u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN;
381 gdtcmd->u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL;
382 pds->bid = ha->raw[i].local_no;
384 pds->entries = ha->raw[i].pdev_cnt;
385 cnt = (3*GDTH_SCRATCH/4 - 5 * sizeof(ulong32)) /
386 sizeof(pds->list[0]);
387 if (pds->entries > cnt)
389 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
390 gdth_do_req(scp, gdtcmd, cmnd, 30);
391 if (scp->sr_command->SCp.Status != S_OK)
393 gdth_do_cmd(scp, gdtcmd, cmnd, 30);
394 if (scp->SCp.Status != S_OK)
400 /* other IOCTLs must fit into area GDTH_SCRATCH/4 */
401 for (j = 0; j < ha->raw[i].pdev_cnt; ++j) {
403 TRACE2(("scsi_drv_info() chn %d dev %d\n",
404 i, ha->raw[i].id_list[j]));
405 pdi = (gdth_diskinfo_str *)buf;
406 gdtcmd->Service = CACHESERVICE;
407 gdtcmd->OpCode = GDT_IOCTL;
408 gdtcmd->u.ioctl.p_param = paddr;
409 gdtcmd->u.ioctl.param_size = sizeof(gdth_diskinfo_str);
410 gdtcmd->u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN;
411 gdtcmd->u.ioctl.channel =
412 ha->raw[i].address | ha->raw[i].id_list[j];
413 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
414 gdth_do_req(scp, gdtcmd, cmnd, 30);
415 if (scp->sr_command->SCp.Status == S_OK)
417 gdth_do_cmd(scp, gdtcmd, cmnd, 30);
418 if (scp->SCp.Status == S_OK)
421 strncpy(hrec,pdi->vendor,8);
422 strncpy(hrec+8,pdi->product,16);
423 strncpy(hrec+24,pdi->revision,4);
425 size = sprintf(buffer+len,
426 "\n Chn/ID/LUN: \t%c/%02d/%d \tName: \t%s\n",
427 'A'+i,pdi->target_id,pdi->lun,hrec);
428 len += size; pos = begin + len;
430 pdi->no_ldrive &= 0xffff;
431 if (pdi->no_ldrive == 0xffff)
434 sprintf(hrec,"%d",pdi->no_ldrive);
435 size = sprintf(buffer+len,
436 " Capacity [MB]:\t%-6d \tTo Log. Drive: \t%s\n",
437 pdi->blkcnt/(1024*1024/pdi->blksize),
439 len += size; pos = begin + len;
444 if (pdi->devtype == 0) {
445 /* search retries/reassigns */
446 for (k = 0; k < pds->count; ++k) {
447 if (pds->list[k].tid == pdi->target_id &&
448 pds->list[k].lun == pdi->lun) {
449 size = sprintf(buffer+len,
450 " Retries: \t%-6d \tReassigns: \t%d\n",
451 pds->list[k].retries,
452 pds->list[k].reassigns);
453 len += size; pos = begin + len;
457 /* 2.c grown defects */
458 TRACE2(("scsi_drv_defcnt() chn %d dev %d\n",
459 i, ha->raw[i].id_list[j]));
460 pdef = (gdth_defcnt_str *)buf;
461 gdtcmd->Service = CACHESERVICE;
462 gdtcmd->OpCode = GDT_IOCTL;
463 gdtcmd->u.ioctl.p_param = paddr;
464 gdtcmd->u.ioctl.param_size = sizeof(gdth_defcnt_str);
465 gdtcmd->u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN;
466 gdtcmd->u.ioctl.channel =
467 ha->raw[i].address | ha->raw[i].id_list[j];
468 pdef->sddc_type = 0x08;
469 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
470 gdth_do_req(scp, gdtcmd, cmnd, 30);
471 if (scp->sr_command->SCp.Status == S_OK)
473 gdth_do_cmd(scp, gdtcmd, cmnd, 30);
474 if (scp->SCp.Status == S_OK)
477 size = sprintf(buffer+len,
478 " Grown Defects:\t%d\n",
480 len += size; pos = begin + len;
487 if (pos > offset + length)
491 gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr);
494 size = sprintf(buffer+len, "\n --\n");
495 len += size; pos = begin + len;
498 /* 3. about logical drives */
499 size = sprintf(buffer+len,"\nLogical Drives:");
500 len += size; pos = begin + len;
503 buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr);
506 for (i = 0; i < MAX_LDRIVES; ++i) {
507 if (!ha->hdr[i].is_logdrv)
513 /* 3.a log. drive info */
514 TRACE2(("cache_drv_info() drive no %d\n",drv_no));
515 pcdi = (gdth_cdrinfo_str *)buf;
516 gdtcmd->Service = CACHESERVICE;
517 gdtcmd->OpCode = GDT_IOCTL;
518 gdtcmd->u.ioctl.p_param = paddr;
519 gdtcmd->u.ioctl.param_size = sizeof(gdth_cdrinfo_str);
520 gdtcmd->u.ioctl.subfunc = CACHE_DRV_INFO;
521 gdtcmd->u.ioctl.channel = drv_no;
522 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
523 gdth_do_req(scp, gdtcmd, cmnd, 30);
524 if (scp->sr_command->SCp.Status != S_OK)
526 gdth_do_cmd(scp, gdtcmd, cmnd, 30);
527 if (scp->SCp.Status != S_OK)
532 pcdi->ld_dtype >>= 16;
534 if (pcdi->ld_dtype > 2) {
535 strcpy(hrec, "missing");
536 } else if (pcdi->ld_error & 1) {
537 strcpy(hrec, "fault");
538 } else if (pcdi->ld_error & 2) {
539 strcpy(hrec, "invalid");
546 size = sprintf(buffer+len,
547 "\n Number: \t%-2d \tStatus: \t%s\n",
549 len += size; pos = begin + len;
551 no_mdrv = pcdi->cd_ldcnt;
552 if (no_mdrv > 1 || pcdi->ld_slave != -1) {
554 strcpy(hrec, "RAID-1");
555 } else if (pcdi->ld_dtype == 0) {
556 strcpy(hrec, "Disk");
557 } else if (pcdi->ld_dtype == 1) {
558 strcpy(hrec, "RAID-0");
559 } else if (pcdi->ld_dtype == 2) {
560 strcpy(hrec, "Chain");
564 size = sprintf(buffer+len,
565 " Capacity [MB]:\t%-6d \tType: \t%s\n",
566 pcdi->ld_blkcnt/(1024*1024/pcdi->ld_blksize),
568 len += size; pos = begin + len;
570 size = sprintf(buffer+len,
571 " Slave Number: \t%-2d \tStatus: \t%s\n",
572 drv_no & 0x7fff, hrec);
573 len += size; pos = begin + len;
575 drv_no = pcdi->ld_slave;
580 if (pos > offset + length)
582 } while (drv_no != -1);
585 size = sprintf(buffer+len,
586 " Missing Drv.: \t%-2d \tInvalid Drv.: \t%d\n",
588 len += size; pos = begin + len;
591 if (!ha->hdr[i].is_arraydrv)
594 sprintf(hrec, "%d", ha->hdr[i].master_no);
595 size = sprintf(buffer+len,
596 " To Array Drv.:\t%s\n", hrec);
597 len += size; pos = begin + len;
602 if (pos > offset + length)
605 gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr);
608 size = sprintf(buffer+len, "\n --\n");
609 len += size; pos = begin + len;
612 /* 4. about array drives */
613 size = sprintf(buffer+len,"\nArray Drives:");
614 len += size; pos = begin + len;
617 buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr);
620 for (i = 0; i < MAX_LDRIVES; ++i) {
621 if (!(ha->hdr[i].is_arraydrv && ha->hdr[i].is_master))
623 /* 4.a array drive info */
624 TRACE2(("array_info() drive no %d\n",i));
625 pai = (gdth_arrayinf_str *)buf;
626 gdtcmd->Service = CACHESERVICE;
627 gdtcmd->OpCode = GDT_IOCTL;
628 gdtcmd->u.ioctl.p_param = paddr;
629 gdtcmd->u.ioctl.param_size = sizeof(gdth_arrayinf_str);
630 gdtcmd->u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN;
631 gdtcmd->u.ioctl.channel = i;
632 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
633 gdth_do_req(scp, gdtcmd, cmnd, 30);
634 if (scp->sr_command->SCp.Status == S_OK)
636 gdth_do_cmd(scp, gdtcmd, cmnd, 30);
637 if (scp->SCp.Status == S_OK)
640 if (pai->ai_state == 0)
641 strcpy(hrec, "idle");
642 else if (pai->ai_state == 2)
643 strcpy(hrec, "build");
644 else if (pai->ai_state == 4)
645 strcpy(hrec, "ready");
646 else if (pai->ai_state == 6)
647 strcpy(hrec, "fail");
648 else if (pai->ai_state == 8 || pai->ai_state == 10)
649 strcpy(hrec, "rebuild");
651 strcpy(hrec, "error");
652 if (pai->ai_ext_state & 0x10)
653 strcat(hrec, "/expand");
654 else if (pai->ai_ext_state & 0x1)
655 strcat(hrec, "/patch");
656 size = sprintf(buffer+len,
657 "\n Number: \t%-2d \tStatus: \t%s\n",
659 len += size; pos = begin + len;
662 if (pai->ai_type == 0)
663 strcpy(hrec, "RAID-0");
664 else if (pai->ai_type == 4)
665 strcpy(hrec, "RAID-4");
666 else if (pai->ai_type == 5)
667 strcpy(hrec, "RAID-5");
669 strcpy(hrec, "RAID-10");
670 size = sprintf(buffer+len,
671 " Capacity [MB]:\t%-6d \tType: \t%s\n",
672 pai->ai_size/(1024*1024/pai->ai_secsize),
674 len += size; pos = begin + len;
679 if (pos > offset + length)
683 gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr);
686 size = sprintf(buffer+len, "\n --\n");
687 len += size; pos = begin + len;
690 /* 5. about host drives */
691 size = sprintf(buffer+len,"\nHost Drives:");
692 len += size; pos = begin + len;
695 buf = gdth_ioctl_alloc(hanum, sizeof(gdth_hget_str), FALSE, &paddr);
698 for (i = 0; i < MAX_LDRIVES; ++i) {
699 if (!ha->hdr[i].is_logdrv ||
700 (ha->hdr[i].is_arraydrv && !ha->hdr[i].is_master))
702 /* 5.a get host drive list */
703 TRACE2(("host_get() drv_no %d\n",i));
704 phg = (gdth_hget_str *)buf;
705 gdtcmd->Service = CACHESERVICE;
706 gdtcmd->OpCode = GDT_IOCTL;
707 gdtcmd->u.ioctl.p_param = paddr;
708 gdtcmd->u.ioctl.param_size = sizeof(gdth_hget_str);
709 gdtcmd->u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN;
710 gdtcmd->u.ioctl.channel = i;
711 phg->entries = MAX_HDRIVES;
712 phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]);
713 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
714 gdth_do_req(scp, gdtcmd, cmnd, 30);
715 if (scp->sr_command->SCp.Status != S_OK)
717 gdth_do_cmd(scp, gdtcmd, cmnd, 30);
718 if (scp->SCp.Status != S_OK)
721 ha->hdr[i].ldr_no = i;
722 ha->hdr[i].rw_attribs = 0;
723 ha->hdr[i].start_sec = 0;
725 for (j = 0; j < phg->entries; ++j) {
726 k = phg->entry[j].host_drive;
727 if (k >= MAX_LDRIVES)
729 ha->hdr[k].ldr_no = phg->entry[j].log_drive;
730 ha->hdr[k].rw_attribs = phg->entry[j].rw_attribs;
731 ha->hdr[k].start_sec = phg->entry[j].start_sec;
735 gdth_ioctl_free(hanum, sizeof(gdth_hget_str), buf, paddr);
737 for (i = 0; i < MAX_HDRIVES; ++i) {
738 if (!(ha->hdr[i].present))
741 size = sprintf(buffer+len,
742 "\n Number: \t%-2d \tArr/Log. Drive:\t%d\n",
743 i, ha->hdr[i].ldr_no);
744 len += size; pos = begin + len;
747 size = sprintf(buffer+len,
748 " Capacity [MB]:\t%-6d \tStart Sector: \t%d\n",
749 (ulong32)(ha->hdr[i].size/2048), ha->hdr[i].start_sec);
750 len += size; pos = begin + len;
755 if (pos > offset + length)
760 size = sprintf(buffer+len, "\n --\n");
761 len += size; pos = begin + len;
765 /* controller events */
766 size = sprintf(buffer+len,"\nController Events:\n");
767 len += size; pos = begin + len;
770 id = gdth_read_event(ha, id, estr);
771 if (estr->event_source == 0)
773 if (estr->event_data.eu.driver.ionode == hanum &&
774 estr->event_source == ES_ASYNC) {
775 gdth_log_event(&estr->event_data, hrec);
776 do_gettimeofday(&tv);
777 sec = (int)(tv.tv_sec - estr->first_stamp);
778 if (sec < 0) sec = 0;
779 size = sprintf(buffer+len," date- %02d:%02d:%02d\t%s\n",
780 sec/3600, sec%3600/60, sec%60, hrec);
781 len += size; pos = begin + len;
786 if (pos > offset + length)
794 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
795 scsi_release_request(scp);
796 scsi_free_host_dev(sdev);
798 scsi_release_command(scp);
799 scsi_free_host_dev(sdev);
801 *start = buffer +(offset-begin);
802 len -= (offset-begin);
805 TRACE2(("get_info() len %d pos %d begin %d offset %d length %d size %d\n",
806 len,(int)pos,(int)begin,(int)offset,length,size));
816 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
817 static void gdth_do_req(Scsi_Request *scp, gdth_cmd_str *gdtcmd,
818 char *cmnd, int timeout)
821 DECLARE_COMPLETION(wait);
823 TRACE2(("gdth_do_req()\n"));
824 if (gdtcmd != NULL) {
825 bufflen = sizeof(gdth_cmd_str);
829 scp->sr_request->rq_status = RQ_SCSI_BUSY;
830 scp->sr_request->waiting = &wait;
831 scsi_do_req(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
832 wait_for_completion(&wait);
836 static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *gdtcmd,
837 char *cmnd, int timeout)
840 DECLARE_COMPLETION(wait);
842 TRACE2(("gdth_do_cmd()\n"));
843 if (gdtcmd != NULL) {
844 scp->SCp.this_residual = IOCTL_PRI;
845 bufflen = sizeof(gdth_cmd_str);
847 scp->SCp.this_residual = DEFAULT_PRI;
851 scp->request.rq_status = RQ_SCSI_BUSY;
852 scp->request.waiting = &wait;
853 scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
854 wait_for_completion(&wait);
858 void gdth_scsi_done(Scsi_Cmnd *scp)
860 TRACE2(("gdth_scsi_done()\n"));
862 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
863 scp->request->rq_status = RQ_SCSI_DONE;
864 if (scp->request->waiting != NULL)
865 complete(scp->request->waiting);
867 scp->request.rq_status = RQ_SCSI_DONE;
868 if (scp->request.waiting != NULL)
869 complete(scp->request.waiting);
873 static char *gdth_ioctl_alloc(int hanum, int size, int scratch,
883 ha = HADATA(gdth_ctr_tab[hanum]);
884 spin_lock_irqsave(&ha->smp_lock, flags);
886 if (!ha->scratch_busy && size <= GDTH_SCRATCH) {
887 ha->scratch_busy = TRUE;
888 ret_val = ha->pscratch;
889 *paddr = ha->scratch_phys;
890 } else if (scratch) {
895 ret_val = pci_alloc_consistent(ha->pdev, size, &dma_addr);
899 spin_unlock_irqrestore(&ha->smp_lock, flags);
903 static void gdth_ioctl_free(int hanum, int size, char *buf, ulong64 paddr)
908 ha = HADATA(gdth_ctr_tab[hanum]);
909 spin_lock_irqsave(&ha->smp_lock, flags);
911 if (buf == ha->pscratch) {
912 ha->scratch_busy = FALSE;
914 pci_free_consistent(ha->pdev, size, buf, paddr);
917 spin_unlock_irqrestore(&ha->smp_lock, flags);
920 #ifdef GDTH_IOCTL_PROC
921 static int gdth_ioctl_check_bin(int hanum, ushort size)
927 ha = HADATA(gdth_ctr_tab[hanum]);
928 spin_lock_irqsave(&ha->smp_lock, flags);
931 if (ha->scratch_busy) {
932 if (((gdth_iord_str *)ha->pscratch)->size == (ulong32)size)
935 spin_unlock_irqrestore(&ha->smp_lock, flags);
940 static void gdth_wait_completion(int hanum, int busnum, int id)
948 ha = HADATA(gdth_ctr_tab[hanum]);
949 spin_lock_irqsave(&ha->smp_lock, flags);
951 for (i = 0; i < GDTH_MAXCMDS; ++i) {
952 scp = ha->cmd_tab[i].cmnd;
954 b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
956 if (!SPECIAL_SCP(scp) && t == (unchar)id &&
957 b == (unchar)busnum) {
958 scp->SCp.have_data_in = 0;
959 spin_unlock_irqrestore(&ha->smp_lock, flags);
960 while (!scp->SCp.have_data_in)
962 spin_lock_irqsave(&ha->smp_lock, flags);
965 spin_unlock_irqrestore(&ha->smp_lock, flags);
968 static void gdth_stop_timeout(int hanum, int busnum, int id)
975 ha = HADATA(gdth_ctr_tab[hanum]);
976 spin_lock_irqsave(&ha->smp_lock, flags);
978 for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
979 b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
981 if (t == (unchar)id && b == (unchar)busnum) {
982 TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
983 scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
986 spin_unlock_irqrestore(&ha->smp_lock, flags);
989 static void gdth_start_timeout(int hanum, int busnum, int id)
996 ha = HADATA(gdth_ctr_tab[hanum]);
997 spin_lock_irqsave(&ha->smp_lock, flags);
999 for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
1000 b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
1001 t = scp->device->id;
1002 if (t == (unchar)id && b == (unchar)busnum) {
1003 TRACE2(("gdth_start_timeout(): update_timeout()\n"));
1004 gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual);
1007 spin_unlock_irqrestore(&ha->smp_lock, flags);
1010 static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout)
1014 oldto = scp->timeout_per_command;
1015 scp->timeout_per_command = timeout;
1018 del_timer(&scp->eh_timeout);
1019 scp->eh_timeout.data = (unsigned long) NULL;
1020 scp->eh_timeout.expires = 0;
1022 if (scp->eh_timeout.data != (unsigned long) NULL)
1023 del_timer(&scp->eh_timeout);
1024 scp->eh_timeout.data = (unsigned long) scp;
1025 scp->eh_timeout.expires = jiffies + timeout;
1026 add_timer(&scp->eh_timeout);