This source file includes following definitions.
- ecb_dma_to_cpu
- ecb_cpu_to_dma
- aha1740_show_info
- aha1740_makecode
- aha1740_test_port
- aha1740_intr_handle
- aha1740_queuecommand_lck
- DEF_SCSI_QCMD
- aha1740_biosparam
- aha1740_eh_abort_handler
- aha1740_probe
- aha1740_remove
- aha1740_init
- aha1740_exit
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
72 struct 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
80 struct 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
88 static 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
99 static 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
109 static 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
119 static 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
197 static 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
207 static 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)(struct scsi_cmnd *);
211 int errstatus, adapstat;
212 int number_serviced;
213 struct ecb *ecbptr;
214 struct 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
314 static int aha1740_queuecommand_lck(struct scsi_cmnd * SCpnt,
315 void (*done)(struct scsi_cmnd *))
316 {
317 unchar direction;
318 unchar *cmd = (unchar *) SCpnt->cmnd;
319 unchar target = scmd_id(SCpnt);
320 struct aha1740_hostdata *host = HOSTDATA(SCpnt->device->host);
321 unsigned long flags;
322 dma_addr_t sg_dma;
323 struct aha1740_sg *sgptr;
324 int ecbno, nseg;
325 DEB(int i);
326
327 if(*cmd == REQUEST_SENSE) {
328 SCpnt->result = 0;
329 done(SCpnt);
330 return 0;
331 }
332
333 #ifdef DEBUG
334 if (*cmd == READ_10 || *cmd == WRITE_10)
335 i = xscsi2int(cmd+2);
336 else if (*cmd == READ_6 || *cmd == WRITE_6)
337 i = scsi2int(cmd+2);
338 else
339 i = -1;
340 printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ",
341 target, *cmd, i, bufflen);
342 printk("scsi cmd:");
343 for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]);
344 printk("\n");
345 #endif
346
347
348 spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
349 ecbno = host->last_ecb_used + 1;
350 if (ecbno >= AHA1740_ECBS)
351 ecbno = 0;
352 do {
353 if (!host->ecb[ecbno].cmdw)
354 break;
355 ecbno++;
356 if (ecbno >= AHA1740_ECBS)
357 ecbno = 0;
358 } while (ecbno != host->last_ecb_used);
359
360 if (host->ecb[ecbno].cmdw)
361 panic("Unable to find empty ecb for aha1740.\n");
362
363 host->ecb[ecbno].cmdw = AHA1740CMD_INIT;
364
365
366 host->last_ecb_used = ecbno;
367 spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
368
369 #ifdef DEBUG
370 printk("Sending command (%d %x)...", ecbno, done);
371 #endif
372
373 host->ecb[ecbno].cdblen = SCpnt->cmd_len;
374
375
376
377 direction = 0;
378 if (*cmd == READ_10 || *cmd == READ_6)
379 direction = 1;
380 else if (*cmd == WRITE_10 || *cmd == WRITE_6)
381 direction = 0;
382
383 memcpy(host->ecb[ecbno].cdb, cmd, SCpnt->cmd_len);
384
385 SCpnt->host_scribble = dma_alloc_coherent (&host->edev->dev,
386 sizeof (struct aha1740_sg),
387 &sg_dma, GFP_ATOMIC);
388 if(SCpnt->host_scribble == NULL) {
389 printk(KERN_WARNING "aha1740: out of memory in queuecommand!\n");
390 return 1;
391 }
392 sgptr = (struct aha1740_sg *) SCpnt->host_scribble;
393 sgptr->sg_dma_addr = sg_dma;
394
395 nseg = scsi_dma_map(SCpnt);
396 BUG_ON(nseg < 0);
397 if (nseg) {
398 struct scatterlist *sg;
399 struct aha1740_chain * cptr;
400 int i;
401 DEB(unsigned char * ptr);
402
403 host->ecb[ecbno].sg = 1;
404
405 cptr = sgptr->sg_chain;
406 scsi_for_each_sg(SCpnt, sg, nseg, i) {
407 cptr[i].datalen = sg_dma_len (sg);
408 cptr[i].dataptr = sg_dma_address (sg);
409 }
410 host->ecb[ecbno].datalen = nseg * sizeof(struct aha1740_chain);
411 host->ecb[ecbno].dataptr = sg_dma;
412 #ifdef DEBUG
413 printk("cptr %x: ",cptr);
414 ptr = (unsigned char *) cptr;
415 for(i=0;i<24;i++) printk("%02x ", ptr[i]);
416 #endif
417 } else {
418 host->ecb[ecbno].datalen = 0;
419 host->ecb[ecbno].dataptr = 0;
420 }
421 host->ecb[ecbno].lun = SCpnt->device->lun;
422 host->ecb[ecbno].ses = 1;
423 host->ecb[ecbno].dir = direction;
424 host->ecb[ecbno].ars = 1;
425 host->ecb[ecbno].senselen = 12;
426 host->ecb[ecbno].senseptr = ecb_cpu_to_dma (SCpnt->device->host,
427 host->ecb[ecbno].sense);
428 host->ecb[ecbno].statusptr = ecb_cpu_to_dma (SCpnt->device->host,
429 host->ecb[ecbno].status);
430 host->ecb[ecbno].done = done;
431 host->ecb[ecbno].SCpnt = SCpnt;
432 #ifdef DEBUG
433 {
434 int i;
435 printk("aha1740_command: sending.. ");
436 for (i = 0; i < sizeof(host->ecb[ecbno]) - 10; i++)
437 printk("%02x ", ((unchar *)&host->ecb[ecbno])[i]);
438 }
439 printk("\n");
440 #endif
441 if (done) {
442
443
444
445
446
447
448
449
450
451
452
453
454 #define LOOPCNT_WARN 10
455 #define LOOPCNT_MAX 1000000
456 int loopcnt;
457 unsigned int base = SCpnt->device->host->io_port;
458 DEB(printk("aha1740[%d] critical section\n",ecbno));
459
460 spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
461 for (loopcnt = 0; ; loopcnt++) {
462 if (inb(G2STAT(base)) & G2STAT_MBXOUT) break;
463 if (loopcnt == LOOPCNT_WARN) {
464 printk("aha1740[%d]_mbxout wait!\n",ecbno);
465 }
466 if (loopcnt == LOOPCNT_MAX)
467 panic("aha1740.c: mbxout busy!\n");
468 }
469 outl (ecb_cpu_to_dma (SCpnt->device->host, host->ecb + ecbno),
470 MBOXOUT0(base));
471 for (loopcnt = 0; ; loopcnt++) {
472 if (! (inb(G2STAT(base)) & G2STAT_BUSY)) break;
473 if (loopcnt == LOOPCNT_WARN) {
474 printk("aha1740[%d]_attn wait!\n",ecbno);
475 }
476 if (loopcnt == LOOPCNT_MAX)
477 panic("aha1740.c: attn wait failed!\n");
478 }
479 outb(ATTN_START | (target & 7), ATTN(base));
480 spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
481 DEB(printk("aha1740[%d] request queued.\n",ecbno));
482 } else
483 printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n");
484 return 0;
485 }
486
487 static DEF_SCSI_QCMD(aha1740_queuecommand)
488
489
490
491
492 static void aha1740_getconfig(unsigned int base, unsigned int *irq_level,
493 unsigned int *irq_type,
494 unsigned int *translation)
495 {
496 static int intab[] = { 9, 10, 11, 12, 0, 14, 15, 0 };
497
498 *irq_level = intab[inb(INTDEF(base)) & 0x7];
499 *irq_type = (inb(INTDEF(base)) & 0x8) >> 3;
500 *translation = inb(RESV1(base)) & 0x1;
501 outb(inb(INTDEF(base)) | 0x10, INTDEF(base));
502 }
503
504 static int aha1740_biosparam(struct scsi_device *sdev,
505 struct block_device *dev,
506 sector_t capacity, int* ip)
507 {
508 int size = capacity;
509 int extended = HOSTDATA(sdev->host)->translation;
510
511 DEB(printk("aha1740_biosparam\n"));
512 if (extended && (ip[2] > 1024)) {
513 ip[0] = 255;
514 ip[1] = 63;
515 ip[2] = size / (255 * 63);
516 } else {
517 ip[0] = 64;
518 ip[1] = 32;
519 ip[2] = size >> 11;
520 }
521 return 0;
522 }
523
524 static int aha1740_eh_abort_handler (struct scsi_cmnd *dummy)
525 {
526
527
528
529
530
531
532
533
534
535 return SUCCESS;
536 }
537
538 static struct scsi_host_template aha1740_template = {
539 .module = THIS_MODULE,
540 .proc_name = "aha1740",
541 .show_info = aha1740_show_info,
542 .name = "Adaptec 174x (EISA)",
543 .queuecommand = aha1740_queuecommand,
544 .bios_param = aha1740_biosparam,
545 .can_queue = AHA1740_ECBS,
546 .this_id = 7,
547 .sg_tablesize = AHA1740_SCATTER,
548 .eh_abort_handler = aha1740_eh_abort_handler,
549 };
550
551 static 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_host_put (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
629 static 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
646 static struct eisa_device_id aha1740_ids[] = {
647 { "ADP0000" },
648 { "ADP0001" },
649 { "ADP0002" },
650 { "ADP0400" },
651 { "" }
652 };
653 MODULE_DEVICE_TABLE(eisa, aha1740_ids);
654
655 static 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
664 static __init int aha1740_init (void)
665 {
666 return eisa_driver_register (&aha1740_driver);
667 }
668
669 static __exit void aha1740_exit (void)
670 {
671 eisa_driver_unregister (&aha1740_driver);
672 }
673
674 module_init (aha1740_init);
675 module_exit (aha1740_exit);
676
677 MODULE_LICENSE("GPL");