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#include "aic79xx_osm.h"
46#include "aic79xx_inline.h"
47#include <scsi/scsicam.h>
48
49static struct scsi_transport_template *ahd_linux_transport_template = NULL;
50
51#include <linux/init.h>
52#include <linux/mm.h>
53#include <linux/blkdev.h>
54#include <linux/delay.h>
55#include <linux/device.h>
56#include <linux/slab.h>
57
58
59
60
61#define AHD_LINUX_ERR_THRESH 1000
62
63
64
65
66
67
68
69#ifdef CONFIG_AIC79XX_RESET_DELAY_MS
70#define AIC79XX_RESET_DELAY CONFIG_AIC79XX_RESET_DELAY_MS
71#else
72#define AIC79XX_RESET_DELAY 5000
73#endif
74
75
76
77
78
79
80
81
82
83
84
85
86typedef struct {
87 uint16_t tag_commands[16];
88} adapter_tag_info_t;
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
123
124
125
126
127
128
129
130
131
132
133#ifdef CONFIG_AIC79XX_CMDS_PER_DEVICE
134#define AIC79XX_CMDS_PER_DEVICE CONFIG_AIC79XX_CMDS_PER_DEVICE
135#else
136#define AIC79XX_CMDS_PER_DEVICE AHD_MAX_QUEUE
137#endif
138
139#define AIC79XX_CONFIGED_TAG_COMMANDS { \
140 AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \
141 AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \
142 AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \
143 AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \
144 AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \
145 AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \
146 AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \
147 AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE \
148}
149
150
151
152
153
154static adapter_tag_info_t aic79xx_tag_info[] =
155{
156 {AIC79XX_CONFIGED_TAG_COMMANDS},
157 {AIC79XX_CONFIGED_TAG_COMMANDS},
158 {AIC79XX_CONFIGED_TAG_COMMANDS},
159 {AIC79XX_CONFIGED_TAG_COMMANDS},
160 {AIC79XX_CONFIGED_TAG_COMMANDS},
161 {AIC79XX_CONFIGED_TAG_COMMANDS},
162 {AIC79XX_CONFIGED_TAG_COMMANDS},
163 {AIC79XX_CONFIGED_TAG_COMMANDS},
164 {AIC79XX_CONFIGED_TAG_COMMANDS},
165 {AIC79XX_CONFIGED_TAG_COMMANDS},
166 {AIC79XX_CONFIGED_TAG_COMMANDS},
167 {AIC79XX_CONFIGED_TAG_COMMANDS},
168 {AIC79XX_CONFIGED_TAG_COMMANDS},
169 {AIC79XX_CONFIGED_TAG_COMMANDS},
170 {AIC79XX_CONFIGED_TAG_COMMANDS},
171 {AIC79XX_CONFIGED_TAG_COMMANDS}
172};
173
174
175
176
177
178
179struct ahd_linux_iocell_opts
180{
181 uint8_t precomp;
182 uint8_t slewrate;
183 uint8_t amplitude;
184};
185#define AIC79XX_DEFAULT_PRECOMP 0xFF
186#define AIC79XX_DEFAULT_SLEWRATE 0xFF
187#define AIC79XX_DEFAULT_AMPLITUDE 0xFF
188#define AIC79XX_DEFAULT_IOOPTS \
189{ \
190 AIC79XX_DEFAULT_PRECOMP, \
191 AIC79XX_DEFAULT_SLEWRATE, \
192 AIC79XX_DEFAULT_AMPLITUDE \
193}
194#define AIC79XX_PRECOMP_INDEX 0
195#define AIC79XX_SLEWRATE_INDEX 1
196#define AIC79XX_AMPLITUDE_INDEX 2
197static const struct ahd_linux_iocell_opts aic79xx_iocell_info[] =
198{
199 AIC79XX_DEFAULT_IOOPTS,
200 AIC79XX_DEFAULT_IOOPTS,
201 AIC79XX_DEFAULT_IOOPTS,
202 AIC79XX_DEFAULT_IOOPTS,
203 AIC79XX_DEFAULT_IOOPTS,
204 AIC79XX_DEFAULT_IOOPTS,
205 AIC79XX_DEFAULT_IOOPTS,
206 AIC79XX_DEFAULT_IOOPTS,
207 AIC79XX_DEFAULT_IOOPTS,
208 AIC79XX_DEFAULT_IOOPTS,
209 AIC79XX_DEFAULT_IOOPTS,
210 AIC79XX_DEFAULT_IOOPTS,
211 AIC79XX_DEFAULT_IOOPTS,
212 AIC79XX_DEFAULT_IOOPTS,
213 AIC79XX_DEFAULT_IOOPTS,
214 AIC79XX_DEFAULT_IOOPTS
215};
216
217
218
219
220
221#define DID_UNDERFLOW DID_ERROR
222
223void
224ahd_print_path(struct ahd_softc *ahd, struct scb *scb)
225{
226 printk("(scsi%d:%c:%d:%d): ",
227 ahd->platform_data->host->host_no,
228 scb != NULL ? SCB_GET_CHANNEL(ahd, scb) : 'X',
229 scb != NULL ? SCB_GET_TARGET(ahd, scb) : -1,
230 scb != NULL ? SCB_GET_LUN(scb) : -1);
231}
232
233
234
235
236
237
238
239
240
241
242
243
244static uint32_t aic79xx_no_reset;
245
246
247
248
249
250
251static uint32_t aic79xx_extended;
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267static uint32_t aic79xx_pci_parity = ~0;
268
269
270
271
272
273
274
275uint32_t aic79xx_allow_memio = ~0;
276
277
278
279
280
281
282
283
284
285
286
287static uint32_t aic79xx_seltime;
288
289
290
291
292
293
294
295
296
297static uint32_t aic79xx_periodic_otag;
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312uint32_t aic79xx_slowcrc;
313
314
315
316
317static char *aic79xx = NULL;
318
319MODULE_AUTHOR("Maintainer: Hannes Reinecke <hare@suse.de>");
320MODULE_DESCRIPTION("Adaptec AIC790X U320 SCSI Host Bus Adapter driver");
321MODULE_LICENSE("Dual BSD/GPL");
322MODULE_VERSION(AIC79XX_DRIVER_VERSION);
323module_param(aic79xx, charp, 0444);
324MODULE_PARM_DESC(aic79xx,
325"period-delimited options string:\n"
326" verbose Enable verbose/diagnostic logging\n"
327" allow_memio Allow device registers to be memory mapped\n"
328" debug Bitmask of debug values to enable\n"
329" no_reset Suppress initial bus resets\n"
330" extended Enable extended geometry on all controllers\n"
331" periodic_otag Send an ordered tagged transaction\n"
332" periodically to prevent tag starvation.\n"
333" This may be required by some older disk\n"
334" or drives/RAID arrays.\n"
335" tag_info:<tag_str> Set per-target tag depth\n"
336" global_tag_depth:<int> Global tag depth for all targets on all buses\n"
337" slewrate:<slewrate_list>Set the signal slew rate (0-15).\n"
338" precomp:<pcomp_list> Set the signal precompensation (0-7).\n"
339" amplitude:<int> Set the signal amplitude (0-7).\n"
340" seltime:<int> Selection Timeout:\n"
341" (0/256ms,1/128ms,2/64ms,3/32ms)\n"
342" slowcrc Turn on the SLOWCRC bit (Rev B only)\n"
343"\n"
344" Sample modprobe configuration file:\n"
345" # Enable verbose logging\n"
346" # Set tag depth on Controller 2/Target 2 to 10 tags\n"
347" # Shorten the selection timeout to 128ms\n"
348"\n"
349" options aic79xx 'aic79xx=verbose.tag_info:{{}.{}.{..10}}.seltime:1'\n"
350);
351
352static void ahd_linux_handle_scsi_status(struct ahd_softc *,
353 struct scsi_device *,
354 struct scb *);
355static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd,
356 struct scsi_cmnd *cmd);
357static int ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd);
358static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd);
359static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd,
360 struct ahd_devinfo *devinfo);
361static void ahd_linux_device_queue_depth(struct scsi_device *);
362static int ahd_linux_run_command(struct ahd_softc*,
363 struct ahd_linux_device *,
364 struct scsi_cmnd *);
365static void ahd_linux_setup_tag_info_global(char *p);
366static int aic79xx_setup(char *c);
367static void ahd_freeze_simq(struct ahd_softc *ahd);
368static void ahd_release_simq(struct ahd_softc *ahd);
369
370static int ahd_linux_unit;
371
372
373
374void ahd_delay(long);
375void
376ahd_delay(long usec)
377{
378
379
380
381
382
383 while (usec > 0) {
384 udelay(usec % 1024);
385 usec -= 1024;
386 }
387}
388
389
390
391uint8_t ahd_inb(struct ahd_softc * ahd, long port);
392void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val);
393void ahd_outw_atomic(struct ahd_softc * ahd,
394 long port, uint16_t val);
395void ahd_outsb(struct ahd_softc * ahd, long port,
396 uint8_t *, int count);
397void ahd_insb(struct ahd_softc * ahd, long port,
398 uint8_t *, int count);
399
400uint8_t
401ahd_inb(struct ahd_softc * ahd, long port)
402{
403 uint8_t x;
404
405 if (ahd->tags[0] == BUS_SPACE_MEMIO) {
406 x = readb(ahd->bshs[0].maddr + port);
407 } else {
408 x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
409 }
410 mb();
411 return (x);
412}
413
414#if 0
415static uint16_t
416ahd_inw_atomic(struct ahd_softc * ahd, long port)
417{
418 uint8_t x;
419
420 if (ahd->tags[0] == BUS_SPACE_MEMIO) {
421 x = readw(ahd->bshs[0].maddr + port);
422 } else {
423 x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
424 }
425 mb();
426 return (x);
427}
428#endif
429
430void
431ahd_outb(struct ahd_softc * ahd, long port, uint8_t val)
432{
433 if (ahd->tags[0] == BUS_SPACE_MEMIO) {
434 writeb(val, ahd->bshs[0].maddr + port);
435 } else {
436 outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
437 }
438 mb();
439}
440
441void
442ahd_outw_atomic(struct ahd_softc * ahd, long port, uint16_t val)
443{
444 if (ahd->tags[0] == BUS_SPACE_MEMIO) {
445 writew(val, ahd->bshs[0].maddr + port);
446 } else {
447 outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
448 }
449 mb();
450}
451
452void
453ahd_outsb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
454{
455 int i;
456
457
458
459
460
461
462 for (i = 0; i < count; i++)
463 ahd_outb(ahd, port, *array++);
464}
465
466void
467ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
468{
469 int i;
470
471
472
473
474
475
476 for (i = 0; i < count; i++)
477 *array++ = ahd_inb(ahd, port);
478}
479
480
481uint32_t
482ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width)
483{
484 switch (width) {
485 case 1:
486 {
487 uint8_t retval;
488
489 pci_read_config_byte(pci, reg, &retval);
490 return (retval);
491 }
492 case 2:
493 {
494 uint16_t retval;
495 pci_read_config_word(pci, reg, &retval);
496 return (retval);
497 }
498 case 4:
499 {
500 uint32_t retval;
501 pci_read_config_dword(pci, reg, &retval);
502 return (retval);
503 }
504 default:
505 panic("ahd_pci_read_config: Read size too big");
506
507 return (0);
508 }
509}
510
511void
512ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width)
513{
514 switch (width) {
515 case 1:
516 pci_write_config_byte(pci, reg, value);
517 break;
518 case 2:
519 pci_write_config_word(pci, reg, value);
520 break;
521 case 4:
522 pci_write_config_dword(pci, reg, value);
523 break;
524 default:
525 panic("ahd_pci_write_config: Write size too big");
526
527 }
528}
529
530
531static void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
532
533static void
534ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
535{
536 struct scsi_cmnd *cmd;
537
538 cmd = scb->io_ctx;
539 ahd_sync_sglist(ahd, scb, BUS_DMASYNC_POSTWRITE);
540 scsi_dma_unmap(cmd);
541}
542
543
544#define BUILD_SCSIID(ahd, cmd) \
545 (((scmd_id(cmd) << TID_SHIFT) & TID) | (ahd)->our_id)
546
547
548
549
550static const char *
551ahd_linux_info(struct Scsi_Host *host)
552{
553 static char buffer[512];
554 char ahd_info[256];
555 char *bp;
556 struct ahd_softc *ahd;
557
558 bp = &buffer[0];
559 ahd = *(struct ahd_softc **)host->hostdata;
560 memset(bp, 0, sizeof(buffer));
561 strcpy(bp, "Adaptec AIC79XX PCI-X SCSI HBA DRIVER, Rev " AIC79XX_DRIVER_VERSION "\n"
562 " <");
563 strcat(bp, ahd->description);
564 strcat(bp, ">\n"
565 " ");
566 ahd_controller_info(ahd, ahd_info);
567 strcat(bp, ahd_info);
568
569 return (bp);
570}
571
572
573
574
575static int
576ahd_linux_queue_lck(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
577{
578 struct ahd_softc *ahd;
579 struct ahd_linux_device *dev = scsi_transport_device_data(cmd->device);
580 int rtn = SCSI_MLQUEUE_HOST_BUSY;
581
582 ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
583
584 cmd->scsi_done = scsi_done;
585 cmd->result = CAM_REQ_INPROG << 16;
586 rtn = ahd_linux_run_command(ahd, dev, cmd);
587
588 return rtn;
589}
590
591static DEF_SCSI_QCMD(ahd_linux_queue)
592
593static struct scsi_target **
594ahd_linux_target_in_softc(struct scsi_target *starget)
595{
596 struct ahd_softc *ahd =
597 *((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata);
598 unsigned int target_offset;
599
600 target_offset = starget->id;
601 if (starget->channel != 0)
602 target_offset += 8;
603
604 return &ahd->platform_data->starget[target_offset];
605}
606
607static int
608ahd_linux_target_alloc(struct scsi_target *starget)
609{
610 struct ahd_softc *ahd =
611 *((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata);
612 struct seeprom_config *sc = ahd->seep_config;
613 unsigned long flags;
614 struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget);
615 struct ahd_devinfo devinfo;
616 struct ahd_initiator_tinfo *tinfo;
617 struct ahd_tmode_tstate *tstate;
618 char channel = starget->channel + 'A';
619
620 ahd_lock(ahd, &flags);
621
622 BUG_ON(*ahd_targp != NULL);
623
624 *ahd_targp = starget;
625
626 if (sc) {
627 int flags = sc->device_flags[starget->id];
628
629 tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
630 starget->id, &tstate);
631
632 if ((flags & CFPACKETIZED) == 0) {
633
634 spi_max_iu(starget) = 0;
635 } else {
636 if ((ahd->features & AHD_RTI) == 0)
637 spi_rti(starget) = 0;
638 }
639
640 if ((flags & CFQAS) == 0)
641 spi_max_qas(starget) = 0;
642
643
644 spi_max_width(starget) = (flags & CFWIDEB) ? 1 : 0;
645 spi_min_period(starget) = tinfo->user.period;
646 spi_max_offset(starget) = tinfo->user.offset;
647 }
648
649 tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id,
650 starget->id, &tstate);
651 ahd_compile_devinfo(&devinfo, ahd->our_id, starget->id,
652 CAM_LUN_WILDCARD, channel,
653 ROLE_INITIATOR);
654 ahd_set_syncrate(ahd, &devinfo, 0, 0, 0,
655 AHD_TRANS_GOAL, FALSE);
656 ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
657 AHD_TRANS_GOAL, FALSE);
658 ahd_unlock(ahd, &flags);
659
660 return 0;
661}
662
663static void
664ahd_linux_target_destroy(struct scsi_target *starget)
665{
666 struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget);
667
668 *ahd_targp = NULL;
669}
670
671static int
672ahd_linux_slave_alloc(struct scsi_device *sdev)
673{
674 struct ahd_softc *ahd =
675 *((struct ahd_softc **)sdev->host->hostdata);
676 struct ahd_linux_device *dev;
677
678 if (bootverbose)
679 printk("%s: Slave Alloc %d\n", ahd_name(ahd), sdev->id);
680
681 dev = scsi_transport_device_data(sdev);
682 memset(dev, 0, sizeof(*dev));
683
684
685
686
687
688 dev->openings = 1;
689
690
691
692
693
694
695 dev->maxtags = 0;
696
697 return (0);
698}
699
700static int
701ahd_linux_slave_configure(struct scsi_device *sdev)
702{
703 struct ahd_softc *ahd;
704
705 ahd = *((struct ahd_softc **)sdev->host->hostdata);
706 if (bootverbose)
707 sdev_printk(KERN_INFO, sdev, "Slave Configure\n");
708
709 ahd_linux_device_queue_depth(sdev);
710
711
712 if (!spi_initial_dv(sdev->sdev_target))
713 spi_dv_device(sdev);
714
715 return 0;
716}
717
718#if defined(__i386__)
719
720
721
722static int
723ahd_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev,
724 sector_t capacity, int geom[])
725{
726 uint8_t *bh;
727 int heads;
728 int sectors;
729 int cylinders;
730 int ret;
731 int extended;
732 struct ahd_softc *ahd;
733
734 ahd = *((struct ahd_softc **)sdev->host->hostdata);
735
736 bh = scsi_bios_ptable(bdev);
737 if (bh) {
738 ret = scsi_partsize(bh, capacity,
739 &geom[2], &geom[0], &geom[1]);
740 kfree(bh);
741 if (ret != -1)
742 return (ret);
743 }
744 heads = 64;
745 sectors = 32;
746 cylinders = aic_sector_div(capacity, heads, sectors);
747
748 if (aic79xx_extended != 0)
749 extended = 1;
750 else
751 extended = (ahd->flags & AHD_EXTENDED_TRANS_A) != 0;
752 if (extended && cylinders >= 1024) {
753 heads = 255;
754 sectors = 63;
755 cylinders = aic_sector_div(capacity, heads, sectors);
756 }
757 geom[0] = heads;
758 geom[1] = sectors;
759 geom[2] = cylinders;
760 return (0);
761}
762#endif
763
764
765
766
767static int
768ahd_linux_abort(struct scsi_cmnd *cmd)
769{
770 int error;
771
772 error = ahd_linux_queue_abort_cmd(cmd);
773
774 return error;
775}
776
777
778
779
780static int
781ahd_linux_dev_reset(struct scsi_cmnd *cmd)
782{
783 struct ahd_softc *ahd;
784 struct ahd_linux_device *dev;
785 struct scb *reset_scb;
786 u_int cdb_byte;
787 int retval = SUCCESS;
788 int paused;
789 int wait;
790 struct ahd_initiator_tinfo *tinfo;
791 struct ahd_tmode_tstate *tstate;
792 unsigned long flags;
793 DECLARE_COMPLETION_ONSTACK(done);
794
795 reset_scb = NULL;
796 paused = FALSE;
797 wait = FALSE;
798 ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
799
800 scmd_printk(KERN_INFO, cmd,
801 "Attempting to queue a TARGET RESET message:");
802
803 printk("CDB:");
804 for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
805 printk(" 0x%x", cmd->cmnd[cdb_byte]);
806 printk("\n");
807
808
809
810
811 dev = scsi_transport_device_data(cmd->device);
812
813 if (dev == NULL) {
814
815
816
817
818 scmd_printk(KERN_INFO, cmd, "Is not an active device\n");
819 return SUCCESS;
820 }
821
822
823
824
825 reset_scb = ahd_get_scb(ahd, AHD_NEVER_COL_IDX);
826 if (!reset_scb) {
827 scmd_printk(KERN_INFO, cmd, "No SCB available\n");
828 return FAILED;
829 }
830
831 tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
832 cmd->device->id, &tstate);
833 reset_scb->io_ctx = cmd;
834 reset_scb->platform_data->dev = dev;
835 reset_scb->sg_count = 0;
836 ahd_set_residual(reset_scb, 0);
837 ahd_set_sense_residual(reset_scb, 0);
838 reset_scb->platform_data->xfer_len = 0;
839 reset_scb->hscb->control = 0;
840 reset_scb->hscb->scsiid = BUILD_SCSIID(ahd,cmd);
841 reset_scb->hscb->lun = cmd->device->lun;
842 reset_scb->hscb->cdb_len = 0;
843 reset_scb->hscb->task_management = SIU_TASKMGMT_LUN_RESET;
844 reset_scb->flags |= SCB_DEVICE_RESET|SCB_RECOVERY_SCB|SCB_ACTIVE;
845 if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
846 reset_scb->flags |= SCB_PACKETIZED;
847 } else {
848 reset_scb->hscb->control |= MK_MESSAGE;
849 }
850 dev->openings--;
851 dev->active++;
852 dev->commands_issued++;
853
854 ahd_lock(ahd, &flags);
855
856 LIST_INSERT_HEAD(&ahd->pending_scbs, reset_scb, pending_links);
857 ahd_queue_scb(ahd, reset_scb);
858
859 ahd->platform_data->eh_done = &done;
860 ahd_unlock(ahd, &flags);
861
862 printk("%s: Device reset code sleeping\n", ahd_name(ahd));
863 if (!wait_for_completion_timeout(&done, 5 * HZ)) {
864 ahd_lock(ahd, &flags);
865 ahd->platform_data->eh_done = NULL;
866 ahd_unlock(ahd, &flags);
867 printk("%s: Device reset timer expired (active %d)\n",
868 ahd_name(ahd), dev->active);
869 retval = FAILED;
870 }
871 printk("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval);
872
873 return (retval);
874}
875
876
877
878
879static int
880ahd_linux_bus_reset(struct scsi_cmnd *cmd)
881{
882 struct ahd_softc *ahd;
883 int found;
884 unsigned long flags;
885
886 ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
887#ifdef AHD_DEBUG
888 if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
889 printk("%s: Bus reset called for cmd %p\n",
890 ahd_name(ahd), cmd);
891#endif
892 ahd_lock(ahd, &flags);
893
894 found = ahd_reset_channel(ahd, scmd_channel(cmd) + 'A',
895 TRUE);
896 ahd_unlock(ahd, &flags);
897
898 if (bootverbose)
899 printk("%s: SCSI bus reset delivered. "
900 "%d SCBs aborted.\n", ahd_name(ahd), found);
901
902 return (SUCCESS);
903}
904
905struct scsi_host_template aic79xx_driver_template = {
906 .module = THIS_MODULE,
907 .name = "aic79xx",
908 .proc_name = "aic79xx",
909 .proc_info = ahd_linux_proc_info,
910 .info = ahd_linux_info,
911 .queuecommand = ahd_linux_queue,
912 .eh_abort_handler = ahd_linux_abort,
913 .eh_device_reset_handler = ahd_linux_dev_reset,
914 .eh_bus_reset_handler = ahd_linux_bus_reset,
915#if defined(__i386__)
916 .bios_param = ahd_linux_biosparam,
917#endif
918 .can_queue = AHD_MAX_QUEUE,
919 .this_id = -1,
920 .max_sectors = 8192,
921 .cmd_per_lun = 2,
922 .use_clustering = ENABLE_CLUSTERING,
923 .slave_alloc = ahd_linux_slave_alloc,
924 .slave_configure = ahd_linux_slave_configure,
925 .target_alloc = ahd_linux_target_alloc,
926 .target_destroy = ahd_linux_target_destroy,
927};
928
929
930int
931ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent,
932 bus_size_t alignment, bus_size_t boundary,
933 dma_addr_t lowaddr, dma_addr_t highaddr,
934 bus_dma_filter_t *filter, void *filterarg,
935 bus_size_t maxsize, int nsegments,
936 bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag)
937{
938 bus_dma_tag_t dmat;
939
940 dmat = kmalloc(sizeof(*dmat), GFP_ATOMIC);
941 if (dmat == NULL)
942 return (ENOMEM);
943
944
945
946
947
948
949
950
951 dmat->alignment = alignment;
952 dmat->boundary = boundary;
953 dmat->maxsize = maxsize;
954 *ret_tag = dmat;
955 return (0);
956}
957
958void
959ahd_dma_tag_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat)
960{
961 kfree(dmat);
962}
963
964int
965ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr,
966 int flags, bus_dmamap_t *mapp)
967{
968 *vaddr = pci_alloc_consistent(ahd->dev_softc,
969 dmat->maxsize, mapp);
970 if (*vaddr == NULL)
971 return (ENOMEM);
972 return(0);
973}
974
975void
976ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat,
977 void* vaddr, bus_dmamap_t map)
978{
979 pci_free_consistent(ahd->dev_softc, dmat->maxsize,
980 vaddr, map);
981}
982
983int
984ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map,
985 void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb,
986 void *cb_arg, int flags)
987{
988
989
990
991
992 bus_dma_segment_t stack_sg;
993
994 stack_sg.ds_addr = map;
995 stack_sg.ds_len = dmat->maxsize;
996 cb(cb_arg, &stack_sg, 1, 0);
997 return (0);
998}
999
1000void
1001ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map)
1002{
1003}
1004
1005int
1006ahd_dmamap_unload(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map)
1007{
1008
1009 return (0);
1010}
1011
1012
1013static void
1014ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value)
1015{
1016
1017 if ((instance >= 0)
1018 && (instance < ARRAY_SIZE(aic79xx_iocell_info))) {
1019 uint8_t *iocell_info;
1020
1021 iocell_info = (uint8_t*)&aic79xx_iocell_info[instance];
1022 iocell_info[index] = value & 0xFFFF;
1023 if (bootverbose)
1024 printk("iocell[%d:%ld] = %d\n", instance, index, value);
1025 }
1026}
1027
1028static void
1029ahd_linux_setup_tag_info_global(char *p)
1030{
1031 int tags, i, j;
1032
1033 tags = simple_strtoul(p + 1, NULL, 0) & 0xff;
1034 printk("Setting Global Tags= %d\n", tags);
1035
1036 for (i = 0; i < ARRAY_SIZE(aic79xx_tag_info); i++) {
1037 for (j = 0; j < AHD_NUM_TARGETS; j++) {
1038 aic79xx_tag_info[i].tag_commands[j] = tags;
1039 }
1040 }
1041}
1042
1043static void
1044ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
1045{
1046
1047 if ((instance >= 0) && (targ >= 0)
1048 && (instance < ARRAY_SIZE(aic79xx_tag_info))
1049 && (targ < AHD_NUM_TARGETS)) {
1050 aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF;
1051 if (bootverbose)
1052 printk("tag_info[%d:%d] = %d\n", instance, targ, value);
1053 }
1054}
1055
1056static char *
1057ahd_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,
1058 void (*callback)(u_long, int, int, int32_t),
1059 u_long callback_arg)
1060{
1061 char *tok_end;
1062 char *tok_end2;
1063 int i;
1064 int instance;
1065 int targ;
1066 int done;
1067 char tok_list[] = {'.', ',', '{', '}', '\0'};
1068
1069
1070 if (*opt_arg != ':')
1071 return (opt_arg);
1072 opt_arg++;
1073 instance = -1;
1074 targ = -1;
1075 done = FALSE;
1076
1077
1078
1079
1080 tok_end = strchr(opt_arg, '\0');
1081 if (tok_end < end)
1082 *tok_end = ',';
1083 while (!done) {
1084 switch (*opt_arg) {
1085 case '{':
1086 if (instance == -1) {
1087 instance = 0;
1088 } else {
1089 if (depth > 1) {
1090 if (targ == -1)
1091 targ = 0;
1092 } else {
1093 printk("Malformed Option %s\n",
1094 opt_name);
1095 done = TRUE;
1096 }
1097 }
1098 opt_arg++;
1099 break;
1100 case '}':
1101 if (targ != -1)
1102 targ = -1;
1103 else if (instance != -1)
1104 instance = -1;
1105 opt_arg++;
1106 break;
1107 case ',':
1108 case '.':
1109 if (instance == -1)
1110 done = TRUE;
1111 else if (targ >= 0)
1112 targ++;
1113 else if (instance >= 0)
1114 instance++;
1115 opt_arg++;
1116 break;
1117 case '\0':
1118 done = TRUE;
1119 break;
1120 default:
1121 tok_end = end;
1122 for (i = 0; tok_list[i]; i++) {
1123 tok_end2 = strchr(opt_arg, tok_list[i]);
1124 if ((tok_end2) && (tok_end2 < tok_end))
1125 tok_end = tok_end2;
1126 }
1127 callback(callback_arg, instance, targ,
1128 simple_strtol(opt_arg, NULL, 0));
1129 opt_arg = tok_end;
1130 break;
1131 }
1132 }
1133 return (opt_arg);
1134}
1135
1136
1137
1138
1139
1140
1141static int
1142aic79xx_setup(char *s)
1143{
1144 int i, n;
1145 char *p;
1146 char *end;
1147
1148 static const struct {
1149 const char *name;
1150 uint32_t *flag;
1151 } options[] = {
1152 { "extended", &aic79xx_extended },
1153 { "no_reset", &aic79xx_no_reset },
1154 { "verbose", &aic79xx_verbose },
1155 { "allow_memio", &aic79xx_allow_memio},
1156#ifdef AHD_DEBUG
1157 { "debug", &ahd_debug },
1158#endif
1159 { "periodic_otag", &aic79xx_periodic_otag },
1160 { "pci_parity", &aic79xx_pci_parity },
1161 { "seltime", &aic79xx_seltime },
1162 { "tag_info", NULL },
1163 { "global_tag_depth", NULL},
1164 { "slewrate", NULL },
1165 { "precomp", NULL },
1166 { "amplitude", NULL },
1167 { "slowcrc", &aic79xx_slowcrc },
1168 };
1169
1170 end = strchr(s, '\0');
1171
1172
1173
1174
1175
1176 n = 0;
1177
1178 while ((p = strsep(&s, ",.")) != NULL) {
1179 if (*p == '\0')
1180 continue;
1181 for (i = 0; i < ARRAY_SIZE(options); i++) {
1182
1183 n = strlen(options[i].name);
1184 if (strncmp(options[i].name, p, n) == 0)
1185 break;
1186 }
1187 if (i == ARRAY_SIZE(options))
1188 continue;
1189
1190 if (strncmp(p, "global_tag_depth", n) == 0) {
1191 ahd_linux_setup_tag_info_global(p + n);
1192 } else if (strncmp(p, "tag_info", n) == 0) {
1193 s = ahd_parse_brace_option("tag_info", p + n, end,
1194 2, ahd_linux_setup_tag_info, 0);
1195 } else if (strncmp(p, "slewrate", n) == 0) {
1196 s = ahd_parse_brace_option("slewrate",
1197 p + n, end, 1, ahd_linux_setup_iocell_info,
1198 AIC79XX_SLEWRATE_INDEX);
1199 } else if (strncmp(p, "precomp", n) == 0) {
1200 s = ahd_parse_brace_option("precomp",
1201 p + n, end, 1, ahd_linux_setup_iocell_info,
1202 AIC79XX_PRECOMP_INDEX);
1203 } else if (strncmp(p, "amplitude", n) == 0) {
1204 s = ahd_parse_brace_option("amplitude",
1205 p + n, end, 1, ahd_linux_setup_iocell_info,
1206 AIC79XX_AMPLITUDE_INDEX);
1207 } else if (p[n] == ':') {
1208 *(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0);
1209 } else if (!strncmp(p, "verbose", n)) {
1210 *(options[i].flag) = 1;
1211 } else {
1212 *(options[i].flag) ^= 0xFFFFFFFF;
1213 }
1214 }
1215 return 1;
1216}
1217
1218__setup("aic79xx=", aic79xx_setup);
1219
1220uint32_t aic79xx_verbose;
1221
1222int
1223ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *template)
1224{
1225 char buf[80];
1226 struct Scsi_Host *host;
1227 char *new_name;
1228 u_long s;
1229 int retval;
1230
1231 template->name = ahd->description;
1232 host = scsi_host_alloc(template, sizeof(struct ahd_softc *));
1233 if (host == NULL)
1234 return (ENOMEM);
1235
1236 *((struct ahd_softc **)host->hostdata) = ahd;
1237 ahd->platform_data->host = host;
1238 host->can_queue = AHD_MAX_QUEUE;
1239 host->cmd_per_lun = 2;
1240 host->sg_tablesize = AHD_NSEG;
1241 host->this_id = ahd->our_id;
1242 host->irq = ahd->platform_data->irq;
1243 host->max_id = (ahd->features & AHD_WIDE) ? 16 : 8;
1244 host->max_lun = AHD_NUM_LUNS;
1245 host->max_channel = 0;
1246 host->sg_tablesize = AHD_NSEG;
1247 ahd_lock(ahd, &s);
1248 ahd_set_unit(ahd, ahd_linux_unit++);
1249 ahd_unlock(ahd, &s);
1250 sprintf(buf, "scsi%d", host->host_no);
1251 new_name = kmalloc(strlen(buf) + 1, GFP_ATOMIC);
1252 if (new_name != NULL) {
1253 strcpy(new_name, buf);
1254 ahd_set_name(ahd, new_name);
1255 }
1256 host->unique_id = ahd->unit;
1257 ahd_linux_initialize_scsi_bus(ahd);
1258 ahd_intr_enable(ahd, TRUE);
1259
1260 host->transportt = ahd_linux_transport_template;
1261
1262 retval = scsi_add_host(host, &ahd->dev_softc->dev);
1263 if (retval) {
1264 printk(KERN_WARNING "aic79xx: scsi_add_host failed\n");
1265 scsi_host_put(host);
1266 return retval;
1267 }
1268
1269 scsi_scan_host(host);
1270 return 0;
1271}
1272
1273
1274
1275
1276
1277
1278static void
1279ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd)
1280{
1281 u_int target_id;
1282 u_int numtarg;
1283 unsigned long s;
1284
1285 target_id = 0;
1286 numtarg = 0;
1287
1288 if (aic79xx_no_reset != 0)
1289 ahd->flags &= ~AHD_RESET_BUS_A;
1290
1291 if ((ahd->flags & AHD_RESET_BUS_A) != 0)
1292 ahd_reset_channel(ahd, 'A', TRUE);
1293 else
1294 numtarg = (ahd->features & AHD_WIDE) ? 16 : 8;
1295
1296 ahd_lock(ahd, &s);
1297
1298
1299
1300
1301
1302 for (; target_id < numtarg; target_id++) {
1303 struct ahd_devinfo devinfo;
1304 struct ahd_initiator_tinfo *tinfo;
1305 struct ahd_tmode_tstate *tstate;
1306
1307 tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
1308 target_id, &tstate);
1309 ahd_compile_devinfo(&devinfo, ahd->our_id, target_id,
1310 CAM_LUN_WILDCARD, 'A', ROLE_INITIATOR);
1311 ahd_update_neg_request(ahd, &devinfo, tstate,
1312 tinfo, AHD_NEG_ALWAYS);
1313 }
1314 ahd_unlock(ahd, &s);
1315
1316 if ((ahd->flags & AHD_RESET_BUS_A) != 0) {
1317 ahd_freeze_simq(ahd);
1318 msleep(AIC79XX_RESET_DELAY);
1319 ahd_release_simq(ahd);
1320 }
1321}
1322
1323int
1324ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
1325{
1326 ahd->platform_data =
1327 kmalloc(sizeof(struct ahd_platform_data), GFP_ATOMIC);
1328 if (ahd->platform_data == NULL)
1329 return (ENOMEM);
1330 memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data));
1331 ahd->platform_data->irq = AHD_LINUX_NOIRQ;
1332 ahd_lockinit(ahd);
1333 ahd->seltime = (aic79xx_seltime & 0x3) << 4;
1334 return (0);
1335}
1336
1337void
1338ahd_platform_free(struct ahd_softc *ahd)
1339{
1340 struct scsi_target *starget;
1341 int i;
1342
1343 if (ahd->platform_data != NULL) {
1344
1345 for (i = 0; i < AHD_NUM_TARGETS; i++) {
1346 starget = ahd->platform_data->starget[i];
1347 if (starget != NULL) {
1348 ahd->platform_data->starget[i] = NULL;
1349 }
1350 }
1351
1352 if (ahd->platform_data->irq != AHD_LINUX_NOIRQ)
1353 free_irq(ahd->platform_data->irq, ahd);
1354 if (ahd->tags[0] == BUS_SPACE_PIO
1355 && ahd->bshs[0].ioport != 0)
1356 release_region(ahd->bshs[0].ioport, 256);
1357 if (ahd->tags[1] == BUS_SPACE_PIO
1358 && ahd->bshs[1].ioport != 0)
1359 release_region(ahd->bshs[1].ioport, 256);
1360 if (ahd->tags[0] == BUS_SPACE_MEMIO
1361 && ahd->bshs[0].maddr != NULL) {
1362 iounmap(ahd->bshs[0].maddr);
1363 release_mem_region(ahd->platform_data->mem_busaddr,
1364 0x1000);
1365 }
1366 if (ahd->platform_data->host)
1367 scsi_host_put(ahd->platform_data->host);
1368
1369 kfree(ahd->platform_data);
1370 }
1371}
1372
1373void
1374ahd_platform_init(struct ahd_softc *ahd)
1375{
1376
1377
1378
1379 if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) {
1380 const struct ahd_linux_iocell_opts *iocell_opts;
1381
1382 iocell_opts = &aic79xx_iocell_info[ahd->unit];
1383 if (iocell_opts->precomp != AIC79XX_DEFAULT_PRECOMP)
1384 AHD_SET_PRECOMP(ahd, iocell_opts->precomp);
1385 if (iocell_opts->slewrate != AIC79XX_DEFAULT_SLEWRATE)
1386 AHD_SET_SLEWRATE(ahd, iocell_opts->slewrate);
1387 if (iocell_opts->amplitude != AIC79XX_DEFAULT_AMPLITUDE)
1388 AHD_SET_AMPLITUDE(ahd, iocell_opts->amplitude);
1389 }
1390
1391}
1392
1393void
1394ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb)
1395{
1396 ahd_platform_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),
1397 SCB_GET_CHANNEL(ahd, scb),
1398 SCB_GET_LUN(scb), SCB_LIST_NULL,
1399 ROLE_UNKNOWN, CAM_REQUEUE_REQ);
1400}
1401
1402void
1403ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev,
1404 struct ahd_devinfo *devinfo, ahd_queue_alg alg)
1405{
1406 struct ahd_linux_device *dev;
1407 int was_queuing;
1408 int now_queuing;
1409
1410 if (sdev == NULL)
1411 return;
1412
1413 dev = scsi_transport_device_data(sdev);
1414
1415 if (dev == NULL)
1416 return;
1417 was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED);
1418 switch (alg) {
1419 default:
1420 case AHD_QUEUE_NONE:
1421 now_queuing = 0;
1422 break;
1423 case AHD_QUEUE_BASIC:
1424 now_queuing = AHD_DEV_Q_BASIC;
1425 break;
1426 case AHD_QUEUE_TAGGED:
1427 now_queuing = AHD_DEV_Q_TAGGED;
1428 break;
1429 }
1430 if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) == 0
1431 && (was_queuing != now_queuing)
1432 && (dev->active != 0)) {
1433 dev->flags |= AHD_DEV_FREEZE_TIL_EMPTY;
1434 dev->qfrozen++;
1435 }
1436
1437 dev->flags &= ~(AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED|AHD_DEV_PERIODIC_OTAG);
1438 if (now_queuing) {
1439 u_int usertags;
1440
1441 usertags = ahd_linux_user_tagdepth(ahd, devinfo);
1442 if (!was_queuing) {
1443
1444
1445
1446
1447
1448 dev->maxtags = usertags;
1449 dev->openings = dev->maxtags - dev->active;
1450 }
1451 if (dev->maxtags == 0) {
1452
1453
1454
1455 dev->openings = 1;
1456 } else if (alg == AHD_QUEUE_TAGGED) {
1457 dev->flags |= AHD_DEV_Q_TAGGED;
1458 if (aic79xx_periodic_otag != 0)
1459 dev->flags |= AHD_DEV_PERIODIC_OTAG;
1460 } else
1461 dev->flags |= AHD_DEV_Q_BASIC;
1462 } else {
1463
1464 dev->maxtags = 0;
1465 dev->openings = 1 - dev->active;
1466 }
1467
1468 switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) {
1469 case AHD_DEV_Q_BASIC:
1470 scsi_set_tag_type(sdev, MSG_SIMPLE_TASK);
1471 scsi_activate_tcq(sdev, dev->openings + dev->active);
1472 break;
1473 case AHD_DEV_Q_TAGGED:
1474 scsi_set_tag_type(sdev, MSG_ORDERED_TASK);
1475 scsi_activate_tcq(sdev, dev->openings + dev->active);
1476 break;
1477 default:
1478
1479
1480
1481
1482
1483
1484 scsi_deactivate_tcq(sdev, 1);
1485 break;
1486 }
1487}
1488
1489int
1490ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel,
1491 int lun, u_int tag, role_t role, uint32_t status)
1492{
1493 return 0;
1494}
1495
1496static u_int
1497ahd_linux_user_tagdepth(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
1498{
1499 static int warned_user;
1500 u_int tags;
1501
1502 tags = 0;
1503 if ((ahd->user_discenable & devinfo->target_mask) != 0) {
1504 if (ahd->unit >= ARRAY_SIZE(aic79xx_tag_info)) {
1505
1506 if (warned_user == 0) {
1507 printk(KERN_WARNING
1508"aic79xx: WARNING: Insufficient tag_info instances\n"
1509"aic79xx: for installed controllers. Using defaults\n"
1510"aic79xx: Please update the aic79xx_tag_info array in\n"
1511"aic79xx: the aic79xx_osm.c source file.\n");
1512 warned_user++;
1513 }
1514 tags = AHD_MAX_QUEUE;
1515 } else {
1516 adapter_tag_info_t *tag_info;
1517
1518 tag_info = &aic79xx_tag_info[ahd->unit];
1519 tags = tag_info->tag_commands[devinfo->target_offset];
1520 if (tags > AHD_MAX_QUEUE)
1521 tags = AHD_MAX_QUEUE;
1522 }
1523 }
1524 return (tags);
1525}
1526
1527
1528
1529
1530static void
1531ahd_linux_device_queue_depth(struct scsi_device *sdev)
1532{
1533 struct ahd_devinfo devinfo;
1534 u_int tags;
1535 struct ahd_softc *ahd = *((struct ahd_softc **)sdev->host->hostdata);
1536
1537 ahd_compile_devinfo(&devinfo,
1538 ahd->our_id,
1539 sdev->sdev_target->id, sdev->lun,
1540 sdev->sdev_target->channel == 0 ? 'A' : 'B',
1541 ROLE_INITIATOR);
1542 tags = ahd_linux_user_tagdepth(ahd, &devinfo);
1543 if (tags != 0 && sdev->tagged_supported != 0) {
1544
1545 ahd_platform_set_tags(ahd, sdev, &devinfo, AHD_QUEUE_TAGGED);
1546 ahd_send_async(ahd, devinfo.channel, devinfo.target,
1547 devinfo.lun, AC_TRANSFER_NEG);
1548 ahd_print_devinfo(ahd, &devinfo);
1549 printk("Tagged Queuing enabled. Depth %d\n", tags);
1550 } else {
1551 ahd_platform_set_tags(ahd, sdev, &devinfo, AHD_QUEUE_NONE);
1552 ahd_send_async(ahd, devinfo.channel, devinfo.target,
1553 devinfo.lun, AC_TRANSFER_NEG);
1554 }
1555}
1556
1557static int
1558ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
1559 struct scsi_cmnd *cmd)
1560{
1561 struct scb *scb;
1562 struct hardware_scb *hscb;
1563 struct ahd_initiator_tinfo *tinfo;
1564 struct ahd_tmode_tstate *tstate;
1565 u_int col_idx;
1566 uint16_t mask;
1567 unsigned long flags;
1568 int nseg;
1569
1570 nseg = scsi_dma_map(cmd);
1571 if (nseg < 0)
1572 return SCSI_MLQUEUE_HOST_BUSY;
1573
1574 ahd_lock(ahd, &flags);
1575
1576
1577
1578
1579 tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
1580 cmd->device->id, &tstate);
1581 if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0
1582 || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
1583 col_idx = AHD_NEVER_COL_IDX;
1584 } else {
1585 col_idx = AHD_BUILD_COL_IDX(cmd->device->id,
1586 cmd->device->lun);
1587 }
1588 if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
1589 ahd->flags |= AHD_RESOURCE_SHORTAGE;
1590 ahd_unlock(ahd, &flags);
1591 scsi_dma_unmap(cmd);
1592 return SCSI_MLQUEUE_HOST_BUSY;
1593 }
1594
1595 scb->io_ctx = cmd;
1596 scb->platform_data->dev = dev;
1597 hscb = scb->hscb;
1598 cmd->host_scribble = (char *)scb;
1599
1600
1601
1602
1603 hscb->control = 0;
1604 hscb->scsiid = BUILD_SCSIID(ahd, cmd);
1605 hscb->lun = cmd->device->lun;
1606 scb->hscb->task_management = 0;
1607 mask = SCB_GET_TARGET_MASK(ahd, scb);
1608
1609 if ((ahd->user_discenable & mask) != 0)
1610 hscb->control |= DISCENB;
1611
1612 if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0)
1613 scb->flags |= SCB_PACKETIZED;
1614
1615 if ((tstate->auto_negotiate & mask) != 0) {
1616 scb->flags |= SCB_AUTO_NEGOTIATE;
1617 scb->hscb->control |= MK_MESSAGE;
1618 }
1619
1620 if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {
1621 int msg_bytes;
1622 uint8_t tag_msgs[2];
1623
1624 msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
1625 if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
1626 hscb->control |= tag_msgs[0];
1627 if (tag_msgs[0] == MSG_ORDERED_TASK)
1628 dev->commands_since_idle_or_otag = 0;
1629 } else
1630 if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH
1631 && (dev->flags & AHD_DEV_Q_TAGGED) != 0) {
1632 hscb->control |= MSG_ORDERED_TASK;
1633 dev->commands_since_idle_or_otag = 0;
1634 } else {
1635 hscb->control |= MSG_SIMPLE_TASK;
1636 }
1637 }
1638
1639 hscb->cdb_len = cmd->cmd_len;
1640 memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len);
1641
1642 scb->platform_data->xfer_len = 0;
1643 ahd_set_residual(scb, 0);
1644 ahd_set_sense_residual(scb, 0);
1645 scb->sg_count = 0;
1646
1647 if (nseg > 0) {
1648 void *sg = scb->sg_list;
1649 struct scatterlist *cur_seg;
1650 int i;
1651
1652 scb->platform_data->xfer_len = 0;
1653
1654 scsi_for_each_sg(cmd, cur_seg, nseg, i) {
1655 dma_addr_t addr;
1656 bus_size_t len;
1657
1658 addr = sg_dma_address(cur_seg);
1659 len = sg_dma_len(cur_seg);
1660 scb->platform_data->xfer_len += len;
1661 sg = ahd_sg_setup(ahd, scb, sg, addr, len,
1662 i == (nseg - 1));
1663 }
1664 }
1665
1666 LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
1667 dev->openings--;
1668 dev->active++;
1669 dev->commands_issued++;
1670
1671 if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0)
1672 dev->commands_since_idle_or_otag++;
1673 scb->flags |= SCB_ACTIVE;
1674 ahd_queue_scb(ahd, scb);
1675
1676 ahd_unlock(ahd, &flags);
1677
1678 return 0;
1679}
1680
1681
1682
1683
1684irqreturn_t
1685ahd_linux_isr(int irq, void *dev_id)
1686{
1687 struct ahd_softc *ahd;
1688 u_long flags;
1689 int ours;
1690
1691 ahd = (struct ahd_softc *) dev_id;
1692 ahd_lock(ahd, &flags);
1693 ours = ahd_intr(ahd);
1694 ahd_unlock(ahd, &flags);
1695 return IRQ_RETVAL(ours);
1696}
1697
1698void
1699ahd_send_async(struct ahd_softc *ahd, char channel,
1700 u_int target, u_int lun, ac_code code)
1701{
1702 switch (code) {
1703 case AC_TRANSFER_NEG:
1704 {
1705 char buf[80];
1706 struct scsi_target *starget;
1707 struct info_str info;
1708 struct ahd_initiator_tinfo *tinfo;
1709 struct ahd_tmode_tstate *tstate;
1710 unsigned int target_ppr_options;
1711
1712 BUG_ON(target == CAM_TARGET_WILDCARD);
1713
1714 info.buffer = buf;
1715 info.length = sizeof(buf);
1716 info.offset = 0;
1717 info.pos = 0;
1718 tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id,
1719 target, &tstate);
1720
1721
1722
1723
1724
1725 if (tinfo->curr.period != tinfo->goal.period
1726 || tinfo->curr.width != tinfo->goal.width
1727 || tinfo->curr.offset != tinfo->goal.offset
1728 || tinfo->curr.ppr_options != tinfo->goal.ppr_options)
1729 if (bootverbose == 0)
1730 break;
1731
1732
1733
1734
1735
1736 starget = ahd->platform_data->starget[target];
1737 if (starget == NULL)
1738 break;
1739
1740 target_ppr_options =
1741 (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0)
1742 + (spi_qas(starget) ? MSG_EXT_PPR_QAS_REQ : 0)
1743 + (spi_iu(starget) ? MSG_EXT_PPR_IU_REQ : 0)
1744 + (spi_rd_strm(starget) ? MSG_EXT_PPR_RD_STRM : 0)
1745 + (spi_pcomp_en(starget) ? MSG_EXT_PPR_PCOMP_EN : 0)
1746 + (spi_rti(starget) ? MSG_EXT_PPR_RTI : 0)
1747 + (spi_wr_flow(starget) ? MSG_EXT_PPR_WR_FLOW : 0)
1748 + (spi_hold_mcs(starget) ? MSG_EXT_PPR_HOLD_MCS : 0);
1749
1750 if (tinfo->curr.period == spi_period(starget)
1751 && tinfo->curr.width == spi_width(starget)
1752 && tinfo->curr.offset == spi_offset(starget)
1753 && tinfo->curr.ppr_options == target_ppr_options)
1754 if (bootverbose == 0)
1755 break;
1756
1757 spi_period(starget) = tinfo->curr.period;
1758 spi_width(starget) = tinfo->curr.width;
1759 spi_offset(starget) = tinfo->curr.offset;
1760 spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ ? 1 : 0;
1761 spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ ? 1 : 0;
1762 spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ ? 1 : 0;
1763 spi_rd_strm(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_RD_STRM ? 1 : 0;
1764 spi_pcomp_en(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_PCOMP_EN ? 1 : 0;
1765 spi_rti(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_RTI ? 1 : 0;
1766 spi_wr_flow(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_WR_FLOW ? 1 : 0;
1767 spi_hold_mcs(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_HOLD_MCS ? 1 : 0;
1768 spi_display_xfer_agreement(starget);
1769 break;
1770 }
1771 case AC_SENT_BDR:
1772 {
1773 WARN_ON(lun != CAM_LUN_WILDCARD);
1774 scsi_report_device_reset(ahd->platform_data->host,
1775 channel - 'A', target);
1776 break;
1777 }
1778 case AC_BUS_RESET:
1779 if (ahd->platform_data->host != NULL) {
1780 scsi_report_bus_reset(ahd->platform_data->host,
1781 channel - 'A');
1782 }
1783 break;
1784 default:
1785 panic("ahd_send_async: Unexpected async event");
1786 }
1787}
1788
1789
1790
1791
1792void
1793ahd_done(struct ahd_softc *ahd, struct scb *scb)
1794{
1795 struct scsi_cmnd *cmd;
1796 struct ahd_linux_device *dev;
1797
1798 if ((scb->flags & SCB_ACTIVE) == 0) {
1799 printk("SCB %d done'd twice\n", SCB_GET_TAG(scb));
1800 ahd_dump_card_state(ahd);
1801 panic("Stopping for safety");
1802 }
1803 LIST_REMOVE(scb, pending_links);
1804 cmd = scb->io_ctx;
1805 dev = scb->platform_data->dev;
1806 dev->active--;
1807 dev->openings++;
1808 if ((cmd->result & (CAM_DEV_QFRZN << 16)) != 0) {
1809 cmd->result &= ~(CAM_DEV_QFRZN << 16);
1810 dev->qfrozen--;
1811 }
1812 ahd_linux_unmap_scb(ahd, scb);
1813
1814
1815
1816
1817
1818
1819
1820 cmd->sense_buffer[0] = 0;
1821 if (ahd_get_transaction_status(scb) == CAM_REQ_INPROG) {
1822 uint32_t amount_xferred;
1823
1824 amount_xferred =
1825 ahd_get_transfer_length(scb) - ahd_get_residual(scb);
1826 if ((scb->flags & SCB_TRANSMISSION_ERROR) != 0) {
1827#ifdef AHD_DEBUG
1828 if ((ahd_debug & AHD_SHOW_MISC) != 0) {
1829 ahd_print_path(ahd, scb);
1830 printk("Set CAM_UNCOR_PARITY\n");
1831 }
1832#endif
1833 ahd_set_transaction_status(scb, CAM_UNCOR_PARITY);
1834#ifdef AHD_REPORT_UNDERFLOWS
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844 } else if (amount_xferred < scb->io_ctx->underflow) {
1845 u_int i;
1846
1847 ahd_print_path(ahd, scb);
1848 printk("CDB:");
1849 for (i = 0; i < scb->io_ctx->cmd_len; i++)
1850 printk(" 0x%x", scb->io_ctx->cmnd[i]);
1851 printk("\n");
1852 ahd_print_path(ahd, scb);
1853 printk("Saw underflow (%ld of %ld bytes). "
1854 "Treated as error\n",
1855 ahd_get_residual(scb),
1856 ahd_get_transfer_length(scb));
1857 ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR);
1858#endif
1859 } else {
1860 ahd_set_transaction_status(scb, CAM_REQ_CMP);
1861 }
1862 } else if (ahd_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) {
1863 ahd_linux_handle_scsi_status(ahd, cmd->device, scb);
1864 }
1865
1866 if (dev->openings == 1
1867 && ahd_get_transaction_status(scb) == CAM_REQ_CMP
1868 && ahd_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL)
1869 dev->tag_success_count++;
1870
1871
1872
1873
1874
1875
1876 if ((dev->openings + dev->active) < dev->maxtags
1877 && dev->tag_success_count > AHD_TAG_SUCCESS_INTERVAL) {
1878 dev->tag_success_count = 0;
1879 dev->openings++;
1880 }
1881
1882 if (dev->active == 0)
1883 dev->commands_since_idle_or_otag = 0;
1884
1885 if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
1886 printk("Recovery SCB completes\n");
1887 if (ahd_get_transaction_status(scb) == CAM_BDR_SENT
1888 || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED)
1889 ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
1890
1891 if (ahd->platform_data->eh_done)
1892 complete(ahd->platform_data->eh_done);
1893 }
1894
1895 ahd_free_scb(ahd, scb);
1896 ahd_linux_queue_cmd_complete(ahd, cmd);
1897}
1898
1899static void
1900ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
1901 struct scsi_device *sdev, struct scb *scb)
1902{
1903 struct ahd_devinfo devinfo;
1904 struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
1905
1906 ahd_compile_devinfo(&devinfo,
1907 ahd->our_id,
1908 sdev->sdev_target->id, sdev->lun,
1909 sdev->sdev_target->channel == 0 ? 'A' : 'B',
1910 ROLE_INITIATOR);
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922 switch (ahd_get_scsi_status(scb)) {
1923 default:
1924 break;
1925 case SCSI_STATUS_CHECK_COND:
1926 case SCSI_STATUS_CMD_TERMINATED:
1927 {
1928 struct scsi_cmnd *cmd;
1929
1930
1931
1932
1933
1934 cmd = scb->io_ctx;
1935 if ((scb->flags & (SCB_SENSE|SCB_PKT_SENSE)) != 0) {
1936 struct scsi_status_iu_header *siu;
1937 u_int sense_size;
1938 u_int sense_offset;
1939
1940 if (scb->flags & SCB_SENSE) {
1941 sense_size = min(sizeof(struct scsi_sense_data)
1942 - ahd_get_sense_residual(scb),
1943 (u_long)SCSI_SENSE_BUFFERSIZE);
1944 sense_offset = 0;
1945 } else {
1946
1947
1948
1949
1950 siu = (struct scsi_status_iu_header *)
1951 scb->sense_data;
1952 sense_size = min_t(size_t,
1953 scsi_4btoul(siu->sense_length),
1954 SCSI_SENSE_BUFFERSIZE);
1955 sense_offset = SIU_SENSE_OFFSET(siu);
1956 }
1957
1958 memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
1959 memcpy(cmd->sense_buffer,
1960 ahd_get_sense_buf(ahd, scb)
1961 + sense_offset, sense_size);
1962 cmd->result |= (DRIVER_SENSE << 24);
1963
1964#ifdef AHD_DEBUG
1965 if (ahd_debug & AHD_SHOW_SENSE) {
1966 int i;
1967
1968 printk("Copied %d bytes of sense data at %d:",
1969 sense_size, sense_offset);
1970 for (i = 0; i < sense_size; i++) {
1971 if ((i & 0xF) == 0)
1972 printk("\n");
1973 printk("0x%x ", cmd->sense_buffer[i]);
1974 }
1975 printk("\n");
1976 }
1977#endif
1978 }
1979 break;
1980 }
1981 case SCSI_STATUS_QUEUE_FULL:
1982
1983
1984
1985
1986
1987
1988
1989
1990 dev->tag_success_count = 0;
1991 if (dev->active != 0) {
1992
1993
1994
1995
1996 dev->openings = 0;
1997#ifdef AHD_DEBUG
1998 if ((ahd_debug & AHD_SHOW_QFULL) != 0) {
1999 ahd_print_path(ahd, scb);
2000 printk("Dropping tag count to %d\n",
2001 dev->active);
2002 }
2003#endif
2004 if (dev->active == dev->tags_on_last_queuefull) {
2005
2006 dev->last_queuefull_same_count++;
2007
2008
2009
2010
2011
2012
2013
2014
2015 if (dev->last_queuefull_same_count
2016 == AHD_LOCK_TAGS_COUNT) {
2017 dev->maxtags = dev->active;
2018 ahd_print_path(ahd, scb);
2019 printk("Locking max tag count at %d\n",
2020 dev->active);
2021 }
2022 } else {
2023 dev->tags_on_last_queuefull = dev->active;
2024 dev->last_queuefull_same_count = 0;
2025 }
2026 ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);
2027 ahd_set_scsi_status(scb, SCSI_STATUS_OK);
2028 ahd_platform_set_tags(ahd, sdev, &devinfo,
2029 (dev->flags & AHD_DEV_Q_BASIC)
2030 ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED);
2031 break;
2032 }
2033
2034
2035
2036
2037 dev->openings = 1;
2038 ahd_platform_set_tags(ahd, sdev, &devinfo,
2039 (dev->flags & AHD_DEV_Q_BASIC)
2040 ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED);
2041 ahd_set_scsi_status(scb, SCSI_STATUS_BUSY);
2042 }
2043}
2044
2045static void
2046ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd)
2047{
2048 int status;
2049 int new_status = DID_OK;
2050 int do_fallback = 0;
2051 int scsi_status;
2052
2053
2054
2055
2056
2057
2058
2059
2060 status = ahd_cmd_get_transaction_status(cmd);
2061 switch (status) {
2062 case CAM_REQ_INPROG:
2063 case CAM_REQ_CMP:
2064 new_status = DID_OK;
2065 break;
2066 case CAM_AUTOSENSE_FAIL:
2067 new_status = DID_ERROR;
2068
2069 case CAM_SCSI_STATUS_ERROR:
2070 scsi_status = ahd_cmd_get_scsi_status(cmd);
2071
2072 switch(scsi_status) {
2073 case SCSI_STATUS_CMD_TERMINATED:
2074 case SCSI_STATUS_CHECK_COND:
2075 if ((cmd->result >> 24) != DRIVER_SENSE) {
2076 do_fallback = 1;
2077 } else {
2078 struct scsi_sense_data *sense;
2079
2080 sense = (struct scsi_sense_data *)
2081 cmd->sense_buffer;
2082 if (sense->extra_len >= 5 &&
2083 (sense->add_sense_code == 0x47
2084 || sense->add_sense_code == 0x48))
2085 do_fallback = 1;
2086 }
2087 break;
2088 default:
2089 break;
2090 }
2091 break;
2092 case CAM_REQ_ABORTED:
2093 new_status = DID_ABORT;
2094 break;
2095 case CAM_BUSY:
2096 new_status = DID_BUS_BUSY;
2097 break;
2098 case CAM_REQ_INVALID:
2099 case CAM_PATH_INVALID:
2100 new_status = DID_BAD_TARGET;
2101 break;
2102 case CAM_SEL_TIMEOUT:
2103 new_status = DID_NO_CONNECT;
2104 break;
2105 case CAM_SCSI_BUS_RESET:
2106 case CAM_BDR_SENT:
2107 new_status = DID_RESET;
2108 break;
2109 case CAM_UNCOR_PARITY:
2110 new_status = DID_PARITY;
2111 do_fallback = 1;
2112 break;
2113 case CAM_CMD_TIMEOUT:
2114 new_status = DID_TIME_OUT;
2115 do_fallback = 1;
2116 break;
2117 case CAM_REQ_CMP_ERR:
2118 case CAM_UNEXP_BUSFREE:
2119 case CAM_DATA_RUN_ERR:
2120 new_status = DID_ERROR;
2121 do_fallback = 1;
2122 break;
2123 case CAM_UA_ABORT:
2124 case CAM_NO_HBA:
2125 case CAM_SEQUENCE_FAIL:
2126 case CAM_CCB_LEN_ERR:
2127 case CAM_PROVIDE_FAIL:
2128 case CAM_REQ_TERMIO:
2129 case CAM_UNREC_HBA_ERROR:
2130 case CAM_REQ_TOO_BIG:
2131 new_status = DID_ERROR;
2132 break;
2133 case CAM_REQUEUE_REQ:
2134 new_status = DID_REQUEUE;
2135 break;
2136 default:
2137
2138 new_status = DID_ERROR;
2139 break;
2140 }
2141
2142 if (do_fallback) {
2143 printk("%s: device overrun (status %x) on %d:%d:%d\n",
2144 ahd_name(ahd), status, cmd->device->channel,
2145 cmd->device->id, cmd->device->lun);
2146 }
2147
2148 ahd_cmd_set_transaction_status(cmd, new_status);
2149
2150 cmd->scsi_done(cmd);
2151}
2152
2153static void
2154ahd_freeze_simq(struct ahd_softc *ahd)
2155{
2156 scsi_block_requests(ahd->platform_data->host);
2157}
2158
2159static void
2160ahd_release_simq(struct ahd_softc *ahd)
2161{
2162 scsi_unblock_requests(ahd->platform_data->host);
2163}
2164
2165static int
2166ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd)
2167{
2168 struct ahd_softc *ahd;
2169 struct ahd_linux_device *dev;
2170 struct scb *pending_scb;
2171 u_int saved_scbptr;
2172 u_int active_scbptr;
2173 u_int last_phase;
2174 u_int saved_scsiid;
2175 u_int cdb_byte;
2176 int retval;
2177 int was_paused;
2178 int paused;
2179 int wait;
2180 int disconnected;
2181 ahd_mode_state saved_modes;
2182 unsigned long flags;
2183
2184 pending_scb = NULL;
2185 paused = FALSE;
2186 wait = FALSE;
2187 ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
2188
2189 scmd_printk(KERN_INFO, cmd,
2190 "Attempting to queue an ABORT message:");
2191
2192 printk("CDB:");
2193 for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
2194 printk(" 0x%x", cmd->cmnd[cdb_byte]);
2195 printk("\n");
2196
2197 ahd_lock(ahd, &flags);
2198
2199
2200
2201
2202
2203
2204
2205
2206 dev = scsi_transport_device_data(cmd->device);
2207
2208 if (dev == NULL) {
2209
2210
2211
2212
2213 scmd_printk(KERN_INFO, cmd, "Is not an active device\n");
2214 retval = SUCCESS;
2215 goto no_cmd;
2216 }
2217
2218
2219
2220
2221 LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
2222 if (pending_scb->io_ctx == cmd)
2223 break;
2224 }
2225
2226 if (pending_scb == NULL) {
2227 scmd_printk(KERN_INFO, cmd, "Command not found\n");
2228 goto no_cmd;
2229 }
2230
2231 if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) {
2232
2233
2234
2235 retval = FAILED;
2236 goto done;
2237 }
2238
2239
2240
2241
2242
2243
2244
2245 was_paused = ahd_is_paused(ahd);
2246 ahd_pause_and_flushwork(ahd);
2247 paused = TRUE;
2248
2249 if ((pending_scb->flags & SCB_ACTIVE) == 0) {
2250 scmd_printk(KERN_INFO, cmd, "Command already completed\n");
2251 goto no_cmd;
2252 }
2253
2254 printk("%s: At time of recovery, card was %spaused\n",
2255 ahd_name(ahd), was_paused ? "" : "not ");
2256 ahd_dump_card_state(ahd);
2257
2258 disconnected = TRUE;
2259 if (ahd_search_qinfifo(ahd, cmd->device->id,
2260 cmd->device->channel + 'A',
2261 cmd->device->lun,
2262 pending_scb->hscb->tag,
2263 ROLE_INITIATOR, CAM_REQ_ABORTED,
2264 SEARCH_COMPLETE) > 0) {
2265 printk("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
2266 ahd_name(ahd), cmd->device->channel,
2267 cmd->device->id, cmd->device->lun);
2268 retval = SUCCESS;
2269 goto done;
2270 }
2271
2272 saved_modes = ahd_save_modes(ahd);
2273 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
2274 last_phase = ahd_inb(ahd, LASTPHASE);
2275 saved_scbptr = ahd_get_scbptr(ahd);
2276 active_scbptr = saved_scbptr;
2277 if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) {
2278 struct scb *bus_scb;
2279
2280 bus_scb = ahd_lookup_scb(ahd, active_scbptr);
2281 if (bus_scb == pending_scb)
2282 disconnected = FALSE;
2283 }
2284
2285
2286
2287
2288
2289
2290 saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
2291 if (last_phase != P_BUSFREE
2292 && SCB_GET_TAG(pending_scb) == active_scbptr) {
2293
2294
2295
2296
2297
2298 pending_scb = ahd_lookup_scb(ahd, active_scbptr);
2299 pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
2300 ahd_outb(ahd, MSG_OUT, HOST_MSG);
2301 ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
2302 scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n");
2303 wait = TRUE;
2304 } else if (disconnected) {
2305
2306
2307
2308
2309
2310 pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
2311 ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));
2312 pending_scb->hscb->cdb_len = 0;
2313 pending_scb->hscb->task_attribute = 0;
2314 pending_scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK;
2315
2316 if ((pending_scb->flags & SCB_PACKETIZED) != 0) {
2317
2318
2319
2320
2321
2322
2323
2324 ahd_outb(ahd, SCB_TASK_MANAGEMENT,
2325 pending_scb->hscb->task_management);
2326 } else {
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336 pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
2337
2338
2339
2340
2341
2342
2343
2344 ahd_outb(ahd, SCB_CONTROL,
2345 ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE);
2346 }
2347
2348
2349
2350
2351
2352
2353 ahd_search_qinfifo(ahd, cmd->device->id,
2354 cmd->device->channel + 'A', cmd->device->lun,
2355 SCB_LIST_NULL, ROLE_INITIATOR,
2356 CAM_REQUEUE_REQ, SEARCH_COMPLETE);
2357 ahd_qinfifo_requeue_tail(ahd, pending_scb);
2358 ahd_set_scbptr(ahd, saved_scbptr);
2359 ahd_print_path(ahd, pending_scb);
2360 printk("Device is disconnected, re-queuing SCB\n");
2361 wait = TRUE;
2362 } else {
2363 scmd_printk(KERN_INFO, cmd, "Unable to deliver message\n");
2364 retval = FAILED;
2365 goto done;
2366 }
2367
2368no_cmd:
2369
2370
2371
2372
2373
2374
2375 retval = SUCCESS;
2376done:
2377 if (paused)
2378 ahd_unpause(ahd);
2379 if (wait) {
2380 DECLARE_COMPLETION_ONSTACK(done);
2381
2382 ahd->platform_data->eh_done = &done;
2383 ahd_unlock(ahd, &flags);
2384
2385 printk("%s: Recovery code sleeping\n", ahd_name(ahd));
2386 if (!wait_for_completion_timeout(&done, 5 * HZ)) {
2387 ahd_lock(ahd, &flags);
2388 ahd->platform_data->eh_done = NULL;
2389 ahd_unlock(ahd, &flags);
2390 printk("%s: Timer Expired (active %d)\n",
2391 ahd_name(ahd), dev->active);
2392 retval = FAILED;
2393 }
2394 printk("Recovery code awake\n");
2395 } else
2396 ahd_unlock(ahd, &flags);
2397
2398 if (retval != SUCCESS)
2399 printk("%s: Command abort returning 0x%x\n",
2400 ahd_name(ahd), retval);
2401
2402 return retval;
2403}
2404
2405static void ahd_linux_set_width(struct scsi_target *starget, int width)
2406{
2407 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2408 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2409 struct ahd_devinfo devinfo;
2410 unsigned long flags;
2411
2412 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2413 starget->channel + 'A', ROLE_INITIATOR);
2414 ahd_lock(ahd, &flags);
2415 ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE);
2416 ahd_unlock(ahd, &flags);
2417}
2418
2419static void ahd_linux_set_period(struct scsi_target *starget, int period)
2420{
2421 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2422 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2423 struct ahd_tmode_tstate *tstate;
2424 struct ahd_initiator_tinfo *tinfo
2425 = ahd_fetch_transinfo(ahd,
2426 starget->channel + 'A',
2427 shost->this_id, starget->id, &tstate);
2428 struct ahd_devinfo devinfo;
2429 unsigned int ppr_options = tinfo->goal.ppr_options;
2430 unsigned int dt;
2431 unsigned long flags;
2432 unsigned long offset = tinfo->goal.offset;
2433
2434#ifdef AHD_DEBUG
2435 if ((ahd_debug & AHD_SHOW_DV) != 0)
2436 printk("%s: set period to %d\n", ahd_name(ahd), period);
2437#endif
2438 if (offset == 0)
2439 offset = MAX_OFFSET;
2440
2441 if (period < 8)
2442 period = 8;
2443 if (period < 10) {
2444 if (spi_max_width(starget)) {
2445 ppr_options |= MSG_EXT_PPR_DT_REQ;
2446 if (period == 8)
2447 ppr_options |= MSG_EXT_PPR_IU_REQ;
2448 } else
2449 period = 10;
2450 }
2451
2452 dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2453
2454 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2455 starget->channel + 'A', ROLE_INITIATOR);
2456
2457
2458 if (ppr_options & ~MSG_EXT_PPR_QAS_REQ) {
2459 if (spi_width(starget) == 0)
2460 ppr_options &= MSG_EXT_PPR_QAS_REQ;
2461 }
2462
2463 ahd_find_syncrate(ahd, &period, &ppr_options,
2464 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2465
2466 ahd_lock(ahd, &flags);
2467 ahd_set_syncrate(ahd, &devinfo, period, offset,
2468 ppr_options, AHD_TRANS_GOAL, FALSE);
2469 ahd_unlock(ahd, &flags);
2470}
2471
2472static void ahd_linux_set_offset(struct scsi_target *starget, int offset)
2473{
2474 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2475 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2476 struct ahd_tmode_tstate *tstate;
2477 struct ahd_initiator_tinfo *tinfo
2478 = ahd_fetch_transinfo(ahd,
2479 starget->channel + 'A',
2480 shost->this_id, starget->id, &tstate);
2481 struct ahd_devinfo devinfo;
2482 unsigned int ppr_options = 0;
2483 unsigned int period = 0;
2484 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2485 unsigned long flags;
2486
2487#ifdef AHD_DEBUG
2488 if ((ahd_debug & AHD_SHOW_DV) != 0)
2489 printk("%s: set offset to %d\n", ahd_name(ahd), offset);
2490#endif
2491
2492 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2493 starget->channel + 'A', ROLE_INITIATOR);
2494 if (offset != 0) {
2495 period = tinfo->goal.period;
2496 ppr_options = tinfo->goal.ppr_options;
2497 ahd_find_syncrate(ahd, &period, &ppr_options,
2498 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2499 }
2500
2501 ahd_lock(ahd, &flags);
2502 ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options,
2503 AHD_TRANS_GOAL, FALSE);
2504 ahd_unlock(ahd, &flags);
2505}
2506
2507static void ahd_linux_set_dt(struct scsi_target *starget, int dt)
2508{
2509 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2510 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2511 struct ahd_tmode_tstate *tstate;
2512 struct ahd_initiator_tinfo *tinfo
2513 = ahd_fetch_transinfo(ahd,
2514 starget->channel + 'A',
2515 shost->this_id, starget->id, &tstate);
2516 struct ahd_devinfo devinfo;
2517 unsigned int ppr_options = tinfo->goal.ppr_options
2518 & ~MSG_EXT_PPR_DT_REQ;
2519 unsigned int period = tinfo->goal.period;
2520 unsigned int width = tinfo->goal.width;
2521 unsigned long flags;
2522
2523#ifdef AHD_DEBUG
2524 if ((ahd_debug & AHD_SHOW_DV) != 0)
2525 printk("%s: %s DT\n", ahd_name(ahd),
2526 dt ? "enabling" : "disabling");
2527#endif
2528 if (dt && spi_max_width(starget)) {
2529 ppr_options |= MSG_EXT_PPR_DT_REQ;
2530 if (!width)
2531 ahd_linux_set_width(starget, 1);
2532 } else {
2533 if (period <= 9)
2534 period = 10;
2535
2536 ppr_options &= ~MSG_EXT_PPR_IU_REQ;
2537 }
2538 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2539 starget->channel + 'A', ROLE_INITIATOR);
2540 ahd_find_syncrate(ahd, &period, &ppr_options,
2541 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2542
2543 ahd_lock(ahd, &flags);
2544 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2545 ppr_options, AHD_TRANS_GOAL, FALSE);
2546 ahd_unlock(ahd, &flags);
2547}
2548
2549static void ahd_linux_set_qas(struct scsi_target *starget, int qas)
2550{
2551 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2552 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2553 struct ahd_tmode_tstate *tstate;
2554 struct ahd_initiator_tinfo *tinfo
2555 = ahd_fetch_transinfo(ahd,
2556 starget->channel + 'A',
2557 shost->this_id, starget->id, &tstate);
2558 struct ahd_devinfo devinfo;
2559 unsigned int ppr_options = tinfo->goal.ppr_options
2560 & ~MSG_EXT_PPR_QAS_REQ;
2561 unsigned int period = tinfo->goal.period;
2562 unsigned int dt;
2563 unsigned long flags;
2564
2565#ifdef AHD_DEBUG
2566 if ((ahd_debug & AHD_SHOW_DV) != 0)
2567 printk("%s: %s QAS\n", ahd_name(ahd),
2568 qas ? "enabling" : "disabling");
2569#endif
2570
2571 if (qas) {
2572 ppr_options |= MSG_EXT_PPR_QAS_REQ;
2573 }
2574
2575 dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2576
2577 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2578 starget->channel + 'A', ROLE_INITIATOR);
2579 ahd_find_syncrate(ahd, &period, &ppr_options,
2580 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2581
2582 ahd_lock(ahd, &flags);
2583 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2584 ppr_options, AHD_TRANS_GOAL, FALSE);
2585 ahd_unlock(ahd, &flags);
2586}
2587
2588static void ahd_linux_set_iu(struct scsi_target *starget, int iu)
2589{
2590 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2591 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2592 struct ahd_tmode_tstate *tstate;
2593 struct ahd_initiator_tinfo *tinfo
2594 = ahd_fetch_transinfo(ahd,
2595 starget->channel + 'A',
2596 shost->this_id, starget->id, &tstate);
2597 struct ahd_devinfo devinfo;
2598 unsigned int ppr_options = tinfo->goal.ppr_options
2599 & ~MSG_EXT_PPR_IU_REQ;
2600 unsigned int period = tinfo->goal.period;
2601 unsigned int dt;
2602 unsigned long flags;
2603
2604#ifdef AHD_DEBUG
2605 if ((ahd_debug & AHD_SHOW_DV) != 0)
2606 printk("%s: %s IU\n", ahd_name(ahd),
2607 iu ? "enabling" : "disabling");
2608#endif
2609
2610 if (iu && spi_max_width(starget)) {
2611 ppr_options |= MSG_EXT_PPR_IU_REQ;
2612 ppr_options |= MSG_EXT_PPR_DT_REQ;
2613 }
2614
2615 dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2616
2617 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2618 starget->channel + 'A', ROLE_INITIATOR);
2619 ahd_find_syncrate(ahd, &period, &ppr_options,
2620 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2621
2622 ahd_lock(ahd, &flags);
2623 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2624 ppr_options, AHD_TRANS_GOAL, FALSE);
2625 ahd_unlock(ahd, &flags);
2626}
2627
2628static void ahd_linux_set_rd_strm(struct scsi_target *starget, int rdstrm)
2629{
2630 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2631 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2632 struct ahd_tmode_tstate *tstate;
2633 struct ahd_initiator_tinfo *tinfo
2634 = ahd_fetch_transinfo(ahd,
2635 starget->channel + 'A',
2636 shost->this_id, starget->id, &tstate);
2637 struct ahd_devinfo devinfo;
2638 unsigned int ppr_options = tinfo->goal.ppr_options
2639 & ~MSG_EXT_PPR_RD_STRM;
2640 unsigned int period = tinfo->goal.period;
2641 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2642 unsigned long flags;
2643
2644#ifdef AHD_DEBUG
2645 if ((ahd_debug & AHD_SHOW_DV) != 0)
2646 printk("%s: %s Read Streaming\n", ahd_name(ahd),
2647 rdstrm ? "enabling" : "disabling");
2648#endif
2649
2650 if (rdstrm && spi_max_width(starget))
2651 ppr_options |= MSG_EXT_PPR_RD_STRM;
2652
2653 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2654 starget->channel + 'A', ROLE_INITIATOR);
2655 ahd_find_syncrate(ahd, &period, &ppr_options,
2656 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2657
2658 ahd_lock(ahd, &flags);
2659 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2660 ppr_options, AHD_TRANS_GOAL, FALSE);
2661 ahd_unlock(ahd, &flags);
2662}
2663
2664static void ahd_linux_set_wr_flow(struct scsi_target *starget, int wrflow)
2665{
2666 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2667 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2668 struct ahd_tmode_tstate *tstate;
2669 struct ahd_initiator_tinfo *tinfo
2670 = ahd_fetch_transinfo(ahd,
2671 starget->channel + 'A',
2672 shost->this_id, starget->id, &tstate);
2673 struct ahd_devinfo devinfo;
2674 unsigned int ppr_options = tinfo->goal.ppr_options
2675 & ~MSG_EXT_PPR_WR_FLOW;
2676 unsigned int period = tinfo->goal.period;
2677 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2678 unsigned long flags;
2679
2680#ifdef AHD_DEBUG
2681 if ((ahd_debug & AHD_SHOW_DV) != 0)
2682 printk("%s: %s Write Flow Control\n", ahd_name(ahd),
2683 wrflow ? "enabling" : "disabling");
2684#endif
2685
2686 if (wrflow && spi_max_width(starget))
2687 ppr_options |= MSG_EXT_PPR_WR_FLOW;
2688
2689 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2690 starget->channel + 'A', ROLE_INITIATOR);
2691 ahd_find_syncrate(ahd, &period, &ppr_options,
2692 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2693
2694 ahd_lock(ahd, &flags);
2695 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2696 ppr_options, AHD_TRANS_GOAL, FALSE);
2697 ahd_unlock(ahd, &flags);
2698}
2699
2700static void ahd_linux_set_rti(struct scsi_target *starget, int rti)
2701{
2702 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2703 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2704 struct ahd_tmode_tstate *tstate;
2705 struct ahd_initiator_tinfo *tinfo
2706 = ahd_fetch_transinfo(ahd,
2707 starget->channel + 'A',
2708 shost->this_id, starget->id, &tstate);
2709 struct ahd_devinfo devinfo;
2710 unsigned int ppr_options = tinfo->goal.ppr_options
2711 & ~MSG_EXT_PPR_RTI;
2712 unsigned int period = tinfo->goal.period;
2713 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2714 unsigned long flags;
2715
2716 if ((ahd->features & AHD_RTI) == 0) {
2717#ifdef AHD_DEBUG
2718 if ((ahd_debug & AHD_SHOW_DV) != 0)
2719 printk("%s: RTI not available\n", ahd_name(ahd));
2720#endif
2721 return;
2722 }
2723
2724#ifdef AHD_DEBUG
2725 if ((ahd_debug & AHD_SHOW_DV) != 0)
2726 printk("%s: %s RTI\n", ahd_name(ahd),
2727 rti ? "enabling" : "disabling");
2728#endif
2729
2730 if (rti && spi_max_width(starget))
2731 ppr_options |= MSG_EXT_PPR_RTI;
2732
2733 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2734 starget->channel + 'A', ROLE_INITIATOR);
2735 ahd_find_syncrate(ahd, &period, &ppr_options,
2736 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2737
2738 ahd_lock(ahd, &flags);
2739 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2740 ppr_options, AHD_TRANS_GOAL, FALSE);
2741 ahd_unlock(ahd, &flags);
2742}
2743
2744static void ahd_linux_set_pcomp_en(struct scsi_target *starget, int pcomp)
2745{
2746 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2747 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2748 struct ahd_tmode_tstate *tstate;
2749 struct ahd_initiator_tinfo *tinfo
2750 = ahd_fetch_transinfo(ahd,
2751 starget->channel + 'A',
2752 shost->this_id, starget->id, &tstate);
2753 struct ahd_devinfo devinfo;
2754 unsigned int ppr_options = tinfo->goal.ppr_options
2755 & ~MSG_EXT_PPR_PCOMP_EN;
2756 unsigned int period = tinfo->goal.period;
2757 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2758 unsigned long flags;
2759
2760#ifdef AHD_DEBUG
2761 if ((ahd_debug & AHD_SHOW_DV) != 0)
2762 printk("%s: %s Precompensation\n", ahd_name(ahd),
2763 pcomp ? "Enable" : "Disable");
2764#endif
2765
2766 if (pcomp && spi_max_width(starget)) {
2767 uint8_t precomp;
2768
2769 if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) {
2770 const struct ahd_linux_iocell_opts *iocell_opts;
2771
2772 iocell_opts = &aic79xx_iocell_info[ahd->unit];
2773 precomp = iocell_opts->precomp;
2774 } else {
2775 precomp = AIC79XX_DEFAULT_PRECOMP;
2776 }
2777 ppr_options |= MSG_EXT_PPR_PCOMP_EN;
2778 AHD_SET_PRECOMP(ahd, precomp);
2779 } else {
2780 AHD_SET_PRECOMP(ahd, 0);
2781 }
2782
2783 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2784 starget->channel + 'A', ROLE_INITIATOR);
2785 ahd_find_syncrate(ahd, &period, &ppr_options,
2786 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2787
2788 ahd_lock(ahd, &flags);
2789 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2790 ppr_options, AHD_TRANS_GOAL, FALSE);
2791 ahd_unlock(ahd, &flags);
2792}
2793
2794static void ahd_linux_set_hold_mcs(struct scsi_target *starget, int hold)
2795{
2796 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2797 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2798 struct ahd_tmode_tstate *tstate;
2799 struct ahd_initiator_tinfo *tinfo
2800 = ahd_fetch_transinfo(ahd,
2801 starget->channel + 'A',
2802 shost->this_id, starget->id, &tstate);
2803 struct ahd_devinfo devinfo;
2804 unsigned int ppr_options = tinfo->goal.ppr_options
2805 & ~MSG_EXT_PPR_HOLD_MCS;
2806 unsigned int period = tinfo->goal.period;
2807 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2808 unsigned long flags;
2809
2810 if (hold && spi_max_width(starget))
2811 ppr_options |= MSG_EXT_PPR_HOLD_MCS;
2812
2813 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2814 starget->channel + 'A', ROLE_INITIATOR);
2815 ahd_find_syncrate(ahd, &period, &ppr_options,
2816 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2817
2818 ahd_lock(ahd, &flags);
2819 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2820 ppr_options, AHD_TRANS_GOAL, FALSE);
2821 ahd_unlock(ahd, &flags);
2822}
2823
2824static void ahd_linux_get_signalling(struct Scsi_Host *shost)
2825{
2826 struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata;
2827 unsigned long flags;
2828 u8 mode;
2829
2830 ahd_lock(ahd, &flags);
2831 ahd_pause(ahd);
2832 mode = ahd_inb(ahd, SBLKCTL);
2833 ahd_unpause(ahd);
2834 ahd_unlock(ahd, &flags);
2835
2836 if (mode & ENAB40)
2837 spi_signalling(shost) = SPI_SIGNAL_LVD;
2838 else if (mode & ENAB20)
2839 spi_signalling(shost) = SPI_SIGNAL_SE;
2840 else
2841 spi_signalling(shost) = SPI_SIGNAL_UNKNOWN;
2842}
2843
2844static struct spi_function_template ahd_linux_transport_functions = {
2845 .set_offset = ahd_linux_set_offset,
2846 .show_offset = 1,
2847 .set_period = ahd_linux_set_period,
2848 .show_period = 1,
2849 .set_width = ahd_linux_set_width,
2850 .show_width = 1,
2851 .set_dt = ahd_linux_set_dt,
2852 .show_dt = 1,
2853 .set_iu = ahd_linux_set_iu,
2854 .show_iu = 1,
2855 .set_qas = ahd_linux_set_qas,
2856 .show_qas = 1,
2857 .set_rd_strm = ahd_linux_set_rd_strm,
2858 .show_rd_strm = 1,
2859 .set_wr_flow = ahd_linux_set_wr_flow,
2860 .show_wr_flow = 1,
2861 .set_rti = ahd_linux_set_rti,
2862 .show_rti = 1,
2863 .set_pcomp_en = ahd_linux_set_pcomp_en,
2864 .show_pcomp_en = 1,
2865 .set_hold_mcs = ahd_linux_set_hold_mcs,
2866 .show_hold_mcs = 1,
2867 .get_signalling = ahd_linux_get_signalling,
2868};
2869
2870static int __init
2871ahd_linux_init(void)
2872{
2873 int error = 0;
2874
2875
2876
2877
2878 if (aic79xx)
2879 aic79xx_setup(aic79xx);
2880
2881 ahd_linux_transport_template =
2882 spi_attach_transport(&ahd_linux_transport_functions);
2883 if (!ahd_linux_transport_template)
2884 return -ENODEV;
2885
2886 scsi_transport_reserve_device(ahd_linux_transport_template,
2887 sizeof(struct ahd_linux_device));
2888
2889 error = ahd_linux_pci_init();
2890 if (error)
2891 spi_release_transport(ahd_linux_transport_template);
2892 return error;
2893}
2894
2895static void __exit
2896ahd_linux_exit(void)
2897{
2898 ahd_linux_pci_exit();
2899 spi_release_transport(ahd_linux_transport_template);
2900}
2901
2902module_init(ahd_linux_init);
2903module_exit(ahd_linux_exit);
2904