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.31-rc7 751 lines 27 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 int hlen; 156 off_t begin = 0,pos = 0; 157 int id, i, j, k, sec, flag; 158 int no_mdrv = 0, drv_no, is_mirr; 159 ulong32 cnt; 160 ulong64 paddr; 161 int rc = -ENOMEM; 162 163 gdth_cmd_str *gdtcmd; 164 gdth_evt_str *estr; 165 char hrec[161]; 166 struct timeval tv; 167 168 char *buf; 169 gdth_dskstat_str *pds; 170 gdth_diskinfo_str *pdi; 171 gdth_arrayinf_str *pai; 172 gdth_defcnt_str *pdef; 173 gdth_cdrinfo_str *pcdi; 174 gdth_hget_str *phg; 175 char cmnd[MAX_COMMAND_SIZE]; 176 177 gdtcmd = kmalloc(sizeof(*gdtcmd), GFP_KERNEL); 178 estr = kmalloc(sizeof(*estr), GFP_KERNEL); 179 if (!gdtcmd || !estr) 180 goto free_fail; 181 182 memset(cmnd, 0xff, 12); 183 memset(gdtcmd, 0, sizeof(gdth_cmd_str)); 184 185 TRACE2(("gdth_get_info() ha %d\n",ha->hanum)); 186 187 188 /* request is i.e. "cat /proc/scsi/gdth/0" */ 189 /* format: %-15s\t%-10s\t%-15s\t%s */ 190 /* driver parameters */ 191 size = sprintf(buffer+len,"Driver Parameters:\n"); 192 len += size; pos = begin + len; 193 if (reserve_list[0] == 0xff) 194 strcpy(hrec, "--"); 195 else { 196 hlen = sprintf(hrec, "%d", reserve_list[0]); 197 for (i = 1; i < MAX_RES_ARGS; i++) { 198 if (reserve_list[i] == 0xff) 199 break; 200 hlen += snprintf(hrec + hlen , 161 - hlen, ",%d", reserve_list[i]); 201 } 202 } 203 size = sprintf(buffer+len, 204 " reserve_mode: \t%d \treserve_list: \t%s\n", 205 reserve_mode, hrec); 206 len += size; pos = begin + len; 207 size = sprintf(buffer+len, 208 " max_ids: \t%-3d \thdr_channel: \t%d\n", 209 max_ids, hdr_channel); 210 len += size; pos = begin + len; 211 212 /* controller information */ 213 size = sprintf(buffer+len,"\nDisk Array Controller Information:\n"); 214 len += size; pos = begin + len; 215 strcpy(hrec, ha->binfo.type_string); 216 size = sprintf(buffer+len, 217 " Number: \t%d \tName: \t%s\n", 218 ha->hanum, hrec); 219 len += size; pos = begin + len; 220 221 if (ha->more_proc) 222 sprintf(hrec, "%d.%02d.%02d-%c%03X", 223 (unchar)(ha->binfo.upd_fw_ver>>24), 224 (unchar)(ha->binfo.upd_fw_ver>>16), 225 (unchar)(ha->binfo.upd_fw_ver), 226 ha->bfeat.raid ? 'R':'N', 227 ha->binfo.upd_revision); 228 else 229 sprintf(hrec, "%d.%02d", (unchar)(ha->cpar.version>>8), 230 (unchar)(ha->cpar.version)); 231 232 size = sprintf(buffer+len, 233 " Driver Ver.: \t%-10s\tFirmware Ver.: \t%s\n", 234 GDTH_VERSION_STR, hrec); 235 len += size; pos = begin + len; 236 237 if (ha->more_proc) { 238 /* more information: 1. about controller */ 239 size = sprintf(buffer+len, 240 " Serial No.: \t0x%8X\tCache RAM size:\t%d KB\n", 241 ha->binfo.ser_no, ha->binfo.memsize / 1024); 242 len += size; pos = begin + len; 243 } 244 245#ifdef GDTH_DMA_STATISTICS 246 /* controller statistics */ 247 size = sprintf(buffer+len,"\nController Statistics:\n"); 248 len += size; pos = begin + len; 249 size = sprintf(buffer+len, 250 " 32-bit DMA buffer:\t%lu\t64-bit DMA buffer:\t%lu\n", 251 ha->dma32_cnt, ha->dma64_cnt); 252 len += size; pos = begin + len; 253#endif 254 255 if (pos < offset) { 256 len = 0; 257 begin = pos; 258 } 259 if (pos > offset + length) 260 goto stop_output; 261 262 if (ha->more_proc) { 263 /* more information: 2. about physical devices */ 264 size = sprintf(buffer+len,"\nPhysical Devices:"); 265 len += size; pos = begin + len; 266 flag = FALSE; 267 268 buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr); 269 if (!buf) 270 goto stop_output; 271 for (i = 0; i < ha->bus_cnt; ++i) { 272 /* 2.a statistics (and retries/reassigns) */ 273 TRACE2(("pdr_statistics() chn %d\n",i)); 274 pds = (gdth_dskstat_str *)(buf + GDTH_SCRATCH/4); 275 gdtcmd->Service = CACHESERVICE; 276 gdtcmd->OpCode = GDT_IOCTL; 277 gdtcmd->u.ioctl.p_param = paddr + GDTH_SCRATCH/4; 278 gdtcmd->u.ioctl.param_size = 3*GDTH_SCRATCH/4; 279 gdtcmd->u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN; 280 gdtcmd->u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL; 281 pds->bid = ha->raw[i].local_no; 282 pds->first = 0; 283 pds->entries = ha->raw[i].pdev_cnt; 284 cnt = (3*GDTH_SCRATCH/4 - 5 * sizeof(ulong32)) / 285 sizeof(pds->list[0]); 286 if (pds->entries > cnt) 287 pds->entries = cnt; 288 289 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) != S_OK) 290 pds->count = 0; 291 292 /* other IOCTLs must fit into area GDTH_SCRATCH/4 */ 293 for (j = 0; j < ha->raw[i].pdev_cnt; ++j) { 294 /* 2.b drive info */ 295 TRACE2(("scsi_drv_info() chn %d dev %d\n", 296 i, ha->raw[i].id_list[j])); 297 pdi = (gdth_diskinfo_str *)buf; 298 gdtcmd->Service = CACHESERVICE; 299 gdtcmd->OpCode = GDT_IOCTL; 300 gdtcmd->u.ioctl.p_param = paddr; 301 gdtcmd->u.ioctl.param_size = sizeof(gdth_diskinfo_str); 302 gdtcmd->u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN; 303 gdtcmd->u.ioctl.channel = 304 ha->raw[i].address | ha->raw[i].id_list[j]; 305 306 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { 307 strncpy(hrec,pdi->vendor,8); 308 strncpy(hrec+8,pdi->product,16); 309 strncpy(hrec+24,pdi->revision,4); 310 hrec[28] = 0; 311 size = sprintf(buffer+len, 312 "\n Chn/ID/LUN: \t%c/%02d/%d \tName: \t%s\n", 313 'A'+i,pdi->target_id,pdi->lun,hrec); 314 len += size; pos = begin + len; 315 flag = TRUE; 316 pdi->no_ldrive &= 0xffff; 317 if (pdi->no_ldrive == 0xffff) 318 strcpy(hrec,"--"); 319 else 320 sprintf(hrec,"%d",pdi->no_ldrive); 321 size = sprintf(buffer+len, 322 " Capacity [MB]:\t%-6d \tTo Log. Drive: \t%s\n", 323 pdi->blkcnt/(1024*1024/pdi->blksize), 324 hrec); 325 len += size; pos = begin + len; 326 } else { 327 pdi->devtype = 0xff; 328 } 329 330 if (pdi->devtype == 0) { 331 /* search retries/reassigns */ 332 for (k = 0; k < pds->count; ++k) { 333 if (pds->list[k].tid == pdi->target_id && 334 pds->list[k].lun == pdi->lun) { 335 size = sprintf(buffer+len, 336 " Retries: \t%-6d \tReassigns: \t%d\n", 337 pds->list[k].retries, 338 pds->list[k].reassigns); 339 len += size; pos = begin + len; 340 break; 341 } 342 } 343 /* 2.c grown defects */ 344 TRACE2(("scsi_drv_defcnt() chn %d dev %d\n", 345 i, ha->raw[i].id_list[j])); 346 pdef = (gdth_defcnt_str *)buf; 347 gdtcmd->Service = CACHESERVICE; 348 gdtcmd->OpCode = GDT_IOCTL; 349 gdtcmd->u.ioctl.p_param = paddr; 350 gdtcmd->u.ioctl.param_size = sizeof(gdth_defcnt_str); 351 gdtcmd->u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN; 352 gdtcmd->u.ioctl.channel = 353 ha->raw[i].address | ha->raw[i].id_list[j]; 354 pdef->sddc_type = 0x08; 355 356 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { 357 size = sprintf(buffer+len, 358 " Grown Defects:\t%d\n", 359 pdef->sddc_cnt); 360 len += size; pos = begin + len; 361 } 362 } 363 if (pos < offset) { 364 len = 0; 365 begin = pos; 366 } 367 if (pos > offset + length) 368 goto stop_output; 369 } 370 } 371 gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr); 372 373 if (!flag) { 374 size = sprintf(buffer+len, "\n --\n"); 375 len += size; pos = begin + len; 376 } 377 378 /* 3. about logical drives */ 379 size = sprintf(buffer+len,"\nLogical Drives:"); 380 len += size; pos = begin + len; 381 flag = FALSE; 382 383 buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr); 384 if (!buf) 385 goto stop_output; 386 for (i = 0; i < MAX_LDRIVES; ++i) { 387 if (!ha->hdr[i].is_logdrv) 388 continue; 389 drv_no = i; 390 j = k = 0; 391 is_mirr = FALSE; 392 do { 393 /* 3.a log. drive info */ 394 TRACE2(("cache_drv_info() drive no %d\n",drv_no)); 395 pcdi = (gdth_cdrinfo_str *)buf; 396 gdtcmd->Service = CACHESERVICE; 397 gdtcmd->OpCode = GDT_IOCTL; 398 gdtcmd->u.ioctl.p_param = paddr; 399 gdtcmd->u.ioctl.param_size = sizeof(gdth_cdrinfo_str); 400 gdtcmd->u.ioctl.subfunc = CACHE_DRV_INFO; 401 gdtcmd->u.ioctl.channel = drv_no; 402 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) != S_OK) 403 break; 404 pcdi->ld_dtype >>= 16; 405 j++; 406 if (pcdi->ld_dtype > 2) { 407 strcpy(hrec, "missing"); 408 } else if (pcdi->ld_error & 1) { 409 strcpy(hrec, "fault"); 410 } else if (pcdi->ld_error & 2) { 411 strcpy(hrec, "invalid"); 412 k++; j--; 413 } else { 414 strcpy(hrec, "ok"); 415 } 416 417 if (drv_no == i) { 418 size = sprintf(buffer+len, 419 "\n Number: \t%-2d \tStatus: \t%s\n", 420 drv_no, hrec); 421 len += size; pos = begin + len; 422 flag = TRUE; 423 no_mdrv = pcdi->cd_ldcnt; 424 if (no_mdrv > 1 || pcdi->ld_slave != -1) { 425 is_mirr = TRUE; 426 strcpy(hrec, "RAID-1"); 427 } else if (pcdi->ld_dtype == 0) { 428 strcpy(hrec, "Disk"); 429 } else if (pcdi->ld_dtype == 1) { 430 strcpy(hrec, "RAID-0"); 431 } else if (pcdi->ld_dtype == 2) { 432 strcpy(hrec, "Chain"); 433 } else { 434 strcpy(hrec, "???"); 435 } 436 size = sprintf(buffer+len, 437 " Capacity [MB]:\t%-6d \tType: \t%s\n", 438 pcdi->ld_blkcnt/(1024*1024/pcdi->ld_blksize), 439 hrec); 440 len += size; pos = begin + len; 441 } else { 442 size = sprintf(buffer+len, 443 " Slave Number: \t%-2d \tStatus: \t%s\n", 444 drv_no & 0x7fff, hrec); 445 len += size; pos = begin + len; 446 } 447 drv_no = pcdi->ld_slave; 448 if (pos < offset) { 449 len = 0; 450 begin = pos; 451 } 452 if (pos > offset + length) 453 goto stop_output; 454 } while (drv_no != -1); 455 456 if (is_mirr) { 457 size = sprintf(buffer+len, 458 " Missing Drv.: \t%-2d \tInvalid Drv.: \t%d\n", 459 no_mdrv - j - k, k); 460 len += size; pos = begin + len; 461 } 462 463 if (!ha->hdr[i].is_arraydrv) 464 strcpy(hrec, "--"); 465 else 466 sprintf(hrec, "%d", ha->hdr[i].master_no); 467 size = sprintf(buffer+len, 468 " To Array Drv.:\t%s\n", hrec); 469 len += size; pos = begin + len; 470 if (pos < offset) { 471 len = 0; 472 begin = pos; 473 } 474 if (pos > offset + length) 475 goto stop_output; 476 } 477 gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr); 478 479 if (!flag) { 480 size = sprintf(buffer+len, "\n --\n"); 481 len += size; pos = begin + len; 482 } 483 484 /* 4. about array drives */ 485 size = sprintf(buffer+len,"\nArray Drives:"); 486 len += size; pos = begin + len; 487 flag = FALSE; 488 489 buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr); 490 if (!buf) 491 goto stop_output; 492 for (i = 0; i < MAX_LDRIVES; ++i) { 493 if (!(ha->hdr[i].is_arraydrv && ha->hdr[i].is_master)) 494 continue; 495 /* 4.a array drive info */ 496 TRACE2(("array_info() drive no %d\n",i)); 497 pai = (gdth_arrayinf_str *)buf; 498 gdtcmd->Service = CACHESERVICE; 499 gdtcmd->OpCode = GDT_IOCTL; 500 gdtcmd->u.ioctl.p_param = paddr; 501 gdtcmd->u.ioctl.param_size = sizeof(gdth_arrayinf_str); 502 gdtcmd->u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN; 503 gdtcmd->u.ioctl.channel = i; 504 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { 505 if (pai->ai_state == 0) 506 strcpy(hrec, "idle"); 507 else if (pai->ai_state == 2) 508 strcpy(hrec, "build"); 509 else if (pai->ai_state == 4) 510 strcpy(hrec, "ready"); 511 else if (pai->ai_state == 6) 512 strcpy(hrec, "fail"); 513 else if (pai->ai_state == 8 || pai->ai_state == 10) 514 strcpy(hrec, "rebuild"); 515 else 516 strcpy(hrec, "error"); 517 if (pai->ai_ext_state & 0x10) 518 strcat(hrec, "/expand"); 519 else if (pai->ai_ext_state & 0x1) 520 strcat(hrec, "/patch"); 521 size = sprintf(buffer+len, 522 "\n Number: \t%-2d \tStatus: \t%s\n", 523 i,hrec); 524 len += size; pos = begin + len; 525 flag = TRUE; 526 527 if (pai->ai_type == 0) 528 strcpy(hrec, "RAID-0"); 529 else if (pai->ai_type == 4) 530 strcpy(hrec, "RAID-4"); 531 else if (pai->ai_type == 5) 532 strcpy(hrec, "RAID-5"); 533 else 534 strcpy(hrec, "RAID-10"); 535 size = sprintf(buffer+len, 536 " Capacity [MB]:\t%-6d \tType: \t%s\n", 537 pai->ai_size/(1024*1024/pai->ai_secsize), 538 hrec); 539 len += size; pos = begin + len; 540 if (pos < offset) { 541 len = 0; 542 begin = pos; 543 } 544 if (pos > offset + length) 545 goto stop_output; 546 } 547 } 548 gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr); 549 550 if (!flag) { 551 size = sprintf(buffer+len, "\n --\n"); 552 len += size; pos = begin + len; 553 } 554 555 /* 5. about host drives */ 556 size = sprintf(buffer+len,"\nHost Drives:"); 557 len += size; pos = begin + len; 558 flag = FALSE; 559 560 buf = gdth_ioctl_alloc(ha, sizeof(gdth_hget_str), FALSE, &paddr); 561 if (!buf) 562 goto stop_output; 563 for (i = 0; i < MAX_LDRIVES; ++i) { 564 if (!ha->hdr[i].is_logdrv || 565 (ha->hdr[i].is_arraydrv && !ha->hdr[i].is_master)) 566 continue; 567 /* 5.a get host drive list */ 568 TRACE2(("host_get() drv_no %d\n",i)); 569 phg = (gdth_hget_str *)buf; 570 gdtcmd->Service = CACHESERVICE; 571 gdtcmd->OpCode = GDT_IOCTL; 572 gdtcmd->u.ioctl.p_param = paddr; 573 gdtcmd->u.ioctl.param_size = sizeof(gdth_hget_str); 574 gdtcmd->u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN; 575 gdtcmd->u.ioctl.channel = i; 576 phg->entries = MAX_HDRIVES; 577 phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]); 578 if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { 579 ha->hdr[i].ldr_no = i; 580 ha->hdr[i].rw_attribs = 0; 581 ha->hdr[i].start_sec = 0; 582 } else { 583 for (j = 0; j < phg->entries; ++j) { 584 k = phg->entry[j].host_drive; 585 if (k >= MAX_LDRIVES) 586 continue; 587 ha->hdr[k].ldr_no = phg->entry[j].log_drive; 588 ha->hdr[k].rw_attribs = phg->entry[j].rw_attribs; 589 ha->hdr[k].start_sec = phg->entry[j].start_sec; 590 } 591 } 592 } 593 gdth_ioctl_free(ha, sizeof(gdth_hget_str), buf, paddr); 594 595 for (i = 0; i < MAX_HDRIVES; ++i) { 596 if (!(ha->hdr[i].present)) 597 continue; 598 599 size = sprintf(buffer+len, 600 "\n Number: \t%-2d \tArr/Log. Drive:\t%d\n", 601 i, ha->hdr[i].ldr_no); 602 len += size; pos = begin + len; 603 flag = TRUE; 604 605 size = sprintf(buffer+len, 606 " Capacity [MB]:\t%-6d \tStart Sector: \t%d\n", 607 (ulong32)(ha->hdr[i].size/2048), ha->hdr[i].start_sec); 608 len += size; pos = begin + len; 609 if (pos < offset) { 610 len = 0; 611 begin = pos; 612 } 613 if (pos > offset + length) 614 goto stop_output; 615 } 616 617 if (!flag) { 618 size = sprintf(buffer+len, "\n --\n"); 619 len += size; pos = begin + len; 620 } 621 } 622 623 /* controller events */ 624 size = sprintf(buffer+len,"\nController Events:\n"); 625 len += size; pos = begin + len; 626 627 for (id = -1;;) { 628 id = gdth_read_event(ha, id, estr); 629 if (estr->event_source == 0) 630 break; 631 if (estr->event_data.eu.driver.ionode == ha->hanum && 632 estr->event_source == ES_ASYNC) { 633 gdth_log_event(&estr->event_data, hrec); 634 do_gettimeofday(&tv); 635 sec = (int)(tv.tv_sec - estr->first_stamp); 636 if (sec < 0) sec = 0; 637 size = sprintf(buffer+len," date- %02d:%02d:%02d\t%s\n", 638 sec/3600, sec%3600/60, sec%60, hrec); 639 len += size; pos = begin + len; 640 if (pos < offset) { 641 len = 0; 642 begin = pos; 643 } 644 if (pos > offset + length) 645 goto stop_output; 646 } 647 if (id == -1) 648 break; 649 } 650 651stop_output: 652 *start = buffer +(offset-begin); 653 len -= (offset-begin); 654 if (len > length) 655 len = length; 656 TRACE2(("get_info() len %d pos %d begin %d offset %d length %d size %d\n", 657 len,(int)pos,(int)begin,(int)offset,length,size)); 658 rc = len; 659 660free_fail: 661 kfree(gdtcmd); 662 kfree(estr); 663 return rc; 664} 665 666static char *gdth_ioctl_alloc(gdth_ha_str *ha, int size, int scratch, 667 ulong64 *paddr) 668{ 669 ulong flags; 670 char *ret_val; 671 672 if (size == 0) 673 return NULL; 674 675 spin_lock_irqsave(&ha->smp_lock, flags); 676 677 if (!ha->scratch_busy && size <= GDTH_SCRATCH) { 678 ha->scratch_busy = TRUE; 679 ret_val = ha->pscratch; 680 *paddr = ha->scratch_phys; 681 } else if (scratch) { 682 ret_val = NULL; 683 } else { 684 dma_addr_t dma_addr; 685 686 ret_val = pci_alloc_consistent(ha->pdev, size, &dma_addr); 687 *paddr = dma_addr; 688 } 689 690 spin_unlock_irqrestore(&ha->smp_lock, flags); 691 return ret_val; 692} 693 694static void gdth_ioctl_free(gdth_ha_str *ha, int size, char *buf, ulong64 paddr) 695{ 696 ulong flags; 697 698 if (buf == ha->pscratch) { 699 spin_lock_irqsave(&ha->smp_lock, flags); 700 ha->scratch_busy = FALSE; 701 spin_unlock_irqrestore(&ha->smp_lock, flags); 702 } else { 703 pci_free_consistent(ha->pdev, size, buf, paddr); 704 } 705} 706 707#ifdef GDTH_IOCTL_PROC 708static int gdth_ioctl_check_bin(gdth_ha_str *ha, ushort size) 709{ 710 ulong flags; 711 int ret_val; 712 713 spin_lock_irqsave(&ha->smp_lock, flags); 714 715 ret_val = FALSE; 716 if (ha->scratch_busy) { 717 if (((gdth_iord_str *)ha->pscratch)->size == (ulong32)size) 718 ret_val = TRUE; 719 } 720 spin_unlock_irqrestore(&ha->smp_lock, flags); 721 return ret_val; 722} 723#endif 724 725static void gdth_wait_completion(gdth_ha_str *ha, int busnum, int id) 726{ 727 ulong flags; 728 int i; 729 Scsi_Cmnd *scp; 730 struct gdth_cmndinfo *cmndinfo; 731 unchar b, t; 732 733 spin_lock_irqsave(&ha->smp_lock, flags); 734 735 for (i = 0; i < GDTH_MAXCMDS; ++i) { 736 scp = ha->cmd_tab[i].cmnd; 737 cmndinfo = gdth_cmnd_priv(scp); 738 739 b = scp->device->channel; 740 t = scp->device->id; 741 if (!SPECIAL_SCP(scp) && t == (unchar)id && 742 b == (unchar)busnum) { 743 cmndinfo->wait_for_completion = 0; 744 spin_unlock_irqrestore(&ha->smp_lock, flags); 745 while (!cmndinfo->wait_for_completion) 746 barrier(); 747 spin_lock_irqsave(&ha->smp_lock, flags); 748 } 749 } 750 spin_unlock_irqrestore(&ha->smp_lock, flags); 751}