]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/scsi/atp870u.c
atp870u: Remove tmport1
[mirror_ubuntu-jammy-kernel.git] / drivers / scsi / atp870u.c
CommitLineData
1da177e4
LT
1/*
2 * Copyright (C) 1997 Wu Ching Chen
3 * 2.1.x update (C) 1998 Krzysztof G. Baranowski
fa195afe
AC
4 * 2.5.x update (C) 2002 Red Hat
5 * 2.6.x update (C) 2004 Red Hat
1da177e4
LT
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 * atp885 support add by ACARD Hao Ping Lian 2005/01/05
18 */
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/interrupt.h>
22#include <linux/kernel.h>
23#include <linux/types.h>
24#include <linux/string.h>
25#include <linux/ioport.h>
26#include <linux/delay.h>
27#include <linux/proc_fs.h>
28#include <linux/spinlock.h>
29#include <linux/pci.h>
30#include <linux/blkdev.h>
910638ae 31#include <linux/dma-mapping.h>
5a0e3ad6 32#include <linux/slab.h>
1da177e4
LT
33#include <asm/io.h>
34
35#include <scsi/scsi.h>
36#include <scsi/scsi_cmnd.h>
37#include <scsi/scsi_device.h>
38#include <scsi/scsi_host.h>
39
40#include "atp870u.h"
41
42static struct scsi_host_template atp870u_template;
43static void send_s870(struct atp_unit *dev,unsigned char c);
44static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c);
45static void tscam_885(void);
46
7d12e780 47static irqreturn_t atp870u_intr_handle(int irq, void *dev_id)
1da177e4
LT
48{
49 unsigned long flags;
50 unsigned short int tmpcip, id;
51 unsigned char i, j, c, target_id, lun,cmdp;
52 unsigned char *prd;
53 struct scsi_cmnd *workreq;
b4263b3c 54 unsigned int tmport;
1da177e4
LT
55 unsigned long adrcnt, k;
56#ifdef ED_DBGP
57 unsigned long l;
58#endif
59 int errstus;
60 struct Scsi_Host *host = dev_id;
61 struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
62
63 for (c = 0; c < 2; c++) {
64 tmport = dev->ioport[c] + 0x1f;
65 j = inb(tmport);
66 if ((j & 0x80) != 0)
67 {
68 goto ch_sel;
69 }
70 dev->in_int[c] = 0;
71 }
72 return IRQ_NONE;
73ch_sel:
74#ifdef ED_DBGP
75 printk("atp870u_intr_handle enter\n");
76#endif
77 dev->in_int[c] = 1;
78 cmdp = inb(dev->ioport[c] + 0x10);
1da177e4
LT
79 if (dev->working[c] != 0) {
80 if (dev->dev_id == ATP885_DEVID) {
b4263b3c
OZ
81 if ((inb(dev->ioport[c] + 0x16) & 0x80) == 0)
82 outb((inb(dev->ioport[c] + 0x16) | 0x80), dev->ioport[c] + 0x16);
1da177e4
LT
83 }
84 tmpcip = dev->pciport[c];
85 if ((inb(tmpcip) & 0x08) != 0)
86 {
87 tmpcip += 0x2;
88 for (k=0; k < 1000; k++) {
89 if ((inb(tmpcip) & 0x08) == 0) {
90 goto stop_dma;
91 }
92 if ((inb(tmpcip) & 0x01) == 0) {
93 goto stop_dma;
94 }
95 }
96 }
97stop_dma:
98 tmpcip = dev->pciport[c];
99 outb(0x00, tmpcip);
100 tmport -= 0x08;
101
102 i = inb(tmport);
103
104 if (dev->dev_id == ATP885_DEVID) {
105 tmpcip += 2;
106 outb(0x06, tmpcip);
107 tmpcip -= 2;
108 }
109
110 tmport -= 0x02;
111 target_id = inb(tmport);
112 tmport += 0x02;
113
114 /*
115 * Remap wide devices onto id numbers
116 */
117
118 if ((target_id & 0x40) != 0) {
119 target_id = (target_id & 0x07) | 0x08;
120 } else {
121 target_id &= 0x07;
122 }
123
124 if ((j & 0x40) != 0) {
125 if (dev->last_cmd[c] == 0xff) {
126 dev->last_cmd[c] = target_id;
127 }
128 dev->last_cmd[c] |= 0x40;
129 }
130 if (dev->dev_id == ATP885_DEVID)
131 dev->r1f[c][target_id] |= j;
132#ifdef ED_DBGP
133 printk("atp870u_intr_handle status = %x\n",i);
134#endif
135 if (i == 0x85) {
136 if ((dev->last_cmd[c] & 0xf0) != 0x40) {
137 dev->last_cmd[c] = 0xff;
138 }
139 if (dev->dev_id == ATP885_DEVID) {
140 tmport -= 0x05;
141 adrcnt = 0;
142 ((unsigned char *) &adrcnt)[2] = inb(tmport++);
143 ((unsigned char *) &adrcnt)[1] = inb(tmport++);
144 ((unsigned char *) &adrcnt)[0] = inb(tmport);
145 if (dev->id[c][target_id].last_len != adrcnt)
146 {
147 k = dev->id[c][target_id].last_len;
148 k -= adrcnt;
149 dev->id[c][target_id].tran_len = k;
150 dev->id[c][target_id].last_len = adrcnt;
151 }
152#ifdef ED_DBGP
153 printk("tmport = %x dev->id[c][target_id].last_len = %d dev->id[c][target_id].tran_len = %d\n",tmport,dev->id[c][target_id].last_len,dev->id[c][target_id].tran_len);
154#endif
155 }
156
157 /*
158 * Flip wide
159 */
160 if (dev->wide_id[c] != 0) {
c43cd036 161 tmport = dev->ioport[c] + 0x1b;
1da177e4
LT
162 outb(0x01, tmport);
163 while ((inb(tmport) & 0x01) != 0x01) {
164 outb(0x01, tmport);
165 }
166 }
167 /*
168 * Issue more commands
169 */
170 spin_lock_irqsave(dev->host->host_lock, flags);
171 if (((dev->quhd[c] != dev->quend[c]) || (dev->last_cmd[c] != 0xff)) &&
172 (dev->in_snd[c] == 0)) {
173#ifdef ED_DBGP
174 printk("Call sent_s870\n");
175#endif
176 send_s870(dev,c);
177 }
178 spin_unlock_irqrestore(dev->host->host_lock, flags);
179 /*
180 * Done
181 */
182 dev->in_int[c] = 0;
183#ifdef ED_DBGP
184 printk("Status 0x85 return\n");
185#endif
186 goto handled;
187 }
188
189 if (i == 0x40) {
190 dev->last_cmd[c] |= 0x40;
191 dev->in_int[c] = 0;
192 goto handled;
193 }
194
195 if (i == 0x21) {
196 if ((dev->last_cmd[c] & 0xf0) != 0x40) {
197 dev->last_cmd[c] = 0xff;
198 }
199 tmport -= 0x05;
200 adrcnt = 0;
201 ((unsigned char *) &adrcnt)[2] = inb(tmport++);
202 ((unsigned char *) &adrcnt)[1] = inb(tmport++);
203 ((unsigned char *) &adrcnt)[0] = inb(tmport);
204 k = dev->id[c][target_id].last_len;
205 k -= adrcnt;
206 dev->id[c][target_id].tran_len = k;
207 dev->id[c][target_id].last_len = adrcnt;
208 tmport -= 0x04;
209 outb(0x41, tmport);
210 tmport += 0x08;
211 outb(0x08, tmport);
212 dev->in_int[c] = 0;
213 goto handled;
214 }
215
216 if (dev->dev_id == ATP885_DEVID) {
217 if ((i == 0x4c) || (i == 0x4d) || (i == 0x8c) || (i == 0x8d)) {
218 if ((i == 0x4c) || (i == 0x8c))
219 i=0x48;
220 else
221 i=0x49;
222 }
223
224 }
225 if ((i == 0x80) || (i == 0x8f)) {
226#ifdef ED_DBGP
227 printk(KERN_DEBUG "Device reselect\n");
228#endif
229 lun = 0;
230 tmport -= 0x07;
231 if (cmdp == 0x44 || i==0x80) {
232 tmport += 0x0d;
233 lun = inb(tmport) & 0x07;
234 } else {
235 if ((dev->last_cmd[c] & 0xf0) != 0x40) {
236 dev->last_cmd[c] = 0xff;
237 }
238 if (cmdp == 0x41) {
239#ifdef ED_DBGP
240 printk("cmdp = 0x41\n");
241#endif
242 tmport += 0x02;
243 adrcnt = 0;
244 ((unsigned char *) &adrcnt)[2] = inb(tmport++);
245 ((unsigned char *) &adrcnt)[1] = inb(tmport++);
246 ((unsigned char *) &adrcnt)[0] = inb(tmport);
247 k = dev->id[c][target_id].last_len;
248 k -= adrcnt;
249 dev->id[c][target_id].tran_len = k;
250 dev->id[c][target_id].last_len = adrcnt;
251 tmport += 0x04;
252 outb(0x08, tmport);
253 dev->in_int[c] = 0;
254 goto handled;
255 } else {
256#ifdef ED_DBGP
257 printk("cmdp != 0x41\n");
258#endif
259 outb(0x46, tmport);
260 dev->id[c][target_id].dirct = 0x00;
261 tmport += 0x02;
262 outb(0x00, tmport++);
263 outb(0x00, tmport++);
264 outb(0x00, tmport++);
265 tmport += 0x03;
266 outb(0x08, tmport);
267 dev->in_int[c] = 0;
268 goto handled;
269 }
270 }
271 if (dev->last_cmd[c] != 0xff) {
272 dev->last_cmd[c] |= 0x40;
273 }
274 if (dev->dev_id == ATP885_DEVID) {
275 j = inb(dev->baseport + 0x29) & 0xfe;
276 outb(j, dev->baseport + 0x29);
c43cd036 277 tmport = dev->ioport[c] + 0x16;
1da177e4 278 } else {
c43cd036 279 tmport = dev->ioport[c] + 0x10;
1da177e4
LT
280 outb(0x45, tmport);
281 tmport += 0x06;
282 }
283
284 target_id = inb(tmport);
285 /*
286 * Remap wide identifiers
287 */
288 if ((target_id & 0x10) != 0) {
289 target_id = (target_id & 0x07) | 0x08;
290 } else {
291 target_id &= 0x07;
292 }
293 if (dev->dev_id == ATP885_DEVID) {
c43cd036 294 tmport = dev->ioport[c] + 0x10;
1da177e4
LT
295 outb(0x45, tmport);
296 }
297 workreq = dev->id[c][target_id].curr_req;
298#ifdef ED_DBGP
017560fc
JG
299 scmd_printk(KERN_DEBUG, workreq, "CDB");
300 for (l = 0; l < workreq->cmd_len; l++)
1da177e4 301 printk(KERN_DEBUG " %x",workreq->cmnd[l]);
017560fc 302 printk("\n");
1da177e4
LT
303#endif
304
c43cd036 305 tmport = dev->ioport[c] + 0x0f;
1da177e4
LT
306 outb(lun, tmport);
307 tmport += 0x02;
308 outb(dev->id[c][target_id].devsp, tmport++);
309 adrcnt = dev->id[c][target_id].tran_len;
310 k = dev->id[c][target_id].last_len;
311
312 outb(((unsigned char *) &k)[2], tmport++);
313 outb(((unsigned char *) &k)[1], tmport++);
314 outb(((unsigned char *) &k)[0], tmport++);
315#ifdef ED_DBGP
316 printk("k %x, k[0] 0x%x k[1] 0x%x k[2] 0x%x\n", k, inb(tmport-1), inb(tmport-2), inb(tmport-3));
317#endif
318 /* Remap wide */
319 j = target_id;
320 if (target_id > 7) {
321 j = (j & 0x07) | 0x40;
322 }
323 /* Add direction */
324 j |= dev->id[c][target_id].dirct;
325 outb(j, tmport++);
326 outb(0x80,tmport);
327
328 /* enable 32 bit fifo transfer */
329 if (dev->dev_id == ATP885_DEVID) {
330 tmpcip = dev->pciport[c] + 1;
331 i=inb(tmpcip) & 0xf3;
332 //j=workreq->cmnd[0];
333 if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
334 i |= 0x0c;
335 }
336 outb(i,tmpcip);
337 } else if ((dev->dev_id == ATP880_DEVID1) ||
338 (dev->dev_id == ATP880_DEVID2) ) {
c43cd036 339 tmport = dev->ioport[c] - 0x05;
1da177e4
LT
340 if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
341 outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
342 } else {
343 outb((unsigned char) (inb(tmport) & 0x3f), tmport);
344 }
345 } else {
c43cd036 346 tmport = dev->ioport[c] + 0x3a;
1da177e4
LT
347 if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
348 outb((unsigned char) ((inb(tmport) & 0xf3) | 0x08), tmport);
349 } else {
350 outb((unsigned char) (inb(tmport) & 0xf3), tmport);
351 }
352 }
c43cd036 353 tmport = dev->ioport[c] + 0x1b;
1da177e4
LT
354 j = 0;
355 id = 1;
356 id = id << target_id;
357 /*
358 * Is this a wide device
359 */
360 if ((id & dev->wide_id[c]) != 0) {
361 j |= 0x01;
362 }
363 outb(j, tmport);
364 while ((inb(tmport) & 0x01) != j) {
365 outb(j,tmport);
366 }
367 if (dev->id[c][target_id].last_len == 0) {
c43cd036 368 tmport = dev->ioport[c] + 0x18;
1da177e4
LT
369 outb(0x08, tmport);
370 dev->in_int[c] = 0;
371#ifdef ED_DBGP
372 printk("dev->id[c][target_id].last_len = 0\n");
373#endif
374 goto handled;
375 }
376#ifdef ED_DBGP
377 printk("target_id = %d adrcnt = %d\n",target_id,adrcnt);
378#endif
379 prd = dev->id[c][target_id].prd_pos;
380 while (adrcnt != 0) {
381 id = ((unsigned short int *)prd)[2];
382 if (id == 0) {
383 k = 0x10000;
384 } else {
385 k = id;
386 }
387 if (k > adrcnt) {
388 ((unsigned short int *)prd)[2] = (unsigned short int)
389 (k - adrcnt);
390 ((unsigned long *)prd)[0] += adrcnt;
391 adrcnt = 0;
392 dev->id[c][target_id].prd_pos = prd;
393 } else {
394 adrcnt -= k;
395 dev->id[c][target_id].prdaddr += 0x08;
396 prd += 0x08;
397 if (adrcnt == 0) {
398 dev->id[c][target_id].prd_pos = prd;
399 }
400 }
401 }
402 tmpcip = dev->pciport[c] + 0x04;
403 outl(dev->id[c][target_id].prdaddr, tmpcip);
404#ifdef ED_DBGP
405 printk("dev->id[%d][%d].prdaddr 0x%8x\n", c, target_id, dev->id[c][target_id].prdaddr);
406#endif
407 if (dev->dev_id == ATP885_DEVID) {
408 tmpcip -= 0x04;
409 } else {
410 tmpcip -= 0x02;
411 outb(0x06, tmpcip);
412 outb(0x00, tmpcip);
413 tmpcip -= 0x02;
414 }
c43cd036 415 tmport = dev->ioport[c] + 0x18;
1da177e4
LT
416 /*
417 * Check transfer direction
418 */
419 if (dev->id[c][target_id].dirct != 0) {
420 outb(0x08, tmport);
421 outb(0x01, tmpcip);
422 dev->in_int[c] = 0;
423#ifdef ED_DBGP
424 printk("status 0x80 return dirct != 0\n");
425#endif
426 goto handled;
427 }
428 outb(0x08, tmport);
429 outb(0x09, tmpcip);
430 dev->in_int[c] = 0;
431#ifdef ED_DBGP
432 printk("status 0x80 return dirct = 0\n");
433#endif
434 goto handled;
435 }
436
437 /*
438 * Current scsi request on this target
439 */
440
441 workreq = dev->id[c][target_id].curr_req;
442
443 if (i == 0x42) {
444 if ((dev->last_cmd[c] & 0xf0) != 0x40)
445 {
446 dev->last_cmd[c] = 0xff;
447 }
448 errstus = 0x02;
449 workreq->result = errstus;
450 goto go_42;
451 }
452 if (i == 0x16) {
453 if ((dev->last_cmd[c] & 0xf0) != 0x40) {
454 dev->last_cmd[c] = 0xff;
455 }
456 errstus = 0;
457 tmport -= 0x08;
458 errstus = inb(tmport);
459 if (((dev->r1f[c][target_id] & 0x10) != 0)&&(dev->dev_id==ATP885_DEVID)) {
460 printk(KERN_WARNING "AEC67162 CRC ERROR !\n");
461 errstus = 0x02;
462 }
463 workreq->result = errstus;
464go_42:
465 if (dev->dev_id == ATP885_DEVID) {
466 j = inb(dev->baseport + 0x29) | 0x01;
467 outb(j, dev->baseport + 0x29);
468 }
469 /*
470 * Complete the command
471 */
fe7ed98f
BH
472 scsi_dma_unmap(workreq);
473
1da177e4
LT
474 spin_lock_irqsave(dev->host->host_lock, flags);
475 (*workreq->scsi_done) (workreq);
476#ifdef ED_DBGP
477 printk("workreq->scsi_done\n");
478#endif
479 /*
480 * Clear it off the queue
481 */
482 dev->id[c][target_id].curr_req = NULL;
483 dev->working[c]--;
484 spin_unlock_irqrestore(dev->host->host_lock, flags);
485 /*
486 * Take it back wide
487 */
488 if (dev->wide_id[c] != 0) {
c43cd036 489 tmport = dev->ioport[c] + 0x1b;
1da177e4
LT
490 outb(0x01, tmport);
491 while ((inb(tmport) & 0x01) != 0x01) {
492 outb(0x01, tmport);
493 }
494 }
495 /*
496 * If there is stuff to send and nothing going then send it
497 */
498 spin_lock_irqsave(dev->host->host_lock, flags);
499 if (((dev->last_cmd[c] != 0xff) || (dev->quhd[c] != dev->quend[c])) &&
500 (dev->in_snd[c] == 0)) {
501#ifdef ED_DBGP
502 printk("Call sent_s870(scsi_done)\n");
503#endif
504 send_s870(dev,c);
505 }
506 spin_unlock_irqrestore(dev->host->host_lock, flags);
507 dev->in_int[c] = 0;
508 goto handled;
509 }
510 if ((dev->last_cmd[c] & 0xf0) != 0x40) {
511 dev->last_cmd[c] = 0xff;
512 }
513 if (i == 0x4f) {
514 i = 0x89;
515 }
516 i &= 0x0f;
517 if (i == 0x09) {
518 tmpcip += 4;
519 outl(dev->id[c][target_id].prdaddr, tmpcip);
520 tmpcip = tmpcip - 2;
521 outb(0x06, tmpcip);
522 outb(0x00, tmpcip);
523 tmpcip = tmpcip - 2;
c43cd036 524 tmport = dev->ioport[c] + 0x10;
1da177e4
LT
525 outb(0x41, tmport);
526 if (dev->dev_id == ATP885_DEVID) {
527 tmport += 2;
528 k = dev->id[c][target_id].last_len;
529 outb((unsigned char) (((unsigned char *) (&k))[2]), tmport++);
530 outb((unsigned char) (((unsigned char *) (&k))[1]), tmport++);
531 outb((unsigned char) (((unsigned char *) (&k))[0]), tmport);
532 dev->id[c][target_id].dirct = 0x00;
533 tmport += 0x04;
534 } else {
535 dev->id[c][target_id].dirct = 0x00;
536 tmport += 0x08;
537 }
538 outb(0x08, tmport);
539 outb(0x09, tmpcip);
540 dev->in_int[c] = 0;
541 goto handled;
542 }
543 if (i == 0x08) {
544 tmpcip += 4;
545 outl(dev->id[c][target_id].prdaddr, tmpcip);
546 tmpcip = tmpcip - 2;
547 outb(0x06, tmpcip);
548 outb(0x00, tmpcip);
549 tmpcip = tmpcip - 2;
c43cd036 550 tmport = dev->ioport[c] + 0x10;
1da177e4
LT
551 outb(0x41, tmport);
552 if (dev->dev_id == ATP885_DEVID) {
553 tmport += 2;
554 k = dev->id[c][target_id].last_len;
555 outb((unsigned char) (((unsigned char *) (&k))[2]), tmport++);
556 outb((unsigned char) (((unsigned char *) (&k))[1]), tmport++);
557 outb((unsigned char) (((unsigned char *) (&k))[0]), tmport++);
558 } else {
559 tmport += 5;
560 }
561 outb((unsigned char) (inb(tmport) | 0x20), tmport);
562 dev->id[c][target_id].dirct = 0x20;
563 tmport += 0x03;
564 outb(0x08, tmport);
565 outb(0x01, tmpcip);
566 dev->in_int[c] = 0;
567 goto handled;
568 }
569 tmport -= 0x07;
570 if (i == 0x0a) {
571 outb(0x30, tmport);
572 } else {
573 outb(0x46, tmport);
574 }
575 dev->id[c][target_id].dirct = 0x00;
576 tmport += 0x02;
577 outb(0x00, tmport++);
578 outb(0x00, tmport++);
579 outb(0x00, tmport++);
580 tmport += 0x03;
581 outb(0x08, tmport);
582 dev->in_int[c] = 0;
583 goto handled;
584 } else {
c43cd036 585// tmport = dev->ioport[c] + 0x17;
1da177e4
LT
586// inb(tmport);
587// dev->working[c] = 0;
588 dev->in_int[c] = 0;
589 goto handled;
590 }
591
592handled:
593#ifdef ED_DBGP
594 printk("atp870u_intr_handle exit\n");
595#endif
596 return IRQ_HANDLED;
597}
598/**
599 * atp870u_queuecommand - Queue SCSI command
600 * @req_p: request block
601 * @done: completion function
602 *
603 * Queue a command to the ATP queue. Called with the host lock held.
604 */
f281233d 605static int atp870u_queuecommand_lck(struct scsi_cmnd *req_p,
1da177e4
LT
606 void (*done) (struct scsi_cmnd *))
607{
608 unsigned char c;
609 unsigned int tmport,m;
610 struct atp_unit *dev;
611 struct Scsi_Host *host;
612
422c0d61 613 c = scmd_channel(req_p);
1da177e4 614 req_p->sense_buffer[0]=0;
fe7ed98f 615 scsi_set_resid(req_p, 0);
422c0d61 616 if (scmd_channel(req_p) > 1) {
1da177e4
LT
617 req_p->result = 0x00040000;
618 done(req_p);
619#ifdef ED_DBGP
620 printk("atp870u_queuecommand : req_p->device->channel > 1\n");
621#endif
622 return 0;
623 }
624
625 host = req_p->device->host;
626 dev = (struct atp_unit *)&host->hostdata;
627
628
629
630 m = 1;
422c0d61 631 m = m << scmd_id(req_p);
1da177e4
LT
632
633 /*
634 * Fake a timeout for missing targets
635 */
636
637 if ((m & dev->active_id[c]) == 0) {
638 req_p->result = 0x00040000;
639 done(req_p);
640 return 0;
641 }
642
643 if (done) {
644 req_p->scsi_done = done;
645 } else {
646#ifdef ED_DBGP
647 printk( "atp870u_queuecommand: done can't be NULL\n");
648#endif
649 req_p->result = 0;
650 done(req_p);
651 return 0;
652 }
653
654 /*
655 * Count new command
656 */
657 dev->quend[c]++;
658 if (dev->quend[c] >= qcnt) {
659 dev->quend[c] = 0;
660 }
661
662 /*
663 * Check queue state
664 */
665 if (dev->quhd[c] == dev->quend[c]) {
666 if (dev->quend[c] == 0) {
667 dev->quend[c] = qcnt;
668 }
669#ifdef ED_DBGP
670 printk("atp870u_queuecommand : dev->quhd[c] == dev->quend[c]\n");
671#endif
672 dev->quend[c]--;
673 req_p->result = 0x00020000;
674 done(req_p);
675 return 0;
676 }
677 dev->quereq[c][dev->quend[c]] = req_p;
678 tmport = dev->ioport[c] + 0x1c;
679#ifdef ED_DBGP
680 printk("dev->ioport[c] = %x inb(tmport) = %x dev->in_int[%d] = %d dev->in_snd[%d] = %d\n",dev->ioport[c],inb(tmport),c,dev->in_int[c],c,dev->in_snd[c]);
681#endif
682 if ((inb(tmport) == 0) && (dev->in_int[c] == 0) && (dev->in_snd[c] == 0)) {
683#ifdef ED_DBGP
684 printk("Call sent_s870(atp870u_queuecommand)\n");
685#endif
686 send_s870(dev,c);
687 }
688#ifdef ED_DBGP
689 printk("atp870u_queuecommand : exit\n");
690#endif
691 return 0;
692}
693
f281233d
JG
694static DEF_SCSI_QCMD(atp870u_queuecommand)
695
1da177e4
LT
696/**
697 * send_s870 - send a command to the controller
698 * @host: host
699 *
700 * On entry there is work queued to be done. We move some of that work to the
701 * controller itself.
702 *
703 * Caller holds the host lock.
704 */
705static void send_s870(struct atp_unit *dev,unsigned char c)
706{
707 unsigned int tmport;
708 struct scsi_cmnd *workreq;
709 unsigned int i;//,k;
710 unsigned char j, target_id;
711 unsigned char *prd;
712 unsigned short int tmpcip, w;
713 unsigned long l, bttl = 0;
1da177e4
LT
714 unsigned long sg_count;
715
716 if (dev->in_snd[c] != 0) {
717#ifdef ED_DBGP
718 printk("cmnd in_snd\n");
719#endif
720 return;
721 }
722#ifdef ED_DBGP
723 printk("Sent_s870 enter\n");
724#endif
725 dev->in_snd[c] = 1;
726 if ((dev->last_cmd[c] != 0xff) && ((dev->last_cmd[c] & 0x40) != 0)) {
727 dev->last_cmd[c] &= 0x0f;
728 workreq = dev->id[c][dev->last_cmd[c]].curr_req;
729 if (workreq != NULL) { /* check NULL pointer */
730 goto cmd_subp;
731 }
732 dev->last_cmd[c] = 0xff;
733 if (dev->quhd[c] == dev->quend[c]) {
734 dev->in_snd[c] = 0;
735 return ;
736 }
737 }
738 if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) {
739 dev->in_snd[c] = 0;
740 return ;
741 }
742 dev->working[c]++;
743 j = dev->quhd[c];
744 dev->quhd[c]++;
745 if (dev->quhd[c] >= qcnt) {
746 dev->quhd[c] = 0;
747 }
748 workreq = dev->quereq[c][dev->quhd[c]];
9bcf0910 749 if (dev->id[c][scmd_id(workreq)].curr_req == NULL) {
422c0d61
JG
750 dev->id[c][scmd_id(workreq)].curr_req = workreq;
751 dev->last_cmd[c] = scmd_id(workreq);
1da177e4
LT
752 goto cmd_subp;
753 }
754 dev->quhd[c] = j;
755 dev->working[c]--;
756 dev->in_snd[c] = 0;
757 return;
758cmd_subp:
c43cd036 759 tmport = dev->ioport[c] + 0x1f;
1da177e4
LT
760 if ((inb(tmport) & 0xb0) != 0) {
761 goto abortsnd;
762 }
c43cd036 763 tmport = dev->ioport[c] + 0x1c;
1da177e4
LT
764 if (inb(tmport) == 0) {
765 goto oktosend;
766 }
767abortsnd:
768#ifdef ED_DBGP
769 printk("Abort to Send\n");
770#endif
771 dev->last_cmd[c] |= 0x40;
772 dev->in_snd[c] = 0;
773 return;
774oktosend:
775#ifdef ED_DBGP
776 printk("OK to Send\n");
422c0d61 777 scmd_printk(KERN_DEBUG, workreq, "CDB");
1da177e4
LT
778 for(i=0;i<workreq->cmd_len;i++) {
779 printk(" %x",workreq->cmnd[i]);
780 }
422c0d61 781 printk("\n");
1da177e4 782#endif
fe7ed98f
BH
783 l = scsi_bufflen(workreq);
784
1da177e4
LT
785 if (dev->dev_id == ATP885_DEVID) {
786 j = inb(dev->baseport + 0x29) & 0xfe;
787 outb(j, dev->baseport + 0x29);
422c0d61 788 dev->r1f[c][scmd_id(workreq)] = 0;
1da177e4
LT
789 }
790
791 if (workreq->cmnd[0] == READ_CAPACITY) {
fe7ed98f
BH
792 if (l > 8)
793 l = 8;
1da177e4
LT
794 }
795 if (workreq->cmnd[0] == 0x00) {
fe7ed98f 796 l = 0;
1da177e4
LT
797 }
798
c43cd036 799 tmport = dev->ioport[c] + 0x1b;
1da177e4 800 j = 0;
422c0d61 801 target_id = scmd_id(workreq);
1da177e4
LT
802
803 /*
804 * Wide ?
805 */
806 w = 1;
807 w = w << target_id;
808 if ((w & dev->wide_id[c]) != 0) {
809 j |= 0x01;
810 }
811 outb(j, tmport);
812 while ((inb(tmport) & 0x01) != j) {
813 outb(j,tmport);
814#ifdef ED_DBGP
815 printk("send_s870 while loop 1\n");
816#endif
817 }
818 /*
819 * Write the command
820 */
821
c43cd036 822 tmport = dev->ioport[c];
1da177e4
LT
823 outb(workreq->cmd_len, tmport++);
824 outb(0x2c, tmport++);
825 if (dev->dev_id == ATP885_DEVID) {
826 outb(0x7f, tmport++);
827 } else {
828 outb(0xcf, tmport++);
829 }
830 for (i = 0; i < workreq->cmd_len; i++) {
831 outb(workreq->cmnd[i], tmport++);
832 }
c43cd036 833 tmport = dev->ioport[c] + 0x0f;
1da177e4
LT
834 outb(workreq->device->lun, tmport);
835 tmport += 0x02;
836 /*
837 * Write the target
838 */
839 outb(dev->id[c][target_id].devsp, tmport++);
840#ifdef ED_DBGP
841 printk("dev->id[%d][%d].devsp = %2x\n",c,target_id,dev->id[c][target_id].devsp);
842#endif
fe7ed98f
BH
843
844 sg_count = scsi_dma_map(workreq);
1da177e4
LT
845 /*
846 * Write transfer size
847 */
848 outb((unsigned char) (((unsigned char *) (&l))[2]), tmport++);
849 outb((unsigned char) (((unsigned char *) (&l))[1]), tmport++);
850 outb((unsigned char) (((unsigned char *) (&l))[0]), tmport++);
851 j = target_id;
852 dev->id[c][j].last_len = l;
853 dev->id[c][j].tran_len = 0;
854#ifdef ED_DBGP
855 printk("dev->id[%2d][%2d].last_len = %d\n",c,j,dev->id[c][j].last_len);
856#endif
857 /*
858 * Flip the wide bits
859 */
860 if ((j & 0x08) != 0) {
861 j = (j & 0x07) | 0x40;
862 }
863 /*
864 * Check transfer direction
865 */
866 if (workreq->sc_data_direction == DMA_TO_DEVICE) {
867 outb((unsigned char) (j | 0x20), tmport++);
868 } else {
869 outb(j, tmport++);
870 }
871 outb((unsigned char) (inb(tmport) | 0x80), tmport);
872 outb(0x80, tmport);
c43cd036 873 tmport = dev->ioport[c] + 0x1c;
1da177e4
LT
874 dev->id[c][target_id].dirct = 0;
875 if (l == 0) {
876 if (inb(tmport) == 0) {
c43cd036 877 tmport = dev->ioport[c] + 0x18;
1da177e4
LT
878#ifdef ED_DBGP
879 printk("change SCSI_CMD_REG 0x08\n");
880#endif
881 outb(0x08, tmport);
882 } else {
883 dev->last_cmd[c] |= 0x40;
884 }
885 dev->in_snd[c] = 0;
886 return;
887 }
888 tmpcip = dev->pciport[c];
889 prd = dev->id[c][target_id].prd_table;
890 dev->id[c][target_id].prd_pos = prd;
891
892 /*
893 * Now write the request list. Either as scatter/gather or as
894 * a linear chain.
895 */
896
fe7ed98f
BH
897 if (l) {
898 struct scatterlist *sgpnt;
1da177e4 899 i = 0;
fe7ed98f
BH
900 scsi_for_each_sg(workreq, sgpnt, sg_count, j) {
901 bttl = sg_dma_address(sgpnt);
902 l=sg_dma_len(sgpnt);
1da177e4 903#ifdef ED_DBGP
fe7ed98f 904 printk("1. bttl %x, l %x\n",bttl, l);
1da177e4 905#endif
fe7ed98f 906 while (l > 0x10000) {
1da177e4
LT
907 (((u16 *) (prd))[i + 3]) = 0x0000;
908 (((u16 *) (prd))[i + 2]) = 0x0000;
909 (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
910 l -= 0x10000;
911 bttl += 0x10000;
912 i += 0x04;
913 }
914 (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
915 (((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
916 (((u16 *) (prd))[i + 3]) = 0;
917 i += 0x04;
918 }
919 (((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000);
920#ifdef ED_DBGP
921 printk("prd %4x %4x %4x %4x\n",(((unsigned short int *)prd)[0]),(((unsigned short int *)prd)[1]),(((unsigned short int *)prd)[2]),(((unsigned short int *)prd)[3]));
922 printk("2. bttl %x, l %x\n",bttl, l);
923#endif
1da177e4
LT
924 }
925 tmpcip += 4;
926#ifdef ED_DBGP
927 printk("send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d\n", dev->id[c][target_id].prdaddr,tmpcip,target_id);
928#endif
b5683557 929 dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus;
1da177e4
LT
930 outl(dev->id[c][target_id].prdaddr, tmpcip);
931 tmpcip = tmpcip - 2;
932 outb(0x06, tmpcip);
933 outb(0x00, tmpcip);
934 if (dev->dev_id == ATP885_DEVID) {
935 tmpcip--;
936 j=inb(tmpcip) & 0xf3;
937 if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) ||
938 (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
939 j |= 0x0c;
940 }
941 outb(j,tmpcip);
942 tmpcip--;
943 } else if ((dev->dev_id == ATP880_DEVID1) ||
944 (dev->dev_id == ATP880_DEVID2)) {
945 tmpcip =tmpcip -2;
c43cd036 946 tmport = dev->ioport[c] - 0x05;
1da177e4
LT
947 if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
948 outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
949 } else {
950 outb((unsigned char) (inb(tmport) & 0x3f), tmport);
951 }
952 } else {
953 tmpcip =tmpcip -2;
c43cd036 954 tmport = dev->ioport[c] + 0x3a;
1da177e4
LT
955 if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
956 outb((inb(tmport) & 0xf3) | 0x08, tmport);
957 } else {
958 outb(inb(tmport) & 0xf3, tmport);
959 }
960 }
c43cd036 961 tmport = dev->ioport[c] + 0x1c;
1da177e4
LT
962
963 if(workreq->sc_data_direction == DMA_TO_DEVICE) {
964 dev->id[c][target_id].dirct = 0x20;
965 if (inb(tmport) == 0) {
c43cd036 966 tmport = dev->ioport[c] + 0x18;
1da177e4
LT
967 outb(0x08, tmport);
968 outb(0x01, tmpcip);
969#ifdef ED_DBGP
970 printk( "start DMA(to target)\n");
971#endif
972 } else {
973 dev->last_cmd[c] |= 0x40;
974 }
975 dev->in_snd[c] = 0;
976 return;
977 }
978 if (inb(tmport) == 0) {
c43cd036 979 tmport = dev->ioport[c] + 0x18;
1da177e4
LT
980 outb(0x08, tmport);
981 outb(0x09, tmpcip);
982#ifdef ED_DBGP
983 printk( "start DMA(to host)\n");
984#endif
985 } else {
986 dev->last_cmd[c] |= 0x40;
987 }
988 dev->in_snd[c] = 0;
989 return;
990
991}
992
993static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
994{
995 unsigned int tmport;
996 unsigned short int i, k;
997 unsigned char j;
998
999 tmport = dev->ioport[0] + 0x1c;
1000 outw(*val, tmport);
1001FUN_D7:
1002 for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */
1003 k = inw(tmport);
1004 j = (unsigned char) (k >> 8);
1005 if ((k & 0x8000) != 0) { /* DB7 all release? */
1006 goto FUN_D7;
1007 }
1008 }
1009 *val |= 0x4000; /* assert DB6 */
1010 outw(*val, tmport);
1011 *val &= 0xdfff; /* assert DB5 */
1012 outw(*val, tmport);
1013FUN_D5:
1014 for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */
1015 if ((inw(tmport) & 0x2000) != 0) { /* DB5 all release? */
1016 goto FUN_D5;
1017 }
1018 }
1019 *val |= 0x8000; /* no DB4-0, assert DB7 */
1020 *val &= 0xe0ff;
1021 outw(*val, tmport);
1022 *val &= 0xbfff; /* release DB6 */
1023 outw(*val, tmport);
1024FUN_D6:
1025 for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */
1026 if ((inw(tmport) & 0x4000) != 0) { /* DB6 all release? */
1027 goto FUN_D6;
1028 }
1029 }
1030
1031 return j;
1032}
1033
1034static void tscam(struct Scsi_Host *host)
1035{
1036
1037 unsigned int tmport;
1038 unsigned char i, j, k;
1039 unsigned long n;
1040 unsigned short int m, assignid_map, val;
1041 unsigned char mbuf[33], quintet[2];
1042 struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
1043 static unsigned char g2q_tab[8] = {
1044 0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27
1045 };
1046
1047/* I can't believe we need this before we've even done anything. Remove it
1048 * and see if anyone bitches.
1049 for (i = 0; i < 0x10; i++) {
1050 udelay(0xffff);
1051 }
1052 */
1053
1054 tmport = dev->ioport[0] + 1;
1055 outb(0x08, tmport++);
1056 outb(0x7f, tmport);
1057 tmport = dev->ioport[0] + 0x11;
1058 outb(0x20, tmport);
1059
1060 if ((dev->scam_on & 0x40) == 0) {
1061 return;
1062 }
1063 m = 1;
1064 m <<= dev->host_id[0];
1065 j = 16;
1066 if (dev->chip_ver < 4) {
1067 m |= 0xff00;
1068 j = 8;
1069 }
1070 assignid_map = m;
1071 tmport = dev->ioport[0] + 0x02;
1072 outb(0x02, tmport++); /* 2*2=4ms,3EH 2/32*3E=3.9ms */
1073 outb(0, tmport++);
1074 outb(0, tmport++);
1075 outb(0, tmport++);
1076 outb(0, tmport++);
1077 outb(0, tmport++);
1078 outb(0, tmport++);
1079
1080 for (i = 0; i < j; i++) {
1081 m = 1;
1082 m = m << i;
1083 if ((m & assignid_map) != 0) {
1084 continue;
1085 }
1086 tmport = dev->ioport[0] + 0x0f;
1087 outb(0, tmport++);
1088 tmport += 0x02;
1089 outb(0, tmport++);
1090 outb(0, tmport++);
1091 outb(0, tmport++);
1092 if (i > 7) {
1093 k = (i & 0x07) | 0x40;
1094 } else {
1095 k = i;
1096 }
1097 outb(k, tmport++);
1098 tmport = dev->ioport[0] + 0x1b;
1099 if (dev->chip_ver == 4) {
1100 outb(0x01, tmport);
1101 } else {
1102 outb(0x00, tmport);
1103 }
1104wait_rdyok:
1105 tmport = dev->ioport[0] + 0x18;
1106 outb(0x09, tmport);
1107 tmport += 0x07;
1108
1109 while ((inb(tmport) & 0x80) == 0x00)
1110 cpu_relax();
1111 tmport -= 0x08;
1112 k = inb(tmport);
1113 if (k != 0x16) {
1114 if ((k == 0x85) || (k == 0x42)) {
1115 continue;
1116 }
1117 tmport = dev->ioport[0] + 0x10;
1118 outb(0x41, tmport);
1119 goto wait_rdyok;
1120 }
1121 assignid_map |= m;
1122
1123 }
1124 tmport = dev->ioport[0] + 0x02;
1125 outb(0x7f, tmport);
1126 tmport = dev->ioport[0] + 0x1b;
1127 outb(0x02, tmport);
1128
1129 outb(0, 0x80);
1130
1131 val = 0x0080; /* bsy */
1132 tmport = dev->ioport[0] + 0x1c;
1133 outw(val, tmport);
1134 val |= 0x0040; /* sel */
1135 outw(val, tmport);
1136 val |= 0x0004; /* msg */
1137 outw(val, tmport);
1138 inb(0x80); /* 2 deskew delay(45ns*2=90ns) */
1139 val &= 0x007f; /* no bsy */
1140 outw(val, tmport);
1141 mdelay(128);
1142 val &= 0x00fb; /* after 1ms no msg */
1143 outw(val, tmport);
1144wait_nomsg:
1145 if ((inb(tmport) & 0x04) != 0) {
1146 goto wait_nomsg;
1147 }
1148 outb(1, 0x80);
1149 udelay(100);
1150 for (n = 0; n < 0x30000; n++) {
1151 if ((inb(tmport) & 0x80) != 0) { /* bsy ? */
1152 goto wait_io;
1153 }
1154 }
1155 goto TCM_SYNC;
1156wait_io:
1157 for (n = 0; n < 0x30000; n++) {
1158 if ((inb(tmport) & 0x81) == 0x0081) {
1159 goto wait_io1;
1160 }
1161 }
1162 goto TCM_SYNC;
1163wait_io1:
1164 inb(0x80);
1165 val |= 0x8003; /* io,cd,db7 */
1166 outw(val, tmport);
1167 inb(0x80);
1168 val &= 0x00bf; /* no sel */
1169 outw(val, tmport);
1170 outb(2, 0x80);
1171TCM_SYNC:
0f6d93aa
MM
1172 /*
1173 * The funny division into multiple delays is to accomodate
1174 * arches like ARM where udelay() multiplies its argument by
1175 * a large number to initialize a loop counter. To avoid
1176 * overflow, the maximum supported udelay is 2000 microseconds.
1177 *
1178 * XXX it would be more polite to find a way to use msleep()
1179 */
1180 mdelay(2);
1181 udelay(48);
1da177e4
LT
1182 if ((inb(tmport) & 0x80) == 0x00) { /* bsy ? */
1183 outw(0, tmport--);
1184 outb(0, tmport);
1185 tmport = dev->ioport[0] + 0x15;
1186 outb(0, tmport);
1187 tmport += 0x03;
1188 outb(0x09, tmport);
1189 tmport += 0x07;
1190 while ((inb(tmport) & 0x80) == 0)
1191 cpu_relax();
1192 tmport -= 0x08;
1193 inb(tmport);
1194 return;
1195 }
1196 val &= 0x00ff; /* synchronization */
1197 val |= 0x3f00;
1198 fun_scam(dev, &val);
1199 outb(3, 0x80);
1200 val &= 0x00ff; /* isolation */
1201 val |= 0x2000;
1202 fun_scam(dev, &val);
1203 outb(4, 0x80);
1204 i = 8;
1205 j = 0;
1206TCM_ID:
1207 if ((inw(tmport) & 0x2000) == 0) {
1208 goto TCM_ID;
1209 }
1210 outb(5, 0x80);
1211 val &= 0x00ff; /* get ID_STRING */
1212 val |= 0x2000;
1213 k = fun_scam(dev, &val);
1214 if ((k & 0x03) == 0) {
1215 goto TCM_5;
1216 }
1217 mbuf[j] <<= 0x01;
1218 mbuf[j] &= 0xfe;
1219 if ((k & 0x02) != 0) {
1220 mbuf[j] |= 0x01;
1221 }
1222 i--;
1223 if (i > 0) {
1224 goto TCM_ID;
1225 }
1226 j++;
1227 i = 8;
1228 goto TCM_ID;
1229
1230TCM_5: /* isolation complete.. */
1231/* mbuf[32]=0;
1232 printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
1233 i = 15;
1234 j = mbuf[0];
25985edc 1235 if ((j & 0x20) != 0) { /* bit5=1:ID up to 7 */
1da177e4
LT
1236 i = 7;
1237 }
1238 if ((j & 0x06) == 0) { /* IDvalid? */
1239 goto G2Q5;
1240 }
1241 k = mbuf[1];
1242small_id:
1243 m = 1;
1244 m <<= k;
1245 if ((m & assignid_map) == 0) {
1246 goto G2Q_QUIN;
1247 }
1248 if (k > 0) {
1249 k--;
1250 goto small_id;
1251 }
1252G2Q5: /* srch from max acceptable ID# */
1253 k = i; /* max acceptable ID# */
1254G2Q_LP:
1255 m = 1;
1256 m <<= k;
1257 if ((m & assignid_map) == 0) {
1258 goto G2Q_QUIN;
1259 }
1260 if (k > 0) {
1261 k--;
1262 goto G2Q_LP;
1263 }
1264G2Q_QUIN: /* k=binID#, */
1265 assignid_map |= m;
1266 if (k < 8) {
1267 quintet[0] = 0x38; /* 1st dft ID<8 */
1268 } else {
1269 quintet[0] = 0x31; /* 1st ID>=8 */
1270 }
1271 k &= 0x07;
1272 quintet[1] = g2q_tab[k];
1273
1274 val &= 0x00ff; /* AssignID 1stQuintet,AH=001xxxxx */
1275 m = quintet[0] << 8;
1276 val |= m;
1277 fun_scam(dev, &val);
1278 val &= 0x00ff; /* AssignID 2ndQuintet,AH=001xxxxx */
1279 m = quintet[1] << 8;
1280 val |= m;
1281 fun_scam(dev, &val);
1282
1283 goto TCM_SYNC;
1284
1285}
1286
1287static void is870(struct atp_unit *dev, unsigned int wkport)
1288{
1289 unsigned int tmport;
1290 unsigned char i, j, k, rmb, n;
1291 unsigned short int m;
1292 static unsigned char mbuf[512];
1293 static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
1294 static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
1295 static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1296 static unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0c, 0x0e };
1297 static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
1298 static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
1299
1300 tmport = wkport + 0x3a;
1301 outb((unsigned char) (inb(tmport) | 0x10), tmport);
1302
1303 for (i = 0; i < 16; i++) {
1304 if ((dev->chip_ver != 4) && (i > 7)) {
1305 break;
1306 }
1307 m = 1;
1308 m = m << i;
1309 if ((m & dev->active_id[0]) != 0) {
1310 continue;
1311 }
1312 if (i == dev->host_id[0]) {
1313 printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_id[0]);
1314 continue;
1315 }
1316 tmport = wkport + 0x1b;
1317 if (dev->chip_ver == 4) {
1318 outb(0x01, tmport);
1319 } else {
1320 outb(0x00, tmport);
1321 }
1322 tmport = wkport + 1;
1323 outb(0x08, tmport++);
1324 outb(0x7f, tmport++);
1325 outb(satn[0], tmport++);
1326 outb(satn[1], tmport++);
1327 outb(satn[2], tmport++);
1328 outb(satn[3], tmport++);
1329 outb(satn[4], tmport++);
1330 outb(satn[5], tmport++);
1331 tmport += 0x06;
1332 outb(0, tmport);
1333 tmport += 0x02;
1334 outb(dev->id[0][i].devsp, tmport++);
1335 outb(0, tmport++);
1336 outb(satn[6], tmport++);
1337 outb(satn[7], tmport++);
1338 j = i;
1339 if ((j & 0x08) != 0) {
1340 j = (j & 0x07) | 0x40;
1341 }
1342 outb(j, tmport);
1343 tmport += 0x03;
1344 outb(satn[8], tmport);
1345 tmport += 0x07;
1346
1347 while ((inb(tmport) & 0x80) == 0x00)
1348 cpu_relax();
1349
1350 tmport -= 0x08;
1351 if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1352 continue;
1353
1354 while (inb(tmport) != 0x8e)
1355 cpu_relax();
1356
1357 dev->active_id[0] |= m;
1358
1359 tmport = wkport + 0x10;
1360 outb(0x30, tmport);
1361 tmport = wkport + 0x04;
1362 outb(0x00, tmport);
1363
1364phase_cmd:
1365 tmport = wkport + 0x18;
1366 outb(0x08, tmport);
1367 tmport += 0x07;
1368 while ((inb(tmport) & 0x80) == 0x00)
1369 cpu_relax();
1370 tmport -= 0x08;
1371 j = inb(tmport);
1372 if (j != 0x16) {
1373 tmport = wkport + 0x10;
1374 outb(0x41, tmport);
1375 goto phase_cmd;
1376 }
1377sel_ok:
1378 tmport = wkport + 3;
1379 outb(inqd[0], tmport++);
1380 outb(inqd[1], tmport++);
1381 outb(inqd[2], tmport++);
1382 outb(inqd[3], tmport++);
1383 outb(inqd[4], tmport++);
1384 outb(inqd[5], tmport);
1385 tmport += 0x07;
1386 outb(0, tmport);
1387 tmport += 0x02;
1388 outb(dev->id[0][i].devsp, tmport++);
1389 outb(0, tmport++);
1390 outb(inqd[6], tmport++);
1391 outb(inqd[7], tmport++);
1392 tmport += 0x03;
1393 outb(inqd[8], tmport);
1394 tmport += 0x07;
1395
1396 while ((inb(tmport) & 0x80) == 0x00)
1397 cpu_relax();
1398
1399 tmport -= 0x08;
1400 if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1401 continue;
1402
1403 while (inb(tmport) != 0x8e)
1404 cpu_relax();
1405
1406 tmport = wkport + 0x1b;
1407 if (dev->chip_ver == 4)
1408 outb(0x00, tmport);
1409
1410 tmport = wkport + 0x18;
1411 outb(0x08, tmport);
1412 tmport += 0x07;
1413 j = 0;
1414rd_inq_data:
1415 k = inb(tmport);
1416 if ((k & 0x01) != 0) {
1417 tmport -= 0x06;
1418 mbuf[j++] = inb(tmport);
1419 tmport += 0x06;
1420 goto rd_inq_data;
1421 }
1422 if ((k & 0x80) == 0) {
1423 goto rd_inq_data;
1424 }
1425 tmport -= 0x08;
1426 j = inb(tmport);
1427 if (j == 0x16) {
1428 goto inq_ok;
1429 }
1430 tmport = wkport + 0x10;
1431 outb(0x46, tmport);
1432 tmport += 0x02;
1433 outb(0, tmport++);
1434 outb(0, tmport++);
1435 outb(0, tmport++);
1436 tmport += 0x03;
1437 outb(0x08, tmport);
1438 tmport += 0x07;
1439
1440 while ((inb(tmport) & 0x80) == 0x00)
1441 cpu_relax();
1442
1443 tmport -= 0x08;
1444 if (inb(tmport) != 0x16) {
1445 goto sel_ok;
1446 }
1447inq_ok:
1448 mbuf[36] = 0;
1449 printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]);
1450 dev->id[0][i].devtype = mbuf[0];
1451 rmb = mbuf[1];
1452 n = mbuf[7];
1453 if (dev->chip_ver != 4) {
1454 goto not_wide;
1455 }
1456 if ((mbuf[7] & 0x60) == 0) {
1457 goto not_wide;
1458 }
1459 if ((dev->global_map[0] & 0x20) == 0) {
1460 goto not_wide;
1461 }
1462 tmport = wkport + 0x1b;
1463 outb(0x01, tmport);
1464 tmport = wkport + 3;
1465 outb(satn[0], tmport++);
1466 outb(satn[1], tmport++);
1467 outb(satn[2], tmport++);
1468 outb(satn[3], tmport++);
1469 outb(satn[4], tmport++);
1470 outb(satn[5], tmport++);
1471 tmport += 0x06;
1472 outb(0, tmport);
1473 tmport += 0x02;
1474 outb(dev->id[0][i].devsp, tmport++);
1475 outb(0, tmport++);
1476 outb(satn[6], tmport++);
1477 outb(satn[7], tmport++);
1478 tmport += 0x03;
1479 outb(satn[8], tmport);
1480 tmport += 0x07;
1481
1482 while ((inb(tmport) & 0x80) == 0x00)
1483 cpu_relax();
1484
1485 tmport -= 0x08;
1486 if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1487 continue;
1488
1489 while (inb(tmport) != 0x8e)
1490 cpu_relax();
1491
1492try_wide:
1493 j = 0;
1494 tmport = wkport + 0x14;
1495 outb(0x05, tmport);
1496 tmport += 0x04;
1497 outb(0x20, tmport);
1498 tmport += 0x07;
1499
1500 while ((inb(tmport) & 0x80) == 0) {
1501 if ((inb(tmport) & 0x01) != 0) {
1502 tmport -= 0x06;
1503 outb(wide[j++], tmport);
1504 tmport += 0x06;
1505 }
1506 }
1507 tmport -= 0x08;
1508
1509 while ((inb(tmport) & 0x80) == 0x00)
1510 cpu_relax();
1511
1512 j = inb(tmport) & 0x0f;
1513 if (j == 0x0f) {
1514 goto widep_in;
1515 }
1516 if (j == 0x0a) {
1517 goto widep_cmd;
1518 }
1519 if (j == 0x0e) {
1520 goto try_wide;
1521 }
1522 continue;
1523widep_out:
1524 tmport = wkport + 0x18;
1525 outb(0x20, tmport);
1526 tmport += 0x07;
1527 while ((inb(tmport) & 0x80) == 0) {
1528 if ((inb(tmport) & 0x01) != 0) {
1529 tmport -= 0x06;
1530 outb(0, tmport);
1531 tmport += 0x06;
1532 }
1533 }
1534 tmport -= 0x08;
1535 j = inb(tmport) & 0x0f;
1536 if (j == 0x0f) {
1537 goto widep_in;
1538 }
1539 if (j == 0x0a) {
1540 goto widep_cmd;
1541 }
1542 if (j == 0x0e) {
1543 goto widep_out;
1544 }
1545 continue;
1546widep_in:
1547 tmport = wkport + 0x14;
1548 outb(0xff, tmport);
1549 tmport += 0x04;
1550 outb(0x20, tmport);
1551 tmport += 0x07;
1552 k = 0;
1553widep_in1:
1554 j = inb(tmport);
1555 if ((j & 0x01) != 0) {
1556 tmport -= 0x06;
1557 mbuf[k++] = inb(tmport);
1558 tmport += 0x06;
1559 goto widep_in1;
1560 }
1561 if ((j & 0x80) == 0x00) {
1562 goto widep_in1;
1563 }
1564 tmport -= 0x08;
1565 j = inb(tmport) & 0x0f;
1566 if (j == 0x0f) {
1567 goto widep_in;
1568 }
1569 if (j == 0x0a) {
1570 goto widep_cmd;
1571 }
1572 if (j == 0x0e) {
1573 goto widep_out;
1574 }
1575 continue;
1576widep_cmd:
1577 tmport = wkport + 0x10;
1578 outb(0x30, tmport);
1579 tmport = wkport + 0x14;
1580 outb(0x00, tmport);
1581 tmport += 0x04;
1582 outb(0x08, tmport);
1583 tmport += 0x07;
1584
1585 while ((inb(tmport) & 0x80) == 0x00)
1586 cpu_relax();
1587
1588 tmport -= 0x08;
1589 j = inb(tmport);
1590 if (j != 0x16) {
1591 if (j == 0x4e) {
1592 goto widep_out;
1593 }
1594 continue;
1595 }
1596 if (mbuf[0] != 0x01) {
1597 goto not_wide;
1598 }
1599 if (mbuf[1] != 0x02) {
1600 goto not_wide;
1601 }
1602 if (mbuf[2] != 0x03) {
1603 goto not_wide;
1604 }
1605 if (mbuf[3] != 0x01) {
1606 goto not_wide;
1607 }
1608 m = 1;
1609 m = m << i;
1610 dev->wide_id[0] |= m;
1611not_wide:
1612 if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) {
1613 goto set_sync;
1614 }
1615 continue;
1616set_sync:
1617 tmport = wkport + 0x1b;
1618 j = 0;
1619 if ((m & dev->wide_id[0]) != 0) {
1620 j |= 0x01;
1621 }
1622 outb(j, tmport);
1623 tmport = wkport + 3;
1624 outb(satn[0], tmport++);
1625 outb(satn[1], tmport++);
1626 outb(satn[2], tmport++);
1627 outb(satn[3], tmport++);
1628 outb(satn[4], tmport++);
1629 outb(satn[5], tmport++);
1630 tmport += 0x06;
1631 outb(0, tmport);
1632 tmport += 0x02;
1633 outb(dev->id[0][i].devsp, tmport++);
1634 outb(0, tmport++);
1635 outb(satn[6], tmport++);
1636 outb(satn[7], tmport++);
1637 tmport += 0x03;
1638 outb(satn[8], tmport);
1639 tmport += 0x07;
1640
1641 while ((inb(tmport) & 0x80) == 0x00)
1642 cpu_relax();
1643
1644 tmport -= 0x08;
1645 if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1646 continue;
1647
1648 while (inb(tmport) != 0x8e)
1649 cpu_relax();
1650
1651try_sync:
1652 j = 0;
1653 tmport = wkport + 0x14;
1654 outb(0x06, tmport);
1655 tmport += 0x04;
1656 outb(0x20, tmport);
1657 tmport += 0x07;
1658
1659 while ((inb(tmport) & 0x80) == 0) {
1660 if ((inb(tmport) & 0x01) != 0) {
1661 tmport -= 0x06;
1662 if ((m & dev->wide_id[0]) != 0) {
1663 outb(synw[j++], tmport);
1664 } else {
1665 if ((m & dev->ultra_map[0]) != 0) {
1666 outb(synu[j++], tmport);
1667 } else {
1668 outb(synn[j++], tmport);
1669 }
1670 }
1671 tmport += 0x06;
1672 }
1673 }
1674 tmport -= 0x08;
1675
1676 while ((inb(tmport) & 0x80) == 0x00)
1677 cpu_relax();
1678
1679 j = inb(tmport) & 0x0f;
1680 if (j == 0x0f) {
1681 goto phase_ins;
1682 }
1683 if (j == 0x0a) {
1684 goto phase_cmds;
1685 }
1686 if (j == 0x0e) {
1687 goto try_sync;
1688 }
1689 continue;
1690phase_outs:
1691 tmport = wkport + 0x18;
1692 outb(0x20, tmport);
1693 tmport += 0x07;
1694 while ((inb(tmport) & 0x80) == 0x00) {
1695 if ((inb(tmport) & 0x01) != 0x00) {
1696 tmport -= 0x06;
1697 outb(0x00, tmport);
1698 tmport += 0x06;
1699 }
1700 }
1701 tmport -= 0x08;
1702 j = inb(tmport);
1703 if (j == 0x85) {
1704 goto tar_dcons;
1705 }
1706 j &= 0x0f;
1707 if (j == 0x0f) {
1708 goto phase_ins;
1709 }
1710 if (j == 0x0a) {
1711 goto phase_cmds;
1712 }
1713 if (j == 0x0e) {
1714 goto phase_outs;
1715 }
1716 continue;
1717phase_ins:
1718 tmport = wkport + 0x14;
1719 outb(0xff, tmport);
1720 tmport += 0x04;
1721 outb(0x20, tmport);
1722 tmport += 0x07;
1723 k = 0;
1724phase_ins1:
1725 j = inb(tmport);
1726 if ((j & 0x01) != 0x00) {
1727 tmport -= 0x06;
1728 mbuf[k++] = inb(tmport);
1729 tmport += 0x06;
1730 goto phase_ins1;
1731 }
1732 if ((j & 0x80) == 0x00) {
1733 goto phase_ins1;
1734 }
1735 tmport -= 0x08;
1736
1737 while ((inb(tmport) & 0x80) == 0x00)
1738 cpu_relax();
1739
1740 j = inb(tmport);
1741 if (j == 0x85) {
1742 goto tar_dcons;
1743 }
1744 j &= 0x0f;
1745 if (j == 0x0f) {
1746 goto phase_ins;
1747 }
1748 if (j == 0x0a) {
1749 goto phase_cmds;
1750 }
1751 if (j == 0x0e) {
1752 goto phase_outs;
1753 }
1754 continue;
1755phase_cmds:
1756 tmport = wkport + 0x10;
1757 outb(0x30, tmport);
1758tar_dcons:
1759 tmport = wkport + 0x14;
1760 outb(0x00, tmport);
1761 tmport += 0x04;
1762 outb(0x08, tmport);
1763 tmport += 0x07;
1764
1765 while ((inb(tmport) & 0x80) == 0x00)
1766 cpu_relax();
1767
1768 tmport -= 0x08;
1769 j = inb(tmport);
1770 if (j != 0x16) {
1771 continue;
1772 }
1773 if (mbuf[0] != 0x01) {
1774 continue;
1775 }
1776 if (mbuf[1] != 0x03) {
1777 continue;
1778 }
1779 if (mbuf[4] == 0x00) {
1780 continue;
1781 }
1782 if (mbuf[3] > 0x64) {
1783 continue;
1784 }
1785 if (mbuf[4] > 0x0c) {
1786 mbuf[4] = 0x0c;
1787 }
1788 dev->id[0][i].devsp = mbuf[4];
1789 if ((mbuf[3] < 0x0d) && (rmb == 0)) {
1790 j = 0xa0;
1791 goto set_syn_ok;
1792 }
1793 if (mbuf[3] < 0x1a) {
1794 j = 0x20;
1795 goto set_syn_ok;
1796 }
1797 if (mbuf[3] < 0x33) {
1798 j = 0x40;
1799 goto set_syn_ok;
1800 }
1801 if (mbuf[3] < 0x4c) {
1802 j = 0x50;
1803 goto set_syn_ok;
1804 }
1805 j = 0x60;
1806set_syn_ok:
1807 dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j;
1808 }
1809 tmport = wkport + 0x3a;
1810 outb((unsigned char) (inb(tmport) & 0xef), tmport);
1811}
1812
1813static void is880(struct atp_unit *dev, unsigned int wkport)
1814{
1815 unsigned int tmport;
1816 unsigned char i, j, k, rmb, n, lvdmode;
1817 unsigned short int m;
1818 static unsigned char mbuf[512];
1819 static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
1820 static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
1821 static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1822 unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
1823 static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1824 unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
1825 static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
1826 static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 };
1827
1828 lvdmode = inb(wkport + 0x3f) & 0x40;
1829
1830 for (i = 0; i < 16; i++) {
1831 m = 1;
1832 m = m << i;
1833 if ((m & dev->active_id[0]) != 0) {
1834 continue;
1835 }
1836 if (i == dev->host_id[0]) {
1837 printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_id[0]);
1838 continue;
1839 }
1840 tmport = wkport + 0x5b;
1841 outb(0x01, tmport);
1842 tmport = wkport + 0x41;
1843 outb(0x08, tmport++);
1844 outb(0x7f, tmport++);
1845 outb(satn[0], tmport++);
1846 outb(satn[1], tmport++);
1847 outb(satn[2], tmport++);
1848 outb(satn[3], tmport++);
1849 outb(satn[4], tmport++);
1850 outb(satn[5], tmport++);
1851 tmport += 0x06;
1852 outb(0, tmport);
1853 tmport += 0x02;
1854 outb(dev->id[0][i].devsp, tmport++);
1855 outb(0, tmport++);
1856 outb(satn[6], tmport++);
1857 outb(satn[7], tmport++);
1858 j = i;
1859 if ((j & 0x08) != 0) {
1860 j = (j & 0x07) | 0x40;
1861 }
1862 outb(j, tmport);
1863 tmport += 0x03;
1864 outb(satn[8], tmport);
1865 tmport += 0x07;
1866
1867 while ((inb(tmport) & 0x80) == 0x00)
1868 cpu_relax();
1869
1870 tmport -= 0x08;
1871 if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1872 continue;
1873
1874 while (inb(tmport) != 0x8e)
1875 cpu_relax();
1876
1877 dev->active_id[0] |= m;
1878
1879 tmport = wkport + 0x50;
1880 outb(0x30, tmport);
1881 tmport = wkport + 0x54;
1882 outb(0x00, tmport);
1883
1884phase_cmd:
1885 tmport = wkport + 0x58;
1886 outb(0x08, tmport);
1887 tmport += 0x07;
1888
1889 while ((inb(tmport) & 0x80) == 0x00)
1890 cpu_relax();
1891
1892 tmport -= 0x08;
1893 j = inb(tmport);
1894 if (j != 0x16) {
1895 tmport = wkport + 0x50;
1896 outb(0x41, tmport);
1897 goto phase_cmd;
1898 }
1899sel_ok:
1900 tmport = wkport + 0x43;
1901 outb(inqd[0], tmport++);
1902 outb(inqd[1], tmport++);
1903 outb(inqd[2], tmport++);
1904 outb(inqd[3], tmport++);
1905 outb(inqd[4], tmport++);
1906 outb(inqd[5], tmport);
1907 tmport += 0x07;
1908 outb(0, tmport);
1909 tmport += 0x02;
1910 outb(dev->id[0][i].devsp, tmport++);
1911 outb(0, tmport++);
1912 outb(inqd[6], tmport++);
1913 outb(inqd[7], tmport++);
1914 tmport += 0x03;
1915 outb(inqd[8], tmport);
1916 tmport += 0x07;
1917
1918 while ((inb(tmport) & 0x80) == 0x00)
1919 cpu_relax();
1920
1921 tmport -= 0x08;
1922 if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1923 continue;
1924
1925 while (inb(tmport) != 0x8e)
1926 cpu_relax();
1927
1928 tmport = wkport + 0x5b;
1929 outb(0x00, tmport);
1930 tmport = wkport + 0x58;
1931 outb(0x08, tmport);
1932 tmport += 0x07;
1933 j = 0;
1934rd_inq_data:
1935 k = inb(tmport);
1936 if ((k & 0x01) != 0) {
1937 tmport -= 0x06;
1938 mbuf[j++] = inb(tmport);
1939 tmport += 0x06;
1940 goto rd_inq_data;
1941 }
1942 if ((k & 0x80) == 0) {
1943 goto rd_inq_data;
1944 }
1945 tmport -= 0x08;
1946 j = inb(tmport);
1947 if (j == 0x16) {
1948 goto inq_ok;
1949 }
1950 tmport = wkport + 0x50;
1951 outb(0x46, tmport);
1952 tmport += 0x02;
1953 outb(0, tmport++);
1954 outb(0, tmport++);
1955 outb(0, tmport++);
1956 tmport += 0x03;
1957 outb(0x08, tmport);
1958 tmport += 0x07;
1959 while ((inb(tmport) & 0x80) == 0x00)
1960 cpu_relax();
1961
1962 tmport -= 0x08;
1963 if (inb(tmport) != 0x16)
1964 goto sel_ok;
1965
1966inq_ok:
1967 mbuf[36] = 0;
1968 printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]);
1969 dev->id[0][i].devtype = mbuf[0];
1970 rmb = mbuf[1];
1971 n = mbuf[7];
1972 if ((mbuf[7] & 0x60) == 0) {
1973 goto not_wide;
1974 }
1975 if ((i < 8) && ((dev->global_map[0] & 0x20) == 0)) {
1976 goto not_wide;
1977 }
1978 if (lvdmode == 0) {
1979 goto chg_wide;
1980 }
1981 if (dev->sp[0][i] != 0x04) // force u2
1982 {
1983 goto chg_wide;
1984 }
1985
1986 tmport = wkport + 0x5b;
1987 outb(0x01, tmport);
1988 tmport = wkport + 0x43;
1989 outb(satn[0], tmport++);
1990 outb(satn[1], tmport++);
1991 outb(satn[2], tmport++);
1992 outb(satn[3], tmport++);
1993 outb(satn[4], tmport++);
1994 outb(satn[5], tmport++);
1995 tmport += 0x06;
1996 outb(0, tmport);
1997 tmport += 0x02;
1998 outb(dev->id[0][i].devsp, tmport++);
1999 outb(0, tmport++);
2000 outb(satn[6], tmport++);
2001 outb(satn[7], tmport++);
2002 tmport += 0x03;
2003 outb(satn[8], tmport);
2004 tmport += 0x07;
2005
2006 while ((inb(tmport) & 0x80) == 0x00)
2007 cpu_relax();
2008
2009 tmport -= 0x08;
2010
2011 if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
2012 continue;
2013
2014 while (inb(tmport) != 0x8e)
2015 cpu_relax();
2016
2017try_u3:
2018 j = 0;
2019 tmport = wkport + 0x54;
2020 outb(0x09, tmport);
2021 tmport += 0x04;
2022 outb(0x20, tmport);
2023 tmport += 0x07;
2024
2025 while ((inb(tmport) & 0x80) == 0) {
2026 if ((inb(tmport) & 0x01) != 0) {
2027 tmport -= 0x06;
2028 outb(u3[j++], tmport);
2029 tmport += 0x06;
2030 }
2031 }
2032 tmport -= 0x08;
2033
2034 while ((inb(tmport) & 0x80) == 0x00)
2035 cpu_relax();
2036
2037 j = inb(tmport) & 0x0f;
2038 if (j == 0x0f) {
2039 goto u3p_in;
2040 }
2041 if (j == 0x0a) {
2042 goto u3p_cmd;
2043 }
2044 if (j == 0x0e) {
2045 goto try_u3;
2046 }
2047 continue;
2048u3p_out:
2049 tmport = wkport + 0x58;
2050 outb(0x20, tmport);
2051 tmport += 0x07;
2052 while ((inb(tmport) & 0x80) == 0) {
2053 if ((inb(tmport) & 0x01) != 0) {
2054 tmport -= 0x06;
2055 outb(0, tmport);
2056 tmport += 0x06;
2057 }
2058 }
2059 tmport -= 0x08;
2060 j = inb(tmport) & 0x0f;
2061 if (j == 0x0f) {
2062 goto u3p_in;
2063 }
2064 if (j == 0x0a) {
2065 goto u3p_cmd;
2066 }
2067 if (j == 0x0e) {
2068 goto u3p_out;
2069 }
2070 continue;
2071u3p_in:
2072 tmport = wkport + 0x54;
2073 outb(0x09, tmport);
2074 tmport += 0x04;
2075 outb(0x20, tmport);
2076 tmport += 0x07;
2077 k = 0;
2078u3p_in1:
2079 j = inb(tmport);
2080 if ((j & 0x01) != 0) {
2081 tmport -= 0x06;
2082 mbuf[k++] = inb(tmport);
2083 tmport += 0x06;
2084 goto u3p_in1;
2085 }
2086 if ((j & 0x80) == 0x00) {
2087 goto u3p_in1;
2088 }
2089 tmport -= 0x08;
2090 j = inb(tmport) & 0x0f;
2091 if (j == 0x0f) {
2092 goto u3p_in;
2093 }
2094 if (j == 0x0a) {
2095 goto u3p_cmd;
2096 }
2097 if (j == 0x0e) {
2098 goto u3p_out;
2099 }
2100 continue;
2101u3p_cmd:
2102 tmport = wkport + 0x50;
2103 outb(0x30, tmport);
2104 tmport = wkport + 0x54;
2105 outb(0x00, tmport);
2106 tmport += 0x04;
2107 outb(0x08, tmport);
2108 tmport += 0x07;
2109
2110 while ((inb(tmport) & 0x80) == 0x00)
2111 cpu_relax();
2112
2113 tmport -= 0x08;
2114 j = inb(tmport);
2115 if (j != 0x16) {
2116 if (j == 0x4e) {
2117 goto u3p_out;
2118 }
2119 continue;
2120 }
2121 if (mbuf[0] != 0x01) {
2122 goto chg_wide;
2123 }
2124 if (mbuf[1] != 0x06) {
2125 goto chg_wide;
2126 }
2127 if (mbuf[2] != 0x04) {
2128 goto chg_wide;
2129 }
2130 if (mbuf[3] == 0x09) {
2131 m = 1;
2132 m = m << i;
2133 dev->wide_id[0] |= m;
2134 dev->id[0][i].devsp = 0xce;
2135 continue;
2136 }
2137chg_wide:
2138 tmport = wkport + 0x5b;
2139 outb(0x01, tmport);
2140 tmport = wkport + 0x43;
2141 outb(satn[0], tmport++);
2142 outb(satn[1], tmport++);
2143 outb(satn[2], tmport++);
2144 outb(satn[3], tmport++);
2145 outb(satn[4], tmport++);
2146 outb(satn[5], tmport++);
2147 tmport += 0x06;
2148 outb(0, tmport);
2149 tmport += 0x02;
2150 outb(dev->id[0][i].devsp, tmport++);
2151 outb(0, tmport++);
2152 outb(satn[6], tmport++);
2153 outb(satn[7], tmport++);
2154 tmport += 0x03;
2155 outb(satn[8], tmport);
2156 tmport += 0x07;
2157
2158 while ((inb(tmport) & 0x80) == 0x00)
2159 cpu_relax();
2160
2161 tmport -= 0x08;
2162 if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
2163 continue;
2164
2165 while (inb(tmport) != 0x8e)
2166 cpu_relax();
2167
2168try_wide:
2169 j = 0;
2170 tmport = wkport + 0x54;
2171 outb(0x05, tmport);
2172 tmport += 0x04;
2173 outb(0x20, tmport);
2174 tmport += 0x07;
2175
2176 while ((inb(tmport) & 0x80) == 0) {
2177 if ((inb(tmport) & 0x01) != 0) {
2178 tmport -= 0x06;
2179 outb(wide[j++], tmport);
2180 tmport += 0x06;
2181 }
2182 }
2183 tmport -= 0x08;
2184 while ((inb(tmport) & 0x80) == 0x00)
2185 cpu_relax();
2186
2187 j = inb(tmport) & 0x0f;
2188 if (j == 0x0f) {
2189 goto widep_in;
2190 }
2191 if (j == 0x0a) {
2192 goto widep_cmd;
2193 }
2194 if (j == 0x0e) {
2195 goto try_wide;
2196 }
2197 continue;
2198widep_out:
2199 tmport = wkport + 0x58;
2200 outb(0x20, tmport);
2201 tmport += 0x07;
2202 while ((inb(tmport) & 0x80) == 0) {
2203 if ((inb(tmport) & 0x01) != 0) {
2204 tmport -= 0x06;
2205 outb(0, tmport);
2206 tmport += 0x06;
2207 }
2208 }
2209 tmport -= 0x08;
2210 j = inb(tmport) & 0x0f;
2211 if (j == 0x0f) {
2212 goto widep_in;
2213 }
2214 if (j == 0x0a) {
2215 goto widep_cmd;
2216 }
2217 if (j == 0x0e) {
2218 goto widep_out;
2219 }
2220 continue;
2221widep_in:
2222 tmport = wkport + 0x54;
2223 outb(0xff, tmport);
2224 tmport += 0x04;
2225 outb(0x20, tmport);
2226 tmport += 0x07;
2227 k = 0;
2228widep_in1:
2229 j = inb(tmport);
2230 if ((j & 0x01) != 0) {
2231 tmport -= 0x06;
2232 mbuf[k++] = inb(tmport);
2233 tmport += 0x06;
2234 goto widep_in1;
2235 }
2236 if ((j & 0x80) == 0x00) {
2237 goto widep_in1;
2238 }
2239 tmport -= 0x08;
2240 j = inb(tmport) & 0x0f;
2241 if (j == 0x0f) {
2242 goto widep_in;
2243 }
2244 if (j == 0x0a) {
2245 goto widep_cmd;
2246 }
2247 if (j == 0x0e) {
2248 goto widep_out;
2249 }
2250 continue;
2251widep_cmd:
2252 tmport = wkport + 0x50;
2253 outb(0x30, tmport);
2254 tmport = wkport + 0x54;
2255 outb(0x00, tmport);
2256 tmport += 0x04;
2257 outb(0x08, tmport);
2258 tmport += 0x07;
2259
2260 while ((inb(tmport) & 0x80) == 0x00)
2261 cpu_relax();
2262
2263 tmport -= 0x08;
2264 j = inb(tmport);
2265 if (j != 0x16) {
2266 if (j == 0x4e) {
2267 goto widep_out;
2268 }
2269 continue;
2270 }
2271 if (mbuf[0] != 0x01) {
2272 goto not_wide;
2273 }
2274 if (mbuf[1] != 0x02) {
2275 goto not_wide;
2276 }
2277 if (mbuf[2] != 0x03) {
2278 goto not_wide;
2279 }
2280 if (mbuf[3] != 0x01) {
2281 goto not_wide;
2282 }
2283 m = 1;
2284 m = m << i;
2285 dev->wide_id[0] |= m;
2286not_wide:
2287 if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) {
2288 m = 1;
2289 m = m << i;
2290 if ((dev->async[0] & m) != 0) {
2291 goto set_sync;
2292 }
2293 }
2294 continue;
2295set_sync:
2296 if (dev->sp[0][i] == 0x02) {
2297 synu[4] = 0x0c;
2298 synuw[4] = 0x0c;
2299 } else {
2300 if (dev->sp[0][i] >= 0x03) {
2301 synu[4] = 0x0a;
2302 synuw[4] = 0x0a;
2303 }
2304 }
2305 tmport = wkport + 0x5b;
2306 j = 0;
2307 if ((m & dev->wide_id[0]) != 0) {
2308 j |= 0x01;
2309 }
2310 outb(j, tmport);
2311 tmport = wkport + 0x43;
2312 outb(satn[0], tmport++);
2313 outb(satn[1], tmport++);
2314 outb(satn[2], tmport++);
2315 outb(satn[3], tmport++);
2316 outb(satn[4], tmport++);
2317 outb(satn[5], tmport++);
2318 tmport += 0x06;
2319 outb(0, tmport);
2320 tmport += 0x02;
2321 outb(dev->id[0][i].devsp, tmport++);
2322 outb(0, tmport++);
2323 outb(satn[6], tmport++);
2324 outb(satn[7], tmport++);
2325 tmport += 0x03;
2326 outb(satn[8], tmport);
2327 tmport += 0x07;
2328
2329 while ((inb(tmport) & 0x80) == 0x00)
2330 cpu_relax();
2331
2332 tmport -= 0x08;
2333 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
2334 continue;
2335 }
2336 while (inb(tmport) != 0x8e)
2337 cpu_relax();
2338
2339try_sync:
2340 j = 0;
2341 tmport = wkport + 0x54;
2342 outb(0x06, tmport);
2343 tmport += 0x04;
2344 outb(0x20, tmport);
2345 tmport += 0x07;
2346
2347 while ((inb(tmport) & 0x80) == 0) {
2348 if ((inb(tmport) & 0x01) != 0) {
2349 tmport -= 0x06;
2350 if ((m & dev->wide_id[0]) != 0) {
2351 if ((m & dev->ultra_map[0]) != 0) {
2352 outb(synuw[j++], tmport);
2353 } else {
2354 outb(synw[j++], tmport);
2355 }
2356 } else {
2357 if ((m & dev->ultra_map[0]) != 0) {
2358 outb(synu[j++], tmport);
2359 } else {
2360 outb(synn[j++], tmport);
2361 }
2362 }
2363 tmport += 0x06;
2364 }
2365 }
2366 tmport -= 0x08;
2367
2368 while ((inb(tmport) & 0x80) == 0x00)
2369 cpu_relax();
2370
2371 j = inb(tmport) & 0x0f;
2372 if (j == 0x0f) {
2373 goto phase_ins;
2374 }
2375 if (j == 0x0a) {
2376 goto phase_cmds;
2377 }
2378 if (j == 0x0e) {
2379 goto try_sync;
2380 }
2381 continue;
2382phase_outs:
2383 tmport = wkport + 0x58;
2384 outb(0x20, tmport);
2385 tmport += 0x07;
2386 while ((inb(tmport) & 0x80) == 0x00) {
2387 if ((inb(tmport) & 0x01) != 0x00) {
2388 tmport -= 0x06;
2389 outb(0x00, tmport);
2390 tmport += 0x06;
2391 }
2392 }
2393 tmport -= 0x08;
2394 j = inb(tmport);
2395 if (j == 0x85) {
2396 goto tar_dcons;
2397 }
2398 j &= 0x0f;
2399 if (j == 0x0f) {
2400 goto phase_ins;
2401 }
2402 if (j == 0x0a) {
2403 goto phase_cmds;
2404 }
2405 if (j == 0x0e) {
2406 goto phase_outs;
2407 }
2408 continue;
2409phase_ins:
2410 tmport = wkport + 0x54;
2411 outb(0x06, tmport);
2412 tmport += 0x04;
2413 outb(0x20, tmport);
2414 tmport += 0x07;
2415 k = 0;
2416phase_ins1:
2417 j = inb(tmport);
2418 if ((j & 0x01) != 0x00) {
2419 tmport -= 0x06;
2420 mbuf[k++] = inb(tmport);
2421 tmport += 0x06;
2422 goto phase_ins1;
2423 }
2424 if ((j & 0x80) == 0x00) {
2425 goto phase_ins1;
2426 }
2427 tmport -= 0x08;
2428
2429 while ((inb(tmport) & 0x80) == 0x00)
2430 cpu_relax();
2431
2432 j = inb(tmport);
2433 if (j == 0x85) {
2434 goto tar_dcons;
2435 }
2436 j &= 0x0f;
2437 if (j == 0x0f) {
2438 goto phase_ins;
2439 }
2440 if (j == 0x0a) {
2441 goto phase_cmds;
2442 }
2443 if (j == 0x0e) {
2444 goto phase_outs;
2445 }
2446 continue;
2447phase_cmds:
2448 tmport = wkport + 0x50;
2449 outb(0x30, tmport);
2450tar_dcons:
2451 tmport = wkport + 0x54;
2452 outb(0x00, tmport);
2453 tmport += 0x04;
2454 outb(0x08, tmport);
2455 tmport += 0x07;
2456
2457 while ((inb(tmport) & 0x80) == 0x00)
2458 cpu_relax();
2459
2460 tmport -= 0x08;
2461 j = inb(tmport);
2462 if (j != 0x16) {
2463 continue;
2464 }
2465 if (mbuf[0] != 0x01) {
2466 continue;
2467 }
2468 if (mbuf[1] != 0x03) {
2469 continue;
2470 }
2471 if (mbuf[4] == 0x00) {
2472 continue;
2473 }
2474 if (mbuf[3] > 0x64) {
2475 continue;
2476 }
2477 if (mbuf[4] > 0x0e) {
2478 mbuf[4] = 0x0e;
2479 }
2480 dev->id[0][i].devsp = mbuf[4];
2481 if (mbuf[3] < 0x0c) {
2482 j = 0xb0;
2483 goto set_syn_ok;
2484 }
2485 if ((mbuf[3] < 0x0d) && (rmb == 0)) {
2486 j = 0xa0;
2487 goto set_syn_ok;
2488 }
2489 if (mbuf[3] < 0x1a) {
2490 j = 0x20;
2491 goto set_syn_ok;
2492 }
2493 if (mbuf[3] < 0x33) {
2494 j = 0x40;
2495 goto set_syn_ok;
2496 }
2497 if (mbuf[3] < 0x4c) {
2498 j = 0x50;
2499 goto set_syn_ok;
2500 }
2501 j = 0x60;
2502set_syn_ok:
2503 dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j;
2504 }
2505}
2506
2507static void atp870u_free_tables(struct Scsi_Host *host)
2508{
2509 struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
2510 int j, k;
2511 for (j=0; j < 2; j++) {
2512 for (k = 0; k < 16; k++) {
2513 if (!atp_dev->id[j][k].prd_table)
2514 continue;
b5683557 2515 pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prd_bus);
1da177e4
LT
2516 atp_dev->id[j][k].prd_table = NULL;
2517 }
2518 }
2519}
2520
2521static int atp870u_init_tables(struct Scsi_Host *host)
2522{
2523 struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
2524 int c,k;
2525 for(c=0;c < 2;c++) {
2526 for(k=0;k<16;k++) {
b5683557 2527 atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prd_bus));
1da177e4
LT
2528 if (!atp_dev->id[c][k].prd_table) {
2529 printk("atp870u_init_tables fail\n");
2530 atp870u_free_tables(host);
2531 return -ENOMEM;
2532 }
b5683557 2533 atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus;
1da177e4
LT
2534 atp_dev->id[c][k].devsp=0x20;
2535 atp_dev->id[c][k].devtype = 0x7f;
2536 atp_dev->id[c][k].curr_req = NULL;
2537 }
2538
2539 atp_dev->active_id[c] = 0;
2540 atp_dev->wide_id[c] = 0;
2541 atp_dev->host_id[c] = 0x07;
2542 atp_dev->quhd[c] = 0;
2543 atp_dev->quend[c] = 0;
2544 atp_dev->last_cmd[c] = 0xff;
2545 atp_dev->in_snd[c] = 0;
2546 atp_dev->in_int[c] = 0;
2547
2548 for (k = 0; k < qcnt; k++) {
2549 atp_dev->quereq[c][k] = NULL;
2550 }
2551 for (k = 0; k < 16; k++) {
2552 atp_dev->id[c][k].curr_req = NULL;
2553 atp_dev->sp[c][k] = 0x04;
2554 }
2555 }
2556 return 0;
2557}
2558
2559/* return non-zero on detection */
2560static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2561{
2562 unsigned char k, m, c;
2563 unsigned long flags;
2564 unsigned int base_io, tmport, error,n;
2565 unsigned char host_id;
2566 struct Scsi_Host *shpnt = NULL;
dc6a78f1 2567 struct atp_unit *atpdev, *p;
1da177e4
LT
2568 unsigned char setupdata[2][16];
2569 int count = 0;
dc6a78f1
RD
2570
2571 atpdev = kzalloc(sizeof(*atpdev), GFP_KERNEL);
2572 if (!atpdev)
2573 return -ENOMEM;
2574
1da177e4 2575 if (pci_enable_device(pdev))
dc6a78f1 2576 goto err_eio;
1da177e4 2577
284901a9 2578 if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
1da177e4
LT
2579 printk(KERN_INFO "atp870u: use 32bit DMA mask.\n");
2580 } else {
2581 printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
dc6a78f1 2582 goto err_eio;
1da177e4
LT
2583 }
2584
1da177e4
LT
2585 /*
2586 * It's probably easier to weed out some revisions like
2587 * this than via the PCI device table
2588 */
2589 if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) {
7d7311c4 2590 atpdev->chip_ver = pdev->revision;
dc6a78f1
RD
2591 if (atpdev->chip_ver < 2)
2592 goto err_eio;
1da177e4
LT
2593 }
2594
2595 switch (ent->device) {
2596 case PCI_DEVICE_ID_ARTOP_AEC7612UW:
2597 case PCI_DEVICE_ID_ARTOP_AEC7612SUW:
2598 case ATP880_DEVID1:
2599 case ATP880_DEVID2:
2600 case ATP885_DEVID:
dc6a78f1 2601 atpdev->chip_ver = 0x04;
1da177e4
LT
2602 default:
2603 break;
2604 }
2605 base_io = pci_resource_start(pdev, 0);
2606 base_io &= 0xfffffff8;
dc6a78f1 2607
1da177e4 2608 if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) {
7d7311c4 2609 atpdev->chip_ver = pdev->revision;
1da177e4
LT
2610 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
2611
2612 host_id = inb(base_io + 0x39);
2613 host_id >>= 0x04;
2614
2615 printk(KERN_INFO " ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d"
2616 " IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
dc6a78f1
RD
2617 atpdev->ioport[0] = base_io + 0x40;
2618 atpdev->pciport[0] = base_io + 0x28;
2619 atpdev->dev_id = ent->device;
2620 atpdev->host_id[0] = host_id;
1da177e4
LT
2621
2622 tmport = base_io + 0x22;
dc6a78f1 2623 atpdev->scam_on = inb(tmport);
1da177e4 2624 tmport += 0x13;
dc6a78f1 2625 atpdev->global_map[0] = inb(tmport);
1da177e4 2626 tmport += 0x07;
dc6a78f1 2627 atpdev->ultra_map[0] = inw(tmport);
1da177e4
LT
2628
2629 n = 0x3f09;
2630next_fblk_880:
2631 if (n >= 0x4000)
2632 goto flash_ok_880;
2633
2634 m = 0;
2635 outw(n, base_io + 0x34);
2636 n += 0x0002;
2637 if (inb(base_io + 0x30) == 0xff)
2638 goto flash_ok_880;
2639
dc6a78f1
RD
2640 atpdev->sp[0][m++] = inb(base_io + 0x30);
2641 atpdev->sp[0][m++] = inb(base_io + 0x31);
2642 atpdev->sp[0][m++] = inb(base_io + 0x32);
2643 atpdev->sp[0][m++] = inb(base_io + 0x33);
1da177e4
LT
2644 outw(n, base_io + 0x34);
2645 n += 0x0002;
dc6a78f1
RD
2646 atpdev->sp[0][m++] = inb(base_io + 0x30);
2647 atpdev->sp[0][m++] = inb(base_io + 0x31);
2648 atpdev->sp[0][m++] = inb(base_io + 0x32);
2649 atpdev->sp[0][m++] = inb(base_io + 0x33);
1da177e4
LT
2650 outw(n, base_io + 0x34);
2651 n += 0x0002;
dc6a78f1
RD
2652 atpdev->sp[0][m++] = inb(base_io + 0x30);
2653 atpdev->sp[0][m++] = inb(base_io + 0x31);
2654 atpdev->sp[0][m++] = inb(base_io + 0x32);
2655 atpdev->sp[0][m++] = inb(base_io + 0x33);
1da177e4
LT
2656 outw(n, base_io + 0x34);
2657 n += 0x0002;
dc6a78f1
RD
2658 atpdev->sp[0][m++] = inb(base_io + 0x30);
2659 atpdev->sp[0][m++] = inb(base_io + 0x31);
2660 atpdev->sp[0][m++] = inb(base_io + 0x32);
2661 atpdev->sp[0][m++] = inb(base_io + 0x33);
1da177e4
LT
2662 n += 0x0018;
2663 goto next_fblk_880;
2664flash_ok_880:
2665 outw(0, base_io + 0x34);
dc6a78f1
RD
2666 atpdev->ultra_map[0] = 0;
2667 atpdev->async[0] = 0;
1da177e4
LT
2668 for (k = 0; k < 16; k++) {
2669 n = 1;
2670 n = n << k;
dc6a78f1
RD
2671 if (atpdev->sp[0][k] > 1) {
2672 atpdev->ultra_map[0] |= n;
1da177e4 2673 } else {
dc6a78f1
RD
2674 if (atpdev->sp[0][k] == 0)
2675 atpdev->async[0] |= n;
1da177e4
LT
2676 }
2677 }
dc6a78f1
RD
2678 atpdev->async[0] = ~(atpdev->async[0]);
2679 outb(atpdev->global_map[0], base_io + 0x35);
1da177e4
LT
2680
2681 shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
2682 if (!shpnt)
dc6a78f1 2683 goto err_nomem;
1da177e4
LT
2684
2685 p = (struct atp_unit *)&shpnt->hostdata;
2686
dc6a78f1
RD
2687 atpdev->host = shpnt;
2688 atpdev->pdev = pdev;
1da177e4 2689 pci_set_drvdata(pdev, p);
dc6a78f1 2690 memcpy(p, atpdev, sizeof(*atpdev));
1da177e4
LT
2691 if (atp870u_init_tables(shpnt) < 0) {
2692 printk(KERN_ERR "Unable to allocate tables for Acard controller\n");
2693 goto unregister;
2694 }
2695
1d6f359a 2696 if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp880i", shpnt)) {
1da177e4
LT
2697 printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
2698 goto free_tables;
2699 }
2700
2701 spin_lock_irqsave(shpnt->host_lock, flags);
2702 tmport = base_io + 0x38;
2703 k = inb(tmport) & 0x80;
2704 outb(k, tmport);
2705 tmport += 0x03;
2706 outb(0x20, tmport);
2707 mdelay(32);
2708 outb(0, tmport);
2709 mdelay(32);
2710 tmport = base_io + 0x5b;
2711 inb(tmport);
2712 tmport -= 0x04;
2713 inb(tmport);
2714 tmport = base_io + 0x40;
2715 outb((host_id | 0x08), tmport);
2716 tmport += 0x18;
2717 outb(0, tmport);
2718 tmport += 0x07;
2719 while ((inb(tmport) & 0x80) == 0)
2720 mdelay(1);
2721 tmport -= 0x08;
2722 inb(tmport);
2723 tmport = base_io + 0x41;
2724 outb(8, tmport++);
2725 outb(0x7f, tmport);
2726 tmport = base_io + 0x51;
2727 outb(0x20, tmport);
2728
2729 tscam(shpnt);
2730 is880(p, base_io);
2731 tmport = base_io + 0x38;
2732 outb(0xb0, tmport);
2733 shpnt->max_id = 16;
2734 shpnt->this_id = host_id;
2735 shpnt->unique_id = base_io;
2736 shpnt->io_port = base_io;
2737 shpnt->n_io_port = 0x60; /* Number of bytes of I/O space used */
2738 shpnt->irq = pdev->irq;
2739 } else if (ent->device == ATP885_DEVID) {
2740 printk(KERN_INFO " ACARD AEC-67162 PCI Ultra3 LVD Host Adapter: IO:%x, IRQ:%d.\n"
2741 , base_io, pdev->irq);
2742
dc6a78f1
RD
2743 atpdev->pdev = pdev;
2744 atpdev->dev_id = ent->device;
2745 atpdev->baseport = base_io;
2746 atpdev->ioport[0] = base_io + 0x80;
2747 atpdev->ioport[1] = base_io + 0xc0;
2748 atpdev->pciport[0] = base_io + 0x40;
2749 atpdev->pciport[1] = base_io + 0x50;
1da177e4
LT
2750
2751 shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
2752 if (!shpnt)
dc6a78f1 2753 goto err_nomem;
1da177e4
LT
2754
2755 p = (struct atp_unit *)&shpnt->hostdata;
2756
dc6a78f1
RD
2757 atpdev->host = shpnt;
2758 atpdev->pdev = pdev;
1da177e4 2759 pci_set_drvdata(pdev, p);
dc6a78f1 2760 memcpy(p, atpdev, sizeof(struct atp_unit));
1da177e4
LT
2761 if (atp870u_init_tables(shpnt) < 0)
2762 goto unregister;
2763
2764#ifdef ED_DBGP
2765 printk("request_irq() shpnt %p hostdata %p\n", shpnt, p);
2766#endif
1d6f359a 2767 if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp870u", shpnt)) {
1da177e4
LT
2768 printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
2769 goto free_tables;
2770 }
2771
2772 spin_lock_irqsave(shpnt->host_lock, flags);
2773
2774 c=inb(base_io + 0x29);
2775 outb((c | 0x04),base_io + 0x29);
2776
2777 n=0x1f80;
2778next_fblk_885:
2779 if (n >= 0x2000) {
2780 goto flash_ok_885;
2781 }
2782 outw(n,base_io + 0x3c);
2783 if (inl(base_io + 0x38) == 0xffffffff) {
2784 goto flash_ok_885;
2785 }
2786 for (m=0; m < 2; m++) {
2787 p->global_map[m]= 0;
2788 for (k=0; k < 4; k++) {
2789 outw(n++,base_io + 0x3c);
2790 ((unsigned long *)&setupdata[m][0])[k]=inl(base_io + 0x38);
2791 }
2792 for (k=0; k < 4; k++) {
2793 outw(n++,base_io + 0x3c);
2794 ((unsigned long *)&p->sp[m][0])[k]=inl(base_io + 0x38);
2795 }
2796 n += 8;
2797 }
2798 goto next_fblk_885;
2799flash_ok_885:
2800#ifdef ED_DBGP
2801 printk( "Flash Read OK\n");
2802#endif
2803 c=inb(base_io + 0x29);
2804 outb((c & 0xfb),base_io + 0x29);
2805 for (c=0;c < 2;c++) {
2806 p->ultra_map[c]=0;
2807 p->async[c] = 0;
2808 for (k=0; k < 16; k++) {
2809 n=1;
2810 n = n << k;
2811 if (p->sp[c][k] > 1) {
2812 p->ultra_map[c] |= n;
2813 } else {
2814 if (p->sp[c][k] == 0) {
2815 p->async[c] |= n;
2816 }
2817 }
2818 }
2819 p->async[c] = ~(p->async[c]);
2820
2821 if (p->global_map[c] == 0) {
2822 k=setupdata[c][1];
2823 if ((k & 0x40) != 0)
2824 p->global_map[c] |= 0x20;
2825 k &= 0x07;
2826 p->global_map[c] |= k;
2827 if ((setupdata[c][2] & 0x04) != 0)
2828 p->global_map[c] |= 0x08;
2829 p->host_id[c] = setupdata[c][0] & 0x07;
2830 }
2831 }
2832
2833 k = inb(base_io + 0x28) & 0x8f;
2834 k |= 0x10;
2835 outb(k, base_io + 0x28);
2836 outb(0x80, base_io + 0x41);
2837 outb(0x80, base_io + 0x51);
2838 mdelay(100);
2839 outb(0, base_io + 0x41);
2840 outb(0, base_io + 0x51);
2841 mdelay(1000);
2842 inb(base_io + 0x9b);
2843 inb(base_io + 0x97);
2844 inb(base_io + 0xdb);
2845 inb(base_io + 0xd7);
2846 tmport = base_io + 0x80;
2847 k=p->host_id[0];
2848 if (k > 7)
2849 k = (k & 0x07) | 0x40;
2850 k |= 0x08;
2851 outb(k, tmport);
2852 tmport += 0x18;
2853 outb(0, tmport);
2854 tmport += 0x07;
2855
2856 while ((inb(tmport) & 0x80) == 0)
2857 cpu_relax();
2858
2859 tmport -= 0x08;
2860 inb(tmport);
2861 tmport = base_io + 0x81;
2862 outb(8, tmport++);
2863 outb(0x7f, tmport);
2864 tmport = base_io + 0x91;
2865 outb(0x20, tmport);
2866
2867 tmport = base_io + 0xc0;
2868 k=p->host_id[1];
2869 if (k > 7)
2870 k = (k & 0x07) | 0x40;
2871 k |= 0x08;
2872 outb(k, tmport);
2873 tmport += 0x18;
2874 outb(0, tmport);
2875 tmport += 0x07;
2876
2877 while ((inb(tmport) & 0x80) == 0)
2878 cpu_relax();
2879
2880 tmport -= 0x08;
2881 inb(tmport);
2882 tmport = base_io + 0xc1;
2883 outb(8, tmport++);
2884 outb(0x7f, tmport);
2885 tmport = base_io + 0xd1;
2886 outb(0x20, tmport);
2887
2888 tscam_885();
2889 printk(KERN_INFO " Scanning Channel A SCSI Device ...\n");
2890 is885(p, base_io + 0x80, 0);
2891 printk(KERN_INFO " Scanning Channel B SCSI Device ...\n");
2892 is885(p, base_io + 0xc0, 1);
2893
2894 k = inb(base_io + 0x28) & 0xcf;
2895 k |= 0xc0;
2896 outb(k, base_io + 0x28);
2897 k = inb(base_io + 0x1f) | 0x80;
2898 outb(k, base_io + 0x1f);
2899 k = inb(base_io + 0x29) | 0x01;
2900 outb(k, base_io + 0x29);
2901#ifdef ED_DBGP
2902 //printk("atp885: atp_host[0] 0x%p\n", atp_host[0]);
2903#endif
2904 shpnt->max_id = 16;
2905 shpnt->max_lun = (p->global_map[0] & 0x07) + 1;
2906 shpnt->max_channel = 1;
2907 shpnt->this_id = p->host_id[0];
2908 shpnt->unique_id = base_io;
2909 shpnt->io_port = base_io;
2910 shpnt->n_io_port = 0xff; /* Number of bytes of I/O space used */
2911 shpnt->irq = pdev->irq;
2912
2913 } else {
2914 error = pci_read_config_byte(pdev, 0x49, &host_id);
2915
2916 printk(KERN_INFO " ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d "
2917 "IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
2918
dc6a78f1
RD
2919 atpdev->ioport[0] = base_io;
2920 atpdev->pciport[0] = base_io + 0x20;
2921 atpdev->dev_id = ent->device;
1da177e4 2922 host_id &= 0x07;
dc6a78f1 2923 atpdev->host_id[0] = host_id;
1da177e4 2924 tmport = base_io + 0x22;
dc6a78f1 2925 atpdev->scam_on = inb(tmport);
1da177e4 2926 tmport += 0x0b;
dc6a78f1
RD
2927 atpdev->global_map[0] = inb(tmport++);
2928 atpdev->ultra_map[0] = inw(tmport);
1da177e4 2929
dc6a78f1
RD
2930 if (atpdev->ultra_map[0] == 0) {
2931 atpdev->scam_on = 0x00;
2932 atpdev->global_map[0] = 0x20;
2933 atpdev->ultra_map[0] = 0xffff;
1da177e4
LT
2934 }
2935
2936 shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
2937 if (!shpnt)
dc6a78f1 2938 goto err_nomem;
1da177e4
LT
2939
2940 p = (struct atp_unit *)&shpnt->hostdata;
2941
dc6a78f1
RD
2942 atpdev->host = shpnt;
2943 atpdev->pdev = pdev;
1da177e4 2944 pci_set_drvdata(pdev, p);
dc6a78f1 2945 memcpy(p, atpdev, sizeof(*atpdev));
1da177e4
LT
2946 if (atp870u_init_tables(shpnt) < 0)
2947 goto unregister;
2948
1d6f359a 2949 if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp870i", shpnt)) {
1da177e4
LT
2950 printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
2951 goto free_tables;
2952 }
2953
2954 spin_lock_irqsave(shpnt->host_lock, flags);
dc6a78f1 2955 if (atpdev->chip_ver > 0x07) { /* check if atp876 chip then enable terminator */
1da177e4
LT
2956 tmport = base_io + 0x3e;
2957 outb(0x00, tmport);
2958 }
2959
2960 tmport = base_io + 0x3a;
2961 k = (inb(tmport) & 0xf3) | 0x10;
2962 outb(k, tmport);
2963 outb((k & 0xdf), tmport);
2964 mdelay(32);
2965 outb(k, tmport);
2966 mdelay(32);
2967 tmport = base_io;
2968 outb((host_id | 0x08), tmport);
2969 tmport += 0x18;
2970 outb(0, tmport);
2971 tmport += 0x07;
2972 while ((inb(tmport) & 0x80) == 0)
2973 mdelay(1);
2974
2975 tmport -= 0x08;
2976 inb(tmport);
2977 tmport = base_io + 1;
2978 outb(8, tmport++);
2979 outb(0x7f, tmport);
2980 tmport = base_io + 0x11;
2981 outb(0x20, tmport);
2982
2983 tscam(shpnt);
2984 is870(p, base_io);
2985 tmport = base_io + 0x3a;
2986 outb((inb(tmport) & 0xef), tmport);
2987 tmport++;
2988 outb((inb(tmport) | 0x20), tmport);
dc6a78f1 2989 if (atpdev->chip_ver == 4)
1da177e4
LT
2990 shpnt->max_id = 16;
2991 else
2b89dad0 2992 shpnt->max_id = 8;
1da177e4
LT
2993 shpnt->this_id = host_id;
2994 shpnt->unique_id = base_io;
2995 shpnt->io_port = base_io;
2996 shpnt->n_io_port = 0x40; /* Number of bytes of I/O space used */
2997 shpnt->irq = pdev->irq;
2998 }
2999 spin_unlock_irqrestore(shpnt->host_lock, flags);
3000 if(ent->device==ATP885_DEVID) {
3001 if(!request_region(base_io, 0xff, "atp870u")) /* Register the IO ports that we use */
3002 goto request_io_fail;
3003 } else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
3004 if(!request_region(base_io, 0x60, "atp870u")) /* Register the IO ports that we use */
3005 goto request_io_fail;
3006 } else {
3007 if(!request_region(base_io, 0x40, "atp870u")) /* Register the IO ports that we use */
3008 goto request_io_fail;
3009 }
3010 count++;
3011 if (scsi_add_host(shpnt, &pdev->dev))
3012 goto scsi_add_fail;
3013 scsi_scan_host(shpnt);
3014#ifdef ED_DBGP
3015 printk("atp870u_prob : exit\n");
3016#endif
3017 return 0;
3018
3019scsi_add_fail:
3020 printk("atp870u_prob:scsi_add_fail\n");
3021 if(ent->device==ATP885_DEVID) {
3022 release_region(base_io, 0xff);
3023 } else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
3024 release_region(base_io, 0x60);
3025 } else {
3026 release_region(base_io, 0x40);
3027 }
3028request_io_fail:
3029 printk("atp870u_prob:request_io_fail\n");
3030 free_irq(pdev->irq, shpnt);
3031free_tables:
3032 printk("atp870u_prob:free_table\n");
3033 atp870u_free_tables(shpnt);
3034unregister:
3035 printk("atp870u_prob:unregister\n");
3036 scsi_host_put(shpnt);
3037 return -1;
dc6a78f1
RD
3038err_eio:
3039 kfree(atpdev);
3040 return -EIO;
3041err_nomem:
3042 kfree(atpdev);
3043 return -ENOMEM;
1da177e4
LT
3044}
3045
3046/* The abort command does not leave the device in a clean state where
3047 it is available to be used again. Until this gets worked out, we will
3048 leave it commented out. */
3049
3050static int atp870u_abort(struct scsi_cmnd * SCpnt)
3051{
3052 unsigned char j, k, c;
3053 struct scsi_cmnd *workrequ;
3054 unsigned int tmport;
3055 struct atp_unit *dev;
3056 struct Scsi_Host *host;
3057 host = SCpnt->device->host;
3058
3059 dev = (struct atp_unit *)&host->hostdata;
422c0d61 3060 c = scmd_channel(SCpnt);
1da177e4
LT
3061 printk(" atp870u: abort Channel = %x \n", c);
3062 printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]);
3063 printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]);
3064 tmport = dev->ioport[c];
3065 for (j = 0; j < 0x18; j++) {
3066 printk(" r%2x=%2x", j, inb(tmport++));
3067 }
3068 tmport += 0x04;
3069 printk(" r1c=%2x", inb(tmport));
3070 tmport += 0x03;
3071 printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd[c]);
3072 tmport= dev->pciport[c];
3073 printk(" d00=%2x", inb(tmport));
3074 tmport += 0x02;
3075 printk(" d02=%2x", inb(tmport));
3076 for(j=0;j<16;j++) {
3077 if (dev->id[c][j].curr_req != NULL) {
3078 workrequ = dev->id[c][j].curr_req;
3079 printk("\n que cdb= ");
3080 for (k=0; k < workrequ->cmd_len; k++) {
3081 printk(" %2x ",workrequ->cmnd[k]);
3082 }
3083 printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len);
3084 }
3085 }
3086 return SUCCESS;
3087}
3088
3089static const char *atp870u_info(struct Scsi_Host *notused)
3090{
3091 static char buffer[128];
3092
3093 strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac ");
3094
3095 return buffer;
3096}
3097
d773e422 3098static int atp870u_show_info(struct seq_file *m, struct Scsi_Host *HBAptr)
1da177e4 3099{
3d30079c
RV
3100 seq_puts(m, "ACARD AEC-671X Driver Version: 2.6+ac\n\n"
3101 "Adapter Configuration:\n");
d773e422
AV
3102 seq_printf(m, " Base IO: %#.4lx\n", HBAptr->io_port);
3103 seq_printf(m, " IRQ: %d\n", HBAptr->irq);
3104 return 0;
1da177e4
LT
3105}
3106
3107
3108static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev,
3109 sector_t capacity, int *ip)
3110{
3111 int heads, sectors, cylinders;
3112
3113 heads = 64;
3114 sectors = 32;
3115 cylinders = (unsigned long)capacity / (heads * sectors);
3116 if (cylinders > 1024) {
3117 heads = 255;
3118 sectors = 63;
3119 cylinders = (unsigned long)capacity / (heads * sectors);
3120 }
3121 ip[0] = heads;
3122 ip[1] = sectors;
3123 ip[2] = cylinders;
3124
3125 return 0;
3126}
3127
3128static void atp870u_remove (struct pci_dev *pdev)
3129{
3130 struct atp_unit *devext = pci_get_drvdata(pdev);
3131 struct Scsi_Host *pshost = devext->host;
3132
3133
3134 scsi_remove_host(pshost);
3135 printk(KERN_INFO "free_irq : %d\n",pshost->irq);
3136 free_irq(pshost->irq, pshost);
3137 release_region(pshost->io_port, pshost->n_io_port);
3138 printk(KERN_INFO "atp870u_free_tables : %p\n",pshost);
3139 atp870u_free_tables(pshost);
3140 printk(KERN_INFO "scsi_host_put : %p\n",pshost);
3141 scsi_host_put(pshost);
1da177e4
LT
3142}
3143MODULE_LICENSE("GPL");
3144
3145static struct scsi_host_template atp870u_template = {
3146 .module = THIS_MODULE,
3147 .name = "atp870u" /* name */,
3148 .proc_name = "atp870u",
d773e422 3149 .show_info = atp870u_show_info,
1da177e4
LT
3150 .info = atp870u_info /* info */,
3151 .queuecommand = atp870u_queuecommand /* queuecommand */,
3152 .eh_abort_handler = atp870u_abort /* abort */,
3153 .bios_param = atp870u_biosparam /* biosparm */,
3154 .can_queue = qcnt /* can_queue */,
3155 .this_id = 7 /* SCSI ID */,
3156 .sg_tablesize = ATP870U_SCATTER /*SG_ALL*/ /*SG_NONE*/,
1da177e4
LT
3157 .use_clustering = ENABLE_CLUSTERING,
3158 .max_sectors = ATP870U_MAX_SECTORS,
3159};
3160
3161static struct pci_device_id atp870u_id_table[] = {
3162 { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID) },
3163 { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1) },
3164 { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2) },
3165 { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610) },
3166 { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW) },
3167 { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U) },
3168 { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612S) },
3169 { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612D) },
3170 { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612SUW) },
3171 { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_8060) },
3172 { 0, },
3173};
3174
3175MODULE_DEVICE_TABLE(pci, atp870u_id_table);
3176
3177static struct pci_driver atp870u_driver = {
3178 .id_table = atp870u_id_table,
3179 .name = "atp870u",
3180 .probe = atp870u_probe,
6f039790 3181 .remove = atp870u_remove,
1da177e4
LT
3182};
3183
3184static int __init atp870u_init(void)
3185{
3186#ifdef ED_DBGP
3187 printk("atp870u_init: Entry\n");
3188#endif
3189 return pci_register_driver(&atp870u_driver);
3190}
3191
3192static void __exit atp870u_exit(void)
3193{
3194#ifdef ED_DBGP
3195 printk("atp870u_exit: Entry\n");
3196#endif
3197 pci_unregister_driver(&atp870u_driver);
3198}
3199
3200static void tscam_885(void)
3201{
3202 unsigned char i;
3203
3204 for (i = 0; i < 0x2; i++) {
3205 mdelay(300);
3206 }
3207 return;
3208}
3209
3210
3211
3212static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c)
3213{
3214 unsigned int tmport;
3215 unsigned char i, j, k, rmb, n, lvdmode;
3216 unsigned short int m;
3217 static unsigned char mbuf[512];
3218 static unsigned char satn[9] = {0, 0, 0, 0, 0, 0, 0, 6, 6};
3219 static unsigned char inqd[9] = {0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6};
3220 static unsigned char synn[6] = {0x80, 1, 3, 1, 0x19, 0x0e};
3221 unsigned char synu[6] = {0x80, 1, 3, 1, 0x0a, 0x0e};
3222 static unsigned char synw[6] = {0x80, 1, 3, 1, 0x19, 0x0e};
3223 unsigned char synuw[6] = {0x80, 1, 3, 1, 0x0a, 0x0e};
3224 static unsigned char wide[6] = {0x80, 1, 2, 3, 1, 0};
3225 static unsigned char u3[9] = { 0x80,1,6,4,0x09,00,0x0e,0x01,0x02 };
3226
3227 lvdmode=inb(wkport + 0x1b) >> 7;
3228
3229 for (i = 0; i < 16; i++) {
3230 m = 1;
3231 m = m << i;
3232 if ((m & dev->active_id[c]) != 0) {
3233 continue;
3234 }
3235 if (i == dev->host_id[c]) {
3236 printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_id[c]);
3237 continue;
3238 }
3239 tmport = wkport + 0x1b;
3240 outb(0x01, tmport);
3241 tmport = wkport + 0x01;
3242 outb(0x08, tmport++);
3243 outb(0x7f, tmport++);
3244 outb(satn[0], tmport++);
3245 outb(satn[1], tmport++);
3246 outb(satn[2], tmport++);
3247 outb(satn[3], tmport++);
3248 outb(satn[4], tmport++);
3249 outb(satn[5], tmport++);
3250 tmport += 0x06;
3251 outb(0, tmport);
3252 tmport += 0x02;
3253 outb(dev->id[c][i].devsp, tmport++);
3254
3255 outb(0, tmport++);
3256 outb(satn[6], tmport++);
3257 outb(satn[7], tmport++);
3258 j = i;
3259 if ((j & 0x08) != 0) {
3260 j = (j & 0x07) | 0x40;
3261 }
3262 outb(j, tmport);
3263 tmport += 0x03;
3264 outb(satn[8], tmport);
3265 tmport += 0x07;
3266
3267 while ((inb(tmport) & 0x80) == 0x00)
3268 cpu_relax();
3269 tmport -= 0x08;
3270 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3271 continue;
3272 }
3273 while (inb(tmport) != 0x8e)
3274 cpu_relax();
3275 dev->active_id[c] |= m;
3276
3277 tmport = wkport + 0x10;
3278 outb(0x30, tmport);
3279 tmport = wkport + 0x14;
3280 outb(0x00, tmport);
3281
3282phase_cmd:
3283 tmport = wkport + 0x18;
3284 outb(0x08, tmport);
3285 tmport += 0x07;
3286 while ((inb(tmport) & 0x80) == 0x00)
3287 cpu_relax();
3288 tmport -= 0x08;
3289 j = inb(tmport);
3290 if (j != 0x16) {
3291 tmport = wkport + 0x10;
3292 outb(0x41, tmport);
3293 goto phase_cmd;
3294 }
3295sel_ok:
3296 tmport = wkport + 0x03;
3297 outb(inqd[0], tmport++);
3298 outb(inqd[1], tmport++);
3299 outb(inqd[2], tmport++);
3300 outb(inqd[3], tmport++);
3301 outb(inqd[4], tmport++);
3302 outb(inqd[5], tmport);
3303 tmport += 0x07;
3304 outb(0, tmport);
3305 tmport += 0x02;
3306 outb(dev->id[c][i].devsp, tmport++);
3307 outb(0, tmport++);
3308 outb(inqd[6], tmport++);
3309 outb(inqd[7], tmport++);
3310 tmport += 0x03;
3311 outb(inqd[8], tmport);
3312 tmport += 0x07;
3313 while ((inb(tmport) & 0x80) == 0x00)
3314 cpu_relax();
3315 tmport -= 0x08;
3316 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3317 continue;
3318 }
3319 while (inb(tmport) != 0x8e)
3320 cpu_relax();
3321 tmport = wkport + 0x1b;
3322 outb(0x00, tmport);
3323 tmport = wkport + 0x18;
3324 outb(0x08, tmport);
3325 tmport += 0x07;
3326 j = 0;
3327rd_inq_data:
3328 k = inb(tmport);
3329 if ((k & 0x01) != 0) {
3330 tmport -= 0x06;
3331 mbuf[j++] = inb(tmport);
3332 tmport += 0x06;
3333 goto rd_inq_data;
3334 }
3335 if ((k & 0x80) == 0) {
3336 goto rd_inq_data;
3337 }
3338 tmport -= 0x08;
3339 j = inb(tmport);
3340 if (j == 0x16) {
3341 goto inq_ok;
3342 }
3343 tmport = wkport + 0x10;
3344 outb(0x46, tmport);
3345 tmport += 0x02;
3346 outb(0, tmport++);
3347 outb(0, tmport++);
3348 outb(0, tmport++);
3349 tmport += 0x03;
3350 outb(0x08, tmport);
3351 tmport += 0x07;
3352 while ((inb(tmport) & 0x80) == 0x00)
3353 cpu_relax();
3354 tmport -= 0x08;
3355 if (inb(tmport) != 0x16) {
3356 goto sel_ok;
3357 }
3358inq_ok:
3359 mbuf[36] = 0;
3360 printk( KERN_INFO" ID: %2d %s\n", i, &mbuf[8]);
3361 dev->id[c][i].devtype = mbuf[0];
3362 rmb = mbuf[1];
3363 n = mbuf[7];
3364 if ((mbuf[7] & 0x60) == 0) {
3365 goto not_wide;
3366 }
3367 if ((i < 8) && ((dev->global_map[c] & 0x20) == 0)) {
3368 goto not_wide;
3369 }
3370 if (lvdmode == 0) {
3371 goto chg_wide;
3372 }
3373 if (dev->sp[c][i] != 0x04) { // force u2
3374 goto chg_wide;
3375 }
3376
3377 tmport = wkport + 0x1b;
3378 outb(0x01, tmport);
3379 tmport = wkport + 0x03;
3380 outb(satn[0], tmport++);
3381 outb(satn[1], tmport++);
3382 outb(satn[2], tmport++);
3383 outb(satn[3], tmport++);
3384 outb(satn[4], tmport++);
3385 outb(satn[5], tmport++);
3386 tmport += 0x06;
3387 outb(0, tmport);
3388 tmport += 0x02;
3389 outb(dev->id[c][i].devsp, tmport++);
3390 outb(0, tmport++);
3391 outb(satn[6], tmport++);
3392 outb(satn[7], tmport++);
3393 tmport += 0x03;
3394 outb(satn[8], tmport);
3395 tmport += 0x07;
3396
3397 while ((inb(tmport) & 0x80) == 0x00)
3398 cpu_relax();
3399 tmport -= 0x08;
3400 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3401 continue;
3402 }
3403 while (inb(tmport) != 0x8e)
3404 cpu_relax();
3405try_u3:
3406 j = 0;
3407 tmport = wkport + 0x14;
3408 outb(0x09, tmport);
3409 tmport += 0x04;
3410 outb(0x20, tmport);
3411 tmport += 0x07;
3412
3413 while ((inb(tmport) & 0x80) == 0) {
3414 if ((inb(tmport) & 0x01) != 0) {
3415 tmport -= 0x06;
3416 outb(u3[j++], tmport);
3417 tmport += 0x06;
3418 }
3419 cpu_relax();
3420 }
3421 tmport -= 0x08;
3422 while ((inb(tmport) & 0x80) == 0x00)
3423 cpu_relax();
3424 j = inb(tmport) & 0x0f;
3425 if (j == 0x0f) {
3426 goto u3p_in;
3427 }
3428 if (j == 0x0a) {
3429 goto u3p_cmd;
3430 }
3431 if (j == 0x0e) {
3432 goto try_u3;
3433 }
3434 continue;
3435u3p_out:
3436 tmport = wkport + 0x18;
3437 outb(0x20, tmport);
3438 tmport += 0x07;
3439 while ((inb(tmport) & 0x80) == 0) {
3440 if ((inb(tmport) & 0x01) != 0) {
3441 tmport -= 0x06;
3442 outb(0, tmport);
3443 tmport += 0x06;
3444 }
3445 cpu_relax();
3446 }
3447 tmport -= 0x08;
3448 j = inb(tmport) & 0x0f;
3449 if (j == 0x0f) {
3450 goto u3p_in;
3451 }
3452 if (j == 0x0a) {
3453 goto u3p_cmd;
3454 }
3455 if (j == 0x0e) {
3456 goto u3p_out;
3457 }
3458 continue;
3459u3p_in:
3460 tmport = wkport + 0x14;
3461 outb(0x09, tmport);
3462 tmport += 0x04;
3463 outb(0x20, tmport);
3464 tmport += 0x07;
3465 k = 0;
3466u3p_in1:
3467 j = inb(tmport);
3468 if ((j & 0x01) != 0) {
3469 tmport -= 0x06;
3470 mbuf[k++] = inb(tmport);
3471 tmport += 0x06;
3472 goto u3p_in1;
3473 }
3474 if ((j & 0x80) == 0x00) {
3475 goto u3p_in1;
3476 }
3477 tmport -= 0x08;
3478 j = inb(tmport) & 0x0f;
3479 if (j == 0x0f) {
3480 goto u3p_in;
3481 }
3482 if (j == 0x0a) {
3483 goto u3p_cmd;
3484 }
3485 if (j == 0x0e) {
3486 goto u3p_out;
3487 }
3488 continue;
3489u3p_cmd:
3490 tmport = wkport + 0x10;
3491 outb(0x30, tmport);
3492 tmport = wkport + 0x14;
3493 outb(0x00, tmport);
3494 tmport += 0x04;
3495 outb(0x08, tmport);
3496 tmport += 0x07;
3497 while ((inb(tmport) & 0x80) == 0x00);
3498 tmport -= 0x08;
3499 j = inb(tmport);
3500 if (j != 0x16) {
3501 if (j == 0x4e) {
3502 goto u3p_out;
3503 }
3504 continue;
3505 }
3506 if (mbuf[0] != 0x01) {
3507 goto chg_wide;
3508 }
3509 if (mbuf[1] != 0x06) {
3510 goto chg_wide;
3511 }
3512 if (mbuf[2] != 0x04) {
3513 goto chg_wide;
3514 }
3515 if (mbuf[3] == 0x09) {
3516 m = 1;
3517 m = m << i;
3518 dev->wide_id[c] |= m;
3519 dev->id[c][i].devsp = 0xce;
3520#ifdef ED_DBGP
3521 printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
3522#endif
3523 continue;
3524 }
3525chg_wide:
3526 tmport = wkport + 0x1b;
3527 outb(0x01, tmport);
3528 tmport = wkport + 0x03;
3529 outb(satn[0], tmport++);
3530 outb(satn[1], tmport++);
3531 outb(satn[2], tmport++);
3532 outb(satn[3], tmport++);
3533 outb(satn[4], tmport++);
3534 outb(satn[5], tmport++);
3535 tmport += 0x06;
3536 outb(0, tmport);
3537 tmport += 0x02;
3538 outb(dev->id[c][i].devsp, tmport++);
3539 outb(0, tmport++);
3540 outb(satn[6], tmport++);
3541 outb(satn[7], tmport++);
3542 tmport += 0x03;
3543 outb(satn[8], tmport);
3544 tmport += 0x07;
3545
3546 while ((inb(tmport) & 0x80) == 0x00)
3547 cpu_relax();
3548 tmport -= 0x08;
3549 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3550 continue;
3551 }
3552 while (inb(tmport) != 0x8e)
3553 cpu_relax();
3554try_wide:
3555 j = 0;
3556 tmport = wkport + 0x14;
3557 outb(0x05, tmport);
3558 tmport += 0x04;
3559 outb(0x20, tmport);
3560 tmport += 0x07;
3561
3562 while ((inb(tmport) & 0x80) == 0) {
3563 if ((inb(tmport) & 0x01) != 0) {
3564 tmport -= 0x06;
3565 outb(wide[j++], tmport);
3566 tmport += 0x06;
3567 }
3568 cpu_relax();
3569 }
3570 tmport -= 0x08;
3571 while ((inb(tmport) & 0x80) == 0x00)
3572 cpu_relax();
3573 j = inb(tmport) & 0x0f;
3574 if (j == 0x0f) {
3575 goto widep_in;
3576 }
3577 if (j == 0x0a) {
3578 goto widep_cmd;
3579 }
3580 if (j == 0x0e) {
3581 goto try_wide;
3582 }
3583 continue;
3584widep_out:
3585 tmport = wkport + 0x18;
3586 outb(0x20, tmport);
3587 tmport += 0x07;
3588 while ((inb(tmport) & 0x80) == 0) {
3589 if ((inb(tmport) & 0x01) != 0) {
3590 tmport -= 0x06;
3591 outb(0, tmport);
3592 tmport += 0x06;
3593 }
3594 cpu_relax();
3595 }
3596 tmport -= 0x08;
3597 j = inb(tmport) & 0x0f;
3598 if (j == 0x0f) {
3599 goto widep_in;
3600 }
3601 if (j == 0x0a) {
3602 goto widep_cmd;
3603 }
3604 if (j == 0x0e) {
3605 goto widep_out;
3606 }
3607 continue;
3608widep_in:
3609 tmport = wkport + 0x14;
3610 outb(0xff, tmport);
3611 tmport += 0x04;
3612 outb(0x20, tmport);
3613 tmport += 0x07;
3614 k = 0;
3615widep_in1:
3616 j = inb(tmport);
3617 if ((j & 0x01) != 0) {
3618 tmport -= 0x06;
3619 mbuf[k++] = inb(tmport);
3620 tmport += 0x06;
3621 goto widep_in1;
3622 }
3623 if ((j & 0x80) == 0x00) {
3624 goto widep_in1;
3625 }
3626 tmport -= 0x08;
3627 j = inb(tmport) & 0x0f;
3628 if (j == 0x0f) {
3629 goto widep_in;
3630 }
3631 if (j == 0x0a) {
3632 goto widep_cmd;
3633 }
3634 if (j == 0x0e) {
3635 goto widep_out;
3636 }
3637 continue;
3638widep_cmd:
3639 tmport = wkport + 0x10;
3640 outb(0x30, tmport);
3641 tmport = wkport + 0x14;
3642 outb(0x00, tmport);
3643 tmport += 0x04;
3644 outb(0x08, tmport);
3645 tmport += 0x07;
3646 while ((inb(tmport) & 0x80) == 0x00)
3647 cpu_relax();
3648 tmport -= 0x08;
3649 j = inb(tmport);
3650 if (j != 0x16) {
3651 if (j == 0x4e) {
3652 goto widep_out;
3653 }
3654 continue;
3655 }
3656 if (mbuf[0] != 0x01) {
3657 goto not_wide;
3658 }
3659 if (mbuf[1] != 0x02) {
3660 goto not_wide;
3661 }
3662 if (mbuf[2] != 0x03) {
3663 goto not_wide;
3664 }
3665 if (mbuf[3] != 0x01) {
3666 goto not_wide;
3667 }
3668 m = 1;
3669 m = m << i;
3670 dev->wide_id[c] |= m;
3671not_wide:
3672 if ((dev->id[c][i].devtype == 0x00) || (dev->id[c][i].devtype == 0x07) ||
3673 ((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) {
3674 m = 1;
3675 m = m << i;
3676 if ((dev->async[c] & m) != 0) {
3677 goto set_sync;
3678 }
3679 }
3680 continue;
3681set_sync:
3682 if (dev->sp[c][i] == 0x02) {
3683 synu[4]=0x0c;
3684 synuw[4]=0x0c;
3685 } else {
3686 if (dev->sp[c][i] >= 0x03) {
3687 synu[4]=0x0a;
3688 synuw[4]=0x0a;
3689 }
3690 }
3691 tmport = wkport + 0x1b;
3692 j = 0;
3693 if ((m & dev->wide_id[c]) != 0) {
3694 j |= 0x01;
3695 }
3696 outb(j, tmport);
3697 tmport = wkport + 0x03;
3698 outb(satn[0], tmport++);
3699 outb(satn[1], tmport++);
3700 outb(satn[2], tmport++);
3701 outb(satn[3], tmport++);
3702 outb(satn[4], tmport++);
3703 outb(satn[5], tmport++);
3704 tmport += 0x06;
3705 outb(0, tmport);
3706 tmport += 0x02;
3707 outb(dev->id[c][i].devsp, tmport++);
3708 outb(0, tmport++);
3709 outb(satn[6], tmport++);
3710 outb(satn[7], tmport++);
3711 tmport += 0x03;
3712 outb(satn[8], tmport);
3713 tmport += 0x07;
3714
3715 while ((inb(tmport) & 0x80) == 0x00)
3716 cpu_relax();
3717 tmport -= 0x08;
3718 if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3719 continue;
3720 }
3721 while (inb(tmport) != 0x8e)
3722 cpu_relax();
3723try_sync:
3724 j = 0;
3725 tmport = wkport + 0x14;
3726 outb(0x06, tmport);
3727 tmport += 0x04;
3728 outb(0x20, tmport);
3729 tmport += 0x07;
3730
3731 while ((inb(tmport) & 0x80) == 0) {
3732 if ((inb(tmport) & 0x01) != 0) {
3733 tmport -= 0x06;
3734 if ((m & dev->wide_id[c]) != 0) {
3735 if ((m & dev->ultra_map[c]) != 0) {
3736 outb(synuw[j++], tmport);
3737 } else {
3738 outb(synw[j++], tmport);
3739 }
3740 } else {
3741 if ((m & dev->ultra_map[c]) != 0) {
3742 outb(synu[j++], tmport);
3743 } else {
3744 outb(synn[j++], tmport);
3745 }
3746 }
3747 tmport += 0x06;
3748 }
3749 }
3750 tmport -= 0x08;
3751 while ((inb(tmport) & 0x80) == 0x00)
3752 cpu_relax();
3753 j = inb(tmport) & 0x0f;
3754 if (j == 0x0f) {
3755 goto phase_ins;
3756 }
3757 if (j == 0x0a) {
3758 goto phase_cmds;
3759 }
3760 if (j == 0x0e) {
3761 goto try_sync;
3762 }
3763 continue;
3764phase_outs:
3765 tmport = wkport + 0x18;
3766 outb(0x20, tmport);
3767 tmport += 0x07;
3768 while ((inb(tmport) & 0x80) == 0x00) {
3769 if ((inb(tmport) & 0x01) != 0x00) {
3770 tmport -= 0x06;
3771 outb(0x00, tmport);
3772 tmport += 0x06;
3773 }
3774 cpu_relax();
3775 }
3776 tmport -= 0x08;
3777 j = inb(tmport);
3778 if (j == 0x85) {
3779 goto tar_dcons;
3780 }
3781 j &= 0x0f;
3782 if (j == 0x0f) {
3783 goto phase_ins;
3784 }
3785 if (j == 0x0a) {
3786 goto phase_cmds;
3787 }
3788 if (j == 0x0e) {
3789 goto phase_outs;
3790 }
3791 continue;
3792phase_ins:
3793 tmport = wkport + 0x14;
3794 outb(0x06, tmport);
3795 tmport += 0x04;
3796 outb(0x20, tmport);
3797 tmport += 0x07;
3798 k = 0;
3799phase_ins1:
3800 j = inb(tmport);
3801 if ((j & 0x01) != 0x00) {
3802 tmport -= 0x06;
3803 mbuf[k++] = inb(tmport);
3804 tmport += 0x06;
3805 goto phase_ins1;
3806 }
3807 if ((j & 0x80) == 0x00) {
3808 goto phase_ins1;
3809 }
3810 tmport -= 0x08;
3811 while ((inb(tmport) & 0x80) == 0x00);
3812 j = inb(tmport);
3813 if (j == 0x85) {
3814 goto tar_dcons;
3815 }
3816 j &= 0x0f;
3817 if (j == 0x0f) {
3818 goto phase_ins;
3819 }
3820 if (j == 0x0a) {
3821 goto phase_cmds;
3822 }
3823 if (j == 0x0e) {
3824 goto phase_outs;
3825 }
3826 continue;
3827phase_cmds:
3828 tmport = wkport + 0x10;
3829 outb(0x30, tmport);
3830tar_dcons:
3831 tmport = wkport + 0x14;
3832 outb(0x00, tmport);
3833 tmport += 0x04;
3834 outb(0x08, tmport);
3835 tmport += 0x07;
3836 while ((inb(tmport) & 0x80) == 0x00)
3837 cpu_relax();
3838 tmport -= 0x08;
3839 j = inb(tmport);
3840 if (j != 0x16) {
3841 continue;
3842 }
3843 if (mbuf[0] != 0x01) {
3844 continue;
3845 }
3846 if (mbuf[1] != 0x03) {
3847 continue;
3848 }
3849 if (mbuf[4] == 0x00) {
3850 continue;
3851 }
3852 if (mbuf[3] > 0x64) {
3853 continue;
3854 }
3855 if (mbuf[4] > 0x0e) {
3856 mbuf[4] = 0x0e;
3857 }
3858 dev->id[c][i].devsp = mbuf[4];
3859 if (mbuf[3] < 0x0c){
3860 j = 0xb0;
3861 goto set_syn_ok;
3862 }
3863 if ((mbuf[3] < 0x0d) && (rmb == 0)) {
3864 j = 0xa0;
3865 goto set_syn_ok;
3866 }
3867 if (mbuf[3] < 0x1a) {
3868 j = 0x20;
3869 goto set_syn_ok;
3870 }
3871 if (mbuf[3] < 0x33) {
3872 j = 0x40;
3873 goto set_syn_ok;
3874 }
3875 if (mbuf[3] < 0x4c) {
3876 j = 0x50;
3877 goto set_syn_ok;
3878 }
3879 j = 0x60;
3880 set_syn_ok:
3881 dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j;
3882#ifdef ED_DBGP
3883 printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
3884#endif
3885 }
3886 tmport = wkport + 0x16;
3887 outb(0x80, tmport);
3888}
3889
3890module_init(atp870u_init);
3891module_exit(atp870u_exit);
3892