[PATCH] update copyright and licensing
[linux-2.6/history.git] / drivers / scsi / atp870u.c
blob8a1d588d3b6d1cadad133f366220946724865c82
1 /* $Id: atp870u.c,v 1.0 1997/05/07 15:22:00 root Exp root $
2 * linux/kernel/atp870u.c
4 * Copyright (C) 1997 Wu Ching Chen
5 * 2.1.x update (C) 1998 Krzysztof G. Baranowski
6 * 2.5.x update (C) 2002 Red Hat <alan@redhat.com>
8 * Marcelo Tosatti <marcelo@conectiva.com.br> : SMP fixes
10 * Wu Ching Chen : NULL pointer fixes 2000/06/02
11 * support atp876 chip
12 * enable 32 bit fifo transfer
13 * support cdrom & remove device run ultra speed
14 * fix disconnect bug 2000/12/21
15 * support atp880 chip lvd u160 2001/05/15
16 * fix prd table bug 2001/09/12 (7.1)
19 #include <linux/module.h>
20 #include <linux/interrupt.h>
21 #include <linux/kernel.h>
22 #include <linux/types.h>
23 #include <linux/string.h>
24 #include <linux/ioport.h>
25 #include <linux/delay.h>
26 #include <linux/proc_fs.h>
27 #include <linux/spinlock.h>
28 #include <linux/pci.h>
29 #include <linux/blkdev.h>
30 #include <linux/stat.h>
32 #include <asm/system.h>
33 #include <asm/io.h>
35 #include "scsi.h"
36 #include "hosts.h"
37 #include "atp870u.h"
40 * static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/atp870u.c,v 1.0 1997/05/07 15:22:00 root Exp root $";
43 static unsigned short int sync_idu;
45 #define MAX_ATP 16
47 struct atp_unit {
48 unsigned long ioport;
49 unsigned long irq;
50 unsigned long pciport;
51 unsigned char last_cmd;
52 unsigned char in_snd;
53 unsigned char in_int;
54 unsigned char quhdu;
55 unsigned char quendu;
56 unsigned char scam_on;
57 unsigned char global_map;
58 unsigned char chip_veru;
59 unsigned char host_idu;
60 int working;
61 unsigned short wide_idu;
62 unsigned short active_idu;
63 unsigned short ultra_map;
64 unsigned short async;
65 unsigned short deviceid;
66 unsigned char ata_cdbu[16];
67 unsigned char sp[16];
68 Scsi_Cmnd *querequ[qcnt];
69 struct atp_id {
70 unsigned char dirctu;
71 unsigned char devspu;
72 unsigned char devtypeu;
73 unsigned long prdaddru;
74 unsigned long tran_lenu;
75 unsigned long last_lenu;
76 unsigned char *prd_posu;
77 unsigned char *prd_tableu;
78 dma_addr_t prd_phys;
79 Scsi_Cmnd *curr_req;
80 } id[16];
81 struct Scsi_Host *host;
82 struct pci_dev *pdev;
85 static struct Scsi_Host *atp_host[MAX_ATP];
87 static void send_s870(struct Scsi_Host *);
89 static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
90 struct pt_regs *regs)
92 unsigned long flags;
93 unsigned short int tmpcip, id;
94 unsigned char i, j, target_id, lun;
95 unsigned char *prd;
96 Scsi_Cmnd *workrequ;
97 unsigned int workportu, tmport;
98 unsigned long adrcntu, k;
99 int errstus;
100 struct Scsi_Host *host = dev_id;
101 struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
103 dev->in_int = 1;
104 workportu = dev->ioport;
105 tmport = workportu;
107 if (dev->working != 0) {
108 tmport += 0x1f;
109 j = inb(tmport);
110 if ((j & 0x80) == 0) {
111 dev->in_int = 0;
112 return IRQ_NONE;
115 tmpcip = dev->pciport;
116 if ((inb(tmpcip) & 0x08) != 0) {
117 tmpcip += 0x2;
118 for (k = 0; k < 1000; k++) {
119 if ((inb(tmpcip) & 0x08) == 0) {
120 goto stop_dma;
122 if ((inb(tmpcip) & 0x01) == 0) {
123 goto stop_dma;
127 stop_dma:
128 tmpcip = dev->pciport;
129 outb(0x00, tmpcip);
130 tmport -= 0x08;
132 i = inb(tmport);
134 tmport -= 0x02;
135 target_id = inb(tmport);
136 tmport += 0x02;
139 * Remap wide devices onto id numbers
142 if ((target_id & 0x40) != 0) {
143 target_id = (target_id & 0x07) | 0x08;
144 } else {
145 target_id &= 0x07;
148 if ((j & 0x40) != 0) {
149 if (dev->last_cmd == 0xff) {
150 dev->last_cmd = target_id;
152 dev->last_cmd |= 0x40;
155 if (i == 0x85) {
156 if ((dev->last_cmd & 0xf0) != 0x40) {
157 dev->last_cmd = 0xff;
160 * Flip wide
162 if (dev->wide_idu != 0) {
163 tmport = workportu + 0x1b;
164 outb(0x01, tmport);
165 while ((inb(tmport) & 0x01) != 0x01) {
166 outb(0x01, tmport);
170 * Issue more commands
172 if (((dev->quhdu != dev->quendu) || (dev->last_cmd != 0xff)) && (dev->in_snd == 0)) {
173 send_s870(host);
176 * Done
178 dev->in_int = 0;
179 goto out;
182 if (i == 0x40) {
183 dev->last_cmd |= 0x40;
184 dev->in_int = 0;
185 goto out;
188 if (i == 0x21) {
189 if ((dev->last_cmd & 0xf0) != 0x40) {
190 dev->last_cmd = 0xff;
192 tmport -= 0x05;
193 adrcntu = 0;
194 ((unsigned char *) &adrcntu)[2] = inb(tmport++);
195 ((unsigned char *) &adrcntu)[1] = inb(tmport++);
196 ((unsigned char *) &adrcntu)[0] = inb(tmport);
197 k = dev->id[target_id].last_lenu;
198 k -= adrcntu;
199 dev->id[target_id].tran_lenu = k;
200 dev->id[target_id].last_lenu = adrcntu;
201 tmport -= 0x04;
202 outb(0x41, tmport);
203 tmport += 0x08;
204 outb(0x08, tmport);
205 dev->in_int = 0;
206 goto out;
208 if ((i == 0x80) || (i == 0x8f)) {
209 lun = 0;
210 tmport -= 0x07;
211 j = inb(tmport);
212 if (j == 0x44 || i == 0x80) {
213 tmport += 0x0d;
214 lun = inb(tmport) & 0x07;
215 } else {
216 if ((dev->last_cmd & 0xf0) != 0x40) {
217 dev->last_cmd = 0xff;
219 if (j == 0x41) {
220 tmport += 0x02;
221 adrcntu = 0;
222 ((unsigned char *) &adrcntu)[2] = inb(tmport++);
223 ((unsigned char *) &adrcntu)[1] = inb(tmport++);
224 ((unsigned char *) &adrcntu)[0] = inb(tmport);
225 k = dev->id[target_id].last_lenu;
226 k -= adrcntu;
227 dev->id[target_id].tran_lenu = k;
228 dev->id[target_id].last_lenu = adrcntu;
229 tmport += 0x04;
230 outb(0x08, tmport);
231 dev->in_int = 0;
232 goto out;
233 } else {
234 outb(0x46, tmport);
235 dev->id[target_id].dirctu = 0x00;
236 tmport += 0x02;
237 outb(0x00, tmport++);
238 outb(0x00, tmport++);
239 outb(0x00, tmport++);
240 tmport += 0x03;
241 outb(0x08, tmport);
242 dev->in_int = 0;
243 goto out;
246 if (dev->last_cmd != 0xff) {
247 dev->last_cmd |= 0x40;
249 tmport = workportu + 0x10;
250 outb(0x45, tmport);
251 tmport += 0x06;
252 target_id = inb(tmport);
254 * Remap wide identifiers
256 if ((target_id & 0x10) != 0) {
257 target_id = (target_id & 0x07) | 0x08;
258 } else {
259 target_id &= 0x07;
261 workrequ = dev->id[target_id].curr_req;
262 tmport = workportu + 0x0f;
263 outb(lun, tmport);
264 tmport += 0x02;
265 outb(dev->id[target_id].devspu, tmport++);
266 adrcntu = dev->id[target_id].tran_lenu;
267 k = dev->id[target_id].last_lenu;
268 outb(((unsigned char *) &k)[2], tmport++);
269 outb(((unsigned char *) &k)[1], tmport++);
270 outb(((unsigned char *) &k)[0], tmport++);
271 /* Remap wide */
272 j = target_id;
273 if (target_id > 7) {
274 j = (j & 0x07) | 0x40;
276 /* Add direction */
277 j |= dev->id[target_id].dirctu;
278 outb(j, tmport++);
279 outb(0x80, tmport);
281 /* enable 32 bit fifo transfer */
282 if (dev->deviceid != 0x8081) {
283 tmport = workportu + 0x3a;
284 if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
285 outb((unsigned char) ((inb(tmport) & 0xf3) | 0x08), tmport);
286 } else {
287 outb((unsigned char) (inb(tmport) & 0xf3), tmport);
289 } else {
290 tmport = workportu - 0x05;
291 if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
292 outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
293 } else {
294 outb((unsigned char) (inb(tmport) & 0x3f), tmport);
298 tmport = workportu + 0x1b;
299 j = 0;
300 id = 1;
301 id = id << target_id;
303 * Is this a wide device
305 if ((id & dev->wide_idu) != 0) {
306 j |= 0x01;
308 outb(j, tmport);
309 while ((inb(tmport) & 0x01) != j) {
310 outb(j, tmport);
313 if (dev->id[target_id].last_lenu == 0) {
314 tmport = workportu + 0x18;
315 outb(0x08, tmport);
316 dev->in_int = 0;
317 goto out;
319 prd = dev->id[target_id].prd_posu;
320 while (adrcntu != 0) {
321 id = ((unsigned short int *) (prd))[2];
322 if (id == 0) {
323 k = 0x10000;
324 } else {
325 k = id;
327 if (k > adrcntu) {
328 ((unsigned short int *) (prd))[2] = (unsigned short int)
329 (k - adrcntu);
330 ((unsigned long *) (prd))[0] += adrcntu;
331 adrcntu = 0;
332 dev->id[target_id].prd_posu = prd;
333 } else {
334 adrcntu -= k;
335 dev->id[target_id].prdaddru += 0x08;
336 prd += 0x08;
337 if (adrcntu == 0) {
338 dev->id[target_id].prd_posu = prd;
342 tmpcip = dev->pciport + 0x04;
343 outl(dev->id[target_id].prdaddru, tmpcip);
344 tmpcip -= 0x02;
345 outb(0x06, tmpcip);
346 outb(0x00, tmpcip);
347 tmpcip -= 0x02;
348 tmport = workportu + 0x18;
350 * Check transfer direction
352 if (dev->id[target_id].dirctu != 0) {
353 outb(0x08, tmport);
354 outb(0x01, tmpcip);
355 dev->in_int = 0;
356 goto out;
358 outb(0x08, tmport);
359 outb(0x09, tmpcip);
360 dev->in_int = 0;
361 goto out;
365 * Current scsi request on this target
368 workrequ = dev->id[target_id].curr_req;
370 if (i == 0x42) {
371 if ((dev->last_cmd & 0xf0) != 0x40) {
372 dev->last_cmd = 0xff;
374 errstus = 0x02;
375 workrequ->result = errstus;
376 goto go_42;
378 if (i == 0x16) {
379 if ((dev->last_cmd & 0xf0) != 0x40) {
380 dev->last_cmd = 0xff;
382 errstus = 0;
383 tmport -= 0x08;
384 errstus = inb(tmport);
385 workrequ->result = errstus;
386 go_42:
388 * Complete the command
391 if(workrequ->use_sg)
392 pci_unmap_sg(dev->pdev, (struct scatterlist *)workrequ->buffer, workrequ->use_sg, scsi_to_pci_dma_dir(workrequ->sc_data_direction));
393 else if(workrequ->request_bufflen && workrequ->sc_data_direction != SCSI_DATA_NONE)
394 pci_unmap_single(dev->pdev, workrequ->SCp.dma_handle, workrequ->request_bufflen, scsi_to_pci_dma_dir(workrequ->sc_data_direction));
395 spin_lock_irqsave(dev->host->host_lock, flags);
396 (*workrequ->scsi_done) (workrequ);
399 * Clear it off the queue
401 dev->id[target_id].curr_req = 0;
402 dev->working--;
403 spin_unlock_irqrestore(dev->host->host_lock, flags);
405 * Take it back wide
407 if (dev->wide_idu != 0) {
408 tmport = workportu + 0x1b;
409 outb(0x01, tmport);
410 while ((inb(tmport) & 0x01) != 0x01) {
411 outb(0x01, tmport);
415 * If there is stuff to send and nothing going then send it
417 if (((dev->last_cmd != 0xff) || (dev->quhdu != dev->quendu)) && (dev->in_snd == 0)) {
418 send_s870(host);
420 dev->in_int = 0;
421 goto out;
423 if ((dev->last_cmd & 0xf0) != 0x40) {
424 dev->last_cmd = 0xff;
426 if (i == 0x4f) {
427 i = 0x89;
429 i &= 0x0f;
430 if (i == 0x09) {
431 tmpcip = tmpcip + 4;
432 outl(dev->id[target_id].prdaddru, tmpcip);
433 tmpcip = tmpcip - 2;
434 outb(0x06, tmpcip);
435 outb(0x00, tmpcip);
436 tmpcip = tmpcip - 2;
437 tmport = workportu + 0x10;
438 outb(0x41, tmport);
439 dev->id[target_id].dirctu = 0x00;
440 tmport += 0x08;
441 outb(0x08, tmport);
442 outb(0x09, tmpcip);
443 dev->in_int = 0;
444 goto out;
446 if (i == 0x08) {
447 tmpcip = tmpcip + 4;
448 outl(dev->id[target_id].prdaddru, tmpcip);
449 tmpcip = tmpcip - 2;
450 outb(0x06, tmpcip);
451 outb(0x00, tmpcip);
452 tmpcip = tmpcip - 2;
453 tmport = workportu + 0x10;
454 outb(0x41, tmport);
455 tmport += 0x05;
456 outb((unsigned char) (inb(tmport) | 0x20), tmport);
457 dev->id[target_id].dirctu = 0x20;
458 tmport += 0x03;
459 outb(0x08, tmport);
460 outb(0x01, tmpcip);
461 dev->in_int = 0;
462 goto out;
464 tmport -= 0x07;
465 if (i == 0x0a) {
466 outb(0x30, tmport);
467 } else {
468 outb(0x46, tmport);
470 dev->id[target_id].dirctu = 0x00;
471 tmport += 0x02;
472 outb(0x00, tmport++);
473 outb(0x00, tmport++);
474 outb(0x00, tmport++);
475 tmport += 0x03;
476 outb(0x08, tmport);
477 dev->in_int = 0;
478 goto out;
479 } else {
480 // tmport = workportu + 0x17;
481 // inb(tmport);
482 // dev->working = 0;
483 dev->in_int = 0;
485 out:
486 return IRQ_HANDLED;
489 static int atp870u_queuecommand(Scsi_Cmnd * req_p, void (*done) (Scsi_Cmnd *))
491 unsigned long flags;
492 unsigned short int m;
493 unsigned int tmport;
494 struct Scsi_Host *host;
495 struct atp_unit *dev;
497 if (req_p->device->channel != 0) {
498 req_p->result = 0x00040000;
499 done(req_p);
500 return 0;
503 host = req_p->device->host;
504 dev = (struct atp_unit *)&host->hostdata;
506 m = 1;
507 m = m << req_p->device->id;
510 * Fake a timeout for missing targets
513 if ((m & dev->active_idu) == 0) {
514 req_p->result = 0x00040000;
515 done(req_p);
516 return 0;
518 if (done) {
519 req_p->scsi_done = done;
520 } else {
521 printk(KERN_WARNING "atp870u_queuecommand: done can't be NULL\n");
522 req_p->result = 0;
523 done(req_p);
524 return 0;
527 * Count new command
530 spin_lock_irqsave(host->host_lock, flags);
531 dev->quendu++;
532 if (dev->quendu >= qcnt) {
533 dev->quendu = 0;
536 * Check queue state
538 if (dev->quhdu == dev->quendu) {
539 if (dev->quendu == 0) {
540 dev->quendu = qcnt;
542 dev->quendu--;
543 req_p->result = 0x00020000;
544 spin_unlock_irqrestore(host->host_lock, flags);
545 done(req_p);
546 return 0;
548 dev->querequ[dev->quendu] = req_p;
549 tmport = dev->ioport + 0x1c;
550 spin_unlock_irqrestore(host->host_lock, flags);
551 if ((inb(tmport) == 0) && (dev->in_int == 0) && (dev->in_snd == 0)) {
552 send_s870(host);
554 return 0;
557 static void send_s870(struct Scsi_Host *host)
559 unsigned int tmport;
560 Scsi_Cmnd *workrequ;
561 unsigned long flags;
562 unsigned int i;
563 unsigned char j, target_id;
564 unsigned char *prd;
565 unsigned short int tmpcip, w;
566 unsigned long l;
567 dma_addr_t bttl;
568 unsigned int workportu;
569 struct scatterlist *sgpnt;
570 struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
571 int sg_count;
573 spin_lock_irqsave(host->host_lock, flags);
575 if (dev->in_snd != 0) {
576 spin_unlock_irqrestore(host->host_lock, flags);
577 return;
579 dev->in_snd = 1;
580 if ((dev->last_cmd != 0xff) && ((dev->last_cmd & 0x40) != 0)) {
581 dev->last_cmd &= 0x0f;
582 workrequ = dev->id[dev->last_cmd].curr_req;
583 if (workrequ != NULL) { /* check NULL pointer */
584 goto cmd_subp;
586 dev->last_cmd = 0xff;
587 if (dev->quhdu == dev->quendu) {
588 dev->in_snd = 0;
589 spin_unlock_irqrestore(dev->host->host_lock, flags);
590 return;
593 if ((dev->last_cmd != 0xff) && (dev->working != 0)) {
594 dev->in_snd = 0;
595 spin_unlock_irqrestore(dev->host->host_lock, flags);
596 return;
598 dev->working++;
599 j = dev->quhdu;
600 dev->quhdu++;
601 if (dev->quhdu >= qcnt) {
602 dev->quhdu = 0;
604 workrequ = dev->querequ[dev->quhdu];
605 if (dev->id[workrequ->device->id].curr_req == 0) {
606 dev->id[workrequ->device->id].curr_req = workrequ;
607 dev->last_cmd = workrequ->device->id;
608 goto cmd_subp;
610 dev->quhdu = j;
611 dev->working--;
612 dev->in_snd = 0;
613 spin_unlock_irqrestore(host->host_lock, flags);
614 return;
615 cmd_subp:
616 workportu = dev->ioport;
617 tmport = workportu + 0x1f;
618 if ((inb(tmport) & 0xb0) != 0) {
619 goto abortsnd;
621 tmport = workportu + 0x1c;
622 if (inb(tmport) == 0) {
623 goto oktosend;
625 abortsnd:
626 dev->last_cmd |= 0x40;
627 dev->in_snd = 0;
628 spin_unlock_irqrestore(dev->host->host_lock, flags);
629 return;
630 oktosend:
631 memcpy(&dev->ata_cdbu[0], &workrequ->cmnd[0], workrequ->cmd_len);
632 if (dev->ata_cdbu[0] == READ_CAPACITY) {
633 if (workrequ->request_bufflen > 8) {
634 workrequ->request_bufflen = 0x08;
637 if (dev->ata_cdbu[0] == 0x00) {
638 workrequ->request_bufflen = 0;
641 tmport = workportu + 0x1b;
642 j = 0;
643 target_id = workrequ->device->id;
646 * Wide ?
648 w = 1;
649 w = w << target_id;
650 if ((w & dev->wide_idu) != 0) {
651 j |= 0x01;
653 outb(j, tmport);
654 while ((inb(tmport) & 0x01) != j) {
655 outb(j, tmport);
659 * Write the command
662 tmport = workportu;
663 outb(workrequ->cmd_len, tmport++);
664 outb(0x2c, tmport++);
665 outb(0xcf, tmport++);
666 for (i = 0; i < workrequ->cmd_len; i++) {
667 outb(dev->ata_cdbu[i], tmport++);
669 tmport = workportu + 0x0f;
670 outb(workrequ->device->lun, tmport);
671 tmport += 0x02;
673 * Write the target
675 outb(dev->id[target_id].devspu, tmport++);
678 * Figure out the transfer size
680 if (workrequ->use_sg) {
681 l = 0;
682 sgpnt = (struct scatterlist *) workrequ->request_buffer;
683 sg_count = pci_map_sg(dev->pdev, sgpnt, workrequ->use_sg, scsi_to_pci_dma_dir(workrequ->sc_data_direction));
684 for (i = 0; i < workrequ->use_sg; i++) {
685 if (sgpnt[i].length == 0 || workrequ->use_sg > ATP870U_SCATTER) {
686 panic("Foooooooood fight!");
688 l += sgpnt[i].length;
690 } else if(workrequ->request_bufflen && workrequ->sc_data_direction != PCI_DMA_NONE) {
691 workrequ->SCp.dma_handle = pci_map_single(dev->pdev, workrequ->request_buffer, workrequ->request_bufflen, scsi_to_pci_dma_dir(workrequ->sc_data_direction));
692 l = workrequ->request_bufflen;
694 else l = 0;
696 * Write transfer size
698 outb((unsigned char) (((unsigned char *) (&l))[2]), tmport++);
699 outb((unsigned char) (((unsigned char *) (&l))[1]), tmport++);
700 outb((unsigned char) (((unsigned char *) (&l))[0]), tmport++);
701 j = target_id;
702 dev->id[j].last_lenu = l;
703 dev->id[j].tran_lenu = 0;
705 * Flip the wide bits
707 if ((j & 0x08) != 0) {
708 j = (j & 0x07) | 0x40;
711 * Check transfer direction
713 if (workrequ->sc_data_direction == SCSI_DATA_WRITE) {
714 outb((unsigned char) (j | 0x20), tmport++);
715 } else {
716 outb(j, tmport++);
718 outb((unsigned char) (inb(tmport) | 0x80), tmport);
719 outb(0x80, tmport);
720 tmport = workportu + 0x1c;
721 dev->id[target_id].dirctu = 0;
722 if (l == 0) {
723 if (inb(tmport) == 0) {
724 tmport = workportu + 0x18;
725 outb(0x08, tmport);
726 } else {
727 dev->last_cmd |= 0x40;
729 dev->in_snd = 0;
730 spin_unlock_irqrestore(host->host_lock, flags);
731 return;
733 tmpcip = dev->pciport;
734 prd = dev->id[target_id].prd_tableu;
735 dev->id[target_id].prd_posu = prd;
738 * Now write the request list. Either as scatter/gather or as
739 * a linear chain.
742 if (workrequ->use_sg) {
743 sgpnt = (struct scatterlist *) workrequ->request_buffer;
744 i = 0;
745 for (j = 0; j < workrequ->use_sg; j++) {
746 bttl = sg_dma_address(&sgpnt[j]);
747 l = sg_dma_len(&sgpnt[j]);
748 while (l > 0x10000) {
749 (u16) (((u16 *) (prd))[i + 3]) = 0x0000;
750 (u16) (((u16 *) (prd))[i + 2]) = 0x0000;
751 (u32) (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
752 l -= 0x10000;
753 bttl += 0x10000;
754 i += 0x04;
756 (u32) (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
757 (u16) (((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
758 (u16) (((u16 *) (prd))[i + 3]) = 0;
759 i += 0x04;
761 (u16) (((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000);
762 } else {
764 * For a linear request write a chain of blocks
766 bttl = workrequ->SCp.dma_handle;
767 l = workrequ->request_bufflen;
768 i = 0;
769 while (l > 0x10000) {
770 (u16) (((u16 *) (prd))[i + 3]) = 0x0000;
771 (u16) (((u16 *) (prd))[i + 2]) = 0x0000;
772 (u32) (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
773 l -= 0x10000;
774 bttl += 0x10000;
775 i += 0x04;
777 (u16) (((u16 *) (prd))[i + 3]) = cpu_to_le16(0x8000);
778 (u16) (((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
779 (u32) (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
781 tmpcip = tmpcip + 4;
782 dev->id[target_id].prdaddru = dev->id[target_id].prd_phys;
783 outl(dev->id[target_id].prd_phys, tmpcip);
784 tmpcip = tmpcip - 2;
785 outb(0x06, tmpcip);
786 outb(0x00, tmpcip);
787 tmpcip = tmpcip - 2;
789 if (dev->deviceid != 0x8081) {
790 tmport = workportu + 0x3a;
791 if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
792 outb((inb(tmport) & 0xf3) | 0x08, tmport);
793 } else {
794 outb(inb(tmport) & 0xf3, tmport);
796 } else {
797 tmport = workportu - 0x05;
798 if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
799 outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
800 } else {
801 outb((unsigned char) (inb(tmport) & 0x3f), tmport);
804 tmport = workportu + 0x1c;
806 if (workrequ->sc_data_direction == SCSI_DATA_WRITE) {
807 dev->id[target_id].dirctu = 0x20;
808 if (inb(tmport) == 0) {
809 tmport = workportu + 0x18;
810 outb(0x08, tmport);
811 outb(0x01, tmpcip);
812 } else {
813 dev->last_cmd |= 0x40;
815 dev->in_snd = 0;
816 spin_unlock_irqrestore(host->host_lock, flags);
817 return;
819 if (inb(tmport) == 0) {
820 tmport = workportu + 0x18;
821 outb(0x08, tmport);
822 outb(0x09, tmpcip);
823 } else {
824 dev->last_cmd |= 0x40;
826 dev->in_snd = 0;
827 spin_unlock_irqrestore(host->host_lock, flags);
828 return;
832 static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
834 unsigned int tmport;
835 unsigned short int i, k;
836 unsigned char j;
838 tmport = dev->ioport + 0x1c;
839 outw(*val, tmport);
840 FUN_D7:
841 for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */
842 k = inw(tmport);
843 j = (unsigned char) (k >> 8);
844 if ((k & 0x8000) != 0) { /* DB7 all release? */
845 goto FUN_D7;
848 *val |= 0x4000; /* assert DB6 */
849 outw(*val, tmport);
850 *val &= 0xdfff; /* assert DB5 */
851 outw(*val, tmport);
852 FUN_D5:
853 for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */
854 if ((inw(tmport) & 0x2000) != 0) { /* DB5 all release? */
855 goto FUN_D5;
858 *val |= 0x8000; /* no DB4-0, assert DB7 */
859 *val &= 0xe0ff;
860 outw(*val, tmport);
861 *val &= 0xbfff; /* release DB6 */
862 outw(*val, tmport);
863 FUN_D6:
864 for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */
865 if ((inw(tmport) & 0x4000) != 0) { /* DB6 all release? */
866 goto FUN_D6;
870 return j;
873 static void tscam(struct Scsi_Host *host)
876 unsigned int tmport;
877 unsigned char i, j, k;
878 unsigned long n;
879 unsigned short int m, assignid_map, val;
880 unsigned char mbuf[33], quintet[2];
881 struct atp_unit *dev = (struct atp_unit *)host->hostdata;
882 static unsigned char g2q_tab[8] = {
883 0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27
886 /* I can't believe we need this before we've even done anything. Remove it
887 * and see if anyone bitches.
888 for (i = 0; i < 0x10; i++) {
889 udelay(0xffff);
893 tmport = dev->ioport + 1;
894 outb(0x08, tmport++);
895 outb(0x7f, tmport);
896 tmport = dev->ioport + 0x11;
897 outb(0x20, tmport);
899 if ((dev->scam_on & 0x40) == 0) {
900 return;
902 m = 1;
903 m <<= dev->host_idu;
904 j = 16;
905 if (dev->chip_veru < 4) {
906 m |= 0xff00;
907 j = 8;
909 assignid_map = m;
910 tmport = dev->ioport + 0x02;
911 outb(0x02, tmport++); /* 2*2=4ms,3EH 2/32*3E=3.9ms */
912 outb(0, tmport++);
913 outb(0, tmport++);
914 outb(0, tmport++);
915 outb(0, tmport++);
916 outb(0, tmport++);
917 outb(0, tmport++);
919 for (i = 0; i < j; i++) {
920 m = 1;
921 m = m << i;
922 if ((m & assignid_map) != 0) {
923 continue;
925 tmport = dev->ioport + 0x0f;
926 outb(0, tmport++);
927 tmport += 0x02;
928 outb(0, tmport++);
929 outb(0, tmport++);
930 outb(0, tmport++);
931 if (i > 7) {
932 k = (i & 0x07) | 0x40;
933 } else {
934 k = i;
936 outb(k, tmport++);
937 tmport = dev->ioport + 0x1b;
938 if (dev->chip_veru == 4) {
939 outb(0x01, tmport);
940 } else {
941 outb(0x00, tmport);
943 wait_rdyok:
944 tmport = dev->ioport + 0x18;
945 outb(0x09, tmport);
946 tmport += 0x07;
948 while ((inb(tmport) & 0x80) == 0x00);
949 tmport -= 0x08;
950 k = inb(tmport);
951 if (k != 0x16) {
952 if ((k == 0x85) || (k == 0x42)) {
953 continue;
955 tmport = dev->ioport + 0x10;
956 outb(0x41, tmport);
957 goto wait_rdyok;
959 assignid_map |= m;
962 tmport = dev->ioport + 0x02;
963 outb(0x7f, tmport);
964 tmport = dev->ioport + 0x1b;
965 outb(0x02, tmport);
967 outb(0, 0x80);
969 val = 0x0080; /* bsy */
970 tmport = dev->ioport + 0x1c;
971 outw(val, tmport);
972 val |= 0x0040; /* sel */
973 outw(val, tmport);
974 val |= 0x0004; /* msg */
975 outw(val, tmport);
976 inb(0x80); /* 2 deskew delay(45ns*2=90ns) */
977 val &= 0x007f; /* no bsy */
978 outw(val, tmport);
979 mdelay(128);
980 val &= 0x00fb; /* after 1ms no msg */
981 outw(val, tmport);
982 wait_nomsg:
983 if ((inb(tmport) & 0x04) != 0) {
984 goto wait_nomsg;
986 outb(1, 0x80);
987 udelay(100);
988 for (n = 0; n < 0x30000; n++) {
989 if ((inb(tmport) & 0x80) != 0) { /* bsy ? */
990 goto wait_io;
993 goto TCM_SYNC;
994 wait_io:
995 for (n = 0; n < 0x30000; n++) {
996 if ((inb(tmport) & 0x81) == 0x0081) {
997 goto wait_io1;
1000 goto TCM_SYNC;
1001 wait_io1:
1002 inb(0x80);
1003 val |= 0x8003; /* io,cd,db7 */
1004 outw(val, tmport);
1005 inb(0x80);
1006 val &= 0x00bf; /* no sel */
1007 outw(val, tmport);
1008 outb(2, 0x80);
1009 TCM_SYNC:
1010 udelay(0x800);
1011 if ((inb(tmport) & 0x80) == 0x00) { /* bsy ? */
1012 outw(0, tmport--);
1013 outb(0, tmport);
1014 tmport = dev->ioport + 0x15;
1015 outb(0, tmport);
1016 tmport += 0x03;
1017 outb(0x09, tmport);
1018 tmport += 0x07;
1019 while ((inb(tmport) & 0x80) == 0);
1020 tmport -= 0x08;
1021 inb(tmport);
1022 return;
1024 val &= 0x00ff; /* synchronization */
1025 val |= 0x3f00;
1026 fun_scam(dev, &val);
1027 outb(3, 0x80);
1028 val &= 0x00ff; /* isolation */
1029 val |= 0x2000;
1030 fun_scam(dev, &val);
1031 outb(4, 0x80);
1032 i = 8;
1033 j = 0;
1034 TCM_ID:
1035 if ((inw(tmport) & 0x2000) == 0) {
1036 goto TCM_ID;
1038 outb(5, 0x80);
1039 val &= 0x00ff; /* get ID_STRING */
1040 val |= 0x2000;
1041 k = fun_scam(dev, &val);
1042 if ((k & 0x03) == 0) {
1043 goto TCM_5;
1045 mbuf[j] <<= 0x01;
1046 mbuf[j] &= 0xfe;
1047 if ((k & 0x02) != 0) {
1048 mbuf[j] |= 0x01;
1050 i--;
1051 if (i > 0) {
1052 goto TCM_ID;
1054 j++;
1055 i = 8;
1056 goto TCM_ID;
1058 TCM_5: /* isolation complete.. */
1059 /* mbuf[32]=0;
1060 printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
1061 i = 15;
1062 j = mbuf[0];
1063 if ((j & 0x20) != 0) { /* bit5=1:ID upto 7 */
1064 i = 7;
1066 if ((j & 0x06) == 0) { /* IDvalid? */
1067 goto G2Q5;
1069 k = mbuf[1];
1070 small_id:
1071 m = 1;
1072 m <<= k;
1073 if ((m & assignid_map) == 0) {
1074 goto G2Q_QUIN;
1076 if (k > 0) {
1077 k--;
1078 goto small_id;
1080 G2Q5: /* srch from max acceptable ID# */
1081 k = i; /* max acceptable ID# */
1082 G2Q_LP:
1083 m = 1;
1084 m <<= k;
1085 if ((m & assignid_map) == 0) {
1086 goto G2Q_QUIN;
1088 if (k > 0) {
1089 k--;
1090 goto G2Q_LP;
1092 G2Q_QUIN: /* k=binID#, */
1093 assignid_map |= m;
1094 if (k < 8) {
1095 quintet[0] = 0x38; /* 1st dft ID<8 */
1096 } else {
1097 quintet[0] = 0x31; /* 1st ID>=8 */
1099 k &= 0x07;
1100 quintet[1] = g2q_tab[k];
1102 val &= 0x00ff; /* AssignID 1stQuintet,AH=001xxxxx */
1103 m = quintet[0] << 8;
1104 val |= m;
1105 fun_scam(dev, &val);
1106 val &= 0x00ff; /* AssignID 2ndQuintet,AH=001xxxxx */
1107 m = quintet[1] << 8;
1108 val |= m;
1109 fun_scam(dev, &val);
1111 goto TCM_SYNC;
1115 void is870(struct Scsi_Host *host, unsigned int wkport)
1117 unsigned int tmport;
1118 unsigned char i, j, k, rmb, n;
1119 unsigned short int m;
1120 static unsigned char mbuf[512];
1121 static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
1122 static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
1123 static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1124 static unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0c, 0x0e };
1125 static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
1126 static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
1127 struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
1129 sync_idu = 0;
1130 tmport = wkport + 0x3a;
1131 outb((unsigned char) (inb(tmport) | 0x10), tmport);
1133 for (i = 0; i < 16; i++) {
1134 if ((dev->chip_veru != 4) && (i > 7)) {
1135 break;
1137 m = 1;
1138 m = m << i;
1139 if ((m & dev->active_idu) != 0) {
1140 continue;
1142 if (i == dev->host_idu) {
1143 printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_idu);
1144 continue;
1146 tmport = wkport + 0x1b;
1147 if (dev->chip_veru == 4) {
1148 outb(0x01, tmport);
1149 } else {
1150 outb(0x00, tmport);
1152 tmport = wkport + 1;
1153 outb(0x08, tmport++);
1154 outb(0x7f, tmport++);
1155 outb(satn[0], tmport++);
1156 outb(satn[1], tmport++);
1157 outb(satn[2], tmport++);
1158 outb(satn[3], tmport++);
1159 outb(satn[4], tmport++);
1160 outb(satn[5], tmport++);
1161 tmport += 0x06;
1162 outb(0, tmport);
1163 tmport += 0x02;
1164 outb(dev->id[i].devspu, tmport++);
1165 outb(0, tmport++);
1166 outb(satn[6], tmport++);
1167 outb(satn[7], tmport++);
1168 j = i;
1169 if ((j & 0x08) != 0) {
1170 j = (j & 0x07) | 0x40;
1172 outb(j, tmport);
1173 tmport += 0x03;
1174 outb(satn[8], tmport);
1175 tmport += 0x07;
1177 while ((inb(tmport) & 0x80) == 0x00);
1178 tmport -= 0x08;
1179 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1180 continue;
1182 while (inb(tmport) != 0x8e);
1183 dev->active_idu |= m;
1185 tmport = wkport + 0x10;
1186 outb(0x30, tmport);
1187 tmport = wkport + 0x04;
1188 outb(0x00, tmport);
1190 phase_cmd:
1191 tmport = wkport + 0x18;
1192 outb(0x08, tmport);
1193 tmport += 0x07;
1194 while ((inb(tmport) & 0x80) == 0x00);
1195 tmport -= 0x08;
1196 j = inb(tmport);
1197 if (j != 0x16) {
1198 tmport = wkport + 0x10;
1199 outb(0x41, tmport);
1200 goto phase_cmd;
1202 sel_ok:
1203 tmport = wkport + 3;
1204 outb(inqd[0], tmport++);
1205 outb(inqd[1], tmport++);
1206 outb(inqd[2], tmport++);
1207 outb(inqd[3], tmport++);
1208 outb(inqd[4], tmport++);
1209 outb(inqd[5], tmport);
1210 tmport += 0x07;
1211 outb(0, tmport);
1212 tmport += 0x02;
1213 outb(dev->id[i].devspu, tmport++);
1214 outb(0, tmport++);
1215 outb(inqd[6], tmport++);
1216 outb(inqd[7], tmport++);
1217 tmport += 0x03;
1218 outb(inqd[8], tmport);
1219 tmport += 0x07;
1220 while ((inb(tmport) & 0x80) == 0x00);
1221 tmport -= 0x08;
1222 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1223 continue;
1225 while (inb(tmport) != 0x8e);
1226 tmport = wkport + 0x1b;
1227 if (dev->chip_veru == 4) {
1228 outb(0x00, tmport);
1230 tmport = wkport + 0x18;
1231 outb(0x08, tmport);
1232 tmport += 0x07;
1233 j = 0;
1234 rd_inq_data:
1235 k = inb(tmport);
1236 if ((k & 0x01) != 0) {
1237 tmport -= 0x06;
1238 mbuf[j++] = inb(tmport);
1239 tmport += 0x06;
1240 goto rd_inq_data;
1242 if ((k & 0x80) == 0) {
1243 goto rd_inq_data;
1245 tmport -= 0x08;
1246 j = inb(tmport);
1247 if (j == 0x16) {
1248 goto inq_ok;
1250 tmport = wkport + 0x10;
1251 outb(0x46, tmport);
1252 tmport += 0x02;
1253 outb(0, tmport++);
1254 outb(0, tmport++);
1255 outb(0, tmport++);
1256 tmport += 0x03;
1257 outb(0x08, tmport);
1258 tmport += 0x07;
1259 while ((inb(tmport) & 0x80) == 0x00);
1260 tmport -= 0x08;
1261 if (inb(tmport) != 0x16) {
1262 goto sel_ok;
1264 inq_ok:
1265 mbuf[36] = 0;
1266 printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]);
1267 dev->id[i].devtypeu = mbuf[0];
1268 rmb = mbuf[1];
1269 n = mbuf[7];
1270 if (dev->chip_veru != 4) {
1271 goto not_wide;
1273 if ((mbuf[7] & 0x60) == 0) {
1274 goto not_wide;
1276 if ((dev->global_map & 0x20) == 0) {
1277 goto not_wide;
1279 tmport = wkport + 0x1b;
1280 outb(0x01, tmport);
1281 tmport = wkport + 3;
1282 outb(satn[0], tmport++);
1283 outb(satn[1], tmport++);
1284 outb(satn[2], tmport++);
1285 outb(satn[3], tmport++);
1286 outb(satn[4], tmport++);
1287 outb(satn[5], tmport++);
1288 tmport += 0x06;
1289 outb(0, tmport);
1290 tmport += 0x02;
1291 outb(dev->id[i].devspu, tmport++);
1292 outb(0, tmport++);
1293 outb(satn[6], tmport++);
1294 outb(satn[7], tmport++);
1295 tmport += 0x03;
1296 outb(satn[8], tmport);
1297 tmport += 0x07;
1299 while ((inb(tmport) & 0x80) == 0x00);
1300 tmport -= 0x08;
1301 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1302 continue;
1304 while (inb(tmport) != 0x8e);
1305 try_wide:
1306 j = 0;
1307 tmport = wkport + 0x14;
1308 outb(0x05, tmport);
1309 tmport += 0x04;
1310 outb(0x20, tmport);
1311 tmport += 0x07;
1313 while ((inb(tmport) & 0x80) == 0) {
1314 if ((inb(tmport) & 0x01) != 0) {
1315 tmport -= 0x06;
1316 outb(wide[j++], tmport);
1317 tmport += 0x06;
1320 tmport -= 0x08;
1321 while ((inb(tmport) & 0x80) == 0x00);
1322 j = inb(tmport) & 0x0f;
1323 if (j == 0x0f) {
1324 goto widep_in;
1326 if (j == 0x0a) {
1327 goto widep_cmd;
1329 if (j == 0x0e) {
1330 goto try_wide;
1332 continue;
1333 widep_out:
1334 tmport = wkport + 0x18;
1335 outb(0x20, tmport);
1336 tmport += 0x07;
1337 while ((inb(tmport) & 0x80) == 0) {
1338 if ((inb(tmport) & 0x01) != 0) {
1339 tmport -= 0x06;
1340 outb(0, tmport);
1341 tmport += 0x06;
1344 tmport -= 0x08;
1345 j = inb(tmport) & 0x0f;
1346 if (j == 0x0f) {
1347 goto widep_in;
1349 if (j == 0x0a) {
1350 goto widep_cmd;
1352 if (j == 0x0e) {
1353 goto widep_out;
1355 continue;
1356 widep_in:
1357 tmport = wkport + 0x14;
1358 outb(0xff, tmport);
1359 tmport += 0x04;
1360 outb(0x20, tmport);
1361 tmport += 0x07;
1362 k = 0;
1363 widep_in1:
1364 j = inb(tmport);
1365 if ((j & 0x01) != 0) {
1366 tmport -= 0x06;
1367 mbuf[k++] = inb(tmport);
1368 tmport += 0x06;
1369 goto widep_in1;
1371 if ((j & 0x80) == 0x00) {
1372 goto widep_in1;
1374 tmport -= 0x08;
1375 j = inb(tmport) & 0x0f;
1376 if (j == 0x0f) {
1377 goto widep_in;
1379 if (j == 0x0a) {
1380 goto widep_cmd;
1382 if (j == 0x0e) {
1383 goto widep_out;
1385 continue;
1386 widep_cmd:
1387 tmport = wkport + 0x10;
1388 outb(0x30, tmport);
1389 tmport = wkport + 0x14;
1390 outb(0x00, tmport);
1391 tmport += 0x04;
1392 outb(0x08, tmport);
1393 tmport += 0x07;
1394 while ((inb(tmport) & 0x80) == 0x00);
1395 tmport -= 0x08;
1396 j = inb(tmport);
1397 if (j != 0x16) {
1398 if (j == 0x4e) {
1399 goto widep_out;
1401 continue;
1403 if (mbuf[0] != 0x01) {
1404 goto not_wide;
1406 if (mbuf[1] != 0x02) {
1407 goto not_wide;
1409 if (mbuf[2] != 0x03) {
1410 goto not_wide;
1412 if (mbuf[3] != 0x01) {
1413 goto not_wide;
1415 m = 1;
1416 m = m << i;
1417 dev->wide_idu |= m;
1418 not_wide:
1419 if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) || ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0))) {
1420 goto set_sync;
1422 continue;
1423 set_sync:
1424 tmport = wkport + 0x1b;
1425 j = 0;
1426 if ((m & dev->wide_idu) != 0) {
1427 j |= 0x01;
1429 outb(j, tmport);
1430 tmport = wkport + 3;
1431 outb(satn[0], tmport++);
1432 outb(satn[1], tmport++);
1433 outb(satn[2], tmport++);
1434 outb(satn[3], tmport++);
1435 outb(satn[4], tmport++);
1436 outb(satn[5], tmport++);
1437 tmport += 0x06;
1438 outb(0, tmport);
1439 tmport += 0x02;
1440 outb(dev->id[i].devspu, tmport++);
1441 outb(0, tmport++);
1442 outb(satn[6], tmport++);
1443 outb(satn[7], tmport++);
1444 tmport += 0x03;
1445 outb(satn[8], tmport);
1446 tmport += 0x07;
1448 while ((inb(tmport) & 0x80) == 0x00);
1449 tmport -= 0x08;
1450 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1451 continue;
1453 while (inb(tmport) != 0x8e);
1454 try_sync:
1455 j = 0;
1456 tmport = wkport + 0x14;
1457 outb(0x06, tmport);
1458 tmport += 0x04;
1459 outb(0x20, tmport);
1460 tmport += 0x07;
1462 while ((inb(tmport) & 0x80) == 0) {
1463 if ((inb(tmport) & 0x01) != 0) {
1464 tmport -= 0x06;
1465 if ((m & dev->wide_idu) != 0) {
1466 outb(synw[j++], tmport);
1467 } else {
1468 if ((m & dev->ultra_map) != 0) {
1469 outb(synu[j++], tmport);
1470 } else {
1471 outb(synn[j++], tmport);
1474 tmport += 0x06;
1477 tmport -= 0x08;
1478 while ((inb(tmport) & 0x80) == 0x00);
1479 j = inb(tmport) & 0x0f;
1480 if (j == 0x0f) {
1481 goto phase_ins;
1483 if (j == 0x0a) {
1484 goto phase_cmds;
1486 if (j == 0x0e) {
1487 goto try_sync;
1489 continue;
1490 phase_outs:
1491 tmport = wkport + 0x18;
1492 outb(0x20, tmport);
1493 tmport += 0x07;
1494 while ((inb(tmport) & 0x80) == 0x00) {
1495 if ((inb(tmport) & 0x01) != 0x00) {
1496 tmport -= 0x06;
1497 outb(0x00, tmport);
1498 tmport += 0x06;
1501 tmport -= 0x08;
1502 j = inb(tmport);
1503 if (j == 0x85) {
1504 goto tar_dcons;
1506 j &= 0x0f;
1507 if (j == 0x0f) {
1508 goto phase_ins;
1510 if (j == 0x0a) {
1511 goto phase_cmds;
1513 if (j == 0x0e) {
1514 goto phase_outs;
1516 continue;
1517 phase_ins:
1518 tmport = wkport + 0x14;
1519 outb(0xff, tmport);
1520 tmport += 0x04;
1521 outb(0x20, tmport);
1522 tmport += 0x07;
1523 k = 0;
1524 phase_ins1:
1525 j = inb(tmport);
1526 if ((j & 0x01) != 0x00) {
1527 tmport -= 0x06;
1528 mbuf[k++] = inb(tmport);
1529 tmport += 0x06;
1530 goto phase_ins1;
1532 if ((j & 0x80) == 0x00) {
1533 goto phase_ins1;
1535 tmport -= 0x08;
1536 while ((inb(tmport) & 0x80) == 0x00);
1537 j = inb(tmport);
1538 if (j == 0x85) {
1539 goto tar_dcons;
1541 j &= 0x0f;
1542 if (j == 0x0f) {
1543 goto phase_ins;
1545 if (j == 0x0a) {
1546 goto phase_cmds;
1548 if (j == 0x0e) {
1549 goto phase_outs;
1551 continue;
1552 phase_cmds:
1553 tmport = wkport + 0x10;
1554 outb(0x30, tmport);
1555 tar_dcons:
1556 tmport = wkport + 0x14;
1557 outb(0x00, tmport);
1558 tmport += 0x04;
1559 outb(0x08, tmport);
1560 tmport += 0x07;
1561 while ((inb(tmport) & 0x80) == 0x00);
1562 tmport -= 0x08;
1563 j = inb(tmport);
1564 if (j != 0x16) {
1565 continue;
1567 if (mbuf[0] != 0x01) {
1568 continue;
1570 if (mbuf[1] != 0x03) {
1571 continue;
1573 if (mbuf[4] == 0x00) {
1574 continue;
1576 if (mbuf[3] > 0x64) {
1577 continue;
1579 if (mbuf[4] > 0x0c) {
1580 mbuf[4] = 0x0c;
1582 dev->id[i].devspu = mbuf[4];
1583 if ((mbuf[3] < 0x0d) && (rmb == 0)) {
1584 j = 0xa0;
1585 goto set_syn_ok;
1587 if (mbuf[3] < 0x1a) {
1588 j = 0x20;
1589 goto set_syn_ok;
1591 if (mbuf[3] < 0x33) {
1592 j = 0x40;
1593 goto set_syn_ok;
1595 if (mbuf[3] < 0x4c) {
1596 j = 0x50;
1597 goto set_syn_ok;
1599 j = 0x60;
1600 set_syn_ok:
1601 dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j;
1603 tmport = wkport + 0x3a;
1604 outb((unsigned char) (inb(tmport) & 0xef), tmport);
1607 static void is880(struct Scsi_Host *host, unsigned int wkport)
1609 unsigned int tmport;
1610 unsigned char i, j, k, rmb, n, lvdmode;
1611 unsigned short int m;
1612 static unsigned char mbuf[512];
1613 static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
1614 static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
1615 static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1616 unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
1617 static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1618 unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
1619 static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
1620 static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 };
1621 struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
1623 sync_idu = 0;
1624 lvdmode = inb(wkport + 0x3f) & 0x40;
1626 for (i = 0; i < 16; i++) {
1627 m = 1;
1628 m = m << i;
1629 if ((m & dev->active_idu) != 0) {
1630 continue;
1632 if (i == dev->host_idu) {
1633 printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_idu);
1634 continue;
1636 tmport = wkport + 0x5b;
1637 outb(0x01, tmport);
1638 tmport = wkport + 0x41;
1639 outb(0x08, tmport++);
1640 outb(0x7f, tmport++);
1641 outb(satn[0], tmport++);
1642 outb(satn[1], tmport++);
1643 outb(satn[2], tmport++);
1644 outb(satn[3], tmport++);
1645 outb(satn[4], tmport++);
1646 outb(satn[5], tmport++);
1647 tmport += 0x06;
1648 outb(0, tmport);
1649 tmport += 0x02;
1650 outb(dev->id[i].devspu, tmport++);
1651 outb(0, tmport++);
1652 outb(satn[6], tmport++);
1653 outb(satn[7], tmport++);
1654 j = i;
1655 if ((j & 0x08) != 0) {
1656 j = (j & 0x07) | 0x40;
1658 outb(j, tmport);
1659 tmport += 0x03;
1660 outb(satn[8], tmport);
1661 tmport += 0x07;
1663 while ((inb(tmport) & 0x80) == 0x00);
1664 tmport -= 0x08;
1665 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1666 continue;
1668 while (inb(tmport) != 0x8e);
1669 dev->active_idu |= m;
1671 tmport = wkport + 0x50;
1672 outb(0x30, tmport);
1673 tmport = wkport + 0x54;
1674 outb(0x00, tmport);
1676 phase_cmd:
1677 tmport = wkport + 0x58;
1678 outb(0x08, tmport);
1679 tmport += 0x07;
1680 while ((inb(tmport) & 0x80) == 0x00);
1681 tmport -= 0x08;
1682 j = inb(tmport);
1683 if (j != 0x16) {
1684 tmport = wkport + 0x50;
1685 outb(0x41, tmport);
1686 goto phase_cmd;
1688 sel_ok:
1689 tmport = wkport + 0x43;
1690 outb(inqd[0], tmport++);
1691 outb(inqd[1], tmport++);
1692 outb(inqd[2], tmport++);
1693 outb(inqd[3], tmport++);
1694 outb(inqd[4], tmport++);
1695 outb(inqd[5], tmport);
1696 tmport += 0x07;
1697 outb(0, tmport);
1698 tmport += 0x02;
1699 outb(dev->id[i].devspu, tmport++);
1700 outb(0, tmport++);
1701 outb(inqd[6], tmport++);
1702 outb(inqd[7], tmport++);
1703 tmport += 0x03;
1704 outb(inqd[8], tmport);
1705 tmport += 0x07;
1706 while ((inb(tmport) & 0x80) == 0x00);
1707 tmport -= 0x08;
1708 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1709 continue;
1711 while (inb(tmport) != 0x8e);
1712 tmport = wkport + 0x5b;
1713 outb(0x00, tmport);
1714 tmport = wkport + 0x58;
1715 outb(0x08, tmport);
1716 tmport += 0x07;
1717 j = 0;
1718 rd_inq_data:
1719 k = inb(tmport);
1720 if ((k & 0x01) != 0) {
1721 tmport -= 0x06;
1722 mbuf[j++] = inb(tmport);
1723 tmport += 0x06;
1724 goto rd_inq_data;
1726 if ((k & 0x80) == 0) {
1727 goto rd_inq_data;
1729 tmport -= 0x08;
1730 j = inb(tmport);
1731 if (j == 0x16) {
1732 goto inq_ok;
1734 tmport = wkport + 0x50;
1735 outb(0x46, tmport);
1736 tmport += 0x02;
1737 outb(0, tmport++);
1738 outb(0, tmport++);
1739 outb(0, tmport++);
1740 tmport += 0x03;
1741 outb(0x08, tmport);
1742 tmport += 0x07;
1743 while ((inb(tmport) & 0x80) == 0x00);
1744 tmport -= 0x08;
1745 if (inb(tmport) != 0x16) {
1746 goto sel_ok;
1748 inq_ok:
1749 mbuf[36] = 0;
1750 printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]);
1751 dev->id[i].devtypeu = mbuf[0];
1752 rmb = mbuf[1];
1753 n = mbuf[7];
1754 if ((mbuf[7] & 0x60) == 0) {
1755 goto not_wide;
1757 if ((i < 8) && ((dev->global_map & 0x20) == 0)) {
1758 goto not_wide;
1760 if (lvdmode == 0) {
1761 goto chg_wide;
1763 if (dev->sp[i] != 0x04) // force u2
1765 goto chg_wide;
1768 tmport = wkport + 0x5b;
1769 outb(0x01, tmport);
1770 tmport = wkport + 0x43;
1771 outb(satn[0], tmport++);
1772 outb(satn[1], tmport++);
1773 outb(satn[2], tmport++);
1774 outb(satn[3], tmport++);
1775 outb(satn[4], tmport++);
1776 outb(satn[5], tmport++);
1777 tmport += 0x06;
1778 outb(0, tmport);
1779 tmport += 0x02;
1780 outb(dev->id[i].devspu, tmport++);
1781 outb(0, tmport++);
1782 outb(satn[6], tmport++);
1783 outb(satn[7], tmport++);
1784 tmport += 0x03;
1785 outb(satn[8], tmport);
1786 tmport += 0x07;
1788 while ((inb(tmport) & 0x80) == 0x00);
1789 tmport -= 0x08;
1790 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1791 continue;
1793 while (inb(tmport) != 0x8e);
1794 try_u3:
1795 j = 0;
1796 tmport = wkport + 0x54;
1797 outb(0x09, tmport);
1798 tmport += 0x04;
1799 outb(0x20, tmport);
1800 tmport += 0x07;
1802 while ((inb(tmport) & 0x80) == 0) {
1803 if ((inb(tmport) & 0x01) != 0) {
1804 tmport -= 0x06;
1805 outb(u3[j++], tmport);
1806 tmport += 0x06;
1809 tmport -= 0x08;
1810 while ((inb(tmport) & 0x80) == 0x00);
1811 j = inb(tmport) & 0x0f;
1812 if (j == 0x0f) {
1813 goto u3p_in;
1815 if (j == 0x0a) {
1816 goto u3p_cmd;
1818 if (j == 0x0e) {
1819 goto try_u3;
1821 continue;
1822 u3p_out:
1823 tmport = wkport + 0x58;
1824 outb(0x20, tmport);
1825 tmport += 0x07;
1826 while ((inb(tmport) & 0x80) == 0) {
1827 if ((inb(tmport) & 0x01) != 0) {
1828 tmport -= 0x06;
1829 outb(0, tmport);
1830 tmport += 0x06;
1833 tmport -= 0x08;
1834 j = inb(tmport) & 0x0f;
1835 if (j == 0x0f) {
1836 goto u3p_in;
1838 if (j == 0x0a) {
1839 goto u3p_cmd;
1841 if (j == 0x0e) {
1842 goto u3p_out;
1844 continue;
1845 u3p_in:
1846 tmport = wkport + 0x54;
1847 outb(0x09, tmport);
1848 tmport += 0x04;
1849 outb(0x20, tmport);
1850 tmport += 0x07;
1851 k = 0;
1852 u3p_in1:
1853 j = inb(tmport);
1854 if ((j & 0x01) != 0) {
1855 tmport -= 0x06;
1856 mbuf[k++] = inb(tmport);
1857 tmport += 0x06;
1858 goto u3p_in1;
1860 if ((j & 0x80) == 0x00) {
1861 goto u3p_in1;
1863 tmport -= 0x08;
1864 j = inb(tmport) & 0x0f;
1865 if (j == 0x0f) {
1866 goto u3p_in;
1868 if (j == 0x0a) {
1869 goto u3p_cmd;
1871 if (j == 0x0e) {
1872 goto u3p_out;
1874 continue;
1875 u3p_cmd:
1876 tmport = wkport + 0x50;
1877 outb(0x30, tmport);
1878 tmport = wkport + 0x54;
1879 outb(0x00, tmport);
1880 tmport += 0x04;
1881 outb(0x08, tmport);
1882 tmport += 0x07;
1883 while ((inb(tmport) & 0x80) == 0x00);
1884 tmport -= 0x08;
1885 j = inb(tmport);
1886 if (j != 0x16) {
1887 if (j == 0x4e) {
1888 goto u3p_out;
1890 continue;
1892 if (mbuf[0] != 0x01) {
1893 goto chg_wide;
1895 if (mbuf[1] != 0x06) {
1896 goto chg_wide;
1898 if (mbuf[2] != 0x04) {
1899 goto chg_wide;
1901 if (mbuf[3] == 0x09) {
1902 m = 1;
1903 m = m << i;
1904 dev->wide_idu |= m;
1905 dev->id[i].devspu = 0xce;
1906 continue;
1908 chg_wide:
1909 tmport = wkport + 0x5b;
1910 outb(0x01, tmport);
1911 tmport = wkport + 0x43;
1912 outb(satn[0], tmport++);
1913 outb(satn[1], tmport++);
1914 outb(satn[2], tmport++);
1915 outb(satn[3], tmport++);
1916 outb(satn[4], tmport++);
1917 outb(satn[5], tmport++);
1918 tmport += 0x06;
1919 outb(0, tmport);
1920 tmport += 0x02;
1921 outb(dev->id[i].devspu, tmport++);
1922 outb(0, tmport++);
1923 outb(satn[6], tmport++);
1924 outb(satn[7], tmport++);
1925 tmport += 0x03;
1926 outb(satn[8], tmport);
1927 tmport += 0x07;
1929 while ((inb(tmport) & 0x80) == 0x00);
1930 tmport -= 0x08;
1931 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1932 continue;
1934 while (inb(tmport) != 0x8e);
1935 try_wide:
1936 j = 0;
1937 tmport = wkport + 0x54;
1938 outb(0x05, tmport);
1939 tmport += 0x04;
1940 outb(0x20, tmport);
1941 tmport += 0x07;
1943 while ((inb(tmport) & 0x80) == 0) {
1944 if ((inb(tmport) & 0x01) != 0) {
1945 tmport -= 0x06;
1946 outb(wide[j++], tmport);
1947 tmport += 0x06;
1950 tmport -= 0x08;
1951 while ((inb(tmport) & 0x80) == 0x00);
1952 j = inb(tmport) & 0x0f;
1953 if (j == 0x0f) {
1954 goto widep_in;
1956 if (j == 0x0a) {
1957 goto widep_cmd;
1959 if (j == 0x0e) {
1960 goto try_wide;
1962 continue;
1963 widep_out:
1964 tmport = wkport + 0x58;
1965 outb(0x20, tmport);
1966 tmport += 0x07;
1967 while ((inb(tmport) & 0x80) == 0) {
1968 if ((inb(tmport) & 0x01) != 0) {
1969 tmport -= 0x06;
1970 outb(0, tmport);
1971 tmport += 0x06;
1974 tmport -= 0x08;
1975 j = inb(tmport) & 0x0f;
1976 if (j == 0x0f) {
1977 goto widep_in;
1979 if (j == 0x0a) {
1980 goto widep_cmd;
1982 if (j == 0x0e) {
1983 goto widep_out;
1985 continue;
1986 widep_in:
1987 tmport = wkport + 0x54;
1988 outb(0xff, tmport);
1989 tmport += 0x04;
1990 outb(0x20, tmport);
1991 tmport += 0x07;
1992 k = 0;
1993 widep_in1:
1994 j = inb(tmport);
1995 if ((j & 0x01) != 0) {
1996 tmport -= 0x06;
1997 mbuf[k++] = inb(tmport);
1998 tmport += 0x06;
1999 goto widep_in1;
2001 if ((j & 0x80) == 0x00) {
2002 goto widep_in1;
2004 tmport -= 0x08;
2005 j = inb(tmport) & 0x0f;
2006 if (j == 0x0f) {
2007 goto widep_in;
2009 if (j == 0x0a) {
2010 goto widep_cmd;
2012 if (j == 0x0e) {
2013 goto widep_out;
2015 continue;
2016 widep_cmd:
2017 tmport = wkport + 0x50;
2018 outb(0x30, tmport);
2019 tmport = wkport + 0x54;
2020 outb(0x00, tmport);
2021 tmport += 0x04;
2022 outb(0x08, tmport);
2023 tmport += 0x07;
2024 while ((inb(tmport) & 0x80) == 0x00);
2025 tmport -= 0x08;
2026 j = inb(tmport);
2027 if (j != 0x16) {
2028 if (j == 0x4e) {
2029 goto widep_out;
2031 continue;
2033 if (mbuf[0] != 0x01) {
2034 goto not_wide;
2036 if (mbuf[1] != 0x02) {
2037 goto not_wide;
2039 if (mbuf[2] != 0x03) {
2040 goto not_wide;
2042 if (mbuf[3] != 0x01) {
2043 goto not_wide;
2045 m = 1;
2046 m = m << i;
2047 dev->wide_idu |= m;
2048 not_wide:
2049 if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) || ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0))) {
2050 m = 1;
2051 m = m << i;
2052 if ((dev->async & m) != 0) {
2053 goto set_sync;
2056 continue;
2057 set_sync:
2058 if (dev->sp[i] == 0x02) {
2059 synu[4] = 0x0c;
2060 synuw[4] = 0x0c;
2061 } else {
2062 if (dev->sp[i] >= 0x03) {
2063 synu[4] = 0x0a;
2064 synuw[4] = 0x0a;
2067 tmport = wkport + 0x5b;
2068 j = 0;
2069 if ((m & dev->wide_idu) != 0) {
2070 j |= 0x01;
2072 outb(j, tmport);
2073 tmport = wkport + 0x43;
2074 outb(satn[0], tmport++);
2075 outb(satn[1], tmport++);
2076 outb(satn[2], tmport++);
2077 outb(satn[3], tmport++);
2078 outb(satn[4], tmport++);
2079 outb(satn[5], tmport++);
2080 tmport += 0x06;
2081 outb(0, tmport);
2082 tmport += 0x02;
2083 outb(dev->id[i].devspu, tmport++);
2084 outb(0, tmport++);
2085 outb(satn[6], tmport++);
2086 outb(satn[7], tmport++);
2087 tmport += 0x03;
2088 outb(satn[8], tmport);
2089 tmport += 0x07;
2091 while ((inb(tmport) & 0x80) == 0x00);
2092 tmport -= 0x08;
2093 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
2094 continue;
2096 while (inb(tmport) != 0x8e);
2097 try_sync:
2098 j = 0;
2099 tmport = wkport + 0x54;
2100 outb(0x06, tmport);
2101 tmport += 0x04;
2102 outb(0x20, tmport);
2103 tmport += 0x07;
2105 while ((inb(tmport) & 0x80) == 0) {
2106 if ((inb(tmport) & 0x01) != 0) {
2107 tmport -= 0x06;
2108 if ((m & dev->wide_idu) != 0) {
2109 if ((m & dev->ultra_map) != 0) {
2110 outb(synuw[j++], tmport);
2111 } else {
2112 outb(synw[j++], tmport);
2114 } else {
2115 if ((m & dev->ultra_map) != 0) {
2116 outb(synu[j++], tmport);
2117 } else {
2118 outb(synn[j++], tmport);
2121 tmport += 0x06;
2124 tmport -= 0x08;
2125 while ((inb(tmport) & 0x80) == 0x00);
2126 j = inb(tmport) & 0x0f;
2127 if (j == 0x0f) {
2128 goto phase_ins;
2130 if (j == 0x0a) {
2131 goto phase_cmds;
2133 if (j == 0x0e) {
2134 goto try_sync;
2136 continue;
2137 phase_outs:
2138 tmport = wkport + 0x58;
2139 outb(0x20, tmport);
2140 tmport += 0x07;
2141 while ((inb(tmport) & 0x80) == 0x00) {
2142 if ((inb(tmport) & 0x01) != 0x00) {
2143 tmport -= 0x06;
2144 outb(0x00, tmport);
2145 tmport += 0x06;
2148 tmport -= 0x08;
2149 j = inb(tmport);
2150 if (j == 0x85) {
2151 goto tar_dcons;
2153 j &= 0x0f;
2154 if (j == 0x0f) {
2155 goto phase_ins;
2157 if (j == 0x0a) {
2158 goto phase_cmds;
2160 if (j == 0x0e) {
2161 goto phase_outs;
2163 continue;
2164 phase_ins:
2165 tmport = wkport + 0x54;
2166 outb(0x06, tmport);
2167 tmport += 0x04;
2168 outb(0x20, tmport);
2169 tmport += 0x07;
2170 k = 0;
2171 phase_ins1:
2172 j = inb(tmport);
2173 if ((j & 0x01) != 0x00) {
2174 tmport -= 0x06;
2175 mbuf[k++] = inb(tmport);
2176 tmport += 0x06;
2177 goto phase_ins1;
2179 if ((j & 0x80) == 0x00) {
2180 goto phase_ins1;
2182 tmport -= 0x08;
2183 while ((inb(tmport) & 0x80) == 0x00);
2184 j = inb(tmport);
2185 if (j == 0x85) {
2186 goto tar_dcons;
2188 j &= 0x0f;
2189 if (j == 0x0f) {
2190 goto phase_ins;
2192 if (j == 0x0a) {
2193 goto phase_cmds;
2195 if (j == 0x0e) {
2196 goto phase_outs;
2198 continue;
2199 phase_cmds:
2200 tmport = wkport + 0x50;
2201 outb(0x30, tmport);
2202 tar_dcons:
2203 tmport = wkport + 0x54;
2204 outb(0x00, tmport);
2205 tmport += 0x04;
2206 outb(0x08, tmport);
2207 tmport += 0x07;
2208 while ((inb(tmport) & 0x80) == 0x00);
2209 tmport -= 0x08;
2210 j = inb(tmport);
2211 if (j != 0x16) {
2212 continue;
2214 if (mbuf[0] != 0x01) {
2215 continue;
2217 if (mbuf[1] != 0x03) {
2218 continue;
2220 if (mbuf[4] == 0x00) {
2221 continue;
2223 if (mbuf[3] > 0x64) {
2224 continue;
2226 if (mbuf[4] > 0x0e) {
2227 mbuf[4] = 0x0e;
2229 dev->id[i].devspu = mbuf[4];
2230 if (mbuf[3] < 0x0c) {
2231 j = 0xb0;
2232 goto set_syn_ok;
2234 if ((mbuf[3] < 0x0d) && (rmb == 0)) {
2235 j = 0xa0;
2236 goto set_syn_ok;
2238 if (mbuf[3] < 0x1a) {
2239 j = 0x20;
2240 goto set_syn_ok;
2242 if (mbuf[3] < 0x33) {
2243 j = 0x40;
2244 goto set_syn_ok;
2246 if (mbuf[3] < 0x4c) {
2247 j = 0x50;
2248 goto set_syn_ok;
2250 j = 0x60;
2251 set_syn_ok:
2252 dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j;
2257 static void atp870u_init_tables(struct Scsi_Host *host)
2259 struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
2260 int k;
2262 for (k = 0; k < 16; k++) {
2263 /* FIXME */
2264 dev->id[k].prd_tableu = pci_alloc_consistent(dev->pdev, 1024, &dev->id[k].prd_phys);
2265 dev->id[k].devspu = 0x20;
2266 dev->id[k].devtypeu = 0;
2267 dev->id[k].curr_req = NULL;
2269 dev->active_idu = 0;
2270 dev->wide_idu = 0;
2271 dev->host_idu = 0x07;
2272 dev->quhdu = 0;
2273 dev->quendu = 0;
2274 dev->chip_veru = 0;
2275 dev->last_cmd = 0xff;
2276 dev->in_snd = 0;
2277 dev->in_int = 0;
2278 for (k = 0; k < qcnt; k++) {
2279 dev->querequ[k] = 0;
2281 for (k = 0; k < 16; k++) {
2282 dev->id[k].curr_req = 0;
2283 dev->sp[k] = 0x04;
2287 /* return non-zero on detection */
2288 static int atp870u_detect(Scsi_Host_Template * tpnt)
2290 unsigned char irq, h, k, m;
2291 unsigned long flags;
2292 unsigned int base_io, error, tmport;
2293 struct pci_dev *pdev[MAX_ATP];
2294 unsigned char chip_ver[MAX_ATP], host_id;
2295 unsigned short dev_id[MAX_ATP], n;
2296 struct Scsi_Host *shpnt = NULL;
2297 int card = 0;
2298 int count = 0;
2300 static unsigned short devid[9] = {
2301 0x8081, 0x8002, 0x8010, 0x8020, 0x8030, 0x8040, 0x8050, 0x8060, 0
2304 printk(KERN_INFO "aec671x_detect: \n");
2305 tpnt->proc_name = "atp870u";
2307 for (h = 0; devid[h]; h++) {
2308 struct pci_dev *dev = NULL;
2310 while((dev = pci_find_device(0x1191, devid[h], dev))!=NULL)
2312 if(pci_enable_device(dev))
2313 continue;
2315 if(pci_set_dma_mask(dev, 0xFFFFFFFFUL))
2317 printk(KERN_ERR "atp870u: 32bit DMA mask required but not available.\n");
2318 continue;
2320 chip_ver[card] = 0;
2321 dev_id[card] = devid[h];
2323 if (devid[h] == 0x8002) {
2324 error = pci_read_config_byte(dev, 0x08, &chip_ver[card]);
2325 if (chip_ver[card] < 2) {
2326 continue;
2329 if (devid[h] == 0x8010 || devid[h] == 0x8081 || devid[h] == 0x8050) {
2330 chip_ver[card] = 0x04;
2332 pdev[card] = dev;
2333 card++;
2334 if (card == MAX_ATP)
2335 break;
2338 for (h = 0; h < MAX_ATP; h++) {
2339 struct atp_unit tmp, *dev;
2340 if (pdev[h] == NULL) {
2341 return count;
2344 /* Found an atp870u/w. */
2345 base_io = pci_resource_start(pdev[h], 0);
2346 irq = pdev[h]->irq;
2348 if (dev_id[h] != 0x8081) {
2349 error = pci_read_config_byte(pdev[h], 0x49, &host_id);
2351 base_io &= 0xfffffff8;
2353 if (check_region(base_io, 0x40) != 0) {
2354 return 0;
2356 printk(KERN_INFO " ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d IO:%x, IRQ:%d.\n", h, base_io, irq);
2358 tmp.ioport = base_io;
2359 tmp.pciport = base_io + 0x20;
2360 tmp.deviceid = dev_id[h];
2361 host_id &= 0x07;
2362 tmp.host_idu = host_id;
2363 tmp.chip_veru = chip_ver[h];
2365 tmport = base_io + 0x22;
2366 tmp.scam_on = inb(tmport);
2367 tmport += 0x0b;
2368 tmp.global_map = inb(tmport++);
2369 tmp.ultra_map = inw(tmport);
2370 if (tmp.ultra_map == 0) {
2371 tmp.scam_on = 0x00;
2372 tmp.global_map = 0x20;
2373 tmp.ultra_map = 0xffff;
2375 shpnt = scsi_register(tpnt, sizeof(struct atp_unit));
2376 if (shpnt == NULL)
2377 return count;
2378 tmp.host = shpnt;
2379 tmp.pdev = pdev[h];
2380 /* Save the atp_unit data */
2381 memcpy(&shpnt->hostdata, &tmp, sizeof(tmp));
2383 atp870u_init_tables(shpnt);
2384 spin_lock_irqsave(shpnt->host_lock, flags);
2385 if (request_irq(irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) {
2386 printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
2387 goto unregister;
2390 if (chip_ver[h] > 0x07) { /* check if atp876 chip *//* then enable terminator */
2391 tmport = base_io + 0x3e;
2392 outb(0x00, tmport);
2395 tmport = base_io + 0x3a;
2396 k = (inb(tmport) & 0xf3) | 0x10;
2397 outb(k, tmport);
2398 outb((k & 0xdf), tmport);
2399 mdelay(32);
2400 outb(k, tmport);
2401 mdelay(32);
2402 tmport = base_io;
2403 outb((host_id | 0x08), tmport);
2404 tmport += 0x18;
2405 outb(0, tmport);
2406 tmport += 0x07;
2407 while ((inb(tmport) & 0x80) == 0);
2408 tmport -= 0x08;
2409 inb(tmport);
2410 tmport = base_io + 1;
2411 outb(8, tmport++);
2412 outb(0x7f, tmport);
2413 tmport = base_io + 0x11;
2414 outb(0x20, tmport);
2416 tscam(shpnt);
2417 is870(shpnt, base_io);
2418 tmport = base_io + 0x3a;
2419 outb((inb(tmport) & 0xef), tmport);
2420 tmport++;
2421 outb((inb(tmport) | 0x20), tmport);
2422 } else {
2423 base_io &= 0xfffffff8;
2425 if (check_region(base_io, 0x60) != 0) {
2426 return 0;
2428 host_id = inb(base_io + 0x39);
2429 host_id >>= 0x04;
2431 printk(KERN_INFO " ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d IO:%x, IRQ:%d.\n", h, base_io, irq);
2432 tmp.ioport = base_io + 0x40;
2433 tmp.pciport = base_io + 0x28;
2434 tmp.deviceid = dev_id[h];
2435 tmp.host_idu = host_id;
2436 tmp.chip_veru = chip_ver[h];
2438 tmport = base_io + 0x22;
2439 tmp.scam_on = inb(tmport);
2440 tmport += 0x13;
2441 tmp.global_map = inb(tmport);
2442 tmport += 0x07;
2443 tmp.ultra_map = inw(tmport);
2445 n = 0x3f09;
2446 next_fblk:
2447 if (n >= 0x4000) {
2448 goto flash_ok;
2450 m = 0;
2451 outw(n, base_io + 0x34);
2452 n += 0x0002;
2453 if (inb(base_io + 0x30) == 0xff) {
2454 goto flash_ok;
2456 tmp.sp[m++] = inb(base_io + 0x30);
2457 tmp.sp[m++] = inb(base_io + 0x31);
2458 tmp.sp[m++] = inb(base_io + 0x32);
2459 tmp.sp[m++] = inb(base_io + 0x33);
2460 outw(n, base_io + 0x34);
2461 n += 0x0002;
2462 tmp.sp[m++] = inb(base_io + 0x30);
2463 tmp.sp[m++] = inb(base_io + 0x31);
2464 tmp.sp[m++] = inb(base_io + 0x32);
2465 tmp.sp[m++] = inb(base_io + 0x33);
2466 outw(n, base_io + 0x34);
2467 n += 0x0002;
2468 tmp.sp[m++] = inb(base_io + 0x30);
2469 tmp.sp[m++] = inb(base_io + 0x31);
2470 tmp.sp[m++] = inb(base_io + 0x32);
2471 tmp.sp[m++] = inb(base_io + 0x33);
2472 outw(n, base_io + 0x34);
2473 n += 0x0002;
2474 tmp.sp[m++] = inb(base_io + 0x30);
2475 tmp.sp[m++] = inb(base_io + 0x31);
2476 tmp.sp[m++] = inb(base_io + 0x32);
2477 tmp.sp[m++] = inb(base_io + 0x33);
2478 n += 0x0018;
2479 goto next_fblk;
2480 flash_ok:
2481 outw(0, base_io + 0x34);
2482 tmp.ultra_map = 0;
2483 tmp.async = 0;
2484 for (k = 0; k < 16; k++) {
2485 n = 1;
2486 n = n << k;
2487 if (tmp.sp[k] > 1) {
2488 tmp.ultra_map |= n;
2489 } else {
2490 if (tmp.sp[k] == 0) {
2491 tmp.async |= n;
2495 tmp.async = ~(tmp.async);
2496 outb(tmp.global_map, base_io + 0x35);
2498 shpnt = scsi_register(tpnt, sizeof(struct atp_unit));
2499 if (shpnt == NULL)
2500 return count;
2502 tmp.pdev = pdev[h];
2503 memcpy(&shpnt->hostdata, &tmp, sizeof(tmp));
2505 atp870u_init_tables(shpnt);
2507 spin_lock_irqsave(shpnt->host_lock, flags);
2508 if (request_irq(irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) {
2509 printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
2510 goto unregister;
2513 tmport = base_io + 0x38;
2514 k = inb(tmport) & 0x80;
2515 outb(k, tmport);
2516 tmport += 0x03;
2517 outb(0x20, tmport);
2518 mdelay(32);
2519 outb(0, tmport);
2520 mdelay(32);
2521 tmport = base_io + 0x5b;
2522 inb(tmport);
2523 tmport -= 0x04;
2524 inb(tmport);
2525 tmport = base_io + 0x40;
2526 outb((host_id | 0x08), tmport);
2527 tmport += 0x18;
2528 outb(0, tmport);
2529 tmport += 0x07;
2530 while ((inb(tmport) & 0x80) == 0);
2531 tmport -= 0x08;
2532 inb(tmport);
2533 tmport = base_io + 0x41;
2534 outb(8, tmport++);
2535 outb(0x7f, tmport);
2536 tmport = base_io + 0x51;
2537 outb(0x20, tmport);
2539 tscam(shpnt);
2540 is880(shpnt, base_io);
2541 tmport = base_io + 0x38;
2542 outb(0xb0, tmport);
2545 dev = (struct atp_unit *)&shpnt->hostdata;
2547 atp_host[h] = shpnt;
2548 if (dev->chip_veru == 4) {
2549 shpnt->max_id = 16;
2551 shpnt->this_id = host_id;
2552 shpnt->unique_id = base_io;
2553 shpnt->io_port = base_io;
2554 if (dev_id[h] == 0x8081) {
2555 shpnt->n_io_port = 0x60; /* Number of bytes of I/O space used */
2556 } else {
2557 shpnt->n_io_port = 0x40; /* Number of bytes of I/O space used */
2559 shpnt->irq = irq;
2560 spin_unlock_irqrestore(shpnt->host_lock, flags);
2561 if (dev_id[h] == 0x8081) {
2562 request_region(base_io, 0x60, "atp870u"); /* Register the IO ports that we use */
2563 } else {
2564 request_region(base_io, 0x40, "atp870u"); /* Register the IO ports that we use */
2566 count++;
2567 continue;
2568 unregister:
2569 scsi_unregister(shpnt);
2570 spin_unlock_irqrestore(shpnt->host_lock, flags);
2571 continue;
2574 return count;
2577 /* The abort command does not leave the device in a clean state where
2578 it is available to be used again. Until this gets worked out, we will
2579 leave it commented out. */
2581 int atp870u_abort(Scsi_Cmnd * SCpnt)
2583 unsigned char j, k;
2584 Scsi_Cmnd *workrequ;
2585 unsigned int tmport;
2586 struct atp_unit *dev = (struct atp_unit *)&SCpnt->device->host->hostdata;
2588 printk(KERN_DEBUG "working=%x last_cmd=%x ", dev->working, dev->last_cmd);
2589 printk(" quhdu=%x quendu=%x ", dev->quhdu, dev->quendu);
2590 tmport = dev->ioport;
2591 for (j = 0; j < 0x17; j++) {
2592 printk(" r%2x=%2x", j, inb(tmport++));
2594 tmport += 0x05;
2595 printk(" r1c=%2x", inb(tmport));
2596 tmport += 0x03;
2597 printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd);
2598 tmport = dev->pciport;
2599 printk(" r20=%2x", inb(tmport));
2600 tmport += 0x02;
2601 printk(" r22=%2x", inb(tmport));
2602 tmport = dev->ioport + 0x3a;
2603 printk(" r3a=%2x \n", inb(tmport));
2604 tmport = dev->ioport + 0x3b;
2605 printk(" r3b=%2x \n", inb(tmport));
2606 for (j = 0; j < 16; j++) {
2607 if (dev->id[j].curr_req != NULL) {
2608 workrequ = dev->id[j].curr_req;
2609 printk("\n que cdb= ");
2610 for (k = 0; k < workrequ->cmd_len; k++) {
2611 printk(" %2x ", workrequ->cmnd[k]);
2613 printk(" last_lenu= %lx ", dev->id[j].last_lenu);
2616 /* Sort of - the thing handles itself */
2617 return SUCCESS;
2620 const char *atp870u_info(struct Scsi_Host *notused)
2622 static char buffer[128];
2624 strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac ");
2626 return buffer;
2629 int atp870u_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
2631 return -ENOSYS; /* Currently this is a no-op */
2634 #define BLS buffer + len + size
2635 int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer, char **start, off_t offset, int length, int inout)
2637 static u8 buff[512];
2638 int size = 0;
2639 int len = 0;
2640 off_t begin = 0;
2641 off_t pos = 0;
2643 if (inout == TRUE) { /* Has data been written to the file? */
2644 return (atp870u_set_info(buffer, length, HBAptr));
2646 if (offset == 0) {
2647 memset(buff, 0, sizeof(buff));
2649 size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.6+ac\n");
2650 len += size;
2651 pos = begin + len;
2652 size = 0;
2654 size += sprintf(BLS, "\n");
2655 size += sprintf(BLS, "Adapter Configuration:\n");
2656 size += sprintf(BLS, " Base IO: %#.4lx\n", HBAptr->io_port);
2657 size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq);
2658 len += size;
2659 pos = begin + len;
2661 *start = buffer + (offset - begin); /* Start of wanted data */
2662 len -= (offset - begin); /* Start slop */
2663 if (len > length) {
2664 len = length; /* Ending slop */
2666 return (len);
2669 static int atp870u_biosparam(struct scsi_device *sdev,
2670 struct block_device *dev, sector_t capacity, int *ip)
2672 int heads, sectors, cylinders;
2674 heads = 64;
2675 sectors = 32;
2676 cylinders = (unsigned long)capacity / (heads * sectors);
2678 if (cylinders > 1024) {
2679 heads = 255;
2680 sectors = 63;
2681 cylinders = (unsigned long)capacity / (heads * sectors);
2683 ip[0] = heads;
2684 ip[1] = sectors;
2685 ip[2] = cylinders;
2687 return 0;
2691 static int atp870u_release(struct Scsi_Host *pshost)
2693 struct atp_unit *dev = (struct atp_unit *)&pshost->hostdata;
2694 int k;
2695 free_irq(pshost->irq, pshost);
2696 release_region(pshost->io_port, pshost->n_io_port);
2697 scsi_unregister(pshost);
2698 for (k = 0; k < 16; k++)
2699 pci_free_consistent(dev->pdev, 1024, dev->id[k].prd_tableu, dev->id[k].prd_phys);
2700 return 0;
2703 MODULE_LICENSE("GPL");
2705 static Scsi_Host_Template driver_template = {
2706 .proc_info = atp870u_proc_info,
2707 .detect = atp870u_detect,
2708 .release = atp870u_release,
2709 .info = atp870u_info,
2710 .queuecommand = atp870u_queuecommand,
2711 .eh_abort_handler = atp870u_abort,
2712 .bios_param = atp870u_biosparam,
2713 .can_queue = qcnt,
2714 .this_id = 7,
2715 .sg_tablesize = ATP870U_SCATTER,
2716 .cmd_per_lun = ATP870U_CMDLUN,
2717 .use_clustering = ENABLE_CLUSTERING,
2719 #include "scsi_module.c"