1/* $Id: atp870u.c,v 1.1.1.1 2008/10/15 03:26:49 james26_jang Exp $ 2 * linux/kernel/atp870u.c 3 * 4 * Copyright (C) 1997 Wu Ching Chen 5 * 2.1.x update (C) 1998 Krzysztof G. Baranowski 6 * 7 * Marcelo Tosatti <marcelo@conectiva.com.br> : SMP fixes 8 * 9 * Wu Ching Chen : NULL pointer fixes 2000/06/02 10 * support atp876 chip 11 * enable 32 bit fifo transfer 12 * support cdrom & remove device run ultra speed 13 * fix disconnect bug 2000/12/21 14 * support atp880 chip lvd u160 2001/05/15 15 * fix prd table bug 2001/09/12 (7.1) 16 */ 17 18#include <linux/module.h> 19 20#include <linux/kernel.h> 21#include <linux/types.h> 22#include <linux/string.h> 23#include <linux/ioport.h> 24#include <linux/delay.h> 25#include <linux/sched.h> 26#include <linux/proc_fs.h> 27#include <linux/spinlock.h> 28#include <asm/system.h> 29#include <asm/io.h> 30#include <linux/pci.h> 31#include <linux/blk.h> 32#include "scsi.h" 33#include "hosts.h" 34 35 36#include "atp870u.h" 37 38#include<linux/stat.h> 39 40void mydlyu(unsigned int); 41 42/* 43 * static const char RCSid[] = "$Header: /home/user/PROJECT/WL-520gu-NewUI/src/linux/linux/drivers/scsi/atp870u.c,v 1.1.1.1 2008/10/15 03:26:49 james26_jang Exp $"; 44 */ 45 46static unsigned char admaxu = 1; 47static unsigned short int sync_idu; 48 49static unsigned int irqnumu[2] = {0, 0}; 50 51struct atp_unit 52{ 53 unsigned long ioport; 54 unsigned long irq; 55 unsigned long pciport; 56 unsigned char last_cmd; 57 unsigned char in_snd; 58 unsigned char in_int; 59 unsigned char quhdu; 60 unsigned char quendu; 61 unsigned char scam_on; 62 unsigned char global_map; 63 unsigned char chip_veru; 64 unsigned char host_idu; 65 int working; 66 unsigned short wide_idu; 67 unsigned short active_idu; 68 unsigned short ultra_map; 69 unsigned short async; 70 unsigned short deviceid; 71 unsigned char ata_cdbu[16]; 72 unsigned char sp[16]; 73 Scsi_Cmnd *querequ[qcnt]; 74 struct atp_id 75 { 76 unsigned char dirctu; 77 unsigned char devspu; 78 unsigned char devtypeu; 79 unsigned long prdaddru; 80 unsigned long tran_lenu; 81 unsigned long last_lenu; 82 unsigned char *prd_posu; 83 unsigned char *prd_tableu; 84 Scsi_Cmnd *curr_req; 85 } id[16]; 86}; 87 88static struct Scsi_Host *atp_host[2] = {NULL, NULL}; 89static struct atp_unit atp_unit[2]; 90 91static void atp870u_intr_handle(int irq, void *dev_id, struct pt_regs *regs) 92{ 93 unsigned long flags; 94 unsigned short int tmpcip, id; 95 unsigned char i, j, h, target_id, lun; 96 unsigned char *prd; 97 Scsi_Cmnd *workrequ; 98 unsigned int workportu, tmport; 99 unsigned long adrcntu, k; 100 int errstus; 101 struct atp_unit *dev = dev_id; 102 103 for (h = 0; h < 2; h++) { 104 if (irq == irqnumu[h]) { 105 goto irq_numok; 106 } 107 } 108 return; 109irq_numok: 110 dev->in_int = 1; 111 workportu = dev->ioport; 112 tmport = workportu; 113 114 if (dev->working != 0) 115 { 116 tmport += 0x1f; 117 j = inb(tmport); 118 if ((j & 0x80) == 0) 119 { 120 dev->in_int = 0; 121 return; 122 } 123 124 tmpcip = dev->pciport; 125 if ((inb(tmpcip) & 0x08) != 0) 126 { 127 tmpcip += 0x2; 128 for (k=0; k < 1000; k++) 129 { 130 if ((inb(tmpcip) & 0x08) == 0) 131 { 132 goto stop_dma; 133 } 134 if ((inb(tmpcip) & 0x01) == 0) 135 { 136 goto stop_dma; 137 } 138 } 139 } 140stop_dma: 141 tmpcip = dev->pciport; 142 outb(0x00, tmpcip); 143 tmport -= 0x08; 144 145 i = inb(tmport); 146 147 tmport -= 0x02; 148 target_id = inb(tmport); 149 tmport += 0x02; 150 151 /* 152 * Remap wide devices onto id numbers 153 */ 154 155 if ((target_id & 0x40) != 0) { 156 target_id = (target_id & 0x07) | 0x08; 157 } else { 158 target_id &= 0x07; 159 } 160 161 if ((j & 0x40) != 0) 162 { 163 if (dev->last_cmd == 0xff) 164 { 165 dev->last_cmd = target_id; 166 } 167 dev->last_cmd |= 0x40; 168 } 169 170 if (i == 0x85) 171 { 172 if ((dev->last_cmd & 0xf0) != 0x40) 173 { 174 dev->last_cmd = 0xff; 175 } 176 /* 177 * Flip wide 178 */ 179 if (dev->wide_idu != 0) 180 { 181 tmport = workportu + 0x1b; 182 outb(0x01,tmport); 183 while ((inb(tmport) & 0x01) != 0x01) 184 { 185 outb(0x01,tmport); 186 } 187 } 188 /* 189 * Issue more commands 190 */ 191 if (((dev->quhdu != dev->quendu) || (dev->last_cmd != 0xff)) && 192 (dev->in_snd == 0)) 193 { 194 send_s870(h); 195 } 196 /* 197 * Done 198 */ 199 dev->in_int = 0; 200 return; 201 } 202 203 if (i == 0x40) 204 { 205 dev->last_cmd |= 0x40; 206 dev->in_int = 0; 207 return; 208 } 209 210 if (i == 0x21) 211 { 212 if ((dev->last_cmd & 0xf0) != 0x40) 213 { 214 dev->last_cmd = 0xff; 215 } 216 tmport -= 0x05; 217 adrcntu = 0; 218 ((unsigned char *) &adrcntu)[2] = inb(tmport++); 219 ((unsigned char *) &adrcntu)[1] = inb(tmport++); 220 ((unsigned char *) &adrcntu)[0] = inb(tmport); 221 k = dev->id[target_id].last_lenu; 222 k -= adrcntu; 223 dev->id[target_id].tran_lenu = k; 224 dev->id[target_id].last_lenu = adrcntu; 225 tmport -= 0x04; 226 outb(0x41, tmport); 227 tmport += 0x08; 228 outb(0x08, tmport); 229 dev->in_int = 0; 230 return; 231 } 232 if ((i == 0x80) || (i == 0x8f)) 233 { 234 lun = 0; 235 tmport -= 0x07; 236 j = inb(tmport); 237 if (j == 0x44 || i==0x80) { 238 tmport += 0x0d; 239 lun = inb(tmport) & 0x07; 240 } else { 241 if ((dev->last_cmd & 0xf0) != 0x40) 242 { 243 dev->last_cmd = 0xff; 244 } 245 if (j == 0x41) 246 { 247 tmport += 0x02; 248 adrcntu = 0; 249 ((unsigned char *) &adrcntu)[2] = inb(tmport++); 250 ((unsigned char *) &adrcntu)[1] = inb(tmport++); 251 ((unsigned char *) &adrcntu)[0] = inb(tmport); 252 k = dev->id[target_id].last_lenu; 253 k -= adrcntu; 254 dev->id[target_id].tran_lenu = k; 255 dev->id[target_id].last_lenu = adrcntu; 256 tmport += 0x04; 257 outb(0x08, tmport); 258 dev->in_int = 0; 259 return; 260 } 261 else 262 { 263 outb(0x46, tmport); 264 dev->id[target_id].dirctu = 0x00; 265 tmport += 0x02; 266 outb(0x00, tmport++); 267 outb(0x00, tmport++); 268 outb(0x00, tmport++); 269 tmport += 0x03; 270 outb(0x08, tmport); 271 dev->in_int = 0; 272 return; 273 } 274 } 275 if (dev->last_cmd != 0xff) 276 { 277 dev->last_cmd |= 0x40; 278 } 279 tmport = workportu + 0x10; 280 outb(0x45, tmport); 281 tmport += 0x06; 282 target_id = inb(tmport); 283 /* 284 * Remap wide identifiers 285 */ 286 if ((target_id & 0x10) != 0) 287 { 288 target_id = (target_id & 0x07) | 0x08; 289 } else { 290 target_id &= 0x07; 291 } 292 workrequ = dev->id[target_id].curr_req; 293 tmport = workportu + 0x0f; 294 outb(lun, tmport); 295 tmport += 0x02; 296 outb(dev->id[target_id].devspu, tmport++); 297 adrcntu = dev->id[target_id].tran_lenu; 298 k = dev->id[target_id].last_lenu; 299 outb(((unsigned char *) &k)[2], tmport++); 300 outb(((unsigned char *) &k)[1], tmport++); 301 outb(((unsigned char *) &k)[0], tmport++); 302 /* Remap wide */ 303 j = target_id; 304 if (target_id > 7) { 305 j = (j & 0x07) | 0x40; 306 } 307 /* Add direction */ 308 j |= dev->id[target_id].dirctu; 309 outb(j, tmport++); 310 outb(0x80, tmport); 311 312 /* enable 32 bit fifo transfer */ 313 if (dev->deviceid != 0x8081) 314 { 315 tmport = workportu + 0x3a; 316 if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || 317 (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) 318 { 319 outb((unsigned char)((inb(tmport) & 0xf3) | 0x08),tmport); 320 } 321 else 322 { 323 outb((unsigned char)(inb(tmport) & 0xf3),tmport); 324 } 325 } 326 else 327 { 328 tmport = workportu - 0x05; 329 if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || 330 (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) 331 { 332 outb((unsigned char)((inb(tmport) & 0x3f) | 0xc0),tmport); 333 } 334 else 335 { 336 outb((unsigned char)(inb(tmport) & 0x3f),tmport); 337 } 338 } 339 340 tmport = workportu + 0x1b; 341 j = 0; 342 id = 1; 343 id = id << target_id; 344 /* 345 * Is this a wide device 346 */ 347 if ((id & dev->wide_idu) != 0) { 348 j |= 0x01; 349 } 350 outb(j, tmport); 351 while ((inb(tmport) & 0x01) != j) 352 { 353 outb(j,tmport); 354 } 355 356 if (dev->id[target_id].last_lenu == 0) { 357 tmport = workportu + 0x18; 358 outb(0x08, tmport); 359 dev->in_int = 0; 360 return; 361 } 362 prd = dev->id[target_id].prd_posu; 363 while (adrcntu != 0) 364 { 365 id = ((unsigned short int *) (prd))[2]; 366 if (id == 0) { 367 k = 0x10000; 368 } else { 369 k = id; 370 } 371 if (k > adrcntu) { 372 ((unsigned short int *) (prd))[2] = (unsigned short int) 373 (k - adrcntu); 374 ((unsigned long *) (prd))[0] += adrcntu; 375 adrcntu = 0; 376 dev->id[target_id].prd_posu = prd; 377 } else { 378 adrcntu -= k; 379 dev->id[target_id].prdaddru += 0x08; 380 prd += 0x08; 381 if (adrcntu == 0) { 382 dev->id[target_id].prd_posu = prd; 383 } 384 } 385 } 386 tmpcip = dev->pciport + 0x04; 387 outl(dev->id[target_id].prdaddru, tmpcip); 388 tmpcip -= 0x02; 389 outb(0x06, tmpcip); 390 outb(0x00, tmpcip); 391 tmpcip -= 0x02; 392 tmport = workportu + 0x18; 393 /* 394 * Check transfer direction 395 */ 396 if (dev->id[target_id].dirctu != 0) { 397 outb(0x08, tmport); 398 outb(0x01, tmpcip); 399 dev->in_int = 0; 400 return; 401 } 402 outb(0x08, tmport); 403 outb(0x09, tmpcip); 404 dev->in_int = 0; 405 return; 406 } 407 408 /* 409 * Current scsi request on this target 410 */ 411 412 workrequ = dev->id[target_id].curr_req; 413 414 if (i == 0x42) { 415 if ((dev->last_cmd & 0xf0) != 0x40) 416 { 417 dev->last_cmd = 0xff; 418 } 419 errstus = 0x02; 420 workrequ->result = errstus; 421 goto go_42; 422 } 423 if (i == 0x16) 424 { 425 if ((dev->last_cmd & 0xf0) != 0x40) 426 { 427 dev->last_cmd = 0xff; 428 } 429 errstus = 0; 430 tmport -= 0x08; 431 errstus = inb(tmport); 432 workrequ->result = errstus; 433go_42: 434 /* 435 * Complete the command 436 */ 437 spin_lock_irqsave(&io_request_lock, flags); 438 (*workrequ->scsi_done) (workrequ); 439 440 /* 441 * Clear it off the queue 442 */ 443 dev->id[target_id].curr_req = 0; 444 dev->working--; 445 spin_unlock_irqrestore(&io_request_lock, flags); 446 /* 447 * Take it back wide 448 */ 449 if (dev->wide_idu != 0) { 450 tmport = workportu + 0x1b; 451 outb(0x01,tmport); 452 while ((inb(tmport) & 0x01) != 0x01) 453 { 454 outb(0x01,tmport); 455 } 456 } 457 /* 458 * If there is stuff to send and nothing going then send it 459 */ 460 if (((dev->last_cmd != 0xff) || (dev->quhdu != dev->quendu)) && 461 (dev->in_snd == 0)) 462 { 463 send_s870(h); 464 } 465 dev->in_int = 0; 466 return; 467 } 468 if ((dev->last_cmd & 0xf0) != 0x40) 469 { 470 dev->last_cmd = 0xff; 471 } 472 if (i == 0x4f) { 473 i = 0x89; 474 } 475 i &= 0x0f; 476 if (i == 0x09) { 477 tmpcip = tmpcip + 4; 478 outl(dev->id[target_id].prdaddru, tmpcip); 479 tmpcip = tmpcip - 2; 480 outb(0x06, tmpcip); 481 outb(0x00, tmpcip); 482 tmpcip = tmpcip - 2; 483 tmport = workportu + 0x10; 484 outb(0x41, tmport); 485 dev->id[target_id].dirctu = 0x00; 486 tmport += 0x08; 487 outb(0x08, tmport); 488 outb(0x09, tmpcip); 489 dev->in_int = 0; 490 return; 491 } 492 if (i == 0x08) { 493 tmpcip = tmpcip + 4; 494 outl(dev->id[target_id].prdaddru, tmpcip); 495 tmpcip = tmpcip - 2; 496 outb(0x06, tmpcip); 497 outb(0x00, tmpcip); 498 tmpcip = tmpcip - 2; 499 tmport = workportu + 0x10; 500 outb(0x41, tmport); 501 tmport += 0x05; 502 outb((unsigned char) (inb(tmport) | 0x20), tmport); 503 dev->id[target_id].dirctu = 0x20; 504 tmport += 0x03; 505 outb(0x08, tmport); 506 outb(0x01, tmpcip); 507 dev->in_int = 0; 508 return; 509 } 510 tmport -= 0x07; 511 if (i == 0x0a) { 512 outb(0x30, tmport); 513 } else { 514 outb(0x46, tmport); 515 } 516 dev->id[target_id].dirctu = 0x00; 517 tmport += 0x02; 518 outb(0x00, tmport++); 519 outb(0x00, tmport++); 520 outb(0x00, tmport++); 521 tmport += 0x03; 522 outb(0x08, tmport); 523 dev->in_int = 0; 524 return; 525 } else { 526// tmport = workportu + 0x17; 527// inb(tmport); 528// dev->working = 0; 529 dev->in_int = 0; 530 return; 531 } 532} 533 534int atp870u_queuecommand(Scsi_Cmnd * req_p, void (*done) (Scsi_Cmnd *)) 535{ 536 unsigned char h; 537 unsigned long flags; 538 unsigned short int m; 539 unsigned int tmport; 540 struct atp_unit *dev; 541 542 for (h = 0; h <= admaxu; h++) { 543 if (req_p->host == atp_host[h]) { 544 goto host_ok; 545 } 546 } 547 return 0; 548host_ok: 549 if (req_p->channel != 0) { 550 req_p->result = 0x00040000; 551 done(req_p); 552 return 0; 553 } 554 dev = &atp_unit[h]; 555 m = 1; 556 m = m << req_p->target; 557 558 /* 559 * Fake a timeout for missing targets 560 */ 561 562 if ((m & dev->active_idu) == 0) { 563 req_p->result = 0x00040000; 564 done(req_p); 565 return 0; 566 } 567 if (done) { 568 req_p->scsi_done = done; 569 } else { 570 printk(KERN_WARNING "atp870u_queuecommand: done can't be NULL\n"); 571 req_p->result = 0; 572 done(req_p); 573 return 0; 574 } 575 /* 576 * Count new command 577 */ 578 save_flags(flags); 579 cli(); 580 dev->quendu++; 581 if (dev->quendu >= qcnt) { 582 dev->quendu = 0; 583 } 584 /* 585 * Check queue state 586 */ 587 if (dev->quhdu == dev->quendu) { 588 if (dev->quendu == 0) { 589 dev->quendu = qcnt; 590 } 591 dev->quendu--; 592 req_p->result = 0x00020000; 593 done(req_p); 594 restore_flags(flags); 595 return 0; 596 } 597 dev->querequ[dev->quendu] = req_p; 598 tmport = dev->ioport + 0x1c; 599 restore_flags(flags); 600 if ((inb(tmport) == 0) && (dev->in_int == 0) && (dev->in_snd == 0)) { 601 send_s870(h); 602 } 603 return 0; 604} 605 606void mydlyu(unsigned int dlycnt) 607{ 608 unsigned int i; 609 for (i = 0; i < dlycnt; i++) { 610 inb(0x80); 611 } 612} 613 614void send_s870(unsigned char h) 615{ 616 unsigned int tmport; 617 Scsi_Cmnd *workrequ; 618 unsigned long flags; 619 unsigned int i; 620 unsigned char j, target_id; 621 unsigned char *prd; 622 unsigned short int tmpcip, w; 623 unsigned long l, bttl; 624 unsigned int workportu; 625 struct scatterlist *sgpnt; 626 struct atp_unit *dev = &atp_unit[h]; 627 628 save_flags(flags); 629 cli(); 630 if (dev->in_snd != 0) { 631 restore_flags(flags); 632 return; 633 } 634 dev->in_snd = 1; 635 if ((dev->last_cmd != 0xff) && ((dev->last_cmd & 0x40) != 0)) { 636 dev->last_cmd &= 0x0f; 637 workrequ = dev->id[dev->last_cmd].curr_req; 638 if (workrequ != NULL) /* check NULL pointer */ 639 { 640 goto cmd_subp; 641 } 642 dev->last_cmd = 0xff; 643 if (dev->quhdu == dev->quendu) 644 { 645 dev->in_snd = 0; 646 restore_flags(flags); 647 return ; 648 } 649 } 650 if ((dev->last_cmd != 0xff) && (dev->working != 0)) 651 { 652 dev->in_snd = 0; 653 restore_flags(flags); 654 return ; 655 } 656 dev->working++; 657 j = dev->quhdu; 658 dev->quhdu++; 659 if (dev->quhdu >= qcnt) { 660 dev->quhdu = 0; 661 } 662 workrequ = dev->querequ[dev->quhdu]; 663 if (dev->id[workrequ->target].curr_req == 0) { 664 dev->id[workrequ->target].curr_req = workrequ; 665 dev->last_cmd = workrequ->target; 666 goto cmd_subp; 667 } 668 dev->quhdu = j; 669 dev->working--; 670 dev->in_snd = 0; 671 restore_flags(flags); 672 return; 673cmd_subp: 674 workportu = dev->ioport; 675 tmport = workportu + 0x1f; 676 if ((inb(tmport) & 0xb0) != 0) { 677 goto abortsnd; 678 } 679 tmport = workportu + 0x1c; 680 if (inb(tmport) == 0) { 681 goto oktosend; 682 } 683abortsnd: 684 dev->last_cmd |= 0x40; 685 dev->in_snd = 0; 686 restore_flags(flags); 687 return; 688oktosend: 689 memcpy(&dev->ata_cdbu[0], &workrequ->cmnd[0], workrequ->cmd_len); 690 if (dev->ata_cdbu[0] == READ_CAPACITY) { 691 if (workrequ->request_bufflen > 8) { 692 workrequ->request_bufflen = 0x08; 693 } 694 } 695 if (dev->ata_cdbu[0] == 0x00) { 696 workrequ->request_bufflen = 0; 697 } 698 699 tmport = workportu + 0x1b; 700 j = 0; 701 target_id = workrequ->target; 702 703 /* 704 * Wide ? 705 */ 706 w = 1; 707 w = w << target_id; 708 if ((w & dev->wide_idu) != 0) { 709 j |= 0x01; 710 } 711 outb(j, tmport); 712 while ((inb(tmport) & 0x01) != j) 713 { 714 outb(j,tmport); 715 } 716 717 /* 718 * Write the command 719 */ 720 721 tmport = workportu; 722 outb(workrequ->cmd_len, tmport++); 723 outb(0x2c, tmport++); 724 outb(0xcf, tmport++); 725 for (i = 0; i < workrequ->cmd_len; i++) { 726 outb(dev->ata_cdbu[i], tmport++); 727 } 728 tmport = workportu + 0x0f; 729 outb(workrequ->lun, tmport); 730 tmport += 0x02; 731 /* 732 * Write the target 733 */ 734 outb(dev->id[target_id].devspu, tmport++); 735 736 /* 737 * Figure out the transfer size 738 */ 739 if (workrequ->use_sg) 740 { 741 l = 0; 742 sgpnt = (struct scatterlist *) workrequ->request_buffer; 743 for (i = 0; i < workrequ->use_sg; i++) 744 { 745 if (sgpnt[i].length == 0 || workrequ->use_sg > ATP870U_SCATTER) 746 { 747 panic("Foooooooood fight!"); 748 } 749 l += sgpnt[i].length; 750 } 751 } else { 752 l = workrequ->request_bufflen; 753 } 754 /* 755 * Write transfer size 756 */ 757 outb((unsigned char) (((unsigned char *) (&l))[2]), tmport++); 758 outb((unsigned char) (((unsigned char *) (&l))[1]), tmport++); 759 outb((unsigned char) (((unsigned char *) (&l))[0]), tmport++); 760 j = target_id; 761 dev->id[j].last_lenu = l; 762 dev->id[j].tran_lenu = 0; 763 /* 764 * Flip the wide bits 765 */ 766 if ((j & 0x08) != 0) { 767 j = (j & 0x07) | 0x40; 768 } 769 /* 770 * Check transfer direction 771 */ 772 if ((dev->ata_cdbu[0] == WRITE_6) || (dev->ata_cdbu[0] == WRITE_10) || 773 (dev->ata_cdbu[0] == WRITE_12) || (dev->ata_cdbu[0] == MODE_SELECT)) { 774 outb((unsigned char) (j | 0x20), tmport++); 775 } else { 776 outb(j, tmport++); 777 } 778 outb((unsigned char)(inb(tmport) | 0x80),tmport); 779 outb(0x80, tmport); 780 tmport = workportu + 0x1c; 781 dev->id[target_id].dirctu = 0; 782 if (l == 0) { 783 if (inb(tmport) == 0) { 784 tmport = workportu + 0x18; 785 outb(0x08, tmport); 786 } else { 787 dev->last_cmd |= 0x40; 788 } 789 dev->in_snd = 0; 790 restore_flags(flags); 791 return; 792 } 793 tmpcip = dev->pciport; 794 prd = dev->id[target_id].prd_tableu; 795 dev->id[target_id].prd_posu = prd; 796 797 /* 798 * Now write the request list. Either as scatter/gather or as 799 * a linear chain. 800 */ 801 802 if (workrequ->use_sg) 803 { 804 sgpnt = (struct scatterlist *) workrequ->request_buffer; 805 i = 0; 806 for (j = 0; j < workrequ->use_sg; j++) { 807 bttl = virt_to_bus(sgpnt[j].address); 808 l = sgpnt[j].length; 809 while (l > 0x10000) { 810 (unsigned short int) (((unsigned short int *) (prd))[i + 3]) = 0x0000; 811 (unsigned short int) (((unsigned short int *) (prd))[i + 2]) = 0x0000; 812 (unsigned long) (((unsigned long *) (prd))[i >> 1]) = bttl; 813 l -= 0x10000; 814 bttl += 0x10000; 815 i += 0x04; 816 } 817 (unsigned long) (((unsigned long *) (prd))[i >> 1]) = bttl; 818 (unsigned short int) (((unsigned short int *) (prd))[i + 2]) = l; 819 (unsigned short int) (((unsigned short int *) (prd))[i + 3]) = 0; 820 i += 0x04; 821 } 822 (unsigned short int) (((unsigned short int *) (prd))[i - 1]) = 0x8000; 823 } else { 824 /* 825 * For a linear request write a chain of blocks 826 */ 827 bttl = virt_to_bus(workrequ->request_buffer); 828 l = workrequ->request_bufflen; 829 i = 0; 830 while (l > 0x10000) { 831 (unsigned short int) (((unsigned short int *) (prd))[i + 3]) = 0x0000; 832 (unsigned short int) (((unsigned short int *) (prd))[i + 2]) = 0x0000; 833 (unsigned long) (((unsigned long *) (prd))[i >> 1]) = bttl; 834 l -= 0x10000; 835 bttl += 0x10000; 836 i += 0x04; 837 } 838 (unsigned short int) (((unsigned short int *) (prd))[i + 3]) = 0x8000; 839 (unsigned short int) (((unsigned short int *) (prd))[i + 2]) = l; 840 (unsigned long) (((unsigned long *) (prd))[i >> 1]) = bttl; 841 } 842 tmpcip = tmpcip + 4; 843 dev->id[target_id].prdaddru = virt_to_bus(dev->id[target_id].prd_tableu); 844 outl(dev->id[target_id].prdaddru, tmpcip); 845 tmpcip = tmpcip - 2; 846 outb(0x06, tmpcip); 847 outb(0x00, tmpcip); 848 tmpcip = tmpcip - 2; 849 850 if (dev->deviceid != 0x8081) 851 { 852 tmport = workportu + 0x3a; 853 if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || 854 (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) 855 { 856 outb((unsigned char)((inb(tmport) & 0xf3) | 0x08),tmport); 857 } 858 else 859 { 860 outb((unsigned char)(inb(tmport) & 0xf3),tmport); 861 } 862 } 863 else 864 { 865 tmport = workportu - 0x05; 866 if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || 867 (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) 868 { 869 outb((unsigned char)((inb(tmport) & 0x3f) | 0xc0),tmport); 870 } 871 else 872 { 873 outb((unsigned char)(inb(tmport) & 0x3f),tmport); 874 } 875 } 876 tmport = workportu + 0x1c; 877 878 if ((dev->ata_cdbu[0] == WRITE_6) || (dev->ata_cdbu[0] == WRITE_10) || 879 (dev->ata_cdbu[0] == WRITE_12) || (dev->ata_cdbu[0] == MODE_SELECT)) 880 { 881 dev->id[target_id].dirctu = 0x20; 882 if (inb(tmport) == 0) { 883 tmport = workportu + 0x18; 884 outb(0x08, tmport); 885 outb(0x01, tmpcip); 886 } else { 887 dev->last_cmd |= 0x40; 888 } 889 dev->in_snd = 0; 890 restore_flags(flags); 891 return; 892 } 893 if (inb(tmport) == 0) 894 { 895 tmport = workportu + 0x18; 896 outb(0x08, tmport); 897 outb(0x09, tmpcip); 898 } else { 899 dev->last_cmd |= 0x40; 900 } 901 dev->in_snd = 0; 902 restore_flags(flags); 903 return; 904 905} 906 907static void internal_done(Scsi_Cmnd * SCpnt) 908{ 909 SCpnt->SCp.Status++; 910} 911 912int atp870u_command(Scsi_Cmnd * SCpnt) 913{ 914 915 atp870u_queuecommand(SCpnt, internal_done); 916 917 SCpnt->SCp.Status = 0; 918 while (!SCpnt->SCp.Status) 919 barrier(); 920 return SCpnt->result; 921} 922 923unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val) 924{ 925 unsigned int tmport; 926 unsigned short int i, k; 927 unsigned char j; 928 929 tmport = dev->ioport + 0x1c; 930 outw(*val, tmport); 931FUN_D7: 932 for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ 933 k = inw(tmport); 934 j = (unsigned char) (k >> 8); 935 if ((k & 0x8000) != 0) { /* DB7 all release? */ 936 goto FUN_D7; 937 } 938 } 939 *val |= 0x4000; /* assert DB6 */ 940 outw(*val, tmport); 941 *val &= 0xdfff; /* assert DB5 */ 942 outw(*val, tmport); 943FUN_D5: 944 for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ 945 if ((inw(tmport) & 0x2000) != 0) { /* DB5 all release? */ 946 goto FUN_D5; 947 } 948 } 949 *val |= 0x8000; /* no DB4-0, assert DB7 */ 950 *val &= 0xe0ff; 951 outw(*val, tmport); 952 *val &= 0xbfff; /* release DB6 */ 953 outw(*val, tmport); 954 FUN_D6: 955 for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ 956 if ((inw(tmport) & 0x4000) != 0) { /* DB6 all release? */ 957 goto FUN_D6; 958 } 959 } 960 961 return j; 962} 963 964void tscam(unsigned char host) 965{ 966 967 unsigned int tmport; 968 unsigned char i, j, k; 969 unsigned long n; 970 unsigned short int m, assignid_map, val; 971 unsigned char mbuf[33], quintet[2]; 972 struct atp_unit *dev = &atp_unit[host]; 973 static unsigned char g2q_tab[8] = { 974 0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27 975 }; 976 977 978 for (i = 0; i < 0x10; i++) { 979 mydlyu(0xffff); 980 } 981 982 tmport = dev->ioport + 1; 983 outb(0x08, tmport++); 984 outb(0x7f, tmport); 985 tmport = dev->ioport + 0x11; 986 outb(0x20, tmport); 987 988 if ((dev->scam_on & 0x40) == 0) { 989 return; 990 } 991 m = 1; 992 m <<= dev->host_idu; 993 j = 16; 994 if (dev->chip_veru < 4) { 995 m |= 0xff00; 996 j = 8; 997 } 998 assignid_map = m; 999 tmport = dev->ioport + 0x02; 1000 outb(0x02, tmport++); /* 2*2=4ms,3EH 2/32*3E=3.9ms */ 1001 outb(0, tmport++); 1002 outb(0, tmport++); 1003 outb(0, tmport++); 1004 outb(0, tmport++); 1005 outb(0, tmport++); 1006 outb(0, tmport++); 1007 1008 for (i = 0; i < j; i++) { 1009 m = 1; 1010 m = m << i; 1011 if ((m & assignid_map) != 0) { 1012 continue; 1013 } 1014 tmport = dev->ioport + 0x0f; 1015 outb(0, tmport++); 1016 tmport += 0x02; 1017 outb(0, tmport++); 1018 outb(0, tmport++); 1019 outb(0, tmport++); 1020 if (i > 7) { 1021 k = (i & 0x07) | 0x40; 1022 } else { 1023 k = i; 1024 } 1025 outb(k, tmport++); 1026 tmport = dev->ioport + 0x1b; 1027 if (dev->chip_veru == 4) { 1028 outb(0x01, tmport); 1029 } else { 1030 outb(0x00, tmport); 1031 } 1032wait_rdyok: 1033 tmport = dev->ioport + 0x18; 1034 outb(0x09, tmport); 1035 tmport += 0x07; 1036 1037 while ((inb(tmport) & 0x80) == 0x00); 1038 tmport -= 0x08; 1039 k = inb(tmport); 1040 if (k != 0x16) { 1041 if ((k == 0x85) || (k == 0x42)) { 1042 continue; 1043 } 1044 tmport = dev->ioport + 0x10; 1045 outb(0x41, tmport); 1046 goto wait_rdyok; 1047 } 1048 assignid_map |= m; 1049 1050 } 1051 tmport = dev->ioport + 0x02; 1052 outb(0x7f, tmport); 1053 tmport = dev->ioport + 0x1b; 1054 outb(0x02, tmport); 1055 1056 outb(0, 0x80); 1057 1058 val = 0x0080; /* bsy */ 1059 tmport = dev->ioport + 0x1c; 1060 outw(val, tmport); 1061 val |= 0x0040; /* sel */ 1062 outw(val, tmport); 1063 val |= 0x0004; /* msg */ 1064 outw(val, tmport); 1065 inb(0x80); /* 2 deskew delay(45ns*2=90ns) */ 1066 val &= 0x007f; /* no bsy */ 1067 outw(val, tmport); 1068 mydlyu(0xffff); /* recommanded SCAM selection response time */ 1069 mydlyu(0xffff); 1070 val &= 0x00fb; /* after 1ms no msg */ 1071 outw(val, tmport); 1072wait_nomsg: 1073 if ((inb(tmport) & 0x04) != 0) { 1074 goto wait_nomsg; 1075 } 1076 outb(1, 0x80); 1077 mydlyu(100); 1078 for (n = 0; n < 0x30000; n++) { 1079 if ((inb(tmport) & 0x80) != 0) { /* bsy ? */ 1080 goto wait_io; 1081 } 1082 } 1083 goto TCM_SYNC; 1084wait_io: 1085 for (n = 0; n < 0x30000; n++) { 1086 if ((inb(tmport) & 0x81) == 0x0081) { 1087 goto wait_io1; 1088 } 1089 } 1090 goto TCM_SYNC; 1091wait_io1: 1092 inb(0x80); 1093 val |= 0x8003; /* io,cd,db7 */ 1094 outw(val, tmport); 1095 inb(0x80); 1096 val &= 0x00bf; /* no sel */ 1097 outw(val, tmport); 1098 outb(2, 0x80); 1099TCM_SYNC: 1100 mydlyu(0x800); 1101 if ((inb(tmport) & 0x80) == 0x00) { /* bsy ? */ 1102 outw(0, tmport--); 1103 outb(0, tmport); 1104 tmport = dev->ioport + 0x15; 1105 outb(0, tmport); 1106 tmport += 0x03; 1107 outb(0x09, tmport); 1108 tmport += 0x07; 1109 while ((inb(tmport) & 0x80) == 0); 1110 tmport -= 0x08; 1111 inb(tmport); 1112 return; 1113 } 1114 val &= 0x00ff; /* synchronization */ 1115 val |= 0x3f00; 1116 fun_scam(dev, &val); 1117 outb(3, 0x80); 1118 val &= 0x00ff; /* isolation */ 1119 val |= 0x2000; 1120 fun_scam(dev, &val); 1121 outb(4, 0x80); 1122 i = 8; 1123 j = 0; 1124TCM_ID: 1125 if ((inw(tmport) & 0x2000) == 0) { 1126 goto TCM_ID; 1127 } 1128 outb(5, 0x80); 1129 val &= 0x00ff; /* get ID_STRING */ 1130 val |= 0x2000; 1131 k = fun_scam(dev, &val); 1132 if ((k & 0x03) == 0) { 1133 goto TCM_5; 1134 } 1135 mbuf[j] <<= 0x01; 1136 mbuf[j] &= 0xfe; 1137 if ((k & 0x02) != 0) { 1138 mbuf[j] |= 0x01; 1139 } 1140 i--; 1141 if (i > 0) { 1142 goto TCM_ID; 1143 } 1144 j++; 1145 i = 8; 1146 goto TCM_ID; 1147 1148TCM_5: /* isolation complete.. */ 1149/* mbuf[32]=0; 1150 printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */ 1151 i = 15; 1152 j = mbuf[0]; 1153 if ((j & 0x20) != 0) { /* bit5=1:ID upto 7 */ 1154 i = 7; 1155 } 1156 if ((j & 0x06) == 0) { /* IDvalid? */ 1157 goto G2Q5; 1158 } 1159 k = mbuf[1]; 1160small_id: 1161 m = 1; 1162 m <<= k; 1163 if ((m & assignid_map) == 0) { 1164 goto G2Q_QUIN; 1165 } 1166 if (k > 0) { 1167 k--; 1168 goto small_id; 1169 } 1170G2Q5: /* srch from max acceptable ID# */ 1171 k = i; /* max acceptable ID# */ 1172G2Q_LP: 1173 m = 1; 1174 m <<= k; 1175 if ((m & assignid_map) == 0) { 1176 goto G2Q_QUIN; 1177 } 1178 if (k > 0) { 1179 k--; 1180 goto G2Q_LP; 1181 } 1182G2Q_QUIN: /* k=binID#, */ 1183 assignid_map |= m; 1184 if (k < 8) { 1185 quintet[0] = 0x38; /* 1st dft ID<8 */ 1186 } else { 1187 quintet[0] = 0x31; /* 1st ID>=8 */ 1188 } 1189 k &= 0x07; 1190 quintet[1] = g2q_tab[k]; 1191 1192 val &= 0x00ff; /* AssignID 1stQuintet,AH=001xxxxx */ 1193 m = quintet[0] << 8; 1194 val |= m; 1195 fun_scam(dev, &val); 1196 val &= 0x00ff; /* AssignID 2ndQuintet,AH=001xxxxx */ 1197 m = quintet[1] << 8; 1198 val |= m; 1199 fun_scam(dev, &val); 1200 1201 goto TCM_SYNC; 1202 1203} 1204 1205void is870(unsigned long host, unsigned int wkport) 1206{ 1207 unsigned int tmport; 1208 unsigned char i, j, k, rmb, n; 1209 unsigned short int m; 1210 static unsigned char mbuf[512]; 1211 static unsigned char satn[9] = {0, 0, 0, 0, 0, 0, 0, 6, 6}; 1212 static unsigned char inqd[9] = {0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6}; 1213 static unsigned char synn[6] = {0x80, 1, 3, 1, 0x19, 0x0e}; 1214 static unsigned char synu[6] = {0x80, 1, 3, 1, 0x0c, 0x0e}; 1215 static unsigned char synw[6] = {0x80, 1, 3, 1, 0x0c, 0x07}; 1216 static unsigned char wide[6] = {0x80, 1, 2, 3, 1, 0}; 1217 struct atp_unit *dev = &atp_unit[host]; 1218 1219 sync_idu = 0; 1220 tmport = wkport + 0x3a; 1221 outb((unsigned char) (inb(tmport) | 0x10), tmport); 1222 1223 for (i = 0; i < 16; i++) { 1224 if ((dev->chip_veru != 4) && (i > 7)) { 1225 break; 1226 } 1227 m = 1; 1228 m = m << i; 1229 if ((m & dev->active_idu) != 0) { 1230 continue; 1231 } 1232 if (i == dev->host_idu) { 1233 printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_idu); 1234 continue; 1235 } 1236 tmport = wkport + 0x1b; 1237 if (dev->chip_veru == 4) { 1238 outb(0x01, tmport); 1239 } 1240 else 1241 { 1242 outb(0x00, tmport); 1243 } 1244 tmport = wkport + 1; 1245 outb(0x08, tmport++); 1246 outb(0x7f, tmport++); 1247 outb(satn[0], tmport++); 1248 outb(satn[1], tmport++); 1249 outb(satn[2], tmport++); 1250 outb(satn[3], tmport++); 1251 outb(satn[4], tmport++); 1252 outb(satn[5], tmport++); 1253 tmport += 0x06; 1254 outb(0, tmport); 1255 tmport += 0x02; 1256 outb(dev->id[i].devspu, tmport++); 1257 outb(0, tmport++); 1258 outb(satn[6], tmport++); 1259 outb(satn[7], tmport++); 1260 j = i; 1261 if ((j & 0x08) != 0) { 1262 j = (j & 0x07) | 0x40; 1263 } 1264 outb(j, tmport); 1265 tmport += 0x03; 1266 outb(satn[8], tmport); 1267 tmport += 0x07; 1268 1269 while ((inb(tmport) & 0x80) == 0x00); 1270 tmport -= 0x08; 1271 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { 1272 continue; 1273 } 1274 while (inb(tmport) != 0x8e); 1275 dev->active_idu |= m; 1276 1277 tmport = wkport + 0x10; 1278 outb(0x30, tmport); 1279 tmport = wkport + 0x04; 1280 outb(0x00, tmport); 1281 1282phase_cmd: 1283 tmport = wkport + 0x18; 1284 outb(0x08, tmport); 1285 tmport += 0x07; 1286 while ((inb(tmport) & 0x80) == 0x00); 1287 tmport -= 0x08; 1288 j = inb(tmport); 1289 if (j != 0x16) { 1290 tmport = wkport + 0x10; 1291 outb(0x41, tmport); 1292 goto phase_cmd; 1293 } 1294sel_ok: 1295 tmport = wkport + 3; 1296 outb(inqd[0], tmport++); 1297 outb(inqd[1], tmport++); 1298 outb(inqd[2], tmport++); 1299 outb(inqd[3], tmport++); 1300 outb(inqd[4], tmport++); 1301 outb(inqd[5], tmport); 1302 tmport += 0x07; 1303 outb(0, tmport); 1304 tmport += 0x02; 1305 outb(dev->id[i].devspu, tmport++); 1306 outb(0, tmport++); 1307 outb(inqd[6], tmport++); 1308 outb(inqd[7], tmport++); 1309 tmport += 0x03; 1310 outb(inqd[8], tmport); 1311 tmport += 0x07; 1312 while ((inb(tmport) & 0x80) == 0x00); 1313 tmport -= 0x08; 1314 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { 1315 continue; 1316 } 1317 while (inb(tmport) != 0x8e); 1318 tmport = wkport + 0x1b; 1319 if (dev->chip_veru == 4) { 1320 outb(0x00, tmport); 1321 } 1322 tmport = wkport + 0x18; 1323 outb(0x08, tmport); 1324 tmport += 0x07; 1325 j = 0; 1326rd_inq_data: 1327 k = inb(tmport); 1328 if ((k & 0x01) != 0) { 1329 tmport -= 0x06; 1330 mbuf[j++] = inb(tmport); 1331 tmport += 0x06; 1332 goto rd_inq_data; 1333 } 1334 if ((k & 0x80) == 0) { 1335 goto rd_inq_data; 1336 } 1337 tmport -= 0x08; 1338 j = inb(tmport); 1339 if (j == 0x16) { 1340 goto inq_ok; 1341 } 1342 tmport = wkport + 0x10; 1343 outb(0x46, tmport); 1344 tmport += 0x02; 1345 outb(0, tmport++); 1346 outb(0, tmport++); 1347 outb(0, tmport++); 1348 tmport += 0x03; 1349 outb(0x08, tmport); 1350 tmport += 0x07; 1351 while ((inb(tmport) & 0x80) == 0x00); 1352 tmport -= 0x08; 1353 if (inb(tmport) != 0x16) { 1354 goto sel_ok; 1355 } 1356inq_ok: 1357 mbuf[36] = 0; 1358 printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]); 1359 dev->id[i].devtypeu = mbuf[0]; 1360 rmb = mbuf[1]; 1361 n = mbuf[7]; 1362 if (dev->chip_veru != 4) { 1363 goto not_wide; 1364 } 1365 if ((mbuf[7] & 0x60) == 0) { 1366 goto not_wide; 1367 } 1368 if ((dev->global_map & 0x20) == 0) { 1369 goto not_wide; 1370 } 1371 tmport = wkport + 0x1b; 1372 outb(0x01, tmport); 1373 tmport = wkport + 3; 1374 outb(satn[0], tmport++); 1375 outb(satn[1], tmport++); 1376 outb(satn[2], tmport++); 1377 outb(satn[3], tmport++); 1378 outb(satn[4], tmport++); 1379 outb(satn[5], tmport++); 1380 tmport += 0x06; 1381 outb(0, tmport); 1382 tmport += 0x02; 1383 outb(dev->id[i].devspu, tmport++); 1384 outb(0, tmport++); 1385 outb(satn[6], tmport++); 1386 outb(satn[7], tmport++); 1387 tmport += 0x03; 1388 outb(satn[8], tmport); 1389 tmport += 0x07; 1390 1391 while ((inb(tmport) & 0x80) == 0x00); 1392 tmport -= 0x08; 1393 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { 1394 continue; 1395 } 1396 while (inb(tmport) != 0x8e); 1397try_wide: 1398 j = 0; 1399 tmport = wkport + 0x14; 1400 outb(0x05, tmport); 1401 tmport += 0x04; 1402 outb(0x20, tmport); 1403 tmport += 0x07; 1404 1405 while ((inb(tmport) & 0x80) == 0) { 1406 if ((inb(tmport) & 0x01) != 0) { 1407 tmport -= 0x06; 1408 outb(wide[j++], tmport); 1409 tmport += 0x06; 1410 } 1411 } 1412 tmport -= 0x08; 1413 while ((inb(tmport) & 0x80) == 0x00); 1414 j = inb(tmport) & 0x0f; 1415 if (j == 0x0f) { 1416 goto widep_in; 1417 } 1418 if (j == 0x0a) { 1419 goto widep_cmd; 1420 } 1421 if (j == 0x0e) { 1422 goto try_wide; 1423 } 1424 continue; 1425widep_out: 1426 tmport = wkport + 0x18; 1427 outb(0x20, tmport); 1428 tmport += 0x07; 1429 while ((inb(tmport) & 0x80) == 0) { 1430 if ((inb(tmport) & 0x01) != 0) { 1431 tmport -= 0x06; 1432 outb(0, tmport); 1433 tmport += 0x06; 1434 } 1435 } 1436 tmport -= 0x08; 1437 j = inb(tmport) & 0x0f; 1438 if (j == 0x0f) { 1439 goto widep_in; 1440 } 1441 if (j == 0x0a) { 1442 goto widep_cmd; 1443 } 1444 if (j == 0x0e) { 1445 goto widep_out; 1446 } 1447 continue; 1448widep_in: 1449 tmport = wkport + 0x14; 1450 outb(0xff, tmport); 1451 tmport += 0x04; 1452 outb(0x20, tmport); 1453 tmport += 0x07; 1454 k = 0; 1455widep_in1: 1456 j = inb(tmport); 1457 if ((j & 0x01) != 0) { 1458 tmport -= 0x06; 1459 mbuf[k++] = inb(tmport); 1460 tmport += 0x06; 1461 goto widep_in1; 1462 } 1463 if ((j & 0x80) == 0x00) { 1464 goto widep_in1; 1465 } 1466 tmport -= 0x08; 1467 j = inb(tmport) & 0x0f; 1468 if (j == 0x0f) { 1469 goto widep_in; 1470 } 1471 if (j == 0x0a) { 1472 goto widep_cmd; 1473 } 1474 if (j == 0x0e) { 1475 goto widep_out; 1476 } 1477 continue; 1478widep_cmd: 1479 tmport = wkport + 0x10; 1480 outb(0x30, tmport); 1481 tmport = wkport + 0x14; 1482 outb(0x00, tmport); 1483 tmport += 0x04; 1484 outb(0x08, tmport); 1485 tmport += 0x07; 1486 while ((inb(tmport) & 0x80) == 0x00); 1487 tmport -= 0x08; 1488 j = inb(tmport); 1489 if (j != 0x16) { 1490 if (j == 0x4e) { 1491 goto widep_out; 1492 } 1493 continue; 1494 } 1495 if (mbuf[0] != 0x01) { 1496 goto not_wide; 1497 } 1498 if (mbuf[1] != 0x02) { 1499 goto not_wide; 1500 } 1501 if (mbuf[2] != 0x03) { 1502 goto not_wide; 1503 } 1504 if (mbuf[3] != 0x01) { 1505 goto not_wide; 1506 } 1507 m = 1; 1508 m = m << i; 1509 dev->wide_idu |= m; 1510not_wide: 1511 if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) || 1512 ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0))) 1513 { 1514 goto set_sync; 1515 } 1516 continue; 1517set_sync: 1518 tmport = wkport + 0x1b; 1519 j = 0; 1520 if ((m & dev->wide_idu) != 0) { 1521 j |= 0x01; 1522 } 1523 outb(j, tmport); 1524 tmport = wkport + 3; 1525 outb(satn[0], tmport++); 1526 outb(satn[1], tmport++); 1527 outb(satn[2], tmport++); 1528 outb(satn[3], tmport++); 1529 outb(satn[4], tmport++); 1530 outb(satn[5], tmport++); 1531 tmport += 0x06; 1532 outb(0, tmport); 1533 tmport += 0x02; 1534 outb(dev->id[i].devspu, tmport++); 1535 outb(0, tmport++); 1536 outb(satn[6], tmport++); 1537 outb(satn[7], tmport++); 1538 tmport += 0x03; 1539 outb(satn[8], tmport); 1540 tmport += 0x07; 1541 1542 while ((inb(tmport) & 0x80) == 0x00); 1543 tmport -= 0x08; 1544 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { 1545 continue; 1546 } 1547 while (inb(tmport) != 0x8e); 1548try_sync: 1549 j = 0; 1550 tmport = wkport + 0x14; 1551 outb(0x06, tmport); 1552 tmport += 0x04; 1553 outb(0x20, tmport); 1554 tmport += 0x07; 1555 1556 while ((inb(tmport) & 0x80) == 0) { 1557 if ((inb(tmport) & 0x01) != 0) { 1558 tmport -= 0x06; 1559 if ((m & dev->wide_idu) != 0) { 1560 outb(synw[j++], tmport); 1561 } else { 1562 if ((m & dev->ultra_map) != 0) { 1563 outb(synu[j++], tmport); 1564 } else { 1565 outb(synn[j++], tmport); 1566 } 1567 } 1568 tmport += 0x06; 1569 } 1570 } 1571 tmport -= 0x08; 1572 while ((inb(tmport) & 0x80) == 0x00); 1573 j = inb(tmport) & 0x0f; 1574 if (j == 0x0f) { 1575 goto phase_ins; 1576 } 1577 if (j == 0x0a) { 1578 goto phase_cmds; 1579 } 1580 if (j == 0x0e) { 1581 goto try_sync; 1582 } 1583 continue; 1584phase_outs: 1585 tmport = wkport + 0x18; 1586 outb(0x20, tmport); 1587 tmport += 0x07; 1588 while ((inb(tmport) & 0x80) == 0x00) { 1589 if ((inb(tmport) & 0x01) != 0x00) { 1590 tmport -= 0x06; 1591 outb(0x00, tmport); 1592 tmport += 0x06; 1593 } 1594 } 1595 tmport -= 0x08; 1596 j = inb(tmport); 1597 if (j == 0x85) { 1598 goto tar_dcons; 1599 } 1600 j &= 0x0f; 1601 if (j == 0x0f) { 1602 goto phase_ins; 1603 } 1604 if (j == 0x0a) { 1605 goto phase_cmds; 1606 } 1607 if (j == 0x0e) { 1608 goto phase_outs; 1609 } 1610 continue; 1611phase_ins: 1612 tmport = wkport + 0x14; 1613 outb(0xff, tmport); 1614 tmport += 0x04; 1615 outb(0x20, tmport); 1616 tmport += 0x07; 1617 k = 0; 1618phase_ins1: 1619 j = inb(tmport); 1620 if ((j & 0x01) != 0x00) { 1621 tmport -= 0x06; 1622 mbuf[k++] = inb(tmport); 1623 tmport += 0x06; 1624 goto phase_ins1; 1625 } 1626 if ((j & 0x80) == 0x00) { 1627 goto phase_ins1; 1628 } 1629 tmport -= 0x08; 1630 while ((inb(tmport) & 0x80) == 0x00); 1631 j = inb(tmport); 1632 if (j == 0x85) { 1633 goto tar_dcons; 1634 } 1635 j &= 0x0f; 1636 if (j == 0x0f) { 1637 goto phase_ins; 1638 } 1639 if (j == 0x0a) { 1640 goto phase_cmds; 1641 } 1642 if (j == 0x0e) { 1643 goto phase_outs; 1644 } 1645 continue; 1646phase_cmds: 1647 tmport = wkport + 0x10; 1648 outb(0x30, tmport); 1649tar_dcons: 1650 tmport = wkport + 0x14; 1651 outb(0x00, tmport); 1652 tmport += 0x04; 1653 outb(0x08, tmport); 1654 tmport += 0x07; 1655 while ((inb(tmport) & 0x80) == 0x00); 1656 tmport -= 0x08; 1657 j = inb(tmport); 1658 if (j != 0x16) { 1659 continue; 1660 } 1661 if (mbuf[0] != 0x01) { 1662 continue; 1663 } 1664 if (mbuf[1] != 0x03) { 1665 continue; 1666 } 1667 if (mbuf[4] == 0x00) { 1668 continue; 1669 } 1670 if (mbuf[3] > 0x64) { 1671 continue; 1672 } 1673 if (mbuf[4] > 0x0c) { 1674 mbuf[4] = 0x0c; 1675 } 1676 dev->id[i].devspu = mbuf[4]; 1677 if ((mbuf[3] < 0x0d) && (rmb == 0)) { 1678 j = 0xa0; 1679 goto set_syn_ok; 1680 } 1681 if (mbuf[3] < 0x1a) { 1682 j = 0x20; 1683 goto set_syn_ok; 1684 } 1685 if (mbuf[3] < 0x33) { 1686 j = 0x40; 1687 goto set_syn_ok; 1688 } 1689 if (mbuf[3] < 0x4c) { 1690 j = 0x50; 1691 goto set_syn_ok; 1692 } 1693 j = 0x60; 1694 set_syn_ok: 1695 dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j; 1696 } 1697 tmport = wkport + 0x3a; 1698 outb((unsigned char) (inb(tmport) & 0xef), tmport); 1699} 1700 1701void is880(unsigned long host, unsigned int wkport) 1702{ 1703 unsigned int tmport; 1704 unsigned char i, j, k, rmb, n, lvdmode; 1705 unsigned short int m; 1706 static unsigned char mbuf[512]; 1707 static unsigned char satn[9] = {0, 0, 0, 0, 0, 0, 0, 6, 6}; 1708 static unsigned char inqd[9] = {0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6}; 1709 static unsigned char synn[6] = {0x80, 1, 3, 1, 0x19, 0x0e}; 1710 unsigned char synu[6] = {0x80, 1, 3, 1, 0x0a, 0x0e}; 1711 static unsigned char synw[6] = {0x80, 1, 3, 1, 0x19, 0x0e}; 1712 unsigned char synuw[6] = {0x80, 1, 3, 1, 0x0a, 0x0e}; 1713 static unsigned char wide[6] = {0x80, 1, 2, 3, 1, 0}; 1714 static unsigned char u3[9] = { 0x80,1,6,4,0x09,00,0x0e,0x01,0x02 }; 1715 struct atp_unit *dev = &atp_unit[host]; 1716 1717 sync_idu = 0; 1718 lvdmode=inb(wkport + 0x3f) & 0x40; 1719 1720 for (i = 0; i < 16; i++) { 1721 m = 1; 1722 m = m << i; 1723 if ((m & dev->active_idu) != 0) { 1724 continue; 1725 } 1726 if (i == dev->host_idu) { 1727 printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_idu); 1728 continue; 1729 } 1730 tmport = wkport + 0x5b; 1731 outb(0x01, tmport); 1732 tmport = wkport + 0x41; 1733 outb(0x08, tmport++); 1734 outb(0x7f, tmport++); 1735 outb(satn[0], tmport++); 1736 outb(satn[1], tmport++); 1737 outb(satn[2], tmport++); 1738 outb(satn[3], tmport++); 1739 outb(satn[4], tmport++); 1740 outb(satn[5], tmport++); 1741 tmport += 0x06; 1742 outb(0, tmport); 1743 tmport += 0x02; 1744 outb(dev->id[i].devspu, tmport++); 1745 outb(0, tmport++); 1746 outb(satn[6], tmport++); 1747 outb(satn[7], tmport++); 1748 j = i; 1749 if ((j & 0x08) != 0) { 1750 j = (j & 0x07) | 0x40; 1751 } 1752 outb(j, tmport); 1753 tmport += 0x03; 1754 outb(satn[8], tmport); 1755 tmport += 0x07; 1756 1757 while ((inb(tmport) & 0x80) == 0x00); 1758 tmport -= 0x08; 1759 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { 1760 continue; 1761 } 1762 while (inb(tmport) != 0x8e); 1763 dev->active_idu |= m; 1764 1765 tmport = wkport + 0x50; 1766 outb(0x30, tmport); 1767 tmport = wkport + 0x54; 1768 outb(0x00, tmport); 1769 1770phase_cmd: 1771 tmport = wkport + 0x58; 1772 outb(0x08, tmport); 1773 tmport += 0x07; 1774 while ((inb(tmport) & 0x80) == 0x00); 1775 tmport -= 0x08; 1776 j = inb(tmport); 1777 if (j != 0x16) { 1778 tmport = wkport + 0x50; 1779 outb(0x41, tmport); 1780 goto phase_cmd; 1781 } 1782sel_ok: 1783 tmport = wkport + 0x43; 1784 outb(inqd[0], tmport++); 1785 outb(inqd[1], tmport++); 1786 outb(inqd[2], tmport++); 1787 outb(inqd[3], tmport++); 1788 outb(inqd[4], tmport++); 1789 outb(inqd[5], tmport); 1790 tmport += 0x07; 1791 outb(0, tmport); 1792 tmport += 0x02; 1793 outb(dev->id[i].devspu, tmport++); 1794 outb(0, tmport++); 1795 outb(inqd[6], tmport++); 1796 outb(inqd[7], tmport++); 1797 tmport += 0x03; 1798 outb(inqd[8], tmport); 1799 tmport += 0x07; 1800 while ((inb(tmport) & 0x80) == 0x00); 1801 tmport -= 0x08; 1802 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { 1803 continue; 1804 } 1805 while (inb(tmport) != 0x8e); 1806 tmport = wkport + 0x5b; 1807 outb(0x00, tmport); 1808 tmport = wkport + 0x58; 1809 outb(0x08, tmport); 1810 tmport += 0x07; 1811 j = 0; 1812rd_inq_data: 1813 k = inb(tmport); 1814 if ((k & 0x01) != 0) { 1815 tmport -= 0x06; 1816 mbuf[j++] = inb(tmport); 1817 tmport += 0x06; 1818 goto rd_inq_data; 1819 } 1820 if ((k & 0x80) == 0) { 1821 goto rd_inq_data; 1822 } 1823 tmport -= 0x08; 1824 j = inb(tmport); 1825 if (j == 0x16) { 1826 goto inq_ok; 1827 } 1828 tmport = wkport + 0x50; 1829 outb(0x46, tmport); 1830 tmport += 0x02; 1831 outb(0, tmport++); 1832 outb(0, tmport++); 1833 outb(0, tmport++); 1834 tmport += 0x03; 1835 outb(0x08, tmport); 1836 tmport += 0x07; 1837 while ((inb(tmport) & 0x80) == 0x00); 1838 tmport -= 0x08; 1839 if (inb(tmport) != 0x16) { 1840 goto sel_ok; 1841 } 1842inq_ok: 1843 mbuf[36] = 0; 1844 printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]); 1845 dev->id[i].devtypeu = mbuf[0]; 1846 rmb = mbuf[1]; 1847 n = mbuf[7]; 1848 if ((mbuf[7] & 0x60) == 0) { 1849 goto not_wide; 1850 } 1851 if ((i < 8) && ((dev->global_map & 0x20) == 0)) { 1852 goto not_wide; 1853 } 1854 if (lvdmode == 0) 1855 { 1856 goto chg_wide; 1857 } 1858 if (dev->sp[i] != 0x04) // force u2 1859 { 1860 goto chg_wide; 1861 } 1862 1863 tmport = wkport + 0x5b; 1864 outb(0x01, tmport); 1865 tmport = wkport + 0x43; 1866 outb(satn[0], tmport++); 1867 outb(satn[1], tmport++); 1868 outb(satn[2], tmport++); 1869 outb(satn[3], tmport++); 1870 outb(satn[4], tmport++); 1871 outb(satn[5], tmport++); 1872 tmport += 0x06; 1873 outb(0, tmport); 1874 tmport += 0x02; 1875 outb(dev->id[i].devspu, tmport++); 1876 outb(0, tmport++); 1877 outb(satn[6], tmport++); 1878 outb(satn[7], tmport++); 1879 tmport += 0x03; 1880 outb(satn[8], tmport); 1881 tmport += 0x07; 1882 1883 while ((inb(tmport) & 0x80) == 0x00); 1884 tmport -= 0x08; 1885 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { 1886 continue; 1887 } 1888 while (inb(tmport) != 0x8e); 1889try_u3: 1890 j = 0; 1891 tmport = wkport + 0x54; 1892 outb(0x09, tmport); 1893 tmport += 0x04; 1894 outb(0x20, tmport); 1895 tmport += 0x07; 1896 1897 while ((inb(tmport) & 0x80) == 0) { 1898 if ((inb(tmport) & 0x01) != 0) { 1899 tmport -= 0x06; 1900 outb(u3[j++], tmport); 1901 tmport += 0x06; 1902 } 1903 } 1904 tmport -= 0x08; 1905 while ((inb(tmport) & 0x80) == 0x00); 1906 j = inb(tmport) & 0x0f; 1907 if (j == 0x0f) { 1908 goto u3p_in; 1909 } 1910 if (j == 0x0a) { 1911 goto u3p_cmd; 1912 } 1913 if (j == 0x0e) { 1914 goto try_u3; 1915 } 1916 continue; 1917u3p_out: 1918 tmport = wkport + 0x58; 1919 outb(0x20, tmport); 1920 tmport += 0x07; 1921 while ((inb(tmport) & 0x80) == 0) { 1922 if ((inb(tmport) & 0x01) != 0) { 1923 tmport -= 0x06; 1924 outb(0, tmport); 1925 tmport += 0x06; 1926 } 1927 } 1928 tmport -= 0x08; 1929 j = inb(tmport) & 0x0f; 1930 if (j == 0x0f) { 1931 goto u3p_in; 1932 } 1933 if (j == 0x0a) { 1934 goto u3p_cmd; 1935 } 1936 if (j == 0x0e) { 1937 goto u3p_out; 1938 } 1939 continue; 1940u3p_in: 1941 tmport = wkport + 0x54; 1942 outb(0x09, tmport); 1943 tmport += 0x04; 1944 outb(0x20, tmport); 1945 tmport += 0x07; 1946 k = 0; 1947u3p_in1: 1948 j = inb(tmport); 1949 if ((j & 0x01) != 0) { 1950 tmport -= 0x06; 1951 mbuf[k++] = inb(tmport); 1952 tmport += 0x06; 1953 goto u3p_in1; 1954 } 1955 if ((j & 0x80) == 0x00) { 1956 goto u3p_in1; 1957 } 1958 tmport -= 0x08; 1959 j = inb(tmport) & 0x0f; 1960 if (j == 0x0f) { 1961 goto u3p_in; 1962 } 1963 if (j == 0x0a) { 1964 goto u3p_cmd; 1965 } 1966 if (j == 0x0e) { 1967 goto u3p_out; 1968 } 1969 continue; 1970u3p_cmd: 1971 tmport = wkport + 0x50; 1972 outb(0x30, tmport); 1973 tmport = wkport + 0x54; 1974 outb(0x00, tmport); 1975 tmport += 0x04; 1976 outb(0x08, tmport); 1977 tmport += 0x07; 1978 while ((inb(tmport) & 0x80) == 0x00); 1979 tmport -= 0x08; 1980 j = inb(tmport); 1981 if (j != 0x16) { 1982 if (j == 0x4e) { 1983 goto u3p_out; 1984 } 1985 continue; 1986 } 1987 if (mbuf[0] != 0x01) { 1988 goto chg_wide; 1989 } 1990 if (mbuf[1] != 0x06) { 1991 goto chg_wide; 1992 } 1993 if (mbuf[2] != 0x04) { 1994 goto chg_wide; 1995 } 1996 if (mbuf[3] == 0x09) { 1997 m = 1; 1998 m = m << i; 1999 dev->wide_idu |= m; 2000 dev->id[i].devspu = 0xce; 2001 continue; 2002 } 2003chg_wide: 2004 tmport = wkport + 0x5b; 2005 outb(0x01, tmport); 2006 tmport = wkport + 0x43; 2007 outb(satn[0], tmport++); 2008 outb(satn[1], tmport++); 2009 outb(satn[2], tmport++); 2010 outb(satn[3], tmport++); 2011 outb(satn[4], tmport++); 2012 outb(satn[5], tmport++); 2013 tmport += 0x06; 2014 outb(0, tmport); 2015 tmport += 0x02; 2016 outb(dev->id[i].devspu, tmport++); 2017 outb(0, tmport++); 2018 outb(satn[6], tmport++); 2019 outb(satn[7], tmport++); 2020 tmport += 0x03; 2021 outb(satn[8], tmport); 2022 tmport += 0x07; 2023 2024 while ((inb(tmport) & 0x80) == 0x00); 2025 tmport -= 0x08; 2026 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { 2027 continue; 2028 } 2029 while (inb(tmport) != 0x8e); 2030try_wide: 2031 j = 0; 2032 tmport = wkport + 0x54; 2033 outb(0x05, tmport); 2034 tmport += 0x04; 2035 outb(0x20, tmport); 2036 tmport += 0x07; 2037 2038 while ((inb(tmport) & 0x80) == 0) { 2039 if ((inb(tmport) & 0x01) != 0) { 2040 tmport -= 0x06; 2041 outb(wide[j++], tmport); 2042 tmport += 0x06; 2043 } 2044 } 2045 tmport -= 0x08; 2046 while ((inb(tmport) & 0x80) == 0x00); 2047 j = inb(tmport) & 0x0f; 2048 if (j == 0x0f) { 2049 goto widep_in; 2050 } 2051 if (j == 0x0a) { 2052 goto widep_cmd; 2053 } 2054 if (j == 0x0e) { 2055 goto try_wide; 2056 } 2057 continue; 2058widep_out: 2059 tmport = wkport + 0x58; 2060 outb(0x20, tmport); 2061 tmport += 0x07; 2062 while ((inb(tmport) & 0x80) == 0) { 2063 if ((inb(tmport) & 0x01) != 0) { 2064 tmport -= 0x06; 2065 outb(0, tmport); 2066 tmport += 0x06; 2067 } 2068 } 2069 tmport -= 0x08; 2070 j = inb(tmport) & 0x0f; 2071 if (j == 0x0f) { 2072 goto widep_in; 2073 } 2074 if (j == 0x0a) { 2075 goto widep_cmd; 2076 } 2077 if (j == 0x0e) { 2078 goto widep_out; 2079 } 2080 continue; 2081widep_in: 2082 tmport = wkport + 0x54; 2083 outb(0xff, tmport); 2084 tmport += 0x04; 2085 outb(0x20, tmport); 2086 tmport += 0x07; 2087 k = 0; 2088widep_in1: 2089 j = inb(tmport); 2090 if ((j & 0x01) != 0) { 2091 tmport -= 0x06; 2092 mbuf[k++] = inb(tmport); 2093 tmport += 0x06; 2094 goto widep_in1; 2095 } 2096 if ((j & 0x80) == 0x00) { 2097 goto widep_in1; 2098 } 2099 tmport -= 0x08; 2100 j = inb(tmport) & 0x0f; 2101 if (j == 0x0f) { 2102 goto widep_in; 2103 } 2104 if (j == 0x0a) { 2105 goto widep_cmd; 2106 } 2107 if (j == 0x0e) { 2108 goto widep_out; 2109 } 2110 continue; 2111widep_cmd: 2112 tmport = wkport + 0x50; 2113 outb(0x30, tmport); 2114 tmport = wkport + 0x54; 2115 outb(0x00, tmport); 2116 tmport += 0x04; 2117 outb(0x08, tmport); 2118 tmport += 0x07; 2119 while ((inb(tmport) & 0x80) == 0x00); 2120 tmport -= 0x08; 2121 j = inb(tmport); 2122 if (j != 0x16) { 2123 if (j == 0x4e) { 2124 goto widep_out; 2125 } 2126 continue; 2127 } 2128 if (mbuf[0] != 0x01) { 2129 goto not_wide; 2130 } 2131 if (mbuf[1] != 0x02) { 2132 goto not_wide; 2133 } 2134 if (mbuf[2] != 0x03) { 2135 goto not_wide; 2136 } 2137 if (mbuf[3] != 0x01) { 2138 goto not_wide; 2139 } 2140 m = 1; 2141 m = m << i; 2142 dev->wide_idu |= m; 2143not_wide: 2144 if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) || 2145 ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0))) 2146 { 2147 m = 1; 2148 m = m << i; 2149 if ((dev->async & m) != 0) 2150 { 2151 goto set_sync; 2152 } 2153 } 2154 continue; 2155set_sync: 2156 if (dev->sp[i] == 0x02) 2157 { 2158 synu[4]=0x0c; 2159 synuw[4]=0x0c; 2160 } 2161 else 2162 { 2163 if (dev->sp[i] >= 0x03) 2164 { 2165 synu[4]=0x0a; 2166 synuw[4]=0x0a; 2167 } 2168 } 2169 tmport = wkport + 0x5b; 2170 j = 0; 2171 if ((m & dev->wide_idu) != 0) { 2172 j |= 0x01; 2173 } 2174 outb(j, tmport); 2175 tmport = wkport + 0x43; 2176 outb(satn[0], tmport++); 2177 outb(satn[1], tmport++); 2178 outb(satn[2], tmport++); 2179 outb(satn[3], tmport++); 2180 outb(satn[4], tmport++); 2181 outb(satn[5], tmport++); 2182 tmport += 0x06; 2183 outb(0, tmport); 2184 tmport += 0x02; 2185 outb(dev->id[i].devspu, tmport++); 2186 outb(0, tmport++); 2187 outb(satn[6], tmport++); 2188 outb(satn[7], tmport++); 2189 tmport += 0x03; 2190 outb(satn[8], tmport); 2191 tmport += 0x07; 2192 2193 while ((inb(tmport) & 0x80) == 0x00); 2194 tmport -= 0x08; 2195 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { 2196 continue; 2197 } 2198 while (inb(tmport) != 0x8e); 2199try_sync: 2200 j = 0; 2201 tmport = wkport + 0x54; 2202 outb(0x06, tmport); 2203 tmport += 0x04; 2204 outb(0x20, tmport); 2205 tmport += 0x07; 2206 2207 while ((inb(tmport) & 0x80) == 0) { 2208 if ((inb(tmport) & 0x01) != 0) { 2209 tmport -= 0x06; 2210 if ((m & dev->wide_idu) != 0) { 2211 if ((m & dev->ultra_map) != 0) { 2212 outb(synuw[j++], tmport); 2213 } else { 2214 outb(synw[j++], tmport); 2215 } 2216 } else { 2217 if ((m & dev->ultra_map) != 0) { 2218 outb(synu[j++], tmport); 2219 } else { 2220 outb(synn[j++], tmport); 2221 } 2222 } 2223 tmport += 0x06; 2224 } 2225 } 2226 tmport -= 0x08; 2227 while ((inb(tmport) & 0x80) == 0x00); 2228 j = inb(tmport) & 0x0f; 2229 if (j == 0x0f) { 2230 goto phase_ins; 2231 } 2232 if (j == 0x0a) { 2233 goto phase_cmds; 2234 } 2235 if (j == 0x0e) { 2236 goto try_sync; 2237 } 2238 continue; 2239phase_outs: 2240 tmport = wkport + 0x58; 2241 outb(0x20, tmport); 2242 tmport += 0x07; 2243 while ((inb(tmport) & 0x80) == 0x00) { 2244 if ((inb(tmport) & 0x01) != 0x00) { 2245 tmport -= 0x06; 2246 outb(0x00, tmport); 2247 tmport += 0x06; 2248 } 2249 } 2250 tmport -= 0x08; 2251 j = inb(tmport); 2252 if (j == 0x85) { 2253 goto tar_dcons; 2254 } 2255 j &= 0x0f; 2256 if (j == 0x0f) { 2257 goto phase_ins; 2258 } 2259 if (j == 0x0a) { 2260 goto phase_cmds; 2261 } 2262 if (j == 0x0e) { 2263 goto phase_outs; 2264 } 2265 continue; 2266phase_ins: 2267 tmport = wkport + 0x54; 2268 outb(0x06, tmport); 2269 tmport += 0x04; 2270 outb(0x20, tmport); 2271 tmport += 0x07; 2272 k = 0; 2273phase_ins1: 2274 j = inb(tmport); 2275 if ((j & 0x01) != 0x00) { 2276 tmport -= 0x06; 2277 mbuf[k++] = inb(tmport); 2278 tmport += 0x06; 2279 goto phase_ins1; 2280 } 2281 if ((j & 0x80) == 0x00) { 2282 goto phase_ins1; 2283 } 2284 tmport -= 0x08; 2285 while ((inb(tmport) & 0x80) == 0x00); 2286 j = inb(tmport); 2287 if (j == 0x85) { 2288 goto tar_dcons; 2289 } 2290 j &= 0x0f; 2291 if (j == 0x0f) { 2292 goto phase_ins; 2293 } 2294 if (j == 0x0a) { 2295 goto phase_cmds; 2296 } 2297 if (j == 0x0e) { 2298 goto phase_outs; 2299 } 2300 continue; 2301phase_cmds: 2302 tmport = wkport + 0x50; 2303 outb(0x30, tmport); 2304tar_dcons: 2305 tmport = wkport + 0x54; 2306 outb(0x00, tmport); 2307 tmport += 0x04; 2308 outb(0x08, tmport); 2309 tmport += 0x07; 2310 while ((inb(tmport) & 0x80) == 0x00); 2311 tmport -= 0x08; 2312 j = inb(tmport); 2313 if (j != 0x16) { 2314 continue; 2315 } 2316 if (mbuf[0] != 0x01) { 2317 continue; 2318 } 2319 if (mbuf[1] != 0x03) { 2320 continue; 2321 } 2322 if (mbuf[4] == 0x00) { 2323 continue; 2324 } 2325 if (mbuf[3] > 0x64) { 2326 continue; 2327 } 2328 if (mbuf[4] > 0x0e) { 2329 mbuf[4] = 0x0e; 2330 } 2331 dev->id[i].devspu = mbuf[4]; 2332 if (mbuf[3] < 0x0c){ 2333 j = 0xb0; 2334 goto set_syn_ok; 2335 } 2336 if ((mbuf[3] < 0x0d) && (rmb == 0)) { 2337 j = 0xa0; 2338 goto set_syn_ok; 2339 } 2340 if (mbuf[3] < 0x1a) { 2341 j = 0x20; 2342 goto set_syn_ok; 2343 } 2344 if (mbuf[3] < 0x33) { 2345 j = 0x40; 2346 goto set_syn_ok; 2347 } 2348 if (mbuf[3] < 0x4c) { 2349 j = 0x50; 2350 goto set_syn_ok; 2351 } 2352 j = 0x60; 2353 set_syn_ok: 2354 dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j; 2355 } 2356} 2357 2358/* return non-zero on detection */ 2359int atp870u_detect(Scsi_Host_Template * tpnt) 2360{ 2361 unsigned char irq, h, k, m; 2362 unsigned long flags; 2363 unsigned int base_io, error, tmport; 2364 unsigned short index = 0; 2365 struct pci_dev *pdev[3]; 2366 unsigned char chip_ver[3], host_id; 2367 unsigned short dev_id[3], n; 2368 struct Scsi_Host *shpnt = NULL; 2369 int tmpcnt = 0; 2370 int count = 0; 2371 2372 static unsigned short devid[9] = { 2373 0x8081, 0x8002, 0x8010, 0x8020, 0x8030, 0x8040, 0x8050, 0x8060, 0 2374 }; 2375 2376 printk(KERN_INFO "aec671x_detect: \n"); 2377 if (!pci_present()) { 2378 printk(KERN_INFO" NO PCI SUPPORT.\n"); 2379 return count; 2380 } 2381 tpnt->proc_name = "atp870u"; 2382 2383 for (h = 0; h < 2; h++) { 2384 struct atp_unit *dev = &atp_unit[h]; 2385 for(k=0;k<16;k++) 2386 { 2387 dev->id[k].prd_tableu = kmalloc(1024, GFP_KERNEL); 2388 dev->id[k].devspu=0x20; 2389 dev->id[k].devtypeu = 0; 2390 dev->id[k].curr_req = NULL; 2391 } 2392 dev->active_idu = 0; 2393 dev->wide_idu = 0; 2394 dev->host_idu = 0x07; 2395 dev->quhdu = 0; 2396 dev->quendu = 0; 2397 pdev[h]=NULL; 2398 pdev[2]=NULL; 2399 dev->chip_veru = 0; 2400 dev->last_cmd = 0xff; 2401 dev->in_snd = 0; 2402 dev->in_int = 0; 2403 for (k = 0; k < qcnt; k++) { 2404 dev->querequ[k] = 0; 2405 } 2406 for (k = 0; k < 16; k++) { 2407 dev->id[k].curr_req = 0; 2408 dev->sp[k] = 0x04; 2409 } 2410 } 2411 h = 0; 2412 while (devid[h] != 0) { 2413 pdev[2] = pci_find_device(0x1191, devid[h], pdev[2]); 2414 if (pdev[2] == NULL || pci_enable_device(pdev[2])) { 2415 h++; 2416 index = 0; 2417 continue; 2418 } 2419 chip_ver[2] = 0; 2420 dev_id[2] = devid[h]; 2421 2422 if (devid[h] == 0x8002) { 2423 error = pci_read_config_byte(pdev[2], 0x08, &chip_ver[2]); 2424 if (chip_ver[2] < 2) { 2425 goto nxt_devfn; 2426 } 2427 } 2428 if (devid[h] == 0x8010 || devid[h] == 0x8081 || devid[h] == 0x8050) 2429 { 2430 chip_ver[2] = 0x04; 2431 } 2432 pdev[tmpcnt] = pdev[2]; 2433 chip_ver[tmpcnt] = chip_ver[2]; 2434 dev_id[tmpcnt] = dev_id[2]; 2435 tmpcnt++; 2436 nxt_devfn: 2437 index++; 2438 if (index > 3) { 2439 index = 0; 2440 h++; 2441 } 2442 if(tmpcnt>1) 2443 break; 2444 } 2445 for (h = 0; h < 2; h++) { 2446 struct atp_unit *dev=&atp_unit[h]; 2447 if (pdev[h]==NULL) { 2448 return count; 2449 } 2450 2451 /* Found an atp870u/w. */ 2452 base_io = pci_resource_start(pdev[h], 0); 2453 irq = pdev[h]->irq; 2454 2455 if (dev_id[h] != 0x8081) 2456 { 2457 error = pci_read_config_byte(pdev[h],0x49,&host_id); 2458 2459 base_io &= 0xfffffff8; 2460 2461 if (check_region(base_io,0x40) != 0) 2462 { 2463 return 0; 2464 } 2465 printk(KERN_INFO " ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d IO:%x, IRQ:%d.\n" 2466 ,h, base_io, irq); 2467 dev->ioport = base_io; 2468 dev->pciport = base_io + 0x20; 2469 dev->deviceid = dev_id[h]; 2470 irqnumu[h] = irq; 2471 host_id &= 0x07; 2472 dev->host_idu = host_id; 2473 dev->chip_veru = chip_ver[h]; 2474 2475 tmport = base_io + 0x22; 2476 dev->scam_on = inb(tmport); 2477 tmport += 0x0b; 2478 dev->global_map = inb(tmport++); 2479 dev->ultra_map = inw(tmport); 2480 if (dev->ultra_map == 0) { 2481 dev->scam_on = 0x00; 2482 dev->global_map = 0x20; 2483 dev->ultra_map = 0xffff; 2484 } 2485 shpnt = scsi_register(tpnt, 4); 2486 if(shpnt==NULL) 2487 return count; 2488 2489 save_flags(flags); 2490 cli(); 2491 if (request_irq(irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", dev)) { 2492 printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n"); 2493 goto unregister; 2494 } 2495 2496 if (chip_ver[h] > 0x07) /* check if atp876 chip */ 2497 { /* then enable terminator */ 2498 tmport = base_io + 0x3e; 2499 outb(0x00, tmport); 2500 } 2501 2502 tmport = base_io + 0x3a; 2503 k = (inb(tmport) & 0xf3) | 0x10; 2504 outb(k, tmport); 2505 outb((k & 0xdf), tmport); 2506 mydlyu(0x8000); 2507 outb(k, tmport); 2508 mydlyu(0x8000); 2509 tmport = base_io; 2510 outb((host_id | 0x08), tmport); 2511 tmport += 0x18; 2512 outb(0, tmport); 2513 tmport += 0x07; 2514 while ((inb(tmport) & 0x80) == 0); 2515 tmport -= 0x08; 2516 inb(tmport); 2517 tmport = base_io + 1; 2518 outb(8, tmport++); 2519 outb(0x7f, tmport); 2520 tmport = base_io + 0x11; 2521 outb(0x20, tmport); 2522 2523 tscam(h); 2524 is870(h, base_io); 2525 tmport = base_io + 0x3a; 2526 outb((inb(tmport) & 0xef), tmport); 2527 tmport++; 2528 outb((inb(tmport) | 0x20),tmport); 2529 } 2530 else 2531 { 2532 base_io &= 0xfffffff8; 2533 2534 if (check_region(base_io,0x60) != 0) 2535 { 2536 return 0; 2537 } 2538 host_id = inb(base_io + 0x39); 2539 host_id >>= 0x04; 2540 2541 printk(KERN_INFO " ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d IO:%x, IRQ:%d.\n" 2542 ,h, base_io, irq); 2543 dev->ioport = base_io + 0x40; 2544 dev->pciport = base_io + 0x28; 2545 dev->deviceid = dev_id[h]; 2546 irqnumu[h] = irq; 2547 dev->host_idu = host_id; 2548 dev->chip_veru = chip_ver[h]; 2549 2550 tmport = base_io + 0x22; 2551 dev->scam_on = inb(tmport); 2552 tmport += 0x13; 2553 dev->global_map = inb(tmport); 2554 tmport += 0x07; 2555 dev->ultra_map = inw(tmport); 2556 2557 n=0x3f09; 2558next_fblk: 2559 if (n >= 0x4000) 2560 { 2561 goto flash_ok; 2562 } 2563 m=0; 2564 outw(n,base_io + 0x34); 2565 n += 0x0002; 2566 if (inb(base_io + 0x30) == 0xff) 2567 { 2568 goto flash_ok; 2569 } 2570 dev->sp[m++]=inb(base_io + 0x30); 2571 dev->sp[m++]=inb(base_io + 0x31); 2572 dev->sp[m++]=inb(base_io + 0x32); 2573 dev->sp[m++]=inb(base_io + 0x33); 2574 outw(n,base_io + 0x34); 2575 n += 0x0002; 2576 dev->sp[m++]=inb(base_io + 0x30); 2577 dev->sp[m++]=inb(base_io + 0x31); 2578 dev->sp[m++]=inb(base_io + 0x32); 2579 dev->sp[m++]=inb(base_io + 0x33); 2580 outw(n,base_io + 0x34); 2581 n += 0x0002; 2582 dev->sp[m++]=inb(base_io + 0x30); 2583 dev->sp[m++]=inb(base_io + 0x31); 2584 dev->sp[m++]=inb(base_io + 0x32); 2585 dev->sp[m++]=inb(base_io + 0x33); 2586 outw(n,base_io + 0x34); 2587 n += 0x0002; 2588 dev->sp[m++]=inb(base_io + 0x30); 2589 dev->sp[m++]=inb(base_io + 0x31); 2590 dev->sp[m++]=inb(base_io + 0x32); 2591 dev->sp[m++]=inb(base_io + 0x33); 2592 n += 0x0018; 2593 goto next_fblk; 2594flash_ok: 2595 outw(0,base_io + 0x34); 2596 dev->ultra_map=0; 2597 dev->async = 0; 2598 for (k=0; k < 16; k++) 2599 { 2600 n=1; 2601 n = n << k; 2602 if (dev->sp[k] > 1) 2603 { 2604 dev->ultra_map |= n; 2605 } 2606 else 2607 { 2608 if (dev->sp[k] == 0) 2609 { 2610 dev->async |= n; 2611 } 2612 } 2613 } 2614 dev->async = ~(dev->async); 2615 outb(dev->global_map,base_io + 0x35); 2616 2617 shpnt = scsi_register(tpnt, 4); 2618 if(shpnt==NULL) 2619 return count; 2620 2621 save_flags(flags); 2622 cli(); 2623 if (request_irq(irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", dev)) { 2624 printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n"); 2625 goto unregister; 2626 } 2627 2628 tmport = base_io + 0x38; 2629 k = inb(tmport) & 0x80; 2630 outb(k, tmport); 2631 tmport += 0x03; 2632 outb(0x20, tmport); 2633 mydlyu(0x8000); 2634 outb(0, tmport); 2635 mydlyu(0x8000); 2636 tmport = base_io + 0x5b; 2637 inb(tmport); 2638 tmport -= 0x04; 2639 inb(tmport); 2640 tmport = base_io + 0x40; 2641 outb((host_id | 0x08), tmport); 2642 tmport += 0x18; 2643 outb(0, tmport); 2644 tmport += 0x07; 2645 while ((inb(tmport) & 0x80) == 0); 2646 tmport -= 0x08; 2647 inb(tmport); 2648 tmport = base_io + 0x41; 2649 outb(8, tmport++); 2650 outb(0x7f, tmport); 2651 tmport = base_io + 0x51; 2652 outb(0x20, tmport); 2653 2654 tscam(h); 2655 is880(h, base_io); 2656 tmport = base_io + 0x38; 2657 outb(0xb0, tmport); 2658 } 2659 2660 atp_host[h] = shpnt; 2661 if (dev->chip_veru == 4) { 2662 shpnt->max_id = 16; 2663 } 2664 shpnt->this_id = host_id; 2665 shpnt->unique_id = base_io; 2666 shpnt->io_port = base_io; 2667 if (dev_id[h] == 0x8081) 2668 { 2669 shpnt->n_io_port = 0x60; /* Number of bytes of I/O space used */ 2670 } 2671 else 2672 { 2673 shpnt->n_io_port = 0x40; /* Number of bytes of I/O space used */ 2674 } 2675 shpnt->irq = irq; 2676 restore_flags(flags); 2677 if (dev_id[h] == 0x8081) 2678 { 2679 request_region(base_io, 0x60, "atp870u"); /* Register the IO ports that we use */ 2680 } 2681 else 2682 { 2683 request_region(base_io, 0x40, "atp870u"); /* Register the IO ports that we use */ 2684 } 2685 count++; 2686 index++; 2687 continue; 2688unregister: 2689 scsi_unregister(shpnt); 2690 restore_flags(flags); 2691 index++; 2692 continue; 2693 } 2694 2695 return count; 2696} 2697 2698/* The abort command does not leave the device in a clean state where 2699 it is available to be used again. Until this gets worked out, we will 2700 leave it commented out. */ 2701 2702int atp870u_abort(Scsi_Cmnd * SCpnt) 2703{ 2704 unsigned char h, j, k; 2705 Scsi_Cmnd *workrequ; 2706 unsigned int tmport; 2707 struct atp_unit *dev; 2708 for (h = 0; h <= admaxu; h++) { 2709 if (SCpnt->host == atp_host[h]) { 2710 goto find_adp; 2711 } 2712 } 2713 panic("Abort host not found !"); 2714find_adp: 2715 dev=&atp_unit[h]; 2716 printk(KERN_DEBUG "working=%x last_cmd=%x ", dev->working, dev->last_cmd); 2717 printk(" quhdu=%x quendu=%x ", dev->quhdu, dev->quendu); 2718 tmport = dev->ioport; 2719 for (j = 0; j < 0x17; j++) { 2720 printk(" r%2x=%2x", j, inb(tmport++)); 2721 } 2722 tmport += 0x05; 2723 printk(" r1c=%2x", inb(tmport)); 2724 tmport += 0x03; 2725 printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd); 2726 tmport= dev->pciport; 2727 printk(" r20=%2x", inb(tmport)); 2728 tmport += 0x02; 2729 printk(" r22=%2x", inb(tmport)); 2730 tmport = dev->ioport + 0x3a; 2731 printk(" r3a=%2x \n",inb(tmport)); 2732 tmport = dev->ioport + 0x3b; 2733 printk(" r3b=%2x \n",inb(tmport)); 2734 for(j=0;j<16;j++) 2735 { 2736 if (dev->id[j].curr_req != NULL) 2737 { 2738 workrequ = dev->id[j].curr_req; 2739 printk("\n que cdb= "); 2740 for (k=0; k < workrequ->cmd_len; k++) 2741 { 2742 printk(" %2x ",workrequ->cmnd[k]); 2743 } 2744 printk(" last_lenu= %lx ",dev->id[j].last_lenu); 2745 } 2746 } 2747 return (SCSI_ABORT_SNOOZE); 2748} 2749 2750int atp870u_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) 2751{ 2752 unsigned char h; 2753 struct atp_unit *dev; 2754 /* 2755 * See if a bus reset was suggested. 2756 */ 2757 for (h = 0; h <= admaxu; h++) { 2758 if (SCpnt->host == atp_host[h]) { 2759 goto find_host; 2760 } 2761 } 2762 panic("Reset bus host not found !"); 2763find_host: 2764 dev=&atp_unit[h]; 2765/* SCpnt->result = 0x00080000; 2766 SCpnt->scsi_done(SCpnt); 2767 dev->working=0; 2768 dev->quhdu=0; 2769 dev->quendu=0; 2770 return (SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET); */ 2771 return (SCSI_RESET_SNOOZE); 2772} 2773 2774const char *atp870u_info(struct Scsi_Host *notused) 2775{ 2776 static char buffer[128]; 2777 2778 strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac "); 2779 2780 return buffer; 2781} 2782 2783int atp870u_set_info(char *buffer, int length, struct Scsi_Host *HBAptr) 2784{ 2785 return -ENOSYS; /* Currently this is a no-op */ 2786} 2787 2788#define BLS buffer + len + size 2789int atp870u_proc_info(char *buffer, char **start, off_t offset, int length, 2790 int hostno, int inout) 2791{ 2792 struct Scsi_Host *HBAptr; 2793 static u8 buff[512]; 2794 int i; 2795 int size = 0; 2796 int len = 0; 2797 off_t begin = 0; 2798 off_t pos = 0; 2799 2800 HBAptr = NULL; 2801 for (i = 0; i < 2; i++) { 2802 if ((HBAptr = atp_host[i]) != NULL) { 2803 if (HBAptr->host_no == hostno) { 2804 break; 2805 } 2806 HBAptr = NULL; 2807 } 2808 } 2809 2810 if (HBAptr == NULL) { 2811 size += sprintf(BLS, "Can't find adapter for host number %d\n", hostno); 2812 len += size; 2813 pos = begin + len; 2814 size = 0; 2815 goto stop_output; 2816 } 2817 if (inout == TRUE) { /* Has data been written to the file? */ 2818 return (atp870u_set_info(buffer, length, HBAptr)); 2819 } 2820 if (offset == 0) { 2821 memset(buff, 0, sizeof(buff)); 2822 } 2823 size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.6+ac\n"); 2824 len += size; 2825 pos = begin + len; 2826 size = 0; 2827 2828 size += sprintf(BLS, "\n"); 2829 size += sprintf(BLS, "Adapter Configuration:\n"); 2830 size += sprintf(BLS, " Base IO: %#.4lx\n", HBAptr->io_port); 2831 size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq); 2832 len += size; 2833 pos = begin + len; 2834 size = 0; 2835 2836stop_output: 2837 *start = buffer + (offset - begin); /* Start of wanted data */ 2838 len -= (offset - begin); /* Start slop */ 2839 if (len > length) { 2840 len = length; /* Ending slop */ 2841 } 2842 return (len); 2843} 2844 2845#include "sd.h" 2846 2847int atp870u_biosparam(Scsi_Disk * disk, kdev_t dev, int *ip) 2848{ 2849 int heads, sectors, cylinders; 2850 2851 heads = 64; 2852 sectors = 32; 2853 cylinders = disk->capacity / (heads * sectors); 2854 2855 if (cylinders > 1024) { 2856 heads = 255; 2857 sectors = 63; 2858 cylinders = disk->capacity / (heads * sectors); 2859 } 2860 ip[0] = heads; 2861 ip[1] = sectors; 2862 ip[2] = cylinders; 2863 2864 return 0; 2865} 2866 2867 2868int atp870u_release (struct Scsi_Host *pshost) 2869{ 2870 int h; 2871 for (h = 0; h <= admaxu; h++) 2872 { 2873 if (pshost == atp_host[h]) { 2874 int k; 2875 free_irq (pshost->irq, &atp_unit[h]); 2876 release_region (pshost->io_port, pshost->n_io_port); 2877 scsi_unregister(pshost); 2878 for(k=0;k<16;k++) 2879 kfree(atp_unit[h].id[k].prd_tableu); 2880 return 0; 2881 } 2882 } 2883 panic("atp870u: bad scsi host passed.\n"); 2884 2885} 2886MODULE_LICENSE("GPL"); 2887 2888static Scsi_Host_Template driver_template = ATP870U; 2889#include "scsi_module.c" 2890