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