1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40#include <linux/blkdev.h>
41#include <linux/interrupt.h>
42#include <linux/module.h>
43#include <linux/kernel.h>
44#include <linux/types.h>
45#include <linux/string.h>
46#include <linux/ioport.h>
47#include <linux/proc_fs.h>
48#include <linux/stat.h>
49#include <linux/init.h>
50#include <linux/device.h>
51#include <linux/eisa.h>
52#include <linux/dma-mapping.h>
53#include <linux/gfp.h>
54
55#include <asm/dma.h>
56#include <asm/io.h>
57
58#include "scsi.h"
59#include <scsi/scsi_host.h>
60#include "aha1740.h"
61
62
63
64
65
66#ifdef DEBUG
67#define DEB(x) x
68#else
69#define DEB(x)
70#endif
71
72struct aha1740_hostdata {
73 struct eisa_device *edev;
74 unsigned int translation;
75 unsigned int last_ecb_used;
76 dma_addr_t ecb_dma_addr;
77 struct ecb ecb[AHA1740_ECBS];
78};
79
80struct aha1740_sg {
81 struct aha1740_chain sg_chain[AHA1740_SCATTER];
82 dma_addr_t sg_dma_addr;
83 dma_addr_t buf_dma_addr;
84};
85
86#define HOSTDATA(host) ((struct aha1740_hostdata *) &host->hostdata)
87
88static inline struct ecb *ecb_dma_to_cpu (struct Scsi_Host *host,
89 dma_addr_t dma)
90{
91 struct aha1740_hostdata *hdata = HOSTDATA (host);
92 dma_addr_t offset;
93
94 offset = dma - hdata->ecb_dma_addr;
95
96 return (struct ecb *)(((char *) hdata->ecb) + (unsigned int) offset);
97}
98
99static inline dma_addr_t ecb_cpu_to_dma (struct Scsi_Host *host, void *cpu)
100{
101 struct aha1740_hostdata *hdata = HOSTDATA (host);
102 dma_addr_t offset;
103
104 offset = (char *) cpu - (char *) hdata->ecb;
105
106 return hdata->ecb_dma_addr + offset;
107}
108
109static int aha1740_show_info(struct seq_file *m, struct Scsi_Host *shpnt)
110{
111 struct aha1740_hostdata *host = HOSTDATA(shpnt);
112 seq_printf(m, "aha174x at IO:%lx, IRQ %d, SLOT %d.\n"
113 "Extended translation %sabled.\n",
114 shpnt->io_port, shpnt->irq, host->edev->slot,
115 host->translation ? "en" : "dis");
116 return 0;
117}
118
119static int aha1740_makecode(unchar *sense, unchar *status)
120{
121 struct statusword
122 {
123 ushort don:1,
124 du:1,
125 :1, qf:1,
126 sc:1,
127 dor:1,
128 ch:1,
129 intr:1,
130 asa:1,
131 sns:1,
132 :1, ini:1,
133 me:1,
134 :1, eca:1,
135 :1;
136 } status_word;
137 int retval = DID_OK;
138
139 status_word = * (struct statusword *) status;
140#ifdef DEBUG
141 printk("makecode from %x,%x,%x,%x %x,%x,%x,%x",
142 status[0], status[1], status[2], status[3],
143 sense[0], sense[1], sense[2], sense[3]);
144#endif
145 if (!status_word.don) {
146 if ( (status[1]&0x18) || status_word.sc ) {
147
148
149 switch ( status[2] ) {
150 case 0x12:
151 if ( status_word.dor )
152 retval=DID_ERROR;
153
154
155 case 0x00:
156
157 break;
158 case 0x11:
159 case 0x21:
160 retval=DID_TIME_OUT;
161 break;
162 case 0x0a:
163 retval=DID_BAD_TARGET;
164 break;
165 case 0x04:
166 case 0x05:
167 retval=DID_ABORT;
168
169
170 break;
171 default:
172 retval=DID_ERROR;
173
174
175 }
176 } else {
177
178 if ( status_word.qf ) {
179 retval = DID_TIME_OUT;
180
181
182 printk("aha1740.c: WARNING: AHA1740 queue overflow!\n");
183 } else
184 if ( status[0]&0x60 ) {
185
186 retval = DID_ERROR;
187 }
188
189
190
191 }
192 }
193
194 return status[3] | retval << 16;
195}
196
197static int aha1740_test_port(unsigned int base)
198{
199 if ( inb(PORTADR(base)) & PORTADDR_ENH )
200 return 1;
201
202 printk("aha174x: Board detected, but not in enhanced mode, so disabled it.\n");
203 return 0;
204}
205
206
207static irqreturn_t aha1740_intr_handle(int irq, void *dev_id)
208{
209 struct Scsi_Host *host = (struct Scsi_Host *) dev_id;
210 void (*my_done)(Scsi_Cmnd *);
211 int errstatus, adapstat;
212 int number_serviced;
213 struct ecb *ecbptr;
214 Scsi_Cmnd *SCtmp;
215 unsigned int base;
216 unsigned long flags;
217 int handled = 0;
218 struct aha1740_sg *sgptr;
219 struct eisa_device *edev;
220
221 if (!host)
222 panic("aha1740.c: Irq from unknown host!\n");
223 spin_lock_irqsave(host->host_lock, flags);
224 base = host->io_port;
225 number_serviced = 0;
226 edev = HOSTDATA(host)->edev;
227
228 while(inb(G2STAT(base)) & G2STAT_INTPEND) {
229 handled = 1;
230 DEB(printk("aha1740_intr top of loop.\n"));
231 adapstat = inb(G2INTST(base));
232 ecbptr = ecb_dma_to_cpu (host, inl(MBOXIN0(base)));
233 outb(G2CNTRL_IRST,G2CNTRL(base));
234
235 switch ( adapstat & G2INTST_MASK ) {
236 case G2INTST_CCBRETRY:
237 case G2INTST_CCBERROR:
238 case G2INTST_CCBGOOD:
239
240 outb(G2CNTRL_HRDY,G2CNTRL(base));
241 if (!ecbptr) {
242 printk("Aha1740 null ecbptr in interrupt (%x,%x,%x,%d)\n",
243 inb(G2STAT(base)),adapstat,
244 inb(G2INTST(base)), number_serviced++);
245 continue;
246 }
247 SCtmp = ecbptr->SCpnt;
248 if (!SCtmp) {
249 printk("Aha1740 null SCtmp in interrupt (%x,%x,%x,%d)\n",
250 inb(G2STAT(base)),adapstat,
251 inb(G2INTST(base)), number_serviced++);
252 continue;
253 }
254 sgptr = (struct aha1740_sg *) SCtmp->host_scribble;
255 scsi_dma_unmap(SCtmp);
256
257
258 dma_free_coherent (&edev->dev,
259 sizeof (struct aha1740_sg),
260 SCtmp->host_scribble,
261 sgptr->sg_dma_addr);
262
263
264
265
266
267
268 if ( (adapstat & G2INTST_MASK) == G2INTST_CCBERROR ) {
269 memcpy(SCtmp->sense_buffer, ecbptr->sense,
270 SCSI_SENSE_BUFFERSIZE);
271 errstatus = aha1740_makecode(ecbptr->sense,ecbptr->status);
272 } else
273 errstatus = 0;
274 DEB(if (errstatus)
275 printk("aha1740_intr_handle: returning %6x\n",
276 errstatus));
277 SCtmp->result = errstatus;
278 my_done = ecbptr->done;
279 memset(ecbptr,0,sizeof(struct ecb));
280 if ( my_done )
281 my_done(SCtmp);
282 break;
283
284 case G2INTST_HARDFAIL:
285 printk(KERN_ALERT "aha1740 hardware failure!\n");
286 panic("aha1740.c");
287
288 case G2INTST_ASNEVENT:
289 printk("aha1740 asynchronous event: %02x %02x %02x %02x %02x\n",
290 adapstat,
291 inb(MBOXIN0(base)),
292 inb(MBOXIN1(base)),
293 inb(MBOXIN2(base)),
294 inb(MBOXIN3(base)));
295
296 outb(G2CNTRL_HRDY,G2CNTRL(base));
297 break;
298
299 case G2INTST_CMDGOOD:
300
301 break;
302
303 case G2INTST_CMDERROR:
304
305 break;
306 }
307 number_serviced++;
308 }
309
310 spin_unlock_irqrestore(host->host_lock, flags);
311 return IRQ_RETVAL(handled);
312}
313
314static int aha1740_queuecommand_lck(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
315{
316 unchar direction;
317 unchar *cmd = (unchar *) SCpnt->cmnd;
318 unchar target = scmd_id(SCpnt);
319 struct aha1740_hostdata *host = HOSTDATA(SCpnt->device->host);
320 unsigned long flags;
321 dma_addr_t sg_dma;
322 struct aha1740_sg *sgptr;
323 int ecbno, nseg;
324 DEB(int i);
325
326 if(*cmd == REQUEST_SENSE) {
327 SCpnt->result = 0;
328 done(SCpnt);
329 return 0;
330 }
331
332#ifdef DEBUG
333 if (*cmd == READ_10 || *cmd == WRITE_10)
334 i = xscsi2int(cmd+2);
335 else if (*cmd == READ_6 || *cmd == WRITE_6)
336 i = scsi2int(cmd+2);
337 else
338 i = -1;
339 printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ",
340 target, *cmd, i, bufflen);
341 printk("scsi cmd:");
342 for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]);
343 printk("\n");
344#endif
345
346
347 spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
348 ecbno = host->last_ecb_used + 1;
349 if (ecbno >= AHA1740_ECBS)
350 ecbno = 0;
351 do {
352 if (!host->ecb[ecbno].cmdw)
353 break;
354 ecbno++;
355 if (ecbno >= AHA1740_ECBS)
356 ecbno = 0;
357 } while (ecbno != host->last_ecb_used);
358
359 if (host->ecb[ecbno].cmdw)
360 panic("Unable to find empty ecb for aha1740.\n");
361
362 host->ecb[ecbno].cmdw = AHA1740CMD_INIT;
363
364
365 host->last_ecb_used = ecbno;
366 spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
367
368#ifdef DEBUG
369 printk("Sending command (%d %x)...", ecbno, done);
370#endif
371
372 host->ecb[ecbno].cdblen = SCpnt->cmd_len;
373
374
375
376 direction = 0;
377 if (*cmd == READ_10 || *cmd == READ_6)
378 direction = 1;
379 else if (*cmd == WRITE_10 || *cmd == WRITE_6)
380 direction = 0;
381
382 memcpy(host->ecb[ecbno].cdb, cmd, SCpnt->cmd_len);
383
384 SCpnt->host_scribble = dma_alloc_coherent (&host->edev->dev,
385 sizeof (struct aha1740_sg),
386 &sg_dma, GFP_ATOMIC);
387 if(SCpnt->host_scribble == NULL) {
388 printk(KERN_WARNING "aha1740: out of memory in queuecommand!\n");
389 return 1;
390 }
391 sgptr = (struct aha1740_sg *) SCpnt->host_scribble;
392 sgptr->sg_dma_addr = sg_dma;
393
394 nseg = scsi_dma_map(SCpnt);
395 BUG_ON(nseg < 0);
396 if (nseg) {
397 struct scatterlist *sg;
398 struct aha1740_chain * cptr;
399 int i;
400 DEB(unsigned char * ptr);
401
402 host->ecb[ecbno].sg = 1;
403
404 cptr = sgptr->sg_chain;
405 scsi_for_each_sg(SCpnt, sg, nseg, i) {
406 cptr[i].datalen = sg_dma_len (sg);
407 cptr[i].dataptr = sg_dma_address (sg);
408 }
409 host->ecb[ecbno].datalen = nseg * sizeof(struct aha1740_chain);
410 host->ecb[ecbno].dataptr = sg_dma;
411#ifdef DEBUG
412 printk("cptr %x: ",cptr);
413 ptr = (unsigned char *) cptr;
414 for(i=0;i<24;i++) printk("%02x ", ptr[i]);
415#endif
416 } else {
417 host->ecb[ecbno].datalen = 0;
418 host->ecb[ecbno].dataptr = 0;
419 }
420 host->ecb[ecbno].lun = SCpnt->device->lun;
421 host->ecb[ecbno].ses = 1;
422 host->ecb[ecbno].dir = direction;
423 host->ecb[ecbno].ars = 1;
424 host->ecb[ecbno].senselen = 12;
425 host->ecb[ecbno].senseptr = ecb_cpu_to_dma (SCpnt->device->host,
426 host->ecb[ecbno].sense);
427 host->ecb[ecbno].statusptr = ecb_cpu_to_dma (SCpnt->device->host,
428 host->ecb[ecbno].status);
429 host->ecb[ecbno].done = done;
430 host->ecb[ecbno].SCpnt = SCpnt;
431#ifdef DEBUG
432 {
433 int i;
434 printk("aha1740_command: sending.. ");
435 for (i = 0; i < sizeof(host->ecb[ecbno]) - 10; i++)
436 printk("%02x ", ((unchar *)&host->ecb[ecbno])[i]);
437 }
438 printk("\n");
439#endif
440 if (done) {
441
442
443
444
445
446
447
448
449
450
451
452
453#define LOOPCNT_WARN 10
454#define LOOPCNT_MAX 1000000
455 int loopcnt;
456 unsigned int base = SCpnt->device->host->io_port;
457 DEB(printk("aha1740[%d] critical section\n",ecbno));
458
459 spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
460 for (loopcnt = 0; ; loopcnt++) {
461 if (inb(G2STAT(base)) & G2STAT_MBXOUT) break;
462 if (loopcnt == LOOPCNT_WARN) {
463 printk("aha1740[%d]_mbxout wait!\n",ecbno);
464 }
465 if (loopcnt == LOOPCNT_MAX)
466 panic("aha1740.c: mbxout busy!\n");
467 }
468 outl (ecb_cpu_to_dma (SCpnt->device->host, host->ecb + ecbno),
469 MBOXOUT0(base));
470 for (loopcnt = 0; ; loopcnt++) {
471 if (! (inb(G2STAT(base)) & G2STAT_BUSY)) break;
472 if (loopcnt == LOOPCNT_WARN) {
473 printk("aha1740[%d]_attn wait!\n",ecbno);
474 }
475 if (loopcnt == LOOPCNT_MAX)
476 panic("aha1740.c: attn wait failed!\n");
477 }
478 outb(ATTN_START | (target & 7), ATTN(base));
479 spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
480 DEB(printk("aha1740[%d] request queued.\n",ecbno));
481 } else
482 printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n");
483 return 0;
484}
485
486static DEF_SCSI_QCMD(aha1740_queuecommand)
487
488
489
490
491static void aha1740_getconfig(unsigned int base, unsigned int *irq_level,
492 unsigned int *irq_type,
493 unsigned int *translation)
494{
495 static int intab[] = { 9, 10, 11, 12, 0, 14, 15, 0 };
496
497 *irq_level = intab[inb(INTDEF(base)) & 0x7];
498 *irq_type = (inb(INTDEF(base)) & 0x8) >> 3;
499 *translation = inb(RESV1(base)) & 0x1;
500 outb(inb(INTDEF(base)) | 0x10, INTDEF(base));
501}
502
503static int aha1740_biosparam(struct scsi_device *sdev,
504 struct block_device *dev,
505 sector_t capacity, int* ip)
506{
507 int size = capacity;
508 int extended = HOSTDATA(sdev->host)->translation;
509
510 DEB(printk("aha1740_biosparam\n"));
511 if (extended && (ip[2] > 1024)) {
512 ip[0] = 255;
513 ip[1] = 63;
514 ip[2] = size / (255 * 63);
515 } else {
516 ip[0] = 64;
517 ip[1] = 32;
518 ip[2] = size >> 11;
519 }
520 return 0;
521}
522
523static int aha1740_eh_abort_handler (Scsi_Cmnd *dummy)
524{
525
526
527
528
529
530
531
532
533
534 return SUCCESS;
535}
536
537static struct scsi_host_template aha1740_template = {
538 .module = THIS_MODULE,
539 .proc_name = "aha1740",
540 .show_info = aha1740_show_info,
541 .name = "Adaptec 174x (EISA)",
542 .queuecommand = aha1740_queuecommand,
543 .bios_param = aha1740_biosparam,
544 .can_queue = AHA1740_ECBS,
545 .this_id = 7,
546 .sg_tablesize = AHA1740_SCATTER,
547 .use_clustering = ENABLE_CLUSTERING,
548 .eh_abort_handler = aha1740_eh_abort_handler,
549};
550
551static int aha1740_probe (struct device *dev)
552{
553 int slotbase, rc;
554 unsigned int irq_level, irq_type, translation;
555 struct Scsi_Host *shpnt;
556 struct aha1740_hostdata *host;
557 struct eisa_device *edev = to_eisa_device (dev);
558
559 DEB(printk("aha1740_probe: \n"));
560
561 slotbase = edev->base_addr + EISA_VENDOR_ID_OFFSET;
562 if (!request_region(slotbase, SLOTSIZE, "aha1740"))
563 return -EBUSY;
564 if (!aha1740_test_port(slotbase))
565 goto err_release_region;
566 aha1740_getconfig(slotbase,&irq_level,&irq_type,&translation);
567 if ((inb(G2STAT(slotbase)) &
568 (G2STAT_MBXOUT|G2STAT_BUSY)) != G2STAT_MBXOUT) {
569
570 outb(G2CNTRL_HRST, G2CNTRL(slotbase));
571 outb(0, G2CNTRL(slotbase));
572 }
573 printk(KERN_INFO "Configuring slot %d at IO:%x, IRQ %u (%s)\n",
574 edev->slot, slotbase, irq_level, irq_type ? "edge" : "level");
575 printk(KERN_INFO "aha174x: Extended translation %sabled.\n",
576 translation ? "en" : "dis");
577 shpnt = scsi_host_alloc(&aha1740_template,
578 sizeof(struct aha1740_hostdata));
579 if(shpnt == NULL)
580 goto err_release_region;
581
582 shpnt->base = 0;
583 shpnt->io_port = slotbase;
584 shpnt->n_io_port = SLOTSIZE;
585 shpnt->irq = irq_level;
586 shpnt->dma_channel = 0xff;
587 host = HOSTDATA(shpnt);
588 host->edev = edev;
589 host->translation = translation;
590 host->ecb_dma_addr = dma_map_single (&edev->dev, host->ecb,
591 sizeof (host->ecb),
592 DMA_BIDIRECTIONAL);
593 if (!host->ecb_dma_addr) {
594 printk (KERN_ERR "aha1740_probe: Couldn't map ECB, giving up\n");
595 scsi_unregister (shpnt);
596 goto err_host_put;
597 }
598
599 DEB(printk("aha1740_probe: enable interrupt channel %d\n",irq_level));
600 if (request_irq(irq_level,aha1740_intr_handle,irq_type ? 0 : IRQF_SHARED,
601 "aha1740",shpnt)) {
602 printk(KERN_ERR "aha1740_probe: Unable to allocate IRQ %d.\n",
603 irq_level);
604 goto err_unmap;
605 }
606
607 eisa_set_drvdata (edev, shpnt);
608
609 rc = scsi_add_host (shpnt, dev);
610 if (rc)
611 goto err_irq;
612
613 scsi_scan_host (shpnt);
614 return 0;
615
616 err_irq:
617 free_irq(irq_level, shpnt);
618 err_unmap:
619 dma_unmap_single (&edev->dev, host->ecb_dma_addr,
620 sizeof (host->ecb), DMA_BIDIRECTIONAL);
621 err_host_put:
622 scsi_host_put (shpnt);
623 err_release_region:
624 release_region(slotbase, SLOTSIZE);
625
626 return -ENODEV;
627}
628
629static int aha1740_remove (struct device *dev)
630{
631 struct Scsi_Host *shpnt = dev_get_drvdata(dev);
632 struct aha1740_hostdata *host = HOSTDATA (shpnt);
633
634 scsi_remove_host(shpnt);
635
636 free_irq (shpnt->irq, shpnt);
637 dma_unmap_single (dev, host->ecb_dma_addr,
638 sizeof (host->ecb), DMA_BIDIRECTIONAL);
639 release_region (shpnt->io_port, SLOTSIZE);
640
641 scsi_host_put (shpnt);
642
643 return 0;
644}
645
646static struct eisa_device_id aha1740_ids[] = {
647 { "ADP0000" },
648 { "ADP0001" },
649 { "ADP0002" },
650 { "ADP0400" },
651 { "" }
652};
653MODULE_DEVICE_TABLE(eisa, aha1740_ids);
654
655static struct eisa_driver aha1740_driver = {
656 .id_table = aha1740_ids,
657 .driver = {
658 .name = "aha1740",
659 .probe = aha1740_probe,
660 .remove = aha1740_remove,
661 },
662};
663
664static __init int aha1740_init (void)
665{
666 return eisa_driver_register (&aha1740_driver);
667}
668
669static __exit void aha1740_exit (void)
670{
671 eisa_driver_unregister (&aha1740_driver);
672}
673
674module_init (aha1740_init);
675module_exit (aha1740_exit);
676
677MODULE_LICENSE("GPL");
678