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