Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.18-rc3 865 lines 30 kB view raw
1/* gdth_proc.c 2 * $Id: gdth_proc.c,v 1.43 2006/01/11 16:15:00 achim Exp $ 3 */ 4 5#include <linux/completion.h> 6 7#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 8int gdth_proc_info(struct Scsi_Host *host, char *buffer,char **start,off_t offset,int length, 9 int inout) 10{ 11 int hanum,busnum; 12 13 TRACE2(("gdth_proc_info() length %d offs %d inout %d\n", 14 length,(int)offset,inout)); 15 16 hanum = NUMDATA(host)->hanum; 17 busnum= NUMDATA(host)->busnum; 18 19 if (inout) 20 return(gdth_set_info(buffer,length,host,hanum,busnum)); 21 else 22 return(gdth_get_info(buffer,start,offset,length,host,hanum,busnum)); 23} 24#else 25int gdth_proc_info(char *buffer,char **start,off_t offset,int length,int hostno, 26 int inout) 27{ 28 int hanum,busnum,i; 29 30 TRACE2(("gdth_proc_info() length %d offs %d inout %d\n", 31 length,(int)offset,inout)); 32 33 for (i = 0; i < gdth_ctr_vcount; ++i) { 34 if (gdth_ctr_vtab[i]->host_no == hostno) 35 break; 36 } 37 if (i == gdth_ctr_vcount) 38 return(-EINVAL); 39 40 hanum = NUMDATA(gdth_ctr_vtab[i])->hanum; 41 busnum= NUMDATA(gdth_ctr_vtab[i])->busnum; 42 43 if (inout) 44 return(gdth_set_info(buffer,length,gdth_ctr_vtab[i],hanum,busnum)); 45 else 46 return(gdth_get_info(buffer,start,offset,length, 47 gdth_ctr_vtab[i],hanum,busnum)); 48} 49#endif 50 51static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host, 52 int hanum,int busnum) 53{ 54 int ret_val = -EINVAL; 55 56 TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum)); 57 58 if (length >= 4) { 59 if (strncmp(buffer,"gdth",4) == 0) { 60 buffer += 5; 61 length -= 5; 62 ret_val = gdth_set_asc_info(host, buffer, length, hanum); 63 } 64 } 65 66 return ret_val; 67} 68 69static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, 70 int length,int hanum) 71{ 72 int orig_length, drive, wb_mode; 73 int i, found; 74 gdth_ha_str *ha; 75 gdth_cmd_str gdtcmd; 76 gdth_cpar_str *pcpar; 77 ulong64 paddr; 78 79 char cmnd[MAX_COMMAND_SIZE]; 80 memset(cmnd, 0xff, 12); 81 memset(&gdtcmd, 0, sizeof(gdth_cmd_str)); 82 83 TRACE2(("gdth_set_asc_info() ha %d\n",hanum)); 84 ha = HADATA(gdth_ctr_tab[hanum]); 85 orig_length = length + 5; 86 drive = -1; 87 wb_mode = 0; 88 found = FALSE; 89 90 if (length >= 5 && strncmp(buffer,"flush",5)==0) { 91 buffer += 6; 92 length -= 6; 93 if (length && *buffer>='0' && *buffer<='9') { 94 drive = (int)(*buffer-'0'); 95 ++buffer; --length; 96 if (length && *buffer>='0' && *buffer<='9') { 97 drive = drive*10 + (int)(*buffer-'0'); 98 ++buffer; --length; 99 } 100 printk("GDT: Flushing host drive %d .. ",drive); 101 } else { 102 printk("GDT: Flushing all host drives .. "); 103 } 104 for (i = 0; i < MAX_HDRIVES; ++i) { 105 if (ha->hdr[i].present) { 106 if (drive != -1 && i != drive) 107 continue; 108 found = TRUE; 109 gdtcmd.Service = CACHESERVICE; 110 gdtcmd.OpCode = GDT_FLUSH; 111 if (ha->cache_feat & GDT_64BIT) { 112 gdtcmd.u.cache64.DeviceNo = i; 113 gdtcmd.u.cache64.BlockNo = 1; 114 } else { 115 gdtcmd.u.cache.DeviceNo = i; 116 gdtcmd.u.cache.BlockNo = 1; 117 } 118 119 gdth_execute(host, &gdtcmd, cmnd, 30, NULL); 120 } 121 } 122 if (!found) 123 printk("\nNo host drive found !\n"); 124 else 125 printk("Done.\n"); 126 return(orig_length); 127 } 128 129 if (length >= 7 && strncmp(buffer,"wbp_off",7)==0) { 130 buffer += 8; 131 length -= 8; 132 printk("GDT: Disabling write back permanently .. "); 133 wb_mode = 1; 134 } else if (length >= 6 && strncmp(buffer,"wbp_on",6)==0) { 135 buffer += 7; 136 length -= 7; 137 printk("GDT: Enabling write back permanently .. "); 138 wb_mode = 2; 139 } else if (length >= 6 && strncmp(buffer,"wb_off",6)==0) { 140 buffer += 7; 141 length -= 7; 142 printk("GDT: Disabling write back commands .. "); 143 if (ha->cache_feat & GDT_WR_THROUGH) { 144 gdth_write_through = TRUE; 145 printk("Done.\n"); 146 } else { 147 printk("Not supported !\n"); 148 } 149 return(orig_length); 150 } else if (length >= 5 && strncmp(buffer,"wb_on",5)==0) { 151 buffer += 6; 152 length -= 6; 153 printk("GDT: Enabling write back commands .. "); 154 gdth_write_through = FALSE; 155 printk("Done.\n"); 156 return(orig_length); 157 } 158 159 if (wb_mode) { 160 if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str), TRUE, &paddr)) 161 return(-EBUSY); 162 pcpar = (gdth_cpar_str *)ha->pscratch; 163 memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) ); 164 gdtcmd.Service = CACHESERVICE; 165 gdtcmd.OpCode = GDT_IOCTL; 166 gdtcmd.u.ioctl.p_param = paddr; 167 gdtcmd.u.ioctl.param_size = sizeof(gdth_cpar_str); 168 gdtcmd.u.ioctl.subfunc = CACHE_CONFIG; 169 gdtcmd.u.ioctl.channel = INVALID_CHANNEL; 170 pcpar->write_back = wb_mode==1 ? 0:1; 171 172 gdth_execute(host, &gdtcmd, cmnd, 30, NULL); 173 174 gdth_ioctl_free(hanum, GDTH_SCRATCH, ha->pscratch, paddr); 175 printk("Done.\n"); 176 return(orig_length); 177 } 178 179 printk("GDT: Unknown command: %s Length: %d\n",buffer,length); 180 return(-EINVAL); 181} 182 183static int gdth_get_info(char *buffer,char **start,off_t offset,int length, 184 struct Scsi_Host *host,int hanum,int busnum) 185{ 186 int size = 0,len = 0; 187 off_t begin = 0,pos = 0; 188 gdth_ha_str *ha; 189 int id, i, j, k, sec, flag; 190 int no_mdrv = 0, drv_no, is_mirr; 191 ulong32 cnt; 192 ulong64 paddr; 193 int rc = -ENOMEM; 194 195 gdth_cmd_str *gdtcmd; 196 gdth_evt_str *estr; 197 char hrec[161]; 198 struct timeval tv; 199 200 char *buf; 201 gdth_dskstat_str *pds; 202 gdth_diskinfo_str *pdi; 203 gdth_arrayinf_str *pai; 204 gdth_defcnt_str *pdef; 205 gdth_cdrinfo_str *pcdi; 206 gdth_hget_str *phg; 207 char cmnd[MAX_COMMAND_SIZE]; 208 209 gdtcmd = kmalloc(sizeof(*gdtcmd), GFP_KERNEL); 210 estr = kmalloc(sizeof(*estr), GFP_KERNEL); 211 if (!gdtcmd || !estr) 212 goto free_fail; 213 214 memset(cmnd, 0xff, 12); 215 memset(gdtcmd, 0, sizeof(gdth_cmd_str)); 216 217 TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum)); 218 ha = HADATA(gdth_ctr_tab[hanum]); 219 220 221 /* request is i.e. "cat /proc/scsi/gdth/0" */ 222 /* format: %-15s\t%-10s\t%-15s\t%s */ 223 /* driver parameters */ 224 size = sprintf(buffer+len,"Driver Parameters:\n"); 225 len += size; pos = begin + len; 226 if (reserve_list[0] == 0xff) 227 strcpy(hrec, "--"); 228 else { 229 sprintf(hrec, "%d", reserve_list[0]); 230 for (i = 1; i < MAX_RES_ARGS; i++) { 231 if (reserve_list[i] == 0xff) 232 break; 233 sprintf(hrec,"%s,%d", hrec, reserve_list[i]); 234 } 235 } 236 size = sprintf(buffer+len, 237 " reserve_mode: \t%d \treserve_list: \t%s\n", 238 reserve_mode, hrec); 239 len += size; pos = begin + len; 240 size = sprintf(buffer+len, 241 " max_ids: \t%-3d \thdr_channel: \t%d\n", 242 max_ids, hdr_channel); 243 len += size; pos = begin + len; 244 245 /* controller information */ 246 size = sprintf(buffer+len,"\nDisk Array Controller Information:\n"); 247 len += size; pos = begin + len; 248 if (virt_ctr) 249 sprintf(hrec, "%s (Bus %d)", ha->binfo.type_string, busnum); 250 else 251 strcpy(hrec, ha->binfo.type_string); 252 size = sprintf(buffer+len, 253 " Number: \t%d \tName: \t%s\n", 254 hanum, hrec); 255 len += size; pos = begin + len; 256 257 if (ha->more_proc) 258 sprintf(hrec, "%d.%02d.%02d-%c%03X", 259 (unchar)(ha->binfo.upd_fw_ver>>24), 260 (unchar)(ha->binfo.upd_fw_ver>>16), 261 (unchar)(ha->binfo.upd_fw_ver), 262 ha->bfeat.raid ? 'R':'N', 263 ha->binfo.upd_revision); 264 else 265 sprintf(hrec, "%d.%02d", (unchar)(ha->cpar.version>>8), 266 (unchar)(ha->cpar.version)); 267 268 size = sprintf(buffer+len, 269 " Driver Ver.: \t%-10s\tFirmware Ver.: \t%s\n", 270 GDTH_VERSION_STR, hrec); 271 len += size; pos = begin + len; 272 273 if (ha->more_proc) { 274 /* more information: 1. about controller */ 275 size = sprintf(buffer+len, 276 " Serial No.: \t0x%8X\tCache RAM size:\t%d KB\n", 277 ha->binfo.ser_no, ha->binfo.memsize / 1024); 278 len += size; pos = begin + len; 279 } 280 281#ifdef GDTH_DMA_STATISTICS 282 /* controller statistics */ 283 size = sprintf(buffer+len,"\nController Statistics:\n"); 284 len += size; pos = begin + len; 285 size = sprintf(buffer+len, 286 " 32-bit DMA buffer:\t%lu\t64-bit DMA buffer:\t%lu\n", 287 ha->dma32_cnt, ha->dma64_cnt); 288 len += size; pos = begin + len; 289#endif 290 291 if (pos < offset) { 292 len = 0; 293 begin = pos; 294 } 295 if (pos > offset + length) 296 goto stop_output; 297 298 if (ha->more_proc) { 299 /* more information: 2. about physical devices */ 300 size = sprintf(buffer+len,"\nPhysical Devices:"); 301 len += size; pos = begin + len; 302 flag = FALSE; 303 304 buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); 305 if (!buf) 306 goto stop_output; 307 for (i = 0; i < ha->bus_cnt; ++i) { 308 /* 2.a statistics (and retries/reassigns) */ 309 TRACE2(("pdr_statistics() chn %d\n",i)); 310 pds = (gdth_dskstat_str *)(buf + GDTH_SCRATCH/4); 311 gdtcmd->Service = CACHESERVICE; 312 gdtcmd->OpCode = GDT_IOCTL; 313 gdtcmd->u.ioctl.p_param = paddr + GDTH_SCRATCH/4; 314 gdtcmd->u.ioctl.param_size = 3*GDTH_SCRATCH/4; 315 gdtcmd->u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN; 316 gdtcmd->u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL; 317 pds->bid = ha->raw[i].local_no; 318 pds->first = 0; 319 pds->entries = ha->raw[i].pdev_cnt; 320 cnt = (3*GDTH_SCRATCH/4 - 5 * sizeof(ulong32)) / 321 sizeof(pds->list[0]); 322 if (pds->entries > cnt) 323 pds->entries = cnt; 324 325 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) != S_OK) 326 pds->count = 0; 327 328 /* other IOCTLs must fit into area GDTH_SCRATCH/4 */ 329 for (j = 0; j < ha->raw[i].pdev_cnt; ++j) { 330 /* 2.b drive info */ 331 TRACE2(("scsi_drv_info() chn %d dev %d\n", 332 i, ha->raw[i].id_list[j])); 333 pdi = (gdth_diskinfo_str *)buf; 334 gdtcmd->Service = CACHESERVICE; 335 gdtcmd->OpCode = GDT_IOCTL; 336 gdtcmd->u.ioctl.p_param = paddr; 337 gdtcmd->u.ioctl.param_size = sizeof(gdth_diskinfo_str); 338 gdtcmd->u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN; 339 gdtcmd->u.ioctl.channel = 340 ha->raw[i].address | ha->raw[i].id_list[j]; 341 342 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { 343 strncpy(hrec,pdi->vendor,8); 344 strncpy(hrec+8,pdi->product,16); 345 strncpy(hrec+24,pdi->revision,4); 346 hrec[28] = 0; 347 size = sprintf(buffer+len, 348 "\n Chn/ID/LUN: \t%c/%02d/%d \tName: \t%s\n", 349 'A'+i,pdi->target_id,pdi->lun,hrec); 350 len += size; pos = begin + len; 351 flag = TRUE; 352 pdi->no_ldrive &= 0xffff; 353 if (pdi->no_ldrive == 0xffff) 354 strcpy(hrec,"--"); 355 else 356 sprintf(hrec,"%d",pdi->no_ldrive); 357 size = sprintf(buffer+len, 358 " Capacity [MB]:\t%-6d \tTo Log. Drive: \t%s\n", 359 pdi->blkcnt/(1024*1024/pdi->blksize), 360 hrec); 361 len += size; pos = begin + len; 362 } else { 363 pdi->devtype = 0xff; 364 } 365 366 if (pdi->devtype == 0) { 367 /* search retries/reassigns */ 368 for (k = 0; k < pds->count; ++k) { 369 if (pds->list[k].tid == pdi->target_id && 370 pds->list[k].lun == pdi->lun) { 371 size = sprintf(buffer+len, 372 " Retries: \t%-6d \tReassigns: \t%d\n", 373 pds->list[k].retries, 374 pds->list[k].reassigns); 375 len += size; pos = begin + len; 376 break; 377 } 378 } 379 /* 2.c grown defects */ 380 TRACE2(("scsi_drv_defcnt() chn %d dev %d\n", 381 i, ha->raw[i].id_list[j])); 382 pdef = (gdth_defcnt_str *)buf; 383 gdtcmd->Service = CACHESERVICE; 384 gdtcmd->OpCode = GDT_IOCTL; 385 gdtcmd->u.ioctl.p_param = paddr; 386 gdtcmd->u.ioctl.param_size = sizeof(gdth_defcnt_str); 387 gdtcmd->u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN; 388 gdtcmd->u.ioctl.channel = 389 ha->raw[i].address | ha->raw[i].id_list[j]; 390 pdef->sddc_type = 0x08; 391 392 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { 393 size = sprintf(buffer+len, 394 " Grown Defects:\t%d\n", 395 pdef->sddc_cnt); 396 len += size; pos = begin + len; 397 } 398 } 399 if (pos < offset) { 400 len = 0; 401 begin = pos; 402 } 403 if (pos > offset + length) 404 goto stop_output; 405 } 406 } 407 gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); 408 409 if (!flag) { 410 size = sprintf(buffer+len, "\n --\n"); 411 len += size; pos = begin + len; 412 } 413 414 /* 3. about logical drives */ 415 size = sprintf(buffer+len,"\nLogical Drives:"); 416 len += size; pos = begin + len; 417 flag = FALSE; 418 419 buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); 420 if (!buf) 421 goto stop_output; 422 for (i = 0; i < MAX_LDRIVES; ++i) { 423 if (!ha->hdr[i].is_logdrv) 424 continue; 425 drv_no = i; 426 j = k = 0; 427 is_mirr = FALSE; 428 do { 429 /* 3.a log. drive info */ 430 TRACE2(("cache_drv_info() drive no %d\n",drv_no)); 431 pcdi = (gdth_cdrinfo_str *)buf; 432 gdtcmd->Service = CACHESERVICE; 433 gdtcmd->OpCode = GDT_IOCTL; 434 gdtcmd->u.ioctl.p_param = paddr; 435 gdtcmd->u.ioctl.param_size = sizeof(gdth_cdrinfo_str); 436 gdtcmd->u.ioctl.subfunc = CACHE_DRV_INFO; 437 gdtcmd->u.ioctl.channel = drv_no; 438 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) != S_OK) 439 break; 440 pcdi->ld_dtype >>= 16; 441 j++; 442 if (pcdi->ld_dtype > 2) { 443 strcpy(hrec, "missing"); 444 } else if (pcdi->ld_error & 1) { 445 strcpy(hrec, "fault"); 446 } else if (pcdi->ld_error & 2) { 447 strcpy(hrec, "invalid"); 448 k++; j--; 449 } else { 450 strcpy(hrec, "ok"); 451 } 452 453 if (drv_no == i) { 454 size = sprintf(buffer+len, 455 "\n Number: \t%-2d \tStatus: \t%s\n", 456 drv_no, hrec); 457 len += size; pos = begin + len; 458 flag = TRUE; 459 no_mdrv = pcdi->cd_ldcnt; 460 if (no_mdrv > 1 || pcdi->ld_slave != -1) { 461 is_mirr = TRUE; 462 strcpy(hrec, "RAID-1"); 463 } else if (pcdi->ld_dtype == 0) { 464 strcpy(hrec, "Disk"); 465 } else if (pcdi->ld_dtype == 1) { 466 strcpy(hrec, "RAID-0"); 467 } else if (pcdi->ld_dtype == 2) { 468 strcpy(hrec, "Chain"); 469 } else { 470 strcpy(hrec, "???"); 471 } 472 size = sprintf(buffer+len, 473 " Capacity [MB]:\t%-6d \tType: \t%s\n", 474 pcdi->ld_blkcnt/(1024*1024/pcdi->ld_blksize), 475 hrec); 476 len += size; pos = begin + len; 477 } else { 478 size = sprintf(buffer+len, 479 " Slave Number: \t%-2d \tStatus: \t%s\n", 480 drv_no & 0x7fff, hrec); 481 len += size; pos = begin + len; 482 } 483 drv_no = pcdi->ld_slave; 484 if (pos < offset) { 485 len = 0; 486 begin = pos; 487 } 488 if (pos > offset + length) 489 goto stop_output; 490 } while (drv_no != -1); 491 492 if (is_mirr) { 493 size = sprintf(buffer+len, 494 " Missing Drv.: \t%-2d \tInvalid Drv.: \t%d\n", 495 no_mdrv - j - k, k); 496 len += size; pos = begin + len; 497 } 498 499 if (!ha->hdr[i].is_arraydrv) 500 strcpy(hrec, "--"); 501 else 502 sprintf(hrec, "%d", ha->hdr[i].master_no); 503 size = sprintf(buffer+len, 504 " To Array Drv.:\t%s\n", hrec); 505 len += size; pos = begin + len; 506 if (pos < offset) { 507 len = 0; 508 begin = pos; 509 } 510 if (pos > offset + length) 511 goto stop_output; 512 } 513 gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); 514 515 if (!flag) { 516 size = sprintf(buffer+len, "\n --\n"); 517 len += size; pos = begin + len; 518 } 519 520 /* 4. about array drives */ 521 size = sprintf(buffer+len,"\nArray Drives:"); 522 len += size; pos = begin + len; 523 flag = FALSE; 524 525 buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); 526 if (!buf) 527 goto stop_output; 528 for (i = 0; i < MAX_LDRIVES; ++i) { 529 if (!(ha->hdr[i].is_arraydrv && ha->hdr[i].is_master)) 530 continue; 531 /* 4.a array drive info */ 532 TRACE2(("array_info() drive no %d\n",i)); 533 pai = (gdth_arrayinf_str *)buf; 534 gdtcmd->Service = CACHESERVICE; 535 gdtcmd->OpCode = GDT_IOCTL; 536 gdtcmd->u.ioctl.p_param = paddr; 537 gdtcmd->u.ioctl.param_size = sizeof(gdth_arrayinf_str); 538 gdtcmd->u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN; 539 gdtcmd->u.ioctl.channel = i; 540 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { 541 if (pai->ai_state == 0) 542 strcpy(hrec, "idle"); 543 else if (pai->ai_state == 2) 544 strcpy(hrec, "build"); 545 else if (pai->ai_state == 4) 546 strcpy(hrec, "ready"); 547 else if (pai->ai_state == 6) 548 strcpy(hrec, "fail"); 549 else if (pai->ai_state == 8 || pai->ai_state == 10) 550 strcpy(hrec, "rebuild"); 551 else 552 strcpy(hrec, "error"); 553 if (pai->ai_ext_state & 0x10) 554 strcat(hrec, "/expand"); 555 else if (pai->ai_ext_state & 0x1) 556 strcat(hrec, "/patch"); 557 size = sprintf(buffer+len, 558 "\n Number: \t%-2d \tStatus: \t%s\n", 559 i,hrec); 560 len += size; pos = begin + len; 561 flag = TRUE; 562 563 if (pai->ai_type == 0) 564 strcpy(hrec, "RAID-0"); 565 else if (pai->ai_type == 4) 566 strcpy(hrec, "RAID-4"); 567 else if (pai->ai_type == 5) 568 strcpy(hrec, "RAID-5"); 569 else 570 strcpy(hrec, "RAID-10"); 571 size = sprintf(buffer+len, 572 " Capacity [MB]:\t%-6d \tType: \t%s\n", 573 pai->ai_size/(1024*1024/pai->ai_secsize), 574 hrec); 575 len += size; pos = begin + len; 576 if (pos < offset) { 577 len = 0; 578 begin = pos; 579 } 580 if (pos > offset + length) 581 goto stop_output; 582 } 583 } 584 gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); 585 586 if (!flag) { 587 size = sprintf(buffer+len, "\n --\n"); 588 len += size; pos = begin + len; 589 } 590 591 /* 5. about host drives */ 592 size = sprintf(buffer+len,"\nHost Drives:"); 593 len += size; pos = begin + len; 594 flag = FALSE; 595 596 buf = gdth_ioctl_alloc(hanum, sizeof(gdth_hget_str), FALSE, &paddr); 597 if (!buf) 598 goto stop_output; 599 for (i = 0; i < MAX_LDRIVES; ++i) { 600 if (!ha->hdr[i].is_logdrv || 601 (ha->hdr[i].is_arraydrv && !ha->hdr[i].is_master)) 602 continue; 603 /* 5.a get host drive list */ 604 TRACE2(("host_get() drv_no %d\n",i)); 605 phg = (gdth_hget_str *)buf; 606 gdtcmd->Service = CACHESERVICE; 607 gdtcmd->OpCode = GDT_IOCTL; 608 gdtcmd->u.ioctl.p_param = paddr; 609 gdtcmd->u.ioctl.param_size = sizeof(gdth_hget_str); 610 gdtcmd->u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN; 611 gdtcmd->u.ioctl.channel = i; 612 phg->entries = MAX_HDRIVES; 613 phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]); 614 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { 615 ha->hdr[i].ldr_no = i; 616 ha->hdr[i].rw_attribs = 0; 617 ha->hdr[i].start_sec = 0; 618 } else { 619 for (j = 0; j < phg->entries; ++j) { 620 k = phg->entry[j].host_drive; 621 if (k >= MAX_LDRIVES) 622 continue; 623 ha->hdr[k].ldr_no = phg->entry[j].log_drive; 624 ha->hdr[k].rw_attribs = phg->entry[j].rw_attribs; 625 ha->hdr[k].start_sec = phg->entry[j].start_sec; 626 } 627 } 628 } 629 gdth_ioctl_free(hanum, sizeof(gdth_hget_str), buf, paddr); 630 631 for (i = 0; i < MAX_HDRIVES; ++i) { 632 if (!(ha->hdr[i].present)) 633 continue; 634 635 size = sprintf(buffer+len, 636 "\n Number: \t%-2d \tArr/Log. Drive:\t%d\n", 637 i, ha->hdr[i].ldr_no); 638 len += size; pos = begin + len; 639 flag = TRUE; 640 641 size = sprintf(buffer+len, 642 " Capacity [MB]:\t%-6d \tStart Sector: \t%d\n", 643 (ulong32)(ha->hdr[i].size/2048), ha->hdr[i].start_sec); 644 len += size; pos = begin + len; 645 if (pos < offset) { 646 len = 0; 647 begin = pos; 648 } 649 if (pos > offset + length) 650 goto stop_output; 651 } 652 653 if (!flag) { 654 size = sprintf(buffer+len, "\n --\n"); 655 len += size; pos = begin + len; 656 } 657 } 658 659 /* controller events */ 660 size = sprintf(buffer+len,"\nController Events:\n"); 661 len += size; pos = begin + len; 662 663 for (id = -1;;) { 664 id = gdth_read_event(ha, id, estr); 665 if (estr->event_source == 0) 666 break; 667 if (estr->event_data.eu.driver.ionode == hanum && 668 estr->event_source == ES_ASYNC) { 669 gdth_log_event(&estr->event_data, hrec); 670 do_gettimeofday(&tv); 671 sec = (int)(tv.tv_sec - estr->first_stamp); 672 if (sec < 0) sec = 0; 673 size = sprintf(buffer+len," date- %02d:%02d:%02d\t%s\n", 674 sec/3600, sec%3600/60, sec%60, hrec); 675 len += size; pos = begin + len; 676 if (pos < offset) { 677 len = 0; 678 begin = pos; 679 } 680 if (pos > offset + length) 681 goto stop_output; 682 } 683 if (id == -1) 684 break; 685 } 686 687stop_output: 688 *start = buffer +(offset-begin); 689 len -= (offset-begin); 690 if (len > length) 691 len = length; 692 TRACE2(("get_info() len %d pos %d begin %d offset %d length %d size %d\n", 693 len,(int)pos,(int)begin,(int)offset,length,size)); 694 rc = len; 695 696free_fail: 697 kfree(gdtcmd); 698 kfree(estr); 699 return rc; 700} 701 702static char *gdth_ioctl_alloc(int hanum, int size, int scratch, 703 ulong64 *paddr) 704{ 705 gdth_ha_str *ha; 706 ulong flags; 707 char *ret_val; 708 709 if (size == 0) 710 return NULL; 711 712 ha = HADATA(gdth_ctr_tab[hanum]); 713 spin_lock_irqsave(&ha->smp_lock, flags); 714 715 if (!ha->scratch_busy && size <= GDTH_SCRATCH) { 716 ha->scratch_busy = TRUE; 717 ret_val = ha->pscratch; 718 *paddr = ha->scratch_phys; 719 } else if (scratch) { 720 ret_val = NULL; 721 } else { 722 dma_addr_t dma_addr; 723 724 ret_val = pci_alloc_consistent(ha->pdev, size, &dma_addr); 725 *paddr = dma_addr; 726 } 727 728 spin_unlock_irqrestore(&ha->smp_lock, flags); 729 return ret_val; 730} 731 732static void gdth_ioctl_free(int hanum, int size, char *buf, ulong64 paddr) 733{ 734 gdth_ha_str *ha; 735 ulong flags; 736 737 ha = HADATA(gdth_ctr_tab[hanum]); 738 spin_lock_irqsave(&ha->smp_lock, flags); 739 740 if (buf == ha->pscratch) { 741 ha->scratch_busy = FALSE; 742 } else { 743 pci_free_consistent(ha->pdev, size, buf, paddr); 744 } 745 746 spin_unlock_irqrestore(&ha->smp_lock, flags); 747} 748 749#ifdef GDTH_IOCTL_PROC 750static int gdth_ioctl_check_bin(int hanum, ushort size) 751{ 752 gdth_ha_str *ha; 753 ulong flags; 754 int ret_val; 755 756 ha = HADATA(gdth_ctr_tab[hanum]); 757 spin_lock_irqsave(&ha->smp_lock, flags); 758 759 ret_val = FALSE; 760 if (ha->scratch_busy) { 761 if (((gdth_iord_str *)ha->pscratch)->size == (ulong32)size) 762 ret_val = TRUE; 763 } 764 spin_unlock_irqrestore(&ha->smp_lock, flags); 765 return ret_val; 766} 767#endif 768 769static void gdth_wait_completion(int hanum, int busnum, int id) 770{ 771 gdth_ha_str *ha; 772 ulong flags; 773 int i; 774 Scsi_Cmnd *scp; 775 unchar b, t; 776 777 ha = HADATA(gdth_ctr_tab[hanum]); 778 spin_lock_irqsave(&ha->smp_lock, flags); 779 780 for (i = 0; i < GDTH_MAXCMDS; ++i) { 781 scp = ha->cmd_tab[i].cmnd; 782 783 b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; 784 t = scp->device->id; 785 if (!SPECIAL_SCP(scp) && t == (unchar)id && 786 b == (unchar)busnum) { 787 scp->SCp.have_data_in = 0; 788 spin_unlock_irqrestore(&ha->smp_lock, flags); 789 while (!scp->SCp.have_data_in) 790 barrier(); 791 spin_lock_irqsave(&ha->smp_lock, flags); 792 } 793 } 794 spin_unlock_irqrestore(&ha->smp_lock, flags); 795} 796 797static void gdth_stop_timeout(int hanum, int busnum, int id) 798{ 799 gdth_ha_str *ha; 800 ulong flags; 801 Scsi_Cmnd *scp; 802 unchar b, t; 803 804 ha = HADATA(gdth_ctr_tab[hanum]); 805 spin_lock_irqsave(&ha->smp_lock, flags); 806 807 for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { 808 if (scp->done != gdth_scsi_done) { 809 b = virt_ctr ? 810 NUMDATA(scp->device->host)->busnum : scp->device->channel; 811 t = scp->device->id; 812 if (t == (unchar)id && b == (unchar)busnum) { 813 TRACE2(("gdth_stop_timeout(): update_timeout()\n")); 814 scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); 815 } 816 } 817 } 818 spin_unlock_irqrestore(&ha->smp_lock, flags); 819} 820 821static void gdth_start_timeout(int hanum, int busnum, int id) 822{ 823 gdth_ha_str *ha; 824 ulong flags; 825 Scsi_Cmnd *scp; 826 unchar b, t; 827 828 ha = HADATA(gdth_ctr_tab[hanum]); 829 spin_lock_irqsave(&ha->smp_lock, flags); 830 831 for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { 832 if (scp->done != gdth_scsi_done) { 833 b = virt_ctr ? 834 NUMDATA(scp->device->host)->busnum : scp->device->channel; 835 t = scp->device->id; 836 if (t == (unchar)id && b == (unchar)busnum) { 837 TRACE2(("gdth_start_timeout(): update_timeout()\n")); 838 gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual); 839 } 840 } 841 } 842 spin_unlock_irqrestore(&ha->smp_lock, flags); 843} 844 845static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout) 846{ 847 int oldto; 848 849 oldto = scp->timeout_per_command; 850 scp->timeout_per_command = timeout; 851 852 if (timeout == 0) { 853 del_timer(&scp->eh_timeout); 854 scp->eh_timeout.data = (unsigned long) NULL; 855 scp->eh_timeout.expires = 0; 856 } else { 857 if (scp->eh_timeout.data != (unsigned long) NULL) 858 del_timer(&scp->eh_timeout); 859 scp->eh_timeout.data = (unsigned long) scp; 860 scp->eh_timeout.expires = jiffies + timeout; 861 add_timer(&scp->eh_timeout); 862 } 863 864 return oldto; 865}