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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122#include "aic7xxx_osm.h"
123#include "aic7xxx_inline.h"
124#include <scsi/scsicam.h>
125
126static struct scsi_transport_template *ahc_linux_transport_template = NULL;
127
128#include <linux/init.h>
129#include <linux/mm.h>
130#include <linux/blkdev.h>
131#include <linux/delay.h>
132
133
134
135
136
137
138
139
140#ifdef CONFIG_AIC7XXX_RESET_DELAY_MS
141#define AIC7XXX_RESET_DELAY CONFIG_AIC7XXX_RESET_DELAY_MS
142#else
143#define AIC7XXX_RESET_DELAY 5000
144#endif
145
146
147
148
149
150
151
152#ifdef CONFIG_AIC7XXX_PROC_STATS
153#define AIC7XXX_PROC_STATS
154#endif
155
156
157
158
159
160
161
162
163
164
165
166
167typedef struct {
168 uint8_t tag_commands[16];
169} adapter_tag_info_t;
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214#ifdef CONFIG_AIC7XXX_CMDS_PER_DEVICE
215#define AIC7XXX_CMDS_PER_DEVICE CONFIG_AIC7XXX_CMDS_PER_DEVICE
216#else
217#define AIC7XXX_CMDS_PER_DEVICE AHC_MAX_QUEUE
218#endif
219
220#define AIC7XXX_CONFIGED_TAG_COMMANDS { \
221 AIC7XXX_CMDS_PER_DEVICE, AIC7XXX_CMDS_PER_DEVICE, \
222 AIC7XXX_CMDS_PER_DEVICE, AIC7XXX_CMDS_PER_DEVICE, \
223 AIC7XXX_CMDS_PER_DEVICE, AIC7XXX_CMDS_PER_DEVICE, \
224 AIC7XXX_CMDS_PER_DEVICE, AIC7XXX_CMDS_PER_DEVICE, \
225 AIC7XXX_CMDS_PER_DEVICE, AIC7XXX_CMDS_PER_DEVICE, \
226 AIC7XXX_CMDS_PER_DEVICE, AIC7XXX_CMDS_PER_DEVICE, \
227 AIC7XXX_CMDS_PER_DEVICE, AIC7XXX_CMDS_PER_DEVICE, \
228 AIC7XXX_CMDS_PER_DEVICE, AIC7XXX_CMDS_PER_DEVICE \
229}
230
231
232
233
234
235static adapter_tag_info_t aic7xxx_tag_info[] =
236{
237 {AIC7XXX_CONFIGED_TAG_COMMANDS},
238 {AIC7XXX_CONFIGED_TAG_COMMANDS},
239 {AIC7XXX_CONFIGED_TAG_COMMANDS},
240 {AIC7XXX_CONFIGED_TAG_COMMANDS},
241 {AIC7XXX_CONFIGED_TAG_COMMANDS},
242 {AIC7XXX_CONFIGED_TAG_COMMANDS},
243 {AIC7XXX_CONFIGED_TAG_COMMANDS},
244 {AIC7XXX_CONFIGED_TAG_COMMANDS},
245 {AIC7XXX_CONFIGED_TAG_COMMANDS},
246 {AIC7XXX_CONFIGED_TAG_COMMANDS},
247 {AIC7XXX_CONFIGED_TAG_COMMANDS},
248 {AIC7XXX_CONFIGED_TAG_COMMANDS},
249 {AIC7XXX_CONFIGED_TAG_COMMANDS},
250 {AIC7XXX_CONFIGED_TAG_COMMANDS},
251 {AIC7XXX_CONFIGED_TAG_COMMANDS},
252 {AIC7XXX_CONFIGED_TAG_COMMANDS}
253};
254
255
256
257
258
259#define DID_UNDERFLOW DID_ERROR
260
261void
262ahc_print_path(struct ahc_softc *ahc, struct scb *scb)
263{
264 printk("(scsi%d:%c:%d:%d): ",
265 ahc->platform_data->host->host_no,
266 scb != NULL ? SCB_GET_CHANNEL(ahc, scb) : 'X',
267 scb != NULL ? SCB_GET_TARGET(ahc, scb) : -1,
268 scb != NULL ? SCB_GET_LUN(scb) : -1);
269}
270
271
272
273
274
275
276
277
278
279
280
281
282static uint32_t aic7xxx_no_reset;
283
284
285
286
287
288
289static uint32_t aic7xxx_extended;
290
291
292
293
294
295
296
297
298
299
300
301static uint32_t aic7xxx_pci_parity = ~0;
302
303
304
305
306
307
308
309uint32_t aic7xxx_allow_memio = ~0;
310
311
312
313
314
315
316
317
318
319
320
321static uint32_t aic7xxx_seltime;
322
323
324
325
326
327
328
329
330
331static uint32_t aic7xxx_periodic_otag;
332
333
334
335
336static char *aic7xxx = NULL;
337
338MODULE_AUTHOR("Maintainer: Hannes Reinecke <hare@suse.de>");
339MODULE_DESCRIPTION("Adaptec AIC77XX/78XX SCSI Host Bus Adapter driver");
340MODULE_LICENSE("Dual BSD/GPL");
341MODULE_VERSION(AIC7XXX_DRIVER_VERSION);
342module_param(aic7xxx, charp, 0444);
343MODULE_PARM_DESC(aic7xxx,
344"period-delimited options string:\n"
345" verbose Enable verbose/diagnostic logging\n"
346" allow_memio Allow device registers to be memory mapped\n"
347" debug Bitmask of debug values to enable\n"
348" no_probe Toggle EISA/VLB controller probing\n"
349" probe_eisa_vl Toggle EISA/VLB controller probing\n"
350" no_reset Suppress initial bus resets\n"
351" extended Enable extended geometry on all controllers\n"
352" periodic_otag Send an ordered tagged transaction\n"
353" periodically to prevent tag starvation.\n"
354" This may be required by some older disk\n"
355" drives or RAID arrays.\n"
356" tag_info:<tag_str> Set per-target tag depth\n"
357" global_tag_depth:<int> Global tag depth for every target\n"
358" on every bus\n"
359" seltime:<int> Selection Timeout\n"
360" (0/256ms,1/128ms,2/64ms,3/32ms)\n"
361"\n"
362" Sample /etc/modprobe.conf line:\n"
363" Toggle EISA/VLB probing\n"
364" Set tag depth on Controller 1/Target 1 to 10 tags\n"
365" Shorten the selection timeout to 128ms\n"
366"\n"
367" options aic7xxx 'aic7xxx=probe_eisa_vl.tag_info:{{}.{.10}}.seltime:1'\n"
368);
369
370static void ahc_linux_handle_scsi_status(struct ahc_softc *,
371 struct scsi_device *,
372 struct scb *);
373static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc,
374 struct scsi_cmnd *cmd);
375static void ahc_linux_freeze_simq(struct ahc_softc *ahc);
376static void ahc_linux_release_simq(struct ahc_softc *ahc);
377static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
378static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
379static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc,
380 struct ahc_devinfo *devinfo);
381static void ahc_linux_device_queue_depth(struct scsi_device *);
382static int ahc_linux_run_command(struct ahc_softc*,
383 struct ahc_linux_device *,
384 struct scsi_cmnd *);
385static void ahc_linux_setup_tag_info_global(char *p);
386static int aic7xxx_setup(char *s);
387
388static int ahc_linux_unit;
389
390
391
392void
393ahc_delay(long usec)
394{
395
396
397
398
399
400 while (usec > 0) {
401 udelay(usec % 1024);
402 usec -= 1024;
403 }
404}
405
406
407uint8_t
408ahc_inb(struct ahc_softc * ahc, long port)
409{
410 uint8_t x;
411
412 if (ahc->tag == BUS_SPACE_MEMIO) {
413 x = readb(ahc->bsh.maddr + port);
414 } else {
415 x = inb(ahc->bsh.ioport + port);
416 }
417 mb();
418 return (x);
419}
420
421void
422ahc_outb(struct ahc_softc * ahc, long port, uint8_t val)
423{
424 if (ahc->tag == BUS_SPACE_MEMIO) {
425 writeb(val, ahc->bsh.maddr + port);
426 } else {
427 outb(val, ahc->bsh.ioport + port);
428 }
429 mb();
430}
431
432void
433ahc_outsb(struct ahc_softc * ahc, long port, uint8_t *array, int count)
434{
435 int i;
436
437
438
439
440
441
442 for (i = 0; i < count; i++)
443 ahc_outb(ahc, port, *array++);
444}
445
446void
447ahc_insb(struct ahc_softc * ahc, long port, uint8_t *array, int count)
448{
449 int i;
450
451
452
453
454
455
456 for (i = 0; i < count; i++)
457 *array++ = ahc_inb(ahc, port);
458}
459
460
461static void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*);
462
463static int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
464 struct ahc_dma_seg *sg,
465 dma_addr_t addr, bus_size_t len);
466
467static void
468ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb)
469{
470 struct scsi_cmnd *cmd;
471
472 cmd = scb->io_ctx;
473 ahc_sync_sglist(ahc, scb, BUS_DMASYNC_POSTWRITE);
474
475 scsi_dma_unmap(cmd);
476}
477
478static int
479ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
480 struct ahc_dma_seg *sg, dma_addr_t addr, bus_size_t len)
481{
482 int consumed;
483
484 if ((scb->sg_count + 1) > AHC_NSEG)
485 panic("Too few segs for dma mapping. "
486 "Increase AHC_NSEG\n");
487
488 consumed = 1;
489 sg->addr = ahc_htole32(addr & 0xFFFFFFFF);
490 scb->platform_data->xfer_len += len;
491
492 if (sizeof(dma_addr_t) > 4
493 && (ahc->flags & AHC_39BIT_ADDRESSING) != 0)
494 len |= (addr >> 8) & AHC_SG_HIGH_ADDR_MASK;
495
496 sg->len = ahc_htole32(len);
497 return (consumed);
498}
499
500
501
502
503static const char *
504ahc_linux_info(struct Scsi_Host *host)
505{
506 static char buffer[512];
507 char ahc_info[256];
508 char *bp;
509 struct ahc_softc *ahc;
510
511 bp = &buffer[0];
512 ahc = *(struct ahc_softc **)host->hostdata;
513 memset(bp, 0, sizeof(buffer));
514 strcpy(bp, "Adaptec AIC7XXX EISA/VLB/PCI SCSI HBA DRIVER, Rev " AIC7XXX_DRIVER_VERSION "\n"
515 " <");
516 strcat(bp, ahc->description);
517 strcat(bp, ">\n"
518 " ");
519 ahc_controller_info(ahc, ahc_info);
520 strcat(bp, ahc_info);
521 strcat(bp, "\n");
522
523 return (bp);
524}
525
526
527
528
529static int
530ahc_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
531{
532 struct ahc_softc *ahc;
533 struct ahc_linux_device *dev = scsi_transport_device_data(cmd->device);
534 int rtn = SCSI_MLQUEUE_HOST_BUSY;
535 unsigned long flags;
536
537 ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
538
539 ahc_lock(ahc, &flags);
540 if (ahc->platform_data->qfrozen == 0) {
541 cmd->scsi_done = scsi_done;
542 cmd->result = CAM_REQ_INPROG << 16;
543 rtn = ahc_linux_run_command(ahc, dev, cmd);
544 }
545 ahc_unlock(ahc, &flags);
546
547 return rtn;
548}
549
550static inline struct scsi_target **
551ahc_linux_target_in_softc(struct scsi_target *starget)
552{
553 struct ahc_softc *ahc =
554 *((struct ahc_softc **)dev_to_shost(&starget->dev)->hostdata);
555 unsigned int target_offset;
556
557 target_offset = starget->id;
558 if (starget->channel != 0)
559 target_offset += 8;
560
561 return &ahc->platform_data->starget[target_offset];
562}
563
564static int
565ahc_linux_target_alloc(struct scsi_target *starget)
566{
567 struct ahc_softc *ahc =
568 *((struct ahc_softc **)dev_to_shost(&starget->dev)->hostdata);
569 struct seeprom_config *sc = ahc->seep_config;
570 unsigned long flags;
571 struct scsi_target **ahc_targp = ahc_linux_target_in_softc(starget);
572 unsigned short scsirate;
573 struct ahc_devinfo devinfo;
574 struct ahc_initiator_tinfo *tinfo;
575 struct ahc_tmode_tstate *tstate;
576 char channel = starget->channel + 'A';
577 unsigned int our_id = ahc->our_id;
578 unsigned int target_offset;
579
580 target_offset = starget->id;
581 if (starget->channel != 0)
582 target_offset += 8;
583
584 if (starget->channel)
585 our_id = ahc->our_id_b;
586
587 ahc_lock(ahc, &flags);
588
589 BUG_ON(*ahc_targp != NULL);
590
591 *ahc_targp = starget;
592
593 if (sc) {
594 int maxsync = AHC_SYNCRATE_DT;
595 int ultra = 0;
596 int flags = sc->device_flags[target_offset];
597
598 if (ahc->flags & AHC_NEWEEPROM_FMT) {
599 if (flags & CFSYNCHISULTRA)
600 ultra = 1;
601 } else if (flags & CFULTRAEN)
602 ultra = 1;
603
604
605 if(ultra && (flags & CFXFER) == 0x04) {
606 ultra = 0;
607 flags &= ~CFXFER;
608 }
609
610 if ((ahc->features & AHC_ULTRA2) != 0) {
611 scsirate = (flags & CFXFER) | (ultra ? 0x8 : 0);
612 } else {
613 scsirate = (flags & CFXFER) << 4;
614 maxsync = ultra ? AHC_SYNCRATE_ULTRA :
615 AHC_SYNCRATE_FAST;
616 }
617 spi_max_width(starget) = (flags & CFWIDEB) ? 1 : 0;
618 if (!(flags & CFSYNCH))
619 spi_max_offset(starget) = 0;
620 spi_min_period(starget) =
621 ahc_find_period(ahc, scsirate, maxsync);
622
623 tinfo = ahc_fetch_transinfo(ahc, channel, ahc->our_id,
624 starget->id, &tstate);
625 }
626 ahc_compile_devinfo(&devinfo, our_id, starget->id,
627 CAM_LUN_WILDCARD, channel,
628 ROLE_INITIATOR);
629 ahc_set_syncrate(ahc, &devinfo, NULL, 0, 0, 0,
630 AHC_TRANS_GOAL, FALSE);
631 ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
632 AHC_TRANS_GOAL, FALSE);
633 ahc_unlock(ahc, &flags);
634
635 return 0;
636}
637
638static void
639ahc_linux_target_destroy(struct scsi_target *starget)
640{
641 struct scsi_target **ahc_targp = ahc_linux_target_in_softc(starget);
642
643 *ahc_targp = NULL;
644}
645
646static int
647ahc_linux_slave_alloc(struct scsi_device *sdev)
648{
649 struct ahc_softc *ahc =
650 *((struct ahc_softc **)sdev->host->hostdata);
651 struct scsi_target *starget = sdev->sdev_target;
652 struct ahc_linux_device *dev;
653
654 if (bootverbose)
655 printf("%s: Slave Alloc %d\n", ahc_name(ahc), sdev->id);
656
657 dev = scsi_transport_device_data(sdev);
658 memset(dev, 0, sizeof(*dev));
659
660
661
662
663
664 dev->openings = 1;
665
666
667
668
669
670
671 dev->maxtags = 0;
672
673 spi_period(starget) = 0;
674
675 return 0;
676}
677
678static int
679ahc_linux_slave_configure(struct scsi_device *sdev)
680{
681 struct ahc_softc *ahc;
682
683 ahc = *((struct ahc_softc **)sdev->host->hostdata);
684
685 if (bootverbose)
686 sdev_printk(KERN_INFO, sdev, "Slave Configure\n");
687
688 ahc_linux_device_queue_depth(sdev);
689
690
691 if (!spi_initial_dv(sdev->sdev_target))
692 spi_dv_device(sdev);
693
694 return 0;
695}
696
697#if defined(__i386__)
698
699
700
701static int
702ahc_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev,
703 sector_t capacity, int geom[])
704{
705 uint8_t *bh;
706 int heads;
707 int sectors;
708 int cylinders;
709 int ret;
710 int extended;
711 struct ahc_softc *ahc;
712 u_int channel;
713
714 ahc = *((struct ahc_softc **)sdev->host->hostdata);
715 channel = sdev_channel(sdev);
716
717 bh = scsi_bios_ptable(bdev);
718 if (bh) {
719 ret = scsi_partsize(bh, capacity,
720 &geom[2], &geom[0], &geom[1]);
721 kfree(bh);
722 if (ret != -1)
723 return (ret);
724 }
725 heads = 64;
726 sectors = 32;
727 cylinders = aic_sector_div(capacity, heads, sectors);
728
729 if (aic7xxx_extended != 0)
730 extended = 1;
731 else if (channel == 0)
732 extended = (ahc->flags & AHC_EXTENDED_TRANS_A) != 0;
733 else
734 extended = (ahc->flags & AHC_EXTENDED_TRANS_B) != 0;
735 if (extended && cylinders >= 1024) {
736 heads = 255;
737 sectors = 63;
738 cylinders = aic_sector_div(capacity, heads, sectors);
739 }
740 geom[0] = heads;
741 geom[1] = sectors;
742 geom[2] = cylinders;
743 return (0);
744}
745#endif
746
747
748
749
750static int
751ahc_linux_abort(struct scsi_cmnd *cmd)
752{
753 int error;
754
755 error = ahc_linux_queue_recovery_cmd(cmd, SCB_ABORT);
756 if (error != 0)
757 printf("aic7xxx_abort returns 0x%x\n", error);
758 return (error);
759}
760
761
762
763
764static int
765ahc_linux_dev_reset(struct scsi_cmnd *cmd)
766{
767 int error;
768
769 error = ahc_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET);
770 if (error != 0)
771 printf("aic7xxx_dev_reset returns 0x%x\n", error);
772 return (error);
773}
774
775
776
777
778static int
779ahc_linux_bus_reset(struct scsi_cmnd *cmd)
780{
781 struct ahc_softc *ahc;
782 int found;
783 unsigned long flags;
784
785 ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
786
787 ahc_lock(ahc, &flags);
788 found = ahc_reset_channel(ahc, scmd_channel(cmd) + 'A',
789 TRUE);
790 ahc_unlock(ahc, &flags);
791
792 if (bootverbose)
793 printf("%s: SCSI bus reset delivered. "
794 "%d SCBs aborted.\n", ahc_name(ahc), found);
795
796 return SUCCESS;
797}
798
799struct scsi_host_template aic7xxx_driver_template = {
800 .module = THIS_MODULE,
801 .name = "aic7xxx",
802 .proc_name = "aic7xxx",
803 .proc_info = ahc_linux_proc_info,
804 .info = ahc_linux_info,
805 .queuecommand = ahc_linux_queue,
806 .eh_abort_handler = ahc_linux_abort,
807 .eh_device_reset_handler = ahc_linux_dev_reset,
808 .eh_bus_reset_handler = ahc_linux_bus_reset,
809#if defined(__i386__)
810 .bios_param = ahc_linux_biosparam,
811#endif
812 .can_queue = AHC_MAX_QUEUE,
813 .this_id = -1,
814 .max_sectors = 8192,
815 .cmd_per_lun = 2,
816 .use_clustering = ENABLE_CLUSTERING,
817 .slave_alloc = ahc_linux_slave_alloc,
818 .slave_configure = ahc_linux_slave_configure,
819 .target_alloc = ahc_linux_target_alloc,
820 .target_destroy = ahc_linux_target_destroy,
821};
822
823
824
825
826#define BUILD_SCSIID(ahc, cmd) \
827 ((((cmd)->device->id << TID_SHIFT) & TID) \
828 | (((cmd)->device->channel == 0) ? (ahc)->our_id : (ahc)->our_id_b) \
829 | (((cmd)->device->channel == 0) ? 0 : TWIN_CHNLB))
830
831
832int
833ahc_dma_tag_create(struct ahc_softc *ahc, bus_dma_tag_t parent,
834 bus_size_t alignment, bus_size_t boundary,
835 dma_addr_t lowaddr, dma_addr_t highaddr,
836 bus_dma_filter_t *filter, void *filterarg,
837 bus_size_t maxsize, int nsegments,
838 bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag)
839{
840 bus_dma_tag_t dmat;
841
842 dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT);
843 if (dmat == NULL)
844 return (ENOMEM);
845
846
847
848
849
850
851
852
853 dmat->alignment = alignment;
854 dmat->boundary = boundary;
855 dmat->maxsize = maxsize;
856 *ret_tag = dmat;
857 return (0);
858}
859
860void
861ahc_dma_tag_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat)
862{
863 free(dmat, M_DEVBUF);
864}
865
866int
867ahc_dmamem_alloc(struct ahc_softc *ahc, bus_dma_tag_t dmat, void** vaddr,
868 int flags, bus_dmamap_t *mapp)
869{
870 *vaddr = pci_alloc_consistent(ahc->dev_softc,
871 dmat->maxsize, mapp);
872 if (*vaddr == NULL)
873 return ENOMEM;
874 return 0;
875}
876
877void
878ahc_dmamem_free(struct ahc_softc *ahc, bus_dma_tag_t dmat,
879 void* vaddr, bus_dmamap_t map)
880{
881 pci_free_consistent(ahc->dev_softc, dmat->maxsize,
882 vaddr, map);
883}
884
885int
886ahc_dmamap_load(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map,
887 void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb,
888 void *cb_arg, int flags)
889{
890
891
892
893
894 bus_dma_segment_t stack_sg;
895
896 stack_sg.ds_addr = map;
897 stack_sg.ds_len = dmat->maxsize;
898 cb(cb_arg, &stack_sg, 1, 0);
899 return (0);
900}
901
902void
903ahc_dmamap_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map)
904{
905}
906
907int
908ahc_dmamap_unload(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map)
909{
910
911 return (0);
912}
913
914static void
915ahc_linux_setup_tag_info_global(char *p)
916{
917 int tags, i, j;
918
919 tags = simple_strtoul(p + 1, NULL, 0) & 0xff;
920 printf("Setting Global Tags= %d\n", tags);
921
922 for (i = 0; i < ARRAY_SIZE(aic7xxx_tag_info); i++) {
923 for (j = 0; j < AHC_NUM_TARGETS; j++) {
924 aic7xxx_tag_info[i].tag_commands[j] = tags;
925 }
926 }
927}
928
929static void
930ahc_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
931{
932
933 if ((instance >= 0) && (targ >= 0)
934 && (instance < ARRAY_SIZE(aic7xxx_tag_info))
935 && (targ < AHC_NUM_TARGETS)) {
936 aic7xxx_tag_info[instance].tag_commands[targ] = value & 0xff;
937 if (bootverbose)
938 printf("tag_info[%d:%d] = %d\n", instance, targ, value);
939 }
940}
941
942static char *
943ahc_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,
944 void (*callback)(u_long, int, int, int32_t),
945 u_long callback_arg)
946{
947 char *tok_end;
948 char *tok_end2;
949 int i;
950 int instance;
951 int targ;
952 int done;
953 char tok_list[] = {'.', ',', '{', '}', '\0'};
954
955
956 if (*opt_arg != ':')
957 return (opt_arg);
958 opt_arg++;
959 instance = -1;
960 targ = -1;
961 done = FALSE;
962
963
964
965
966 tok_end = strchr(opt_arg, '\0');
967 if (tok_end < end)
968 *tok_end = ',';
969 while (!done) {
970 switch (*opt_arg) {
971 case '{':
972 if (instance == -1) {
973 instance = 0;
974 } else {
975 if (depth > 1) {
976 if (targ == -1)
977 targ = 0;
978 } else {
979 printf("Malformed Option %s\n",
980 opt_name);
981 done = TRUE;
982 }
983 }
984 opt_arg++;
985 break;
986 case '}':
987 if (targ != -1)
988 targ = -1;
989 else if (instance != -1)
990 instance = -1;
991 opt_arg++;
992 break;
993 case ',':
994 case '.':
995 if (instance == -1)
996 done = TRUE;
997 else if (targ >= 0)
998 targ++;
999 else if (instance >= 0)
1000 instance++;
1001 opt_arg++;
1002 break;
1003 case '\0':
1004 done = TRUE;
1005 break;
1006 default:
1007 tok_end = end;
1008 for (i = 0; tok_list[i]; i++) {
1009 tok_end2 = strchr(opt_arg, tok_list[i]);
1010 if ((tok_end2) && (tok_end2 < tok_end))
1011 tok_end = tok_end2;
1012 }
1013 callback(callback_arg, instance, targ,
1014 simple_strtol(opt_arg, NULL, 0));
1015 opt_arg = tok_end;
1016 break;
1017 }
1018 }
1019 return (opt_arg);
1020}
1021
1022
1023
1024
1025
1026
1027static int
1028aic7xxx_setup(char *s)
1029{
1030 int i, n;
1031 char *p;
1032 char *end;
1033
1034 static const struct {
1035 const char *name;
1036 uint32_t *flag;
1037 } options[] = {
1038 { "extended", &aic7xxx_extended },
1039 { "no_reset", &aic7xxx_no_reset },
1040 { "verbose", &aic7xxx_verbose },
1041 { "allow_memio", &aic7xxx_allow_memio},
1042#ifdef AHC_DEBUG
1043 { "debug", &ahc_debug },
1044#endif
1045 { "periodic_otag", &aic7xxx_periodic_otag },
1046 { "pci_parity", &aic7xxx_pci_parity },
1047 { "seltime", &aic7xxx_seltime },
1048 { "tag_info", NULL },
1049 { "global_tag_depth", NULL },
1050 { "dv", NULL }
1051 };
1052
1053 end = strchr(s, '\0');
1054
1055
1056
1057
1058
1059 n = 0;
1060
1061 while ((p = strsep(&s, ",.")) != NULL) {
1062 if (*p == '\0')
1063 continue;
1064 for (i = 0; i < ARRAY_SIZE(options); i++) {
1065
1066 n = strlen(options[i].name);
1067 if (strncmp(options[i].name, p, n) == 0)
1068 break;
1069 }
1070 if (i == ARRAY_SIZE(options))
1071 continue;
1072
1073 if (strncmp(p, "global_tag_depth", n) == 0) {
1074 ahc_linux_setup_tag_info_global(p + n);
1075 } else if (strncmp(p, "tag_info", n) == 0) {
1076 s = ahc_parse_brace_option("tag_info", p + n, end,
1077 2, ahc_linux_setup_tag_info, 0);
1078 } else if (p[n] == ':') {
1079 *(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0);
1080 } else if (strncmp(p, "verbose", n) == 0) {
1081 *(options[i].flag) = 1;
1082 } else {
1083 *(options[i].flag) ^= 0xFFFFFFFF;
1084 }
1085 }
1086 return 1;
1087}
1088
1089__setup("aic7xxx=", aic7xxx_setup);
1090
1091uint32_t aic7xxx_verbose;
1092
1093int
1094ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *template)
1095{
1096 char buf[80];
1097 struct Scsi_Host *host;
1098 char *new_name;
1099 u_long s;
1100 int retval;
1101
1102 template->name = ahc->description;
1103 host = scsi_host_alloc(template, sizeof(struct ahc_softc *));
1104 if (host == NULL)
1105 return (ENOMEM);
1106
1107 *((struct ahc_softc **)host->hostdata) = ahc;
1108 ahc->platform_data->host = host;
1109 host->can_queue = AHC_MAX_QUEUE;
1110 host->cmd_per_lun = 2;
1111
1112 host->this_id = ahc->our_id;
1113 host->irq = ahc->platform_data->irq;
1114 host->max_id = (ahc->features & AHC_WIDE) ? 16 : 8;
1115 host->max_lun = AHC_NUM_LUNS;
1116 host->max_channel = (ahc->features & AHC_TWIN) ? 1 : 0;
1117 host->sg_tablesize = AHC_NSEG;
1118 ahc_lock(ahc, &s);
1119 ahc_set_unit(ahc, ahc_linux_unit++);
1120 ahc_unlock(ahc, &s);
1121 sprintf(buf, "scsi%d", host->host_no);
1122 new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
1123 if (new_name != NULL) {
1124 strcpy(new_name, buf);
1125 ahc_set_name(ahc, new_name);
1126 }
1127 host->unique_id = ahc->unit;
1128 ahc_linux_initialize_scsi_bus(ahc);
1129 ahc_intr_enable(ahc, TRUE);
1130
1131 host->transportt = ahc_linux_transport_template;
1132
1133 retval = scsi_add_host(host,
1134 (ahc->dev_softc ? &ahc->dev_softc->dev : NULL));
1135 if (retval) {
1136 printk(KERN_WARNING "aic7xxx: scsi_add_host failed\n");
1137 scsi_host_put(host);
1138 return retval;
1139 }
1140
1141 scsi_scan_host(host);
1142 return 0;
1143}
1144
1145
1146
1147
1148
1149
1150void
1151ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc)
1152{
1153 int i;
1154 int numtarg;
1155 unsigned long s;
1156
1157 i = 0;
1158 numtarg = 0;
1159
1160 ahc_lock(ahc, &s);
1161
1162 if (aic7xxx_no_reset != 0)
1163 ahc->flags &= ~(AHC_RESET_BUS_A|AHC_RESET_BUS_B);
1164
1165 if ((ahc->flags & AHC_RESET_BUS_A) != 0)
1166 ahc_reset_channel(ahc, 'A', TRUE);
1167 else
1168 numtarg = (ahc->features & AHC_WIDE) ? 16 : 8;
1169
1170 if ((ahc->features & AHC_TWIN) != 0) {
1171
1172 if ((ahc->flags & AHC_RESET_BUS_B) != 0) {
1173 ahc_reset_channel(ahc, 'B', TRUE);
1174 } else {
1175 if (numtarg == 0)
1176 i = 8;
1177 numtarg += 8;
1178 }
1179 }
1180
1181
1182
1183
1184
1185 for (; i < numtarg; i++) {
1186 struct ahc_devinfo devinfo;
1187 struct ahc_initiator_tinfo *tinfo;
1188 struct ahc_tmode_tstate *tstate;
1189 u_int our_id;
1190 u_int target_id;
1191 char channel;
1192
1193 channel = 'A';
1194 our_id = ahc->our_id;
1195 target_id = i;
1196 if (i > 7 && (ahc->features & AHC_TWIN) != 0) {
1197 channel = 'B';
1198 our_id = ahc->our_id_b;
1199 target_id = i % 8;
1200 }
1201 tinfo = ahc_fetch_transinfo(ahc, channel, our_id,
1202 target_id, &tstate);
1203 ahc_compile_devinfo(&devinfo, our_id, target_id,
1204 CAM_LUN_WILDCARD, channel, ROLE_INITIATOR);
1205 ahc_update_neg_request(ahc, &devinfo, tstate,
1206 tinfo, AHC_NEG_ALWAYS);
1207 }
1208 ahc_unlock(ahc, &s);
1209
1210 if ((ahc->flags & (AHC_RESET_BUS_A|AHC_RESET_BUS_B)) != 0) {
1211 ahc_linux_freeze_simq(ahc);
1212 msleep(AIC7XXX_RESET_DELAY);
1213 ahc_linux_release_simq(ahc);
1214 }
1215}
1216
1217int
1218ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg)
1219{
1220
1221 ahc->platform_data =
1222 malloc(sizeof(struct ahc_platform_data), M_DEVBUF, M_NOWAIT);
1223 if (ahc->platform_data == NULL)
1224 return (ENOMEM);
1225 memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data));
1226 ahc->platform_data->irq = AHC_LINUX_NOIRQ;
1227 ahc_lockinit(ahc);
1228 ahc->seltime = (aic7xxx_seltime & 0x3) << 4;
1229 ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4;
1230 if (aic7xxx_pci_parity == 0)
1231 ahc->flags |= AHC_DISABLE_PCI_PERR;
1232
1233 return (0);
1234}
1235
1236void
1237ahc_platform_free(struct ahc_softc *ahc)
1238{
1239 struct scsi_target *starget;
1240 int i;
1241
1242 if (ahc->platform_data != NULL) {
1243
1244 for (i = 0; i < AHC_NUM_TARGETS; i++) {
1245 starget = ahc->platform_data->starget[i];
1246 if (starget != NULL) {
1247 ahc->platform_data->starget[i] = NULL;
1248 }
1249 }
1250
1251 if (ahc->platform_data->irq != AHC_LINUX_NOIRQ)
1252 free_irq(ahc->platform_data->irq, ahc);
1253 if (ahc->tag == BUS_SPACE_PIO
1254 && ahc->bsh.ioport != 0)
1255 release_region(ahc->bsh.ioport, 256);
1256 if (ahc->tag == BUS_SPACE_MEMIO
1257 && ahc->bsh.maddr != NULL) {
1258 iounmap(ahc->bsh.maddr);
1259 release_mem_region(ahc->platform_data->mem_busaddr,
1260 0x1000);
1261 }
1262
1263 if (ahc->platform_data->host)
1264 scsi_host_put(ahc->platform_data->host);
1265
1266 free(ahc->platform_data, M_DEVBUF);
1267 }
1268}
1269
1270void
1271ahc_platform_freeze_devq(struct ahc_softc *ahc, struct scb *scb)
1272{
1273 ahc_platform_abort_scbs(ahc, SCB_GET_TARGET(ahc, scb),
1274 SCB_GET_CHANNEL(ahc, scb),
1275 SCB_GET_LUN(scb), SCB_LIST_NULL,
1276 ROLE_UNKNOWN, CAM_REQUEUE_REQ);
1277}
1278
1279void
1280ahc_platform_set_tags(struct ahc_softc *ahc, struct scsi_device *sdev,
1281 struct ahc_devinfo *devinfo, ahc_queue_alg alg)
1282{
1283 struct ahc_linux_device *dev;
1284 int was_queuing;
1285 int now_queuing;
1286
1287 if (sdev == NULL)
1288 return;
1289 dev = scsi_transport_device_data(sdev);
1290
1291 was_queuing = dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED);
1292 switch (alg) {
1293 default:
1294 case AHC_QUEUE_NONE:
1295 now_queuing = 0;
1296 break;
1297 case AHC_QUEUE_BASIC:
1298 now_queuing = AHC_DEV_Q_BASIC;
1299 break;
1300 case AHC_QUEUE_TAGGED:
1301 now_queuing = AHC_DEV_Q_TAGGED;
1302 break;
1303 }
1304 if ((dev->flags & AHC_DEV_FREEZE_TIL_EMPTY) == 0
1305 && (was_queuing != now_queuing)
1306 && (dev->active != 0)) {
1307 dev->flags |= AHC_DEV_FREEZE_TIL_EMPTY;
1308 dev->qfrozen++;
1309 }
1310
1311 dev->flags &= ~(AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED|AHC_DEV_PERIODIC_OTAG);
1312 if (now_queuing) {
1313 u_int usertags;
1314
1315 usertags = ahc_linux_user_tagdepth(ahc, devinfo);
1316 if (!was_queuing) {
1317
1318
1319
1320
1321
1322 dev->maxtags = usertags;
1323 dev->openings = dev->maxtags - dev->active;
1324 }
1325 if (dev->maxtags == 0) {
1326
1327
1328
1329 dev->openings = 1;
1330 } else if (alg == AHC_QUEUE_TAGGED) {
1331 dev->flags |= AHC_DEV_Q_TAGGED;
1332 if (aic7xxx_periodic_otag != 0)
1333 dev->flags |= AHC_DEV_PERIODIC_OTAG;
1334 } else
1335 dev->flags |= AHC_DEV_Q_BASIC;
1336 } else {
1337
1338 dev->maxtags = 0;
1339 dev->openings = 1 - dev->active;
1340 }
1341 switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) {
1342 case AHC_DEV_Q_BASIC:
1343 scsi_set_tag_type(sdev, MSG_SIMPLE_TAG);
1344 scsi_activate_tcq(sdev, dev->openings + dev->active);
1345 break;
1346 case AHC_DEV_Q_TAGGED:
1347 scsi_set_tag_type(sdev, MSG_ORDERED_TAG);
1348 scsi_activate_tcq(sdev, dev->openings + dev->active);
1349 break;
1350 default:
1351
1352
1353
1354
1355
1356
1357 scsi_deactivate_tcq(sdev, 2);
1358 break;
1359 }
1360}
1361
1362int
1363ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, char channel,
1364 int lun, u_int tag, role_t role, uint32_t status)
1365{
1366 return 0;
1367}
1368
1369static u_int
1370ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
1371{
1372 static int warned_user;
1373 u_int tags;
1374
1375 tags = 0;
1376 if ((ahc->user_discenable & devinfo->target_mask) != 0) {
1377 if (ahc->unit >= ARRAY_SIZE(aic7xxx_tag_info)) {
1378 if (warned_user == 0) {
1379
1380 printf(KERN_WARNING
1381"aic7xxx: WARNING: Insufficient tag_info instances\n"
1382"aic7xxx: for installed controllers. Using defaults\n"
1383"aic7xxx: Please update the aic7xxx_tag_info array in\n"
1384"aic7xxx: the aic7xxx_osm..c source file.\n");
1385 warned_user++;
1386 }
1387 tags = AHC_MAX_QUEUE;
1388 } else {
1389 adapter_tag_info_t *tag_info;
1390
1391 tag_info = &aic7xxx_tag_info[ahc->unit];
1392 tags = tag_info->tag_commands[devinfo->target_offset];
1393 if (tags > AHC_MAX_QUEUE)
1394 tags = AHC_MAX_QUEUE;
1395 }
1396 }
1397 return (tags);
1398}
1399
1400
1401
1402
1403static void
1404ahc_linux_device_queue_depth(struct scsi_device *sdev)
1405{
1406 struct ahc_devinfo devinfo;
1407 u_int tags;
1408 struct ahc_softc *ahc = *((struct ahc_softc **)sdev->host->hostdata);
1409
1410 ahc_compile_devinfo(&devinfo,
1411 sdev->sdev_target->channel == 0
1412 ? ahc->our_id : ahc->our_id_b,
1413 sdev->sdev_target->id, sdev->lun,
1414 sdev->sdev_target->channel == 0 ? 'A' : 'B',
1415 ROLE_INITIATOR);
1416 tags = ahc_linux_user_tagdepth(ahc, &devinfo);
1417 if (tags != 0 && sdev->tagged_supported != 0) {
1418
1419 ahc_platform_set_tags(ahc, sdev, &devinfo, AHC_QUEUE_TAGGED);
1420 ahc_send_async(ahc, devinfo.channel, devinfo.target,
1421 devinfo.lun, AC_TRANSFER_NEG);
1422 ahc_print_devinfo(ahc, &devinfo);
1423 printf("Tagged Queuing enabled. Depth %d\n", tags);
1424 } else {
1425 ahc_platform_set_tags(ahc, sdev, &devinfo, AHC_QUEUE_NONE);
1426 ahc_send_async(ahc, devinfo.channel, devinfo.target,
1427 devinfo.lun, AC_TRANSFER_NEG);
1428 }
1429}
1430
1431static int
1432ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev,
1433 struct scsi_cmnd *cmd)
1434{
1435 struct scb *scb;
1436 struct hardware_scb *hscb;
1437 struct ahc_initiator_tinfo *tinfo;
1438 struct ahc_tmode_tstate *tstate;
1439 uint16_t mask;
1440 struct scb_tailq *untagged_q = NULL;
1441 int nseg;
1442
1443
1444
1445
1446
1447 if (ahc->platform_data->qfrozen != 0)
1448 return SCSI_MLQUEUE_HOST_BUSY;
1449
1450
1451
1452
1453
1454
1455
1456 if (!blk_rq_tagged(cmd->request)
1457 && (ahc->features & AHC_SCB_BTT) == 0) {
1458 int target_offset;
1459
1460 target_offset = cmd->device->id + cmd->device->channel * 8;
1461 untagged_q = &(ahc->untagged_queues[target_offset]);
1462 if (!TAILQ_EMPTY(untagged_q))
1463
1464
1465 return SCSI_MLQUEUE_DEVICE_BUSY;
1466 }
1467
1468 nseg = scsi_dma_map(cmd);
1469 if (nseg < 0)
1470 return SCSI_MLQUEUE_HOST_BUSY;
1471
1472
1473
1474
1475 scb = ahc_get_scb(ahc);
1476 if (!scb) {
1477 scsi_dma_unmap(cmd);
1478 return SCSI_MLQUEUE_HOST_BUSY;
1479 }
1480
1481 scb->io_ctx = cmd;
1482 scb->platform_data->dev = dev;
1483 hscb = scb->hscb;
1484 cmd->host_scribble = (char *)scb;
1485
1486
1487
1488
1489 hscb->control = 0;
1490 hscb->scsiid = BUILD_SCSIID(ahc, cmd);
1491 hscb->lun = cmd->device->lun;
1492 mask = SCB_GET_TARGET_MASK(ahc, scb);
1493 tinfo = ahc_fetch_transinfo(ahc, SCB_GET_CHANNEL(ahc, scb),
1494 SCB_GET_OUR_ID(scb),
1495 SCB_GET_TARGET(ahc, scb), &tstate);
1496 hscb->scsirate = tinfo->scsirate;
1497 hscb->scsioffset = tinfo->curr.offset;
1498 if ((tstate->ultraenb & mask) != 0)
1499 hscb->control |= ULTRAENB;
1500
1501 if ((ahc->user_discenable & mask) != 0)
1502 hscb->control |= DISCENB;
1503
1504 if ((tstate->auto_negotiate & mask) != 0) {
1505 scb->flags |= SCB_AUTO_NEGOTIATE;
1506 scb->hscb->control |= MK_MESSAGE;
1507 }
1508
1509 if ((dev->flags & (AHC_DEV_Q_TAGGED|AHC_DEV_Q_BASIC)) != 0) {
1510 int msg_bytes;
1511 uint8_t tag_msgs[2];
1512
1513 msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
1514 if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
1515 hscb->control |= tag_msgs[0];
1516 if (tag_msgs[0] == MSG_ORDERED_TASK)
1517 dev->commands_since_idle_or_otag = 0;
1518 } else if (dev->commands_since_idle_or_otag == AHC_OTAG_THRESH
1519 && (dev->flags & AHC_DEV_Q_TAGGED) != 0) {
1520 hscb->control |= MSG_ORDERED_TASK;
1521 dev->commands_since_idle_or_otag = 0;
1522 } else {
1523 hscb->control |= MSG_SIMPLE_TASK;
1524 }
1525 }
1526
1527 hscb->cdb_len = cmd->cmd_len;
1528 if (hscb->cdb_len <= 12) {
1529 memcpy(hscb->shared_data.cdb, cmd->cmnd, hscb->cdb_len);
1530 } else {
1531 memcpy(hscb->cdb32, cmd->cmnd, hscb->cdb_len);
1532 scb->flags |= SCB_CDB32_PTR;
1533 }
1534
1535 scb->platform_data->xfer_len = 0;
1536 ahc_set_residual(scb, 0);
1537 ahc_set_sense_residual(scb, 0);
1538 scb->sg_count = 0;
1539
1540 if (nseg > 0) {
1541 struct ahc_dma_seg *sg;
1542 struct scatterlist *cur_seg;
1543 int i;
1544
1545
1546 sg = scb->sg_list;
1547
1548
1549
1550
1551 scsi_for_each_sg(cmd, cur_seg, nseg, i) {
1552 dma_addr_t addr;
1553 bus_size_t len;
1554 int consumed;
1555
1556 addr = sg_dma_address(cur_seg);
1557 len = sg_dma_len(cur_seg);
1558 consumed = ahc_linux_map_seg(ahc, scb,
1559 sg, addr, len);
1560 sg += consumed;
1561 scb->sg_count += consumed;
1562 }
1563 sg--;
1564 sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
1565
1566
1567
1568
1569 scb->hscb->sgptr =
1570 ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
1571
1572
1573
1574
1575
1576 scb->hscb->dataptr = scb->sg_list->addr;
1577 scb->hscb->datacnt = scb->sg_list->len;
1578 } else {
1579 scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL);
1580 scb->hscb->dataptr = 0;
1581 scb->hscb->datacnt = 0;
1582 scb->sg_count = 0;
1583 }
1584
1585 LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links);
1586 dev->openings--;
1587 dev->active++;
1588 dev->commands_issued++;
1589 if ((dev->flags & AHC_DEV_PERIODIC_OTAG) != 0)
1590 dev->commands_since_idle_or_otag++;
1591
1592 scb->flags |= SCB_ACTIVE;
1593 if (untagged_q) {
1594 TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe);
1595 scb->flags |= SCB_UNTAGGEDQ;
1596 }
1597 ahc_queue_scb(ahc, scb);
1598 return 0;
1599}
1600
1601
1602
1603
1604irqreturn_t
1605ahc_linux_isr(int irq, void *dev_id)
1606{
1607 struct ahc_softc *ahc;
1608 u_long flags;
1609 int ours;
1610
1611 ahc = (struct ahc_softc *) dev_id;
1612 ahc_lock(ahc, &flags);
1613 ours = ahc_intr(ahc);
1614 ahc_unlock(ahc, &flags);
1615 return IRQ_RETVAL(ours);
1616}
1617
1618void
1619ahc_platform_flushwork(struct ahc_softc *ahc)
1620{
1621
1622}
1623
1624void
1625ahc_send_async(struct ahc_softc *ahc, char channel,
1626 u_int target, u_int lun, ac_code code)
1627{
1628 switch (code) {
1629 case AC_TRANSFER_NEG:
1630 {
1631 char buf[80];
1632 struct scsi_target *starget;
1633 struct ahc_linux_target *targ;
1634 struct info_str info;
1635 struct ahc_initiator_tinfo *tinfo;
1636 struct ahc_tmode_tstate *tstate;
1637 int target_offset;
1638 unsigned int target_ppr_options;
1639
1640 BUG_ON(target == CAM_TARGET_WILDCARD);
1641
1642 info.buffer = buf;
1643 info.length = sizeof(buf);
1644 info.offset = 0;
1645 info.pos = 0;
1646 tinfo = ahc_fetch_transinfo(ahc, channel,
1647 channel == 'A' ? ahc->our_id
1648 : ahc->our_id_b,
1649 target, &tstate);
1650
1651
1652
1653
1654
1655 if (tinfo->curr.period != tinfo->goal.period
1656 || tinfo->curr.width != tinfo->goal.width
1657 || tinfo->curr.offset != tinfo->goal.offset
1658 || tinfo->curr.ppr_options != tinfo->goal.ppr_options)
1659 if (bootverbose == 0)
1660 break;
1661
1662
1663
1664
1665
1666 target_offset = target;
1667 if (channel == 'B')
1668 target_offset += 8;
1669 starget = ahc->platform_data->starget[target_offset];
1670 if (starget == NULL)
1671 break;
1672 targ = scsi_transport_target_data(starget);
1673
1674 target_ppr_options =
1675 (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0)
1676 + (spi_qas(starget) ? MSG_EXT_PPR_QAS_REQ : 0)
1677 + (spi_iu(starget) ? MSG_EXT_PPR_IU_REQ : 0);
1678
1679 if (tinfo->curr.period == spi_period(starget)
1680 && tinfo->curr.width == spi_width(starget)
1681 && tinfo->curr.offset == spi_offset(starget)
1682 && tinfo->curr.ppr_options == target_ppr_options)
1683 if (bootverbose == 0)
1684 break;
1685
1686 spi_period(starget) = tinfo->curr.period;
1687 spi_width(starget) = tinfo->curr.width;
1688 spi_offset(starget) = tinfo->curr.offset;
1689 spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ ? 1 : 0;
1690 spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ ? 1 : 0;
1691 spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ ? 1 : 0;
1692 spi_display_xfer_agreement(starget);
1693 break;
1694 }
1695 case AC_SENT_BDR:
1696 {
1697 WARN_ON(lun != CAM_LUN_WILDCARD);
1698 scsi_report_device_reset(ahc->platform_data->host,
1699 channel - 'A', target);
1700 break;
1701 }
1702 case AC_BUS_RESET:
1703 if (ahc->platform_data->host != NULL) {
1704 scsi_report_bus_reset(ahc->platform_data->host,
1705 channel - 'A');
1706 }
1707 break;
1708 default:
1709 panic("ahc_send_async: Unexpected async event");
1710 }
1711}
1712
1713
1714
1715
1716void
1717ahc_done(struct ahc_softc *ahc, struct scb *scb)
1718{
1719 struct scsi_cmnd *cmd;
1720 struct ahc_linux_device *dev;
1721
1722 LIST_REMOVE(scb, pending_links);
1723 if ((scb->flags & SCB_UNTAGGEDQ) != 0) {
1724 struct scb_tailq *untagged_q;
1725 int target_offset;
1726
1727 target_offset = SCB_GET_TARGET_OFFSET(ahc, scb);
1728 untagged_q = &(ahc->untagged_queues[target_offset]);
1729 TAILQ_REMOVE(untagged_q, scb, links.tqe);
1730 BUG_ON(!TAILQ_EMPTY(untagged_q));
1731 } else if ((scb->flags & SCB_ACTIVE) == 0) {
1732
1733
1734
1735
1736
1737 printf("SCB %d done'd twice\n", scb->hscb->tag);
1738 ahc_dump_card_state(ahc);
1739 panic("Stopping for safety");
1740 }
1741 cmd = scb->io_ctx;
1742 dev = scb->platform_data->dev;
1743 dev->active--;
1744 dev->openings++;
1745 if ((cmd->result & (CAM_DEV_QFRZN << 16)) != 0) {
1746 cmd->result &= ~(CAM_DEV_QFRZN << 16);
1747 dev->qfrozen--;
1748 }
1749 ahc_linux_unmap_scb(ahc, scb);
1750
1751
1752
1753
1754
1755
1756
1757 cmd->sense_buffer[0] = 0;
1758 if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG) {
1759 uint32_t amount_xferred;
1760
1761 amount_xferred =
1762 ahc_get_transfer_length(scb) - ahc_get_residual(scb);
1763 if ((scb->flags & SCB_TRANSMISSION_ERROR) != 0) {
1764#ifdef AHC_DEBUG
1765 if ((ahc_debug & AHC_SHOW_MISC) != 0) {
1766 ahc_print_path(ahc, scb);
1767 printf("Set CAM_UNCOR_PARITY\n");
1768 }
1769#endif
1770 ahc_set_transaction_status(scb, CAM_UNCOR_PARITY);
1771#ifdef AHC_REPORT_UNDERFLOWS
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781 } else if (amount_xferred < scb->io_ctx->underflow) {
1782 u_int i;
1783
1784 ahc_print_path(ahc, scb);
1785 printf("CDB:");
1786 for (i = 0; i < scb->io_ctx->cmd_len; i++)
1787 printf(" 0x%x", scb->io_ctx->cmnd[i]);
1788 printf("\n");
1789 ahc_print_path(ahc, scb);
1790 printf("Saw underflow (%ld of %ld bytes). "
1791 "Treated as error\n",
1792 ahc_get_residual(scb),
1793 ahc_get_transfer_length(scb));
1794 ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR);
1795#endif
1796 } else {
1797 ahc_set_transaction_status(scb, CAM_REQ_CMP);
1798 }
1799 } else if (ahc_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) {
1800 ahc_linux_handle_scsi_status(ahc, cmd->device, scb);
1801 }
1802
1803 if (dev->openings == 1
1804 && ahc_get_transaction_status(scb) == CAM_REQ_CMP
1805 && ahc_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL)
1806 dev->tag_success_count++;
1807
1808
1809
1810
1811
1812
1813 if ((dev->openings + dev->active) < dev->maxtags
1814 && dev->tag_success_count > AHC_TAG_SUCCESS_INTERVAL) {
1815 dev->tag_success_count = 0;
1816 dev->openings++;
1817 }
1818
1819 if (dev->active == 0)
1820 dev->commands_since_idle_or_otag = 0;
1821
1822 if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
1823 printf("Recovery SCB completes\n");
1824 if (ahc_get_transaction_status(scb) == CAM_BDR_SENT
1825 || ahc_get_transaction_status(scb) == CAM_REQ_ABORTED)
1826 ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT);
1827
1828 if (ahc->platform_data->eh_done)
1829 complete(ahc->platform_data->eh_done);
1830 }
1831
1832 ahc_free_scb(ahc, scb);
1833 ahc_linux_queue_cmd_complete(ahc, cmd);
1834}
1835
1836static void
1837ahc_linux_handle_scsi_status(struct ahc_softc *ahc,
1838 struct scsi_device *sdev, struct scb *scb)
1839{
1840 struct ahc_devinfo devinfo;
1841 struct ahc_linux_device *dev = scsi_transport_device_data(sdev);
1842
1843 ahc_compile_devinfo(&devinfo,
1844 ahc->our_id,
1845 sdev->sdev_target->id, sdev->lun,
1846 sdev->sdev_target->channel == 0 ? 'A' : 'B',
1847 ROLE_INITIATOR);
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859 switch (ahc_get_scsi_status(scb)) {
1860 default:
1861 break;
1862 case SCSI_STATUS_CHECK_COND:
1863 case SCSI_STATUS_CMD_TERMINATED:
1864 {
1865 struct scsi_cmnd *cmd;
1866
1867
1868
1869
1870
1871 cmd = scb->io_ctx;
1872 if (scb->flags & SCB_SENSE) {
1873 u_int sense_size;
1874
1875 sense_size = min(sizeof(struct scsi_sense_data)
1876 - ahc_get_sense_residual(scb),
1877 (u_long)SCSI_SENSE_BUFFERSIZE);
1878 memcpy(cmd->sense_buffer,
1879 ahc_get_sense_buf(ahc, scb), sense_size);
1880 if (sense_size < SCSI_SENSE_BUFFERSIZE)
1881 memset(&cmd->sense_buffer[sense_size], 0,
1882 SCSI_SENSE_BUFFERSIZE - sense_size);
1883 cmd->result |= (DRIVER_SENSE << 24);
1884#ifdef AHC_DEBUG
1885 if (ahc_debug & AHC_SHOW_SENSE) {
1886 int i;
1887
1888 printf("Copied %d bytes of sense data:",
1889 sense_size);
1890 for (i = 0; i < sense_size; i++) {
1891 if ((i & 0xF) == 0)
1892 printf("\n");
1893 printf("0x%x ", cmd->sense_buffer[i]);
1894 }
1895 printf("\n");
1896 }
1897#endif
1898 }
1899 break;
1900 }
1901 case SCSI_STATUS_QUEUE_FULL:
1902 {
1903
1904
1905
1906
1907
1908
1909
1910
1911 dev->tag_success_count = 0;
1912 if (dev->active != 0) {
1913
1914
1915
1916
1917 dev->openings = 0;
1918
1919
1920
1921
1922 if (dev->active == dev->tags_on_last_queuefull) {
1923
1924 dev->last_queuefull_same_count++;
1925
1926
1927
1928
1929
1930
1931
1932
1933 if (dev->last_queuefull_same_count
1934 == AHC_LOCK_TAGS_COUNT) {
1935 dev->maxtags = dev->active;
1936 ahc_print_path(ahc, scb);
1937 printf("Locking max tag count at %d\n",
1938 dev->active);
1939 }
1940 } else {
1941 dev->tags_on_last_queuefull = dev->active;
1942 dev->last_queuefull_same_count = 0;
1943 }
1944 ahc_set_transaction_status(scb, CAM_REQUEUE_REQ);
1945 ahc_set_scsi_status(scb, SCSI_STATUS_OK);
1946 ahc_platform_set_tags(ahc, sdev, &devinfo,
1947 (dev->flags & AHC_DEV_Q_BASIC)
1948 ? AHC_QUEUE_BASIC : AHC_QUEUE_TAGGED);
1949 break;
1950 }
1951
1952
1953
1954
1955 dev->openings = 1;
1956 ahc_set_scsi_status(scb, SCSI_STATUS_BUSY);
1957 ahc_platform_set_tags(ahc, sdev, &devinfo,
1958 (dev->flags & AHC_DEV_Q_BASIC)
1959 ? AHC_QUEUE_BASIC : AHC_QUEUE_TAGGED);
1960 break;
1961 }
1962 }
1963}
1964
1965static void
1966ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd)
1967{
1968
1969
1970
1971
1972
1973
1974 {
1975 u_int new_status;
1976
1977 switch (ahc_cmd_get_transaction_status(cmd)) {
1978 case CAM_REQ_INPROG:
1979 case CAM_REQ_CMP:
1980 case CAM_SCSI_STATUS_ERROR:
1981 new_status = DID_OK;
1982 break;
1983 case CAM_REQ_ABORTED:
1984 new_status = DID_ABORT;
1985 break;
1986 case CAM_BUSY:
1987 new_status = DID_BUS_BUSY;
1988 break;
1989 case CAM_REQ_INVALID:
1990 case CAM_PATH_INVALID:
1991 new_status = DID_BAD_TARGET;
1992 break;
1993 case CAM_SEL_TIMEOUT:
1994 new_status = DID_NO_CONNECT;
1995 break;
1996 case CAM_SCSI_BUS_RESET:
1997 case CAM_BDR_SENT:
1998 new_status = DID_RESET;
1999 break;
2000 case CAM_UNCOR_PARITY:
2001 new_status = DID_PARITY;
2002 break;
2003 case CAM_CMD_TIMEOUT:
2004 new_status = DID_TIME_OUT;
2005 break;
2006 case CAM_UA_ABORT:
2007 case CAM_REQ_CMP_ERR:
2008 case CAM_AUTOSENSE_FAIL:
2009 case CAM_NO_HBA:
2010 case CAM_DATA_RUN_ERR:
2011 case CAM_UNEXP_BUSFREE:
2012 case CAM_SEQUENCE_FAIL:
2013 case CAM_CCB_LEN_ERR:
2014 case CAM_PROVIDE_FAIL:
2015 case CAM_REQ_TERMIO:
2016 case CAM_UNREC_HBA_ERROR:
2017 case CAM_REQ_TOO_BIG:
2018 new_status = DID_ERROR;
2019 break;
2020 case CAM_REQUEUE_REQ:
2021 new_status = DID_REQUEUE;
2022 break;
2023 default:
2024
2025 new_status = DID_ERROR;
2026 break;
2027 }
2028
2029 ahc_cmd_set_transaction_status(cmd, new_status);
2030 }
2031
2032 cmd->scsi_done(cmd);
2033}
2034
2035static void
2036ahc_linux_freeze_simq(struct ahc_softc *ahc)
2037{
2038 unsigned long s;
2039
2040 ahc_lock(ahc, &s);
2041 ahc->platform_data->qfrozen++;
2042 if (ahc->platform_data->qfrozen == 1) {
2043 scsi_block_requests(ahc->platform_data->host);
2044
2045
2046 ahc_platform_abort_scbs(ahc, CAM_TARGET_WILDCARD, ALL_CHANNELS,
2047 CAM_LUN_WILDCARD, SCB_LIST_NULL,
2048 ROLE_INITIATOR, CAM_REQUEUE_REQ);
2049 }
2050 ahc_unlock(ahc, &s);
2051}
2052
2053static void
2054ahc_linux_release_simq(struct ahc_softc *ahc)
2055{
2056 u_long s;
2057 int unblock_reqs;
2058
2059 unblock_reqs = 0;
2060 ahc_lock(ahc, &s);
2061 if (ahc->platform_data->qfrozen > 0)
2062 ahc->platform_data->qfrozen--;
2063 if (ahc->platform_data->qfrozen == 0)
2064 unblock_reqs = 1;
2065 ahc_unlock(ahc, &s);
2066
2067
2068
2069
2070
2071
2072 if (unblock_reqs)
2073 scsi_unblock_requests(ahc->platform_data->host);
2074}
2075
2076static int
2077ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
2078{
2079 struct ahc_softc *ahc;
2080 struct ahc_linux_device *dev;
2081 struct scb *pending_scb;
2082 u_int saved_scbptr;
2083 u_int active_scb_index;
2084 u_int last_phase;
2085 u_int saved_scsiid;
2086 u_int cdb_byte;
2087 int retval;
2088 int was_paused;
2089 int paused;
2090 int wait;
2091 int disconnected;
2092 unsigned long flags;
2093
2094 pending_scb = NULL;
2095 paused = FALSE;
2096 wait = FALSE;
2097 ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
2098
2099 scmd_printk(KERN_INFO, cmd, "Attempting to queue a%s message\n",
2100 flag == SCB_ABORT ? "n ABORT" : " TARGET RESET");
2101
2102 printf("CDB:");
2103 for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
2104 printf(" 0x%x", cmd->cmnd[cdb_byte]);
2105 printf("\n");
2106
2107 ahc_lock(ahc, &flags);
2108
2109
2110
2111
2112
2113
2114
2115
2116 dev = scsi_transport_device_data(cmd->device);
2117
2118 if (dev == NULL) {
2119
2120
2121
2122
2123 printf("%s:%d:%d:%d: Is not an active device\n",
2124 ahc_name(ahc), cmd->device->channel, cmd->device->id,
2125 cmd->device->lun);
2126 retval = SUCCESS;
2127 goto no_cmd;
2128 }
2129
2130 if ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0
2131 && ahc_search_untagged_queues(ahc, cmd, cmd->device->id,
2132 cmd->device->channel + 'A',
2133 cmd->device->lun,
2134 CAM_REQ_ABORTED, SEARCH_COMPLETE) != 0) {
2135 printf("%s:%d:%d:%d: Command found on untagged queue\n",
2136 ahc_name(ahc), cmd->device->channel, cmd->device->id,
2137 cmd->device->lun);
2138 retval = SUCCESS;
2139 goto done;
2140 }
2141
2142
2143
2144
2145 LIST_FOREACH(pending_scb, &ahc->pending_scbs, pending_links) {
2146 if (pending_scb->io_ctx == cmd)
2147 break;
2148 }
2149
2150 if (pending_scb == NULL && flag == SCB_DEVICE_RESET) {
2151
2152
2153 LIST_FOREACH(pending_scb, &ahc->pending_scbs, pending_links) {
2154 if (ahc_match_scb(ahc, pending_scb, scmd_id(cmd),
2155 scmd_channel(cmd) + 'A',
2156 CAM_LUN_WILDCARD,
2157 SCB_LIST_NULL, ROLE_INITIATOR))
2158 break;
2159 }
2160 }
2161
2162 if (pending_scb == NULL) {
2163 scmd_printk(KERN_INFO, cmd, "Command not found\n");
2164 goto no_cmd;
2165 }
2166
2167 if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) {
2168
2169
2170
2171 retval = FAILED;
2172 goto done;
2173 }
2174
2175
2176
2177
2178
2179
2180 was_paused = ahc_is_paused(ahc);
2181 ahc_pause_and_flushwork(ahc);
2182 paused = TRUE;
2183
2184 if ((pending_scb->flags & SCB_ACTIVE) == 0) {
2185 scmd_printk(KERN_INFO, cmd, "Command already completed\n");
2186 goto no_cmd;
2187 }
2188
2189 printf("%s: At time of recovery, card was %spaused\n",
2190 ahc_name(ahc), was_paused ? "" : "not ");
2191 ahc_dump_card_state(ahc);
2192
2193 disconnected = TRUE;
2194 if (flag == SCB_ABORT) {
2195 if (ahc_search_qinfifo(ahc, cmd->device->id,
2196 cmd->device->channel + 'A',
2197 cmd->device->lun,
2198 pending_scb->hscb->tag,
2199 ROLE_INITIATOR, CAM_REQ_ABORTED,
2200 SEARCH_COMPLETE) > 0) {
2201 printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
2202 ahc_name(ahc), cmd->device->channel,
2203 cmd->device->id, cmd->device->lun);
2204 retval = SUCCESS;
2205 goto done;
2206 }
2207 } else if (ahc_search_qinfifo(ahc, cmd->device->id,
2208 cmd->device->channel + 'A',
2209 cmd->device->lun, pending_scb->hscb->tag,
2210 ROLE_INITIATOR, 0,
2211 SEARCH_COUNT) > 0) {
2212 disconnected = FALSE;
2213 }
2214
2215 if (disconnected && (ahc_inb(ahc, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) {
2216 struct scb *bus_scb;
2217
2218 bus_scb = ahc_lookup_scb(ahc, ahc_inb(ahc, SCB_TAG));
2219 if (bus_scb == pending_scb)
2220 disconnected = FALSE;
2221 else if (flag != SCB_ABORT
2222 && ahc_inb(ahc, SAVED_SCSIID) == pending_scb->hscb->scsiid
2223 && ahc_inb(ahc, SAVED_LUN) == SCB_GET_LUN(pending_scb))
2224 disconnected = FALSE;
2225 }
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235 last_phase = ahc_inb(ahc, LASTPHASE);
2236 saved_scbptr = ahc_inb(ahc, SCBPTR);
2237 active_scb_index = ahc_inb(ahc, SCB_TAG);
2238 saved_scsiid = ahc_inb(ahc, SAVED_SCSIID);
2239 if (last_phase != P_BUSFREE
2240 && (pending_scb->hscb->tag == active_scb_index
2241 || (flag == SCB_DEVICE_RESET
2242 && SCSIID_TARGET(ahc, saved_scsiid) == scmd_id(cmd)))) {
2243
2244
2245
2246
2247
2248 pending_scb = ahc_lookup_scb(ahc, active_scb_index);
2249 pending_scb->flags |= SCB_RECOVERY_SCB|flag;
2250 ahc_outb(ahc, MSG_OUT, HOST_MSG);
2251 ahc_outb(ahc, SCSISIGO, last_phase|ATNO);
2252 scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n");
2253 wait = TRUE;
2254 } else if (disconnected) {
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272 pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
2273 pending_scb->flags |= SCB_RECOVERY_SCB|flag;
2274
2275
2276
2277
2278
2279
2280
2281
2282 ahc_search_disc_list(ahc, cmd->device->id,
2283 cmd->device->channel + 'A',
2284 cmd->device->lun, pending_scb->hscb->tag,
2285 TRUE,
2286 TRUE,
2287 FALSE);
2288
2289
2290
2291
2292
2293
2294
2295
2296 if ((ahc->flags & AHC_PAGESCBS) == 0) {
2297 ahc_outb(ahc, SCBPTR, pending_scb->hscb->tag);
2298 ahc_outb(ahc, SCB_CONTROL,
2299 ahc_inb(ahc, SCB_CONTROL)|MK_MESSAGE);
2300 }
2301
2302
2303
2304
2305
2306
2307 ahc_search_qinfifo(ahc, cmd->device->id,
2308 cmd->device->channel + 'A',
2309 cmd->device->lun, SCB_LIST_NULL,
2310 ROLE_INITIATOR, CAM_REQUEUE_REQ,
2311 SEARCH_COMPLETE);
2312 ahc_qinfifo_requeue_tail(ahc, pending_scb);
2313 ahc_outb(ahc, SCBPTR, saved_scbptr);
2314 ahc_print_path(ahc, pending_scb);
2315 printf("Device is disconnected, re-queuing SCB\n");
2316 wait = TRUE;
2317 } else {
2318 scmd_printk(KERN_INFO, cmd, "Unable to deliver message\n");
2319 retval = FAILED;
2320 goto done;
2321 }
2322
2323no_cmd:
2324
2325
2326
2327
2328
2329
2330 retval = SUCCESS;
2331done:
2332 if (paused)
2333 ahc_unpause(ahc);
2334 if (wait) {
2335 DECLARE_COMPLETION_ONSTACK(done);
2336
2337 ahc->platform_data->eh_done = &done;
2338 ahc_unlock(ahc, &flags);
2339
2340 printf("Recovery code sleeping\n");
2341 if (!wait_for_completion_timeout(&done, 5 * HZ)) {
2342 ahc_lock(ahc, &flags);
2343 ahc->platform_data->eh_done = NULL;
2344 ahc_unlock(ahc, &flags);
2345
2346 printf("Timer Expired\n");
2347 retval = FAILED;
2348 }
2349 printf("Recovery code awake\n");
2350 } else
2351 ahc_unlock(ahc, &flags);
2352 return (retval);
2353}
2354
2355void
2356ahc_platform_dump_card_state(struct ahc_softc *ahc)
2357{
2358}
2359
2360static void ahc_linux_set_width(struct scsi_target *starget, int width)
2361{
2362 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2363 struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
2364 struct ahc_devinfo devinfo;
2365 unsigned long flags;
2366
2367 ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2368 starget->channel + 'A', ROLE_INITIATOR);
2369 ahc_lock(ahc, &flags);
2370 ahc_set_width(ahc, &devinfo, width, AHC_TRANS_GOAL, FALSE);
2371 ahc_unlock(ahc, &flags);
2372}
2373
2374static void ahc_linux_set_period(struct scsi_target *starget, int period)
2375{
2376 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2377 struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
2378 struct ahc_tmode_tstate *tstate;
2379 struct ahc_initiator_tinfo *tinfo
2380 = ahc_fetch_transinfo(ahc,
2381 starget->channel + 'A',
2382 shost->this_id, starget->id, &tstate);
2383 struct ahc_devinfo devinfo;
2384 unsigned int ppr_options = tinfo->goal.ppr_options;
2385 unsigned long flags;
2386 unsigned long offset = tinfo->goal.offset;
2387 const struct ahc_syncrate *syncrate;
2388
2389 if (offset == 0)
2390 offset = MAX_OFFSET;
2391
2392 if (period < 9)
2393 period = 9;
2394 if (period == 9) {
2395 if (spi_max_width(starget))
2396 ppr_options |= MSG_EXT_PPR_DT_REQ;
2397 else
2398
2399 period = 10;
2400 }
2401
2402 ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2403 starget->channel + 'A', ROLE_INITIATOR);
2404
2405
2406 if (ppr_options & ~MSG_EXT_PPR_QAS_REQ) {
2407 if (spi_width(starget) == 0)
2408 ppr_options &= MSG_EXT_PPR_QAS_REQ;
2409 }
2410
2411 syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT);
2412 ahc_lock(ahc, &flags);
2413 ahc_set_syncrate(ahc, &devinfo, syncrate, period, offset,
2414 ppr_options, AHC_TRANS_GOAL, FALSE);
2415 ahc_unlock(ahc, &flags);
2416}
2417
2418static void ahc_linux_set_offset(struct scsi_target *starget, int offset)
2419{
2420 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2421 struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
2422 struct ahc_tmode_tstate *tstate;
2423 struct ahc_initiator_tinfo *tinfo
2424 = ahc_fetch_transinfo(ahc,
2425 starget->channel + 'A',
2426 shost->this_id, starget->id, &tstate);
2427 struct ahc_devinfo devinfo;
2428 unsigned int ppr_options = 0;
2429 unsigned int period = 0;
2430 unsigned long flags;
2431 const struct ahc_syncrate *syncrate = NULL;
2432
2433 ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2434 starget->channel + 'A', ROLE_INITIATOR);
2435 if (offset != 0) {
2436 syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT);
2437 period = tinfo->goal.period;
2438 ppr_options = tinfo->goal.ppr_options;
2439 }
2440 ahc_lock(ahc, &flags);
2441 ahc_set_syncrate(ahc, &devinfo, syncrate, period, offset,
2442 ppr_options, AHC_TRANS_GOAL, FALSE);
2443 ahc_unlock(ahc, &flags);
2444}
2445
2446static void ahc_linux_set_dt(struct scsi_target *starget, int dt)
2447{
2448 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2449 struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
2450 struct ahc_tmode_tstate *tstate;
2451 struct ahc_initiator_tinfo *tinfo
2452 = ahc_fetch_transinfo(ahc,
2453 starget->channel + 'A',
2454 shost->this_id, starget->id, &tstate);
2455 struct ahc_devinfo devinfo;
2456 unsigned int ppr_options = tinfo->goal.ppr_options
2457 & ~MSG_EXT_PPR_DT_REQ;
2458 unsigned int period = tinfo->goal.period;
2459 unsigned int width = tinfo->goal.width;
2460 unsigned long flags;
2461 const struct ahc_syncrate *syncrate;
2462
2463 if (dt && spi_max_width(starget)) {
2464 ppr_options |= MSG_EXT_PPR_DT_REQ;
2465 if (!width)
2466 ahc_linux_set_width(starget, 1);
2467 } else if (period == 9)
2468 period = 10;
2469
2470 ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2471 starget->channel + 'A', ROLE_INITIATOR);
2472 syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,AHC_SYNCRATE_DT);
2473 ahc_lock(ahc, &flags);
2474 ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->goal.offset,
2475 ppr_options, AHC_TRANS_GOAL, FALSE);
2476 ahc_unlock(ahc, &flags);
2477}
2478
2479#if 0
2480
2481
2482
2483
2484static void ahc_linux_set_qas(struct scsi_target *starget, int qas)
2485{
2486 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2487 struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
2488 struct ahc_tmode_tstate *tstate;
2489 struct ahc_initiator_tinfo *tinfo
2490 = ahc_fetch_transinfo(ahc,
2491 starget->channel + 'A',
2492 shost->this_id, starget->id, &tstate);
2493 struct ahc_devinfo devinfo;
2494 unsigned int ppr_options = tinfo->goal.ppr_options
2495 & ~MSG_EXT_PPR_QAS_REQ;
2496 unsigned int period = tinfo->goal.period;
2497 unsigned long flags;
2498 struct ahc_syncrate *syncrate;
2499
2500 if (qas)
2501 ppr_options |= MSG_EXT_PPR_QAS_REQ;
2502
2503 ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2504 starget->channel + 'A', ROLE_INITIATOR);
2505 syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT);
2506 ahc_lock(ahc, &flags);
2507 ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->goal.offset,
2508 ppr_options, AHC_TRANS_GOAL, FALSE);
2509 ahc_unlock(ahc, &flags);
2510}
2511
2512static void ahc_linux_set_iu(struct scsi_target *starget, int iu)
2513{
2514 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2515 struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
2516 struct ahc_tmode_tstate *tstate;
2517 struct ahc_initiator_tinfo *tinfo
2518 = ahc_fetch_transinfo(ahc,
2519 starget->channel + 'A',
2520 shost->this_id, starget->id, &tstate);
2521 struct ahc_devinfo devinfo;
2522 unsigned int ppr_options = tinfo->goal.ppr_options
2523 & ~MSG_EXT_PPR_IU_REQ;
2524 unsigned int period = tinfo->goal.period;
2525 unsigned long flags;
2526 struct ahc_syncrate *syncrate;
2527
2528 if (iu)
2529 ppr_options |= MSG_EXT_PPR_IU_REQ;
2530
2531 ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2532 starget->channel + 'A', ROLE_INITIATOR);
2533 syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT);
2534 ahc_lock(ahc, &flags);
2535 ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->goal.offset,
2536 ppr_options, AHC_TRANS_GOAL, FALSE);
2537 ahc_unlock(ahc, &flags);
2538}
2539#endif
2540
2541static void ahc_linux_get_signalling(struct Scsi_Host *shost)
2542{
2543 struct ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata;
2544 unsigned long flags;
2545 u8 mode;
2546
2547 if (!(ahc->features & AHC_ULTRA2)) {
2548
2549 spi_signalling(shost) =
2550 ahc->features & AHC_HVD ?
2551 SPI_SIGNAL_HVD :
2552 SPI_SIGNAL_SE;
2553 return;
2554 }
2555
2556 ahc_lock(ahc, &flags);
2557 ahc_pause(ahc);
2558 mode = ahc_inb(ahc, SBLKCTL);
2559 ahc_unpause(ahc);
2560 ahc_unlock(ahc, &flags);
2561
2562 if (mode & ENAB40)
2563 spi_signalling(shost) = SPI_SIGNAL_LVD;
2564 else if (mode & ENAB20)
2565 spi_signalling(shost) = SPI_SIGNAL_SE;
2566 else
2567 spi_signalling(shost) = SPI_SIGNAL_UNKNOWN;
2568}
2569
2570static struct spi_function_template ahc_linux_transport_functions = {
2571 .set_offset = ahc_linux_set_offset,
2572 .show_offset = 1,
2573 .set_period = ahc_linux_set_period,
2574 .show_period = 1,
2575 .set_width = ahc_linux_set_width,
2576 .show_width = 1,
2577 .set_dt = ahc_linux_set_dt,
2578 .show_dt = 1,
2579#if 0
2580 .set_iu = ahc_linux_set_iu,
2581 .show_iu = 1,
2582 .set_qas = ahc_linux_set_qas,
2583 .show_qas = 1,
2584#endif
2585 .get_signalling = ahc_linux_get_signalling,
2586};
2587
2588
2589
2590static int __init
2591ahc_linux_init(void)
2592{
2593
2594
2595
2596 if (aic7xxx)
2597 aic7xxx_setup(aic7xxx);
2598
2599 ahc_linux_transport_template =
2600 spi_attach_transport(&ahc_linux_transport_functions);
2601 if (!ahc_linux_transport_template)
2602 return -ENODEV;
2603
2604 scsi_transport_reserve_device(ahc_linux_transport_template,
2605 sizeof(struct ahc_linux_device));
2606
2607 ahc_linux_pci_init();
2608 ahc_linux_eisa_init();
2609 return 0;
2610}
2611
2612static void
2613ahc_linux_exit(void)
2614{
2615 ahc_linux_pci_exit();
2616 ahc_linux_eisa_exit();
2617 spi_release_transport(ahc_linux_transport_template);
2618}
2619
2620module_init(ahc_linux_init);
2621module_exit(ahc_linux_exit);
2622