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 .show_info = ahd_linux_show_info,
910 .write_info = ahd_proc_write_seeprom,
911 .info = ahd_linux_info,
912 .queuecommand = ahd_linux_queue,
913 .eh_abort_handler = ahd_linux_abort,
914 .eh_device_reset_handler = ahd_linux_dev_reset,
915 .eh_bus_reset_handler = ahd_linux_bus_reset,
916#if defined(__i386__)
917 .bios_param = ahd_linux_biosparam,
918#endif
919 .can_queue = AHD_MAX_QUEUE,
920 .this_id = -1,
921 .max_sectors = 8192,
922 .cmd_per_lun = 2,
923 .use_clustering = ENABLE_CLUSTERING,
924 .slave_alloc = ahd_linux_slave_alloc,
925 .slave_configure = ahd_linux_slave_configure,
926 .target_alloc = ahd_linux_target_alloc,
927 .target_destroy = ahd_linux_target_destroy,
928};
929
930
931int
932ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent,
933 bus_size_t alignment, bus_size_t boundary,
934 dma_addr_t lowaddr, dma_addr_t highaddr,
935 bus_dma_filter_t *filter, void *filterarg,
936 bus_size_t maxsize, int nsegments,
937 bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag)
938{
939 bus_dma_tag_t dmat;
940
941 dmat = kmalloc(sizeof(*dmat), GFP_ATOMIC);
942 if (dmat == NULL)
943 return (ENOMEM);
944
945
946
947
948
949
950
951
952 dmat->alignment = alignment;
953 dmat->boundary = boundary;
954 dmat->maxsize = maxsize;
955 *ret_tag = dmat;
956 return (0);
957}
958
959void
960ahd_dma_tag_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat)
961{
962 kfree(dmat);
963}
964
965int
966ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr,
967 int flags, bus_dmamap_t *mapp)
968{
969 *vaddr = pci_alloc_consistent(ahd->dev_softc,
970 dmat->maxsize, mapp);
971 if (*vaddr == NULL)
972 return (ENOMEM);
973 return(0);
974}
975
976void
977ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat,
978 void* vaddr, bus_dmamap_t map)
979{
980 pci_free_consistent(ahd->dev_softc, dmat->maxsize,
981 vaddr, map);
982}
983
984int
985ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map,
986 void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb,
987 void *cb_arg, int flags)
988{
989
990
991
992
993 bus_dma_segment_t stack_sg;
994
995 stack_sg.ds_addr = map;
996 stack_sg.ds_len = dmat->maxsize;
997 cb(cb_arg, &stack_sg, 1, 0);
998 return (0);
999}
1000
1001void
1002ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map)
1003{
1004}
1005
1006int
1007ahd_dmamap_unload(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map)
1008{
1009
1010 return (0);
1011}
1012
1013
1014static void
1015ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value)
1016{
1017
1018 if ((instance >= 0)
1019 && (instance < ARRAY_SIZE(aic79xx_iocell_info))) {
1020 uint8_t *iocell_info;
1021
1022 iocell_info = (uint8_t*)&aic79xx_iocell_info[instance];
1023 iocell_info[index] = value & 0xFFFF;
1024 if (bootverbose)
1025 printk("iocell[%d:%ld] = %d\n", instance, index, value);
1026 }
1027}
1028
1029static void
1030ahd_linux_setup_tag_info_global(char *p)
1031{
1032 int tags, i, j;
1033
1034 tags = simple_strtoul(p + 1, NULL, 0) & 0xff;
1035 printk("Setting Global Tags= %d\n", tags);
1036
1037 for (i = 0; i < ARRAY_SIZE(aic79xx_tag_info); i++) {
1038 for (j = 0; j < AHD_NUM_TARGETS; j++) {
1039 aic79xx_tag_info[i].tag_commands[j] = tags;
1040 }
1041 }
1042}
1043
1044static void
1045ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
1046{
1047
1048 if ((instance >= 0) && (targ >= 0)
1049 && (instance < ARRAY_SIZE(aic79xx_tag_info))
1050 && (targ < AHD_NUM_TARGETS)) {
1051 aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF;
1052 if (bootverbose)
1053 printk("tag_info[%d:%d] = %d\n", instance, targ, value);
1054 }
1055}
1056
1057static char *
1058ahd_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,
1059 void (*callback)(u_long, int, int, int32_t),
1060 u_long callback_arg)
1061{
1062 char *tok_end;
1063 char *tok_end2;
1064 int i;
1065 int instance;
1066 int targ;
1067 int done;
1068 char tok_list[] = {'.', ',', '{', '}', '\0'};
1069
1070
1071 if (*opt_arg != ':')
1072 return (opt_arg);
1073 opt_arg++;
1074 instance = -1;
1075 targ = -1;
1076 done = FALSE;
1077
1078
1079
1080
1081 tok_end = strchr(opt_arg, '\0');
1082 if (tok_end < end)
1083 *tok_end = ',';
1084 while (!done) {
1085 switch (*opt_arg) {
1086 case '{':
1087 if (instance == -1) {
1088 instance = 0;
1089 } else {
1090 if (depth > 1) {
1091 if (targ == -1)
1092 targ = 0;
1093 } else {
1094 printk("Malformed Option %s\n",
1095 opt_name);
1096 done = TRUE;
1097 }
1098 }
1099 opt_arg++;
1100 break;
1101 case '}':
1102 if (targ != -1)
1103 targ = -1;
1104 else if (instance != -1)
1105 instance = -1;
1106 opt_arg++;
1107 break;
1108 case ',':
1109 case '.':
1110 if (instance == -1)
1111 done = TRUE;
1112 else if (targ >= 0)
1113 targ++;
1114 else if (instance >= 0)
1115 instance++;
1116 opt_arg++;
1117 break;
1118 case '\0':
1119 done = TRUE;
1120 break;
1121 default:
1122 tok_end = end;
1123 for (i = 0; tok_list[i]; i++) {
1124 tok_end2 = strchr(opt_arg, tok_list[i]);
1125 if ((tok_end2) && (tok_end2 < tok_end))
1126 tok_end = tok_end2;
1127 }
1128 callback(callback_arg, instance, targ,
1129 simple_strtol(opt_arg, NULL, 0));
1130 opt_arg = tok_end;
1131 break;
1132 }
1133 }
1134 return (opt_arg);
1135}
1136
1137
1138
1139
1140
1141
1142static int
1143aic79xx_setup(char *s)
1144{
1145 int i, n;
1146 char *p;
1147 char *end;
1148
1149 static const struct {
1150 const char *name;
1151 uint32_t *flag;
1152 } options[] = {
1153 { "extended", &aic79xx_extended },
1154 { "no_reset", &aic79xx_no_reset },
1155 { "verbose", &aic79xx_verbose },
1156 { "allow_memio", &aic79xx_allow_memio},
1157#ifdef AHD_DEBUG
1158 { "debug", &ahd_debug },
1159#endif
1160 { "periodic_otag", &aic79xx_periodic_otag },
1161 { "pci_parity", &aic79xx_pci_parity },
1162 { "seltime", &aic79xx_seltime },
1163 { "tag_info", NULL },
1164 { "global_tag_depth", NULL},
1165 { "slewrate", NULL },
1166 { "precomp", NULL },
1167 { "amplitude", NULL },
1168 { "slowcrc", &aic79xx_slowcrc },
1169 };
1170
1171 end = strchr(s, '\0');
1172
1173
1174
1175
1176
1177 n = 0;
1178
1179 while ((p = strsep(&s, ",.")) != NULL) {
1180 if (*p == '\0')
1181 continue;
1182 for (i = 0; i < ARRAY_SIZE(options); i++) {
1183
1184 n = strlen(options[i].name);
1185 if (strncmp(options[i].name, p, n) == 0)
1186 break;
1187 }
1188 if (i == ARRAY_SIZE(options))
1189 continue;
1190
1191 if (strncmp(p, "global_tag_depth", n) == 0) {
1192 ahd_linux_setup_tag_info_global(p + n);
1193 } else if (strncmp(p, "tag_info", n) == 0) {
1194 s = ahd_parse_brace_option("tag_info", p + n, end,
1195 2, ahd_linux_setup_tag_info, 0);
1196 } else if (strncmp(p, "slewrate", n) == 0) {
1197 s = ahd_parse_brace_option("slewrate",
1198 p + n, end, 1, ahd_linux_setup_iocell_info,
1199 AIC79XX_SLEWRATE_INDEX);
1200 } else if (strncmp(p, "precomp", n) == 0) {
1201 s = ahd_parse_brace_option("precomp",
1202 p + n, end, 1, ahd_linux_setup_iocell_info,
1203 AIC79XX_PRECOMP_INDEX);
1204 } else if (strncmp(p, "amplitude", n) == 0) {
1205 s = ahd_parse_brace_option("amplitude",
1206 p + n, end, 1, ahd_linux_setup_iocell_info,
1207 AIC79XX_AMPLITUDE_INDEX);
1208 } else if (p[n] == ':') {
1209 *(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0);
1210 } else if (!strncmp(p, "verbose", n)) {
1211 *(options[i].flag) = 1;
1212 } else {
1213 *(options[i].flag) ^= 0xFFFFFFFF;
1214 }
1215 }
1216 return 1;
1217}
1218
1219__setup("aic79xx=", aic79xx_setup);
1220
1221uint32_t aic79xx_verbose;
1222
1223int
1224ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *template)
1225{
1226 char buf[80];
1227 struct Scsi_Host *host;
1228 char *new_name;
1229 u_long s;
1230 int retval;
1231
1232 template->name = ahd->description;
1233 host = scsi_host_alloc(template, sizeof(struct ahd_softc *));
1234 if (host == NULL)
1235 return (ENOMEM);
1236
1237 *((struct ahd_softc **)host->hostdata) = ahd;
1238 ahd->platform_data->host = host;
1239 host->can_queue = AHD_MAX_QUEUE;
1240 host->cmd_per_lun = 2;
1241 host->sg_tablesize = AHD_NSEG;
1242 host->this_id = ahd->our_id;
1243 host->irq = ahd->platform_data->irq;
1244 host->max_id = (ahd->features & AHD_WIDE) ? 16 : 8;
1245 host->max_lun = AHD_NUM_LUNS;
1246 host->max_channel = 0;
1247 host->sg_tablesize = AHD_NSEG;
1248 ahd_lock(ahd, &s);
1249 ahd_set_unit(ahd, ahd_linux_unit++);
1250 ahd_unlock(ahd, &s);
1251 sprintf(buf, "scsi%d", host->host_no);
1252 new_name = kmalloc(strlen(buf) + 1, GFP_ATOMIC);
1253 if (new_name != NULL) {
1254 strcpy(new_name, buf);
1255 ahd_set_name(ahd, new_name);
1256 }
1257 host->unique_id = ahd->unit;
1258 ahd_linux_initialize_scsi_bus(ahd);
1259 ahd_intr_enable(ahd, TRUE);
1260
1261 host->transportt = ahd_linux_transport_template;
1262
1263 retval = scsi_add_host(host, &ahd->dev_softc->dev);
1264 if (retval) {
1265 printk(KERN_WARNING "aic79xx: scsi_add_host failed\n");
1266 scsi_host_put(host);
1267 return retval;
1268 }
1269
1270 scsi_scan_host(host);
1271 return 0;
1272}
1273
1274
1275
1276
1277
1278
1279static void
1280ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd)
1281{
1282 u_int target_id;
1283 u_int numtarg;
1284 unsigned long s;
1285
1286 target_id = 0;
1287 numtarg = 0;
1288
1289 if (aic79xx_no_reset != 0)
1290 ahd->flags &= ~AHD_RESET_BUS_A;
1291
1292 if ((ahd->flags & AHD_RESET_BUS_A) != 0)
1293 ahd_reset_channel(ahd, 'A', TRUE);
1294 else
1295 numtarg = (ahd->features & AHD_WIDE) ? 16 : 8;
1296
1297 ahd_lock(ahd, &s);
1298
1299
1300
1301
1302
1303 for (; target_id < numtarg; target_id++) {
1304 struct ahd_devinfo devinfo;
1305 struct ahd_initiator_tinfo *tinfo;
1306 struct ahd_tmode_tstate *tstate;
1307
1308 tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
1309 target_id, &tstate);
1310 ahd_compile_devinfo(&devinfo, ahd->our_id, target_id,
1311 CAM_LUN_WILDCARD, 'A', ROLE_INITIATOR);
1312 ahd_update_neg_request(ahd, &devinfo, tstate,
1313 tinfo, AHD_NEG_ALWAYS);
1314 }
1315 ahd_unlock(ahd, &s);
1316
1317 if ((ahd->flags & AHD_RESET_BUS_A) != 0) {
1318 ahd_freeze_simq(ahd);
1319 msleep(AIC79XX_RESET_DELAY);
1320 ahd_release_simq(ahd);
1321 }
1322}
1323
1324int
1325ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
1326{
1327 ahd->platform_data =
1328 kmalloc(sizeof(struct ahd_platform_data), GFP_ATOMIC);
1329 if (ahd->platform_data == NULL)
1330 return (ENOMEM);
1331 memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data));
1332 ahd->platform_data->irq = AHD_LINUX_NOIRQ;
1333 ahd_lockinit(ahd);
1334 ahd->seltime = (aic79xx_seltime & 0x3) << 4;
1335 return (0);
1336}
1337
1338void
1339ahd_platform_free(struct ahd_softc *ahd)
1340{
1341 struct scsi_target *starget;
1342 int i;
1343
1344 if (ahd->platform_data != NULL) {
1345
1346 for (i = 0; i < AHD_NUM_TARGETS; i++) {
1347 starget = ahd->platform_data->starget[i];
1348 if (starget != NULL) {
1349 ahd->platform_data->starget[i] = NULL;
1350 }
1351 }
1352
1353 if (ahd->platform_data->irq != AHD_LINUX_NOIRQ)
1354 free_irq(ahd->platform_data->irq, ahd);
1355 if (ahd->tags[0] == BUS_SPACE_PIO
1356 && ahd->bshs[0].ioport != 0)
1357 release_region(ahd->bshs[0].ioport, 256);
1358 if (ahd->tags[1] == BUS_SPACE_PIO
1359 && ahd->bshs[1].ioport != 0)
1360 release_region(ahd->bshs[1].ioport, 256);
1361 if (ahd->tags[0] == BUS_SPACE_MEMIO
1362 && ahd->bshs[0].maddr != NULL) {
1363 iounmap(ahd->bshs[0].maddr);
1364 release_mem_region(ahd->platform_data->mem_busaddr,
1365 0x1000);
1366 }
1367 if (ahd->platform_data->host)
1368 scsi_host_put(ahd->platform_data->host);
1369
1370 kfree(ahd->platform_data);
1371 }
1372}
1373
1374void
1375ahd_platform_init(struct ahd_softc *ahd)
1376{
1377
1378
1379
1380 if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) {
1381 const struct ahd_linux_iocell_opts *iocell_opts;
1382
1383 iocell_opts = &aic79xx_iocell_info[ahd->unit];
1384 if (iocell_opts->precomp != AIC79XX_DEFAULT_PRECOMP)
1385 AHD_SET_PRECOMP(ahd, iocell_opts->precomp);
1386 if (iocell_opts->slewrate != AIC79XX_DEFAULT_SLEWRATE)
1387 AHD_SET_SLEWRATE(ahd, iocell_opts->slewrate);
1388 if (iocell_opts->amplitude != AIC79XX_DEFAULT_AMPLITUDE)
1389 AHD_SET_AMPLITUDE(ahd, iocell_opts->amplitude);
1390 }
1391
1392}
1393
1394void
1395ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb)
1396{
1397 ahd_platform_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),
1398 SCB_GET_CHANNEL(ahd, scb),
1399 SCB_GET_LUN(scb), SCB_LIST_NULL,
1400 ROLE_UNKNOWN, CAM_REQUEUE_REQ);
1401}
1402
1403void
1404ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev,
1405 struct ahd_devinfo *devinfo, ahd_queue_alg alg)
1406{
1407 struct ahd_linux_device *dev;
1408 int was_queuing;
1409 int now_queuing;
1410
1411 if (sdev == NULL)
1412 return;
1413
1414 dev = scsi_transport_device_data(sdev);
1415
1416 if (dev == NULL)
1417 return;
1418 was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED);
1419 switch (alg) {
1420 default:
1421 case AHD_QUEUE_NONE:
1422 now_queuing = 0;
1423 break;
1424 case AHD_QUEUE_BASIC:
1425 now_queuing = AHD_DEV_Q_BASIC;
1426 break;
1427 case AHD_QUEUE_TAGGED:
1428 now_queuing = AHD_DEV_Q_TAGGED;
1429 break;
1430 }
1431 if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) == 0
1432 && (was_queuing != now_queuing)
1433 && (dev->active != 0)) {
1434 dev->flags |= AHD_DEV_FREEZE_TIL_EMPTY;
1435 dev->qfrozen++;
1436 }
1437
1438 dev->flags &= ~(AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED|AHD_DEV_PERIODIC_OTAG);
1439 if (now_queuing) {
1440 u_int usertags;
1441
1442 usertags = ahd_linux_user_tagdepth(ahd, devinfo);
1443 if (!was_queuing) {
1444
1445
1446
1447
1448
1449 dev->maxtags = usertags;
1450 dev->openings = dev->maxtags - dev->active;
1451 }
1452 if (dev->maxtags == 0) {
1453
1454
1455
1456 dev->openings = 1;
1457 } else if (alg == AHD_QUEUE_TAGGED) {
1458 dev->flags |= AHD_DEV_Q_TAGGED;
1459 if (aic79xx_periodic_otag != 0)
1460 dev->flags |= AHD_DEV_PERIODIC_OTAG;
1461 } else
1462 dev->flags |= AHD_DEV_Q_BASIC;
1463 } else {
1464
1465 dev->maxtags = 0;
1466 dev->openings = 1 - dev->active;
1467 }
1468
1469 switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) {
1470 case AHD_DEV_Q_BASIC:
1471 scsi_set_tag_type(sdev, MSG_SIMPLE_TASK);
1472 scsi_activate_tcq(sdev, dev->openings + dev->active);
1473 break;
1474 case AHD_DEV_Q_TAGGED:
1475 scsi_set_tag_type(sdev, MSG_ORDERED_TASK);
1476 scsi_activate_tcq(sdev, dev->openings + dev->active);
1477 break;
1478 default:
1479
1480
1481
1482
1483
1484
1485 scsi_deactivate_tcq(sdev, 1);
1486 break;
1487 }
1488}
1489
1490int
1491ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel,
1492 int lun, u_int tag, role_t role, uint32_t status)
1493{
1494 return 0;
1495}
1496
1497static u_int
1498ahd_linux_user_tagdepth(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
1499{
1500 static int warned_user;
1501 u_int tags;
1502
1503 tags = 0;
1504 if ((ahd->user_discenable & devinfo->target_mask) != 0) {
1505 if (ahd->unit >= ARRAY_SIZE(aic79xx_tag_info)) {
1506
1507 if (warned_user == 0) {
1508 printk(KERN_WARNING
1509"aic79xx: WARNING: Insufficient tag_info instances\n"
1510"aic79xx: for installed controllers. Using defaults\n"
1511"aic79xx: Please update the aic79xx_tag_info array in\n"
1512"aic79xx: the aic79xx_osm.c source file.\n");
1513 warned_user++;
1514 }
1515 tags = AHD_MAX_QUEUE;
1516 } else {
1517 adapter_tag_info_t *tag_info;
1518
1519 tag_info = &aic79xx_tag_info[ahd->unit];
1520 tags = tag_info->tag_commands[devinfo->target_offset];
1521 if (tags > AHD_MAX_QUEUE)
1522 tags = AHD_MAX_QUEUE;
1523 }
1524 }
1525 return (tags);
1526}
1527
1528
1529
1530
1531static void
1532ahd_linux_device_queue_depth(struct scsi_device *sdev)
1533{
1534 struct ahd_devinfo devinfo;
1535 u_int tags;
1536 struct ahd_softc *ahd = *((struct ahd_softc **)sdev->host->hostdata);
1537
1538 ahd_compile_devinfo(&devinfo,
1539 ahd->our_id,
1540 sdev->sdev_target->id, sdev->lun,
1541 sdev->sdev_target->channel == 0 ? 'A' : 'B',
1542 ROLE_INITIATOR);
1543 tags = ahd_linux_user_tagdepth(ahd, &devinfo);
1544 if (tags != 0 && sdev->tagged_supported != 0) {
1545
1546 ahd_platform_set_tags(ahd, sdev, &devinfo, AHD_QUEUE_TAGGED);
1547 ahd_send_async(ahd, devinfo.channel, devinfo.target,
1548 devinfo.lun, AC_TRANSFER_NEG);
1549 ahd_print_devinfo(ahd, &devinfo);
1550 printk("Tagged Queuing enabled. Depth %d\n", tags);
1551 } else {
1552 ahd_platform_set_tags(ahd, sdev, &devinfo, AHD_QUEUE_NONE);
1553 ahd_send_async(ahd, devinfo.channel, devinfo.target,
1554 devinfo.lun, AC_TRANSFER_NEG);
1555 }
1556}
1557
1558static int
1559ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
1560 struct scsi_cmnd *cmd)
1561{
1562 struct scb *scb;
1563 struct hardware_scb *hscb;
1564 struct ahd_initiator_tinfo *tinfo;
1565 struct ahd_tmode_tstate *tstate;
1566 u_int col_idx;
1567 uint16_t mask;
1568 unsigned long flags;
1569 int nseg;
1570
1571 nseg = scsi_dma_map(cmd);
1572 if (nseg < 0)
1573 return SCSI_MLQUEUE_HOST_BUSY;
1574
1575 ahd_lock(ahd, &flags);
1576
1577
1578
1579
1580 tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
1581 cmd->device->id, &tstate);
1582 if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0
1583 || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
1584 col_idx = AHD_NEVER_COL_IDX;
1585 } else {
1586 col_idx = AHD_BUILD_COL_IDX(cmd->device->id,
1587 cmd->device->lun);
1588 }
1589 if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
1590 ahd->flags |= AHD_RESOURCE_SHORTAGE;
1591 ahd_unlock(ahd, &flags);
1592 scsi_dma_unmap(cmd);
1593 return SCSI_MLQUEUE_HOST_BUSY;
1594 }
1595
1596 scb->io_ctx = cmd;
1597 scb->platform_data->dev = dev;
1598 hscb = scb->hscb;
1599 cmd->host_scribble = (char *)scb;
1600
1601
1602
1603
1604 hscb->control = 0;
1605 hscb->scsiid = BUILD_SCSIID(ahd, cmd);
1606 hscb->lun = cmd->device->lun;
1607 scb->hscb->task_management = 0;
1608 mask = SCB_GET_TARGET_MASK(ahd, scb);
1609
1610 if ((ahd->user_discenable & mask) != 0)
1611 hscb->control |= DISCENB;
1612
1613 if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0)
1614 scb->flags |= SCB_PACKETIZED;
1615
1616 if ((tstate->auto_negotiate & mask) != 0) {
1617 scb->flags |= SCB_AUTO_NEGOTIATE;
1618 scb->hscb->control |= MK_MESSAGE;
1619 }
1620
1621 if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {
1622 int msg_bytes;
1623 uint8_t tag_msgs[2];
1624
1625 msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
1626 if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
1627 hscb->control |= tag_msgs[0];
1628 if (tag_msgs[0] == MSG_ORDERED_TASK)
1629 dev->commands_since_idle_or_otag = 0;
1630 } else
1631 if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH
1632 && (dev->flags & AHD_DEV_Q_TAGGED) != 0) {
1633 hscb->control |= MSG_ORDERED_TASK;
1634 dev->commands_since_idle_or_otag = 0;
1635 } else {
1636 hscb->control |= MSG_SIMPLE_TASK;
1637 }
1638 }
1639
1640 hscb->cdb_len = cmd->cmd_len;
1641 memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len);
1642
1643 scb->platform_data->xfer_len = 0;
1644 ahd_set_residual(scb, 0);
1645 ahd_set_sense_residual(scb, 0);
1646 scb->sg_count = 0;
1647
1648 if (nseg > 0) {
1649 void *sg = scb->sg_list;
1650 struct scatterlist *cur_seg;
1651 int i;
1652
1653 scb->platform_data->xfer_len = 0;
1654
1655 scsi_for_each_sg(cmd, cur_seg, nseg, i) {
1656 dma_addr_t addr;
1657 bus_size_t len;
1658
1659 addr = sg_dma_address(cur_seg);
1660 len = sg_dma_len(cur_seg);
1661 scb->platform_data->xfer_len += len;
1662 sg = ahd_sg_setup(ahd, scb, sg, addr, len,
1663 i == (nseg - 1));
1664 }
1665 }
1666
1667 LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
1668 dev->openings--;
1669 dev->active++;
1670 dev->commands_issued++;
1671
1672 if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0)
1673 dev->commands_since_idle_or_otag++;
1674 scb->flags |= SCB_ACTIVE;
1675 ahd_queue_scb(ahd, scb);
1676
1677 ahd_unlock(ahd, &flags);
1678
1679 return 0;
1680}
1681
1682
1683
1684
1685irqreturn_t
1686ahd_linux_isr(int irq, void *dev_id)
1687{
1688 struct ahd_softc *ahd;
1689 u_long flags;
1690 int ours;
1691
1692 ahd = (struct ahd_softc *) dev_id;
1693 ahd_lock(ahd, &flags);
1694 ours = ahd_intr(ahd);
1695 ahd_unlock(ahd, &flags);
1696 return IRQ_RETVAL(ours);
1697}
1698
1699void
1700ahd_send_async(struct ahd_softc *ahd, char channel,
1701 u_int target, u_int lun, ac_code code)
1702{
1703 switch (code) {
1704 case AC_TRANSFER_NEG:
1705 {
1706 struct scsi_target *starget;
1707 struct ahd_initiator_tinfo *tinfo;
1708 struct ahd_tmode_tstate *tstate;
1709 unsigned int target_ppr_options;
1710
1711 BUG_ON(target == CAM_TARGET_WILDCARD);
1712
1713 tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id,
1714 target, &tstate);
1715
1716
1717
1718
1719
1720 if (tinfo->curr.period != tinfo->goal.period
1721 || tinfo->curr.width != tinfo->goal.width
1722 || tinfo->curr.offset != tinfo->goal.offset
1723 || tinfo->curr.ppr_options != tinfo->goal.ppr_options)
1724 if (bootverbose == 0)
1725 break;
1726
1727
1728
1729
1730
1731 starget = ahd->platform_data->starget[target];
1732 if (starget == NULL)
1733 break;
1734
1735 target_ppr_options =
1736 (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0)
1737 + (spi_qas(starget) ? MSG_EXT_PPR_QAS_REQ : 0)
1738 + (spi_iu(starget) ? MSG_EXT_PPR_IU_REQ : 0)
1739 + (spi_rd_strm(starget) ? MSG_EXT_PPR_RD_STRM : 0)
1740 + (spi_pcomp_en(starget) ? MSG_EXT_PPR_PCOMP_EN : 0)
1741 + (spi_rti(starget) ? MSG_EXT_PPR_RTI : 0)
1742 + (spi_wr_flow(starget) ? MSG_EXT_PPR_WR_FLOW : 0)
1743 + (spi_hold_mcs(starget) ? MSG_EXT_PPR_HOLD_MCS : 0);
1744
1745 if (tinfo->curr.period == spi_period(starget)
1746 && tinfo->curr.width == spi_width(starget)
1747 && tinfo->curr.offset == spi_offset(starget)
1748 && tinfo->curr.ppr_options == target_ppr_options)
1749 if (bootverbose == 0)
1750 break;
1751
1752 spi_period(starget) = tinfo->curr.period;
1753 spi_width(starget) = tinfo->curr.width;
1754 spi_offset(starget) = tinfo->curr.offset;
1755 spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ ? 1 : 0;
1756 spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ ? 1 : 0;
1757 spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ ? 1 : 0;
1758 spi_rd_strm(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_RD_STRM ? 1 : 0;
1759 spi_pcomp_en(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_PCOMP_EN ? 1 : 0;
1760 spi_rti(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_RTI ? 1 : 0;
1761 spi_wr_flow(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_WR_FLOW ? 1 : 0;
1762 spi_hold_mcs(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_HOLD_MCS ? 1 : 0;
1763 spi_display_xfer_agreement(starget);
1764 break;
1765 }
1766 case AC_SENT_BDR:
1767 {
1768 WARN_ON(lun != CAM_LUN_WILDCARD);
1769 scsi_report_device_reset(ahd->platform_data->host,
1770 channel - 'A', target);
1771 break;
1772 }
1773 case AC_BUS_RESET:
1774 if (ahd->platform_data->host != NULL) {
1775 scsi_report_bus_reset(ahd->platform_data->host,
1776 channel - 'A');
1777 }
1778 break;
1779 default:
1780 panic("ahd_send_async: Unexpected async event");
1781 }
1782}
1783
1784
1785
1786
1787void
1788ahd_done(struct ahd_softc *ahd, struct scb *scb)
1789{
1790 struct scsi_cmnd *cmd;
1791 struct ahd_linux_device *dev;
1792
1793 if ((scb->flags & SCB_ACTIVE) == 0) {
1794 printk("SCB %d done'd twice\n", SCB_GET_TAG(scb));
1795 ahd_dump_card_state(ahd);
1796 panic("Stopping for safety");
1797 }
1798 LIST_REMOVE(scb, pending_links);
1799 cmd = scb->io_ctx;
1800 dev = scb->platform_data->dev;
1801 dev->active--;
1802 dev->openings++;
1803 if ((cmd->result & (CAM_DEV_QFRZN << 16)) != 0) {
1804 cmd->result &= ~(CAM_DEV_QFRZN << 16);
1805 dev->qfrozen--;
1806 }
1807 ahd_linux_unmap_scb(ahd, scb);
1808
1809
1810
1811
1812
1813
1814
1815 cmd->sense_buffer[0] = 0;
1816 if (ahd_get_transaction_status(scb) == CAM_REQ_INPROG) {
1817 uint32_t amount_xferred;
1818
1819 amount_xferred =
1820 ahd_get_transfer_length(scb) - ahd_get_residual(scb);
1821 if ((scb->flags & SCB_TRANSMISSION_ERROR) != 0) {
1822#ifdef AHD_DEBUG
1823 if ((ahd_debug & AHD_SHOW_MISC) != 0) {
1824 ahd_print_path(ahd, scb);
1825 printk("Set CAM_UNCOR_PARITY\n");
1826 }
1827#endif
1828 ahd_set_transaction_status(scb, CAM_UNCOR_PARITY);
1829#ifdef AHD_REPORT_UNDERFLOWS
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839 } else if (amount_xferred < scb->io_ctx->underflow) {
1840 u_int i;
1841
1842 ahd_print_path(ahd, scb);
1843 printk("CDB:");
1844 for (i = 0; i < scb->io_ctx->cmd_len; i++)
1845 printk(" 0x%x", scb->io_ctx->cmnd[i]);
1846 printk("\n");
1847 ahd_print_path(ahd, scb);
1848 printk("Saw underflow (%ld of %ld bytes). "
1849 "Treated as error\n",
1850 ahd_get_residual(scb),
1851 ahd_get_transfer_length(scb));
1852 ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR);
1853#endif
1854 } else {
1855 ahd_set_transaction_status(scb, CAM_REQ_CMP);
1856 }
1857 } else if (ahd_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) {
1858 ahd_linux_handle_scsi_status(ahd, cmd->device, scb);
1859 }
1860
1861 if (dev->openings == 1
1862 && ahd_get_transaction_status(scb) == CAM_REQ_CMP
1863 && ahd_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL)
1864 dev->tag_success_count++;
1865
1866
1867
1868
1869
1870
1871 if ((dev->openings + dev->active) < dev->maxtags
1872 && dev->tag_success_count > AHD_TAG_SUCCESS_INTERVAL) {
1873 dev->tag_success_count = 0;
1874 dev->openings++;
1875 }
1876
1877 if (dev->active == 0)
1878 dev->commands_since_idle_or_otag = 0;
1879
1880 if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
1881 printk("Recovery SCB completes\n");
1882 if (ahd_get_transaction_status(scb) == CAM_BDR_SENT
1883 || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED)
1884 ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
1885
1886 if (ahd->platform_data->eh_done)
1887 complete(ahd->platform_data->eh_done);
1888 }
1889
1890 ahd_free_scb(ahd, scb);
1891 ahd_linux_queue_cmd_complete(ahd, cmd);
1892}
1893
1894static void
1895ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
1896 struct scsi_device *sdev, struct scb *scb)
1897{
1898 struct ahd_devinfo devinfo;
1899 struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
1900
1901 ahd_compile_devinfo(&devinfo,
1902 ahd->our_id,
1903 sdev->sdev_target->id, sdev->lun,
1904 sdev->sdev_target->channel == 0 ? 'A' : 'B',
1905 ROLE_INITIATOR);
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917 switch (ahd_get_scsi_status(scb)) {
1918 default:
1919 break;
1920 case SCSI_STATUS_CHECK_COND:
1921 case SCSI_STATUS_CMD_TERMINATED:
1922 {
1923 struct scsi_cmnd *cmd;
1924
1925
1926
1927
1928
1929 cmd = scb->io_ctx;
1930 if ((scb->flags & (SCB_SENSE|SCB_PKT_SENSE)) != 0) {
1931 struct scsi_status_iu_header *siu;
1932 u_int sense_size;
1933 u_int sense_offset;
1934
1935 if (scb->flags & SCB_SENSE) {
1936 sense_size = min(sizeof(struct scsi_sense_data)
1937 - ahd_get_sense_residual(scb),
1938 (u_long)SCSI_SENSE_BUFFERSIZE);
1939 sense_offset = 0;
1940 } else {
1941
1942
1943
1944
1945 siu = (struct scsi_status_iu_header *)
1946 scb->sense_data;
1947 sense_size = min_t(size_t,
1948 scsi_4btoul(siu->sense_length),
1949 SCSI_SENSE_BUFFERSIZE);
1950 sense_offset = SIU_SENSE_OFFSET(siu);
1951 }
1952
1953 memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
1954 memcpy(cmd->sense_buffer,
1955 ahd_get_sense_buf(ahd, scb)
1956 + sense_offset, sense_size);
1957 cmd->result |= (DRIVER_SENSE << 24);
1958
1959#ifdef AHD_DEBUG
1960 if (ahd_debug & AHD_SHOW_SENSE) {
1961 int i;
1962
1963 printk("Copied %d bytes of sense data at %d:",
1964 sense_size, sense_offset);
1965 for (i = 0; i < sense_size; i++) {
1966 if ((i & 0xF) == 0)
1967 printk("\n");
1968 printk("0x%x ", cmd->sense_buffer[i]);
1969 }
1970 printk("\n");
1971 }
1972#endif
1973 }
1974 break;
1975 }
1976 case SCSI_STATUS_QUEUE_FULL:
1977
1978
1979
1980
1981
1982
1983
1984
1985 dev->tag_success_count = 0;
1986 if (dev->active != 0) {
1987
1988
1989
1990
1991 dev->openings = 0;
1992#ifdef AHD_DEBUG
1993 if ((ahd_debug & AHD_SHOW_QFULL) != 0) {
1994 ahd_print_path(ahd, scb);
1995 printk("Dropping tag count to %d\n",
1996 dev->active);
1997 }
1998#endif
1999 if (dev->active == dev->tags_on_last_queuefull) {
2000
2001 dev->last_queuefull_same_count++;
2002
2003
2004
2005
2006
2007
2008
2009
2010 if (dev->last_queuefull_same_count
2011 == AHD_LOCK_TAGS_COUNT) {
2012 dev->maxtags = dev->active;
2013 ahd_print_path(ahd, scb);
2014 printk("Locking max tag count at %d\n",
2015 dev->active);
2016 }
2017 } else {
2018 dev->tags_on_last_queuefull = dev->active;
2019 dev->last_queuefull_same_count = 0;
2020 }
2021 ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);
2022 ahd_set_scsi_status(scb, SCSI_STATUS_OK);
2023 ahd_platform_set_tags(ahd, sdev, &devinfo,
2024 (dev->flags & AHD_DEV_Q_BASIC)
2025 ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED);
2026 break;
2027 }
2028
2029
2030
2031
2032 dev->openings = 1;
2033 ahd_platform_set_tags(ahd, sdev, &devinfo,
2034 (dev->flags & AHD_DEV_Q_BASIC)
2035 ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED);
2036 ahd_set_scsi_status(scb, SCSI_STATUS_BUSY);
2037 }
2038}
2039
2040static void
2041ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd)
2042{
2043 int status;
2044 int new_status = DID_OK;
2045 int do_fallback = 0;
2046 int scsi_status;
2047
2048
2049
2050
2051
2052
2053
2054
2055 status = ahd_cmd_get_transaction_status(cmd);
2056 switch (status) {
2057 case CAM_REQ_INPROG:
2058 case CAM_REQ_CMP:
2059 new_status = DID_OK;
2060 break;
2061 case CAM_AUTOSENSE_FAIL:
2062 new_status = DID_ERROR;
2063
2064 case CAM_SCSI_STATUS_ERROR:
2065 scsi_status = ahd_cmd_get_scsi_status(cmd);
2066
2067 switch(scsi_status) {
2068 case SCSI_STATUS_CMD_TERMINATED:
2069 case SCSI_STATUS_CHECK_COND:
2070 if ((cmd->result >> 24) != DRIVER_SENSE) {
2071 do_fallback = 1;
2072 } else {
2073 struct scsi_sense_data *sense;
2074
2075 sense = (struct scsi_sense_data *)
2076 cmd->sense_buffer;
2077 if (sense->extra_len >= 5 &&
2078 (sense->add_sense_code == 0x47
2079 || sense->add_sense_code == 0x48))
2080 do_fallback = 1;
2081 }
2082 break;
2083 default:
2084 break;
2085 }
2086 break;
2087 case CAM_REQ_ABORTED:
2088 new_status = DID_ABORT;
2089 break;
2090 case CAM_BUSY:
2091 new_status = DID_BUS_BUSY;
2092 break;
2093 case CAM_REQ_INVALID:
2094 case CAM_PATH_INVALID:
2095 new_status = DID_BAD_TARGET;
2096 break;
2097 case CAM_SEL_TIMEOUT:
2098 new_status = DID_NO_CONNECT;
2099 break;
2100 case CAM_SCSI_BUS_RESET:
2101 case CAM_BDR_SENT:
2102 new_status = DID_RESET;
2103 break;
2104 case CAM_UNCOR_PARITY:
2105 new_status = DID_PARITY;
2106 do_fallback = 1;
2107 break;
2108 case CAM_CMD_TIMEOUT:
2109 new_status = DID_TIME_OUT;
2110 do_fallback = 1;
2111 break;
2112 case CAM_REQ_CMP_ERR:
2113 case CAM_UNEXP_BUSFREE:
2114 case CAM_DATA_RUN_ERR:
2115 new_status = DID_ERROR;
2116 do_fallback = 1;
2117 break;
2118 case CAM_UA_ABORT:
2119 case CAM_NO_HBA:
2120 case CAM_SEQUENCE_FAIL:
2121 case CAM_CCB_LEN_ERR:
2122 case CAM_PROVIDE_FAIL:
2123 case CAM_REQ_TERMIO:
2124 case CAM_UNREC_HBA_ERROR:
2125 case CAM_REQ_TOO_BIG:
2126 new_status = DID_ERROR;
2127 break;
2128 case CAM_REQUEUE_REQ:
2129 new_status = DID_REQUEUE;
2130 break;
2131 default:
2132
2133 new_status = DID_ERROR;
2134 break;
2135 }
2136
2137 if (do_fallback) {
2138 printk("%s: device overrun (status %x) on %d:%d:%d\n",
2139 ahd_name(ahd), status, cmd->device->channel,
2140 cmd->device->id, cmd->device->lun);
2141 }
2142
2143 ahd_cmd_set_transaction_status(cmd, new_status);
2144
2145 cmd->scsi_done(cmd);
2146}
2147
2148static void
2149ahd_freeze_simq(struct ahd_softc *ahd)
2150{
2151 scsi_block_requests(ahd->platform_data->host);
2152}
2153
2154static void
2155ahd_release_simq(struct ahd_softc *ahd)
2156{
2157 scsi_unblock_requests(ahd->platform_data->host);
2158}
2159
2160static int
2161ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd)
2162{
2163 struct ahd_softc *ahd;
2164 struct ahd_linux_device *dev;
2165 struct scb *pending_scb;
2166 u_int saved_scbptr;
2167 u_int active_scbptr;
2168 u_int last_phase;
2169 u_int saved_scsiid;
2170 u_int cdb_byte;
2171 int retval;
2172 int was_paused;
2173 int paused;
2174 int wait;
2175 int disconnected;
2176 ahd_mode_state saved_modes;
2177 unsigned long flags;
2178
2179 pending_scb = NULL;
2180 paused = FALSE;
2181 wait = FALSE;
2182 ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
2183
2184 scmd_printk(KERN_INFO, cmd,
2185 "Attempting to queue an ABORT message:");
2186
2187 printk("CDB:");
2188 for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
2189 printk(" 0x%x", cmd->cmnd[cdb_byte]);
2190 printk("\n");
2191
2192 ahd_lock(ahd, &flags);
2193
2194
2195
2196
2197
2198
2199
2200
2201 dev = scsi_transport_device_data(cmd->device);
2202
2203 if (dev == NULL) {
2204
2205
2206
2207
2208 scmd_printk(KERN_INFO, cmd, "Is not an active device\n");
2209 retval = SUCCESS;
2210 goto no_cmd;
2211 }
2212
2213
2214
2215
2216 LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
2217 if (pending_scb->io_ctx == cmd)
2218 break;
2219 }
2220
2221 if (pending_scb == NULL) {
2222 scmd_printk(KERN_INFO, cmd, "Command not found\n");
2223 goto no_cmd;
2224 }
2225
2226 if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) {
2227
2228
2229
2230 retval = FAILED;
2231 goto done;
2232 }
2233
2234
2235
2236
2237
2238
2239
2240 was_paused = ahd_is_paused(ahd);
2241 ahd_pause_and_flushwork(ahd);
2242 paused = TRUE;
2243
2244 if ((pending_scb->flags & SCB_ACTIVE) == 0) {
2245 scmd_printk(KERN_INFO, cmd, "Command already completed\n");
2246 goto no_cmd;
2247 }
2248
2249 printk("%s: At time of recovery, card was %spaused\n",
2250 ahd_name(ahd), was_paused ? "" : "not ");
2251 ahd_dump_card_state(ahd);
2252
2253 disconnected = TRUE;
2254 if (ahd_search_qinfifo(ahd, cmd->device->id,
2255 cmd->device->channel + 'A',
2256 cmd->device->lun,
2257 pending_scb->hscb->tag,
2258 ROLE_INITIATOR, CAM_REQ_ABORTED,
2259 SEARCH_COMPLETE) > 0) {
2260 printk("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
2261 ahd_name(ahd), cmd->device->channel,
2262 cmd->device->id, cmd->device->lun);
2263 retval = SUCCESS;
2264 goto done;
2265 }
2266
2267 saved_modes = ahd_save_modes(ahd);
2268 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
2269 last_phase = ahd_inb(ahd, LASTPHASE);
2270 saved_scbptr = ahd_get_scbptr(ahd);
2271 active_scbptr = saved_scbptr;
2272 if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) {
2273 struct scb *bus_scb;
2274
2275 bus_scb = ahd_lookup_scb(ahd, active_scbptr);
2276 if (bus_scb == pending_scb)
2277 disconnected = FALSE;
2278 }
2279
2280
2281
2282
2283
2284
2285 saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
2286 if (last_phase != P_BUSFREE
2287 && SCB_GET_TAG(pending_scb) == active_scbptr) {
2288
2289
2290
2291
2292
2293 pending_scb = ahd_lookup_scb(ahd, active_scbptr);
2294 pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
2295 ahd_outb(ahd, MSG_OUT, HOST_MSG);
2296 ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
2297 scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n");
2298 wait = TRUE;
2299 } else if (disconnected) {
2300
2301
2302
2303
2304
2305 pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
2306 ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));
2307 pending_scb->hscb->cdb_len = 0;
2308 pending_scb->hscb->task_attribute = 0;
2309 pending_scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK;
2310
2311 if ((pending_scb->flags & SCB_PACKETIZED) != 0) {
2312
2313
2314
2315
2316
2317
2318
2319 ahd_outb(ahd, SCB_TASK_MANAGEMENT,
2320 pending_scb->hscb->task_management);
2321 } else {
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331 pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
2332
2333
2334
2335
2336
2337
2338
2339 ahd_outb(ahd, SCB_CONTROL,
2340 ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE);
2341 }
2342
2343
2344
2345
2346
2347
2348 ahd_search_qinfifo(ahd, cmd->device->id,
2349 cmd->device->channel + 'A', cmd->device->lun,
2350 SCB_LIST_NULL, ROLE_INITIATOR,
2351 CAM_REQUEUE_REQ, SEARCH_COMPLETE);
2352 ahd_qinfifo_requeue_tail(ahd, pending_scb);
2353 ahd_set_scbptr(ahd, saved_scbptr);
2354 ahd_print_path(ahd, pending_scb);
2355 printk("Device is disconnected, re-queuing SCB\n");
2356 wait = TRUE;
2357 } else {
2358 scmd_printk(KERN_INFO, cmd, "Unable to deliver message\n");
2359 retval = FAILED;
2360 goto done;
2361 }
2362
2363no_cmd:
2364
2365
2366
2367
2368
2369
2370 retval = SUCCESS;
2371done:
2372 if (paused)
2373 ahd_unpause(ahd);
2374 if (wait) {
2375 DECLARE_COMPLETION_ONSTACK(done);
2376
2377 ahd->platform_data->eh_done = &done;
2378 ahd_unlock(ahd, &flags);
2379
2380 printk("%s: Recovery code sleeping\n", ahd_name(ahd));
2381 if (!wait_for_completion_timeout(&done, 5 * HZ)) {
2382 ahd_lock(ahd, &flags);
2383 ahd->platform_data->eh_done = NULL;
2384 ahd_unlock(ahd, &flags);
2385 printk("%s: Timer Expired (active %d)\n",
2386 ahd_name(ahd), dev->active);
2387 retval = FAILED;
2388 }
2389 printk("Recovery code awake\n");
2390 } else
2391 ahd_unlock(ahd, &flags);
2392
2393 if (retval != SUCCESS)
2394 printk("%s: Command abort returning 0x%x\n",
2395 ahd_name(ahd), retval);
2396
2397 return retval;
2398}
2399
2400static void ahd_linux_set_width(struct scsi_target *starget, int width)
2401{
2402 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2403 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2404 struct ahd_devinfo devinfo;
2405 unsigned long flags;
2406
2407 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2408 starget->channel + 'A', ROLE_INITIATOR);
2409 ahd_lock(ahd, &flags);
2410 ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE);
2411 ahd_unlock(ahd, &flags);
2412}
2413
2414static void ahd_linux_set_period(struct scsi_target *starget, int period)
2415{
2416 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2417 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2418 struct ahd_tmode_tstate *tstate;
2419 struct ahd_initiator_tinfo *tinfo
2420 = ahd_fetch_transinfo(ahd,
2421 starget->channel + 'A',
2422 shost->this_id, starget->id, &tstate);
2423 struct ahd_devinfo devinfo;
2424 unsigned int ppr_options = tinfo->goal.ppr_options;
2425 unsigned int dt;
2426 unsigned long flags;
2427 unsigned long offset = tinfo->goal.offset;
2428
2429#ifdef AHD_DEBUG
2430 if ((ahd_debug & AHD_SHOW_DV) != 0)
2431 printk("%s: set period to %d\n", ahd_name(ahd), period);
2432#endif
2433 if (offset == 0)
2434 offset = MAX_OFFSET;
2435
2436 if (period < 8)
2437 period = 8;
2438 if (period < 10) {
2439 if (spi_max_width(starget)) {
2440 ppr_options |= MSG_EXT_PPR_DT_REQ;
2441 if (period == 8)
2442 ppr_options |= MSG_EXT_PPR_IU_REQ;
2443 } else
2444 period = 10;
2445 }
2446
2447 dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2448
2449 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2450 starget->channel + 'A', ROLE_INITIATOR);
2451
2452
2453 if (ppr_options & ~MSG_EXT_PPR_QAS_REQ) {
2454 if (spi_width(starget) == 0)
2455 ppr_options &= MSG_EXT_PPR_QAS_REQ;
2456 }
2457
2458 ahd_find_syncrate(ahd, &period, &ppr_options,
2459 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2460
2461 ahd_lock(ahd, &flags);
2462 ahd_set_syncrate(ahd, &devinfo, period, offset,
2463 ppr_options, AHD_TRANS_GOAL, FALSE);
2464 ahd_unlock(ahd, &flags);
2465}
2466
2467static void ahd_linux_set_offset(struct scsi_target *starget, int offset)
2468{
2469 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2470 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2471 struct ahd_tmode_tstate *tstate;
2472 struct ahd_initiator_tinfo *tinfo
2473 = ahd_fetch_transinfo(ahd,
2474 starget->channel + 'A',
2475 shost->this_id, starget->id, &tstate);
2476 struct ahd_devinfo devinfo;
2477 unsigned int ppr_options = 0;
2478 unsigned int period = 0;
2479 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2480 unsigned long flags;
2481
2482#ifdef AHD_DEBUG
2483 if ((ahd_debug & AHD_SHOW_DV) != 0)
2484 printk("%s: set offset to %d\n", ahd_name(ahd), offset);
2485#endif
2486
2487 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2488 starget->channel + 'A', ROLE_INITIATOR);
2489 if (offset != 0) {
2490 period = tinfo->goal.period;
2491 ppr_options = tinfo->goal.ppr_options;
2492 ahd_find_syncrate(ahd, &period, &ppr_options,
2493 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2494 }
2495
2496 ahd_lock(ahd, &flags);
2497 ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options,
2498 AHD_TRANS_GOAL, FALSE);
2499 ahd_unlock(ahd, &flags);
2500}
2501
2502static void ahd_linux_set_dt(struct scsi_target *starget, int dt)
2503{
2504 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2505 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2506 struct ahd_tmode_tstate *tstate;
2507 struct ahd_initiator_tinfo *tinfo
2508 = ahd_fetch_transinfo(ahd,
2509 starget->channel + 'A',
2510 shost->this_id, starget->id, &tstate);
2511 struct ahd_devinfo devinfo;
2512 unsigned int ppr_options = tinfo->goal.ppr_options
2513 & ~MSG_EXT_PPR_DT_REQ;
2514 unsigned int period = tinfo->goal.period;
2515 unsigned int width = tinfo->goal.width;
2516 unsigned long flags;
2517
2518#ifdef AHD_DEBUG
2519 if ((ahd_debug & AHD_SHOW_DV) != 0)
2520 printk("%s: %s DT\n", ahd_name(ahd),
2521 dt ? "enabling" : "disabling");
2522#endif
2523 if (dt && spi_max_width(starget)) {
2524 ppr_options |= MSG_EXT_PPR_DT_REQ;
2525 if (!width)
2526 ahd_linux_set_width(starget, 1);
2527 } else {
2528 if (period <= 9)
2529 period = 10;
2530
2531 ppr_options &= ~MSG_EXT_PPR_IU_REQ;
2532 }
2533 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2534 starget->channel + 'A', ROLE_INITIATOR);
2535 ahd_find_syncrate(ahd, &period, &ppr_options,
2536 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2537
2538 ahd_lock(ahd, &flags);
2539 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2540 ppr_options, AHD_TRANS_GOAL, FALSE);
2541 ahd_unlock(ahd, &flags);
2542}
2543
2544static void ahd_linux_set_qas(struct scsi_target *starget, int qas)
2545{
2546 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2547 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2548 struct ahd_tmode_tstate *tstate;
2549 struct ahd_initiator_tinfo *tinfo
2550 = ahd_fetch_transinfo(ahd,
2551 starget->channel + 'A',
2552 shost->this_id, starget->id, &tstate);
2553 struct ahd_devinfo devinfo;
2554 unsigned int ppr_options = tinfo->goal.ppr_options
2555 & ~MSG_EXT_PPR_QAS_REQ;
2556 unsigned int period = tinfo->goal.period;
2557 unsigned int dt;
2558 unsigned long flags;
2559
2560#ifdef AHD_DEBUG
2561 if ((ahd_debug & AHD_SHOW_DV) != 0)
2562 printk("%s: %s QAS\n", ahd_name(ahd),
2563 qas ? "enabling" : "disabling");
2564#endif
2565
2566 if (qas) {
2567 ppr_options |= MSG_EXT_PPR_QAS_REQ;
2568 }
2569
2570 dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2571
2572 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2573 starget->channel + 'A', ROLE_INITIATOR);
2574 ahd_find_syncrate(ahd, &period, &ppr_options,
2575 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2576
2577 ahd_lock(ahd, &flags);
2578 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2579 ppr_options, AHD_TRANS_GOAL, FALSE);
2580 ahd_unlock(ahd, &flags);
2581}
2582
2583static void ahd_linux_set_iu(struct scsi_target *starget, int iu)
2584{
2585 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2586 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2587 struct ahd_tmode_tstate *tstate;
2588 struct ahd_initiator_tinfo *tinfo
2589 = ahd_fetch_transinfo(ahd,
2590 starget->channel + 'A',
2591 shost->this_id, starget->id, &tstate);
2592 struct ahd_devinfo devinfo;
2593 unsigned int ppr_options = tinfo->goal.ppr_options
2594 & ~MSG_EXT_PPR_IU_REQ;
2595 unsigned int period = tinfo->goal.period;
2596 unsigned int dt;
2597 unsigned long flags;
2598
2599#ifdef AHD_DEBUG
2600 if ((ahd_debug & AHD_SHOW_DV) != 0)
2601 printk("%s: %s IU\n", ahd_name(ahd),
2602 iu ? "enabling" : "disabling");
2603#endif
2604
2605 if (iu && spi_max_width(starget)) {
2606 ppr_options |= MSG_EXT_PPR_IU_REQ;
2607 ppr_options |= MSG_EXT_PPR_DT_REQ;
2608 }
2609
2610 dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2611
2612 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2613 starget->channel + 'A', ROLE_INITIATOR);
2614 ahd_find_syncrate(ahd, &period, &ppr_options,
2615 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2616
2617 ahd_lock(ahd, &flags);
2618 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2619 ppr_options, AHD_TRANS_GOAL, FALSE);
2620 ahd_unlock(ahd, &flags);
2621}
2622
2623static void ahd_linux_set_rd_strm(struct scsi_target *starget, int rdstrm)
2624{
2625 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2626 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2627 struct ahd_tmode_tstate *tstate;
2628 struct ahd_initiator_tinfo *tinfo
2629 = ahd_fetch_transinfo(ahd,
2630 starget->channel + 'A',
2631 shost->this_id, starget->id, &tstate);
2632 struct ahd_devinfo devinfo;
2633 unsigned int ppr_options = tinfo->goal.ppr_options
2634 & ~MSG_EXT_PPR_RD_STRM;
2635 unsigned int period = tinfo->goal.period;
2636 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2637 unsigned long flags;
2638
2639#ifdef AHD_DEBUG
2640 if ((ahd_debug & AHD_SHOW_DV) != 0)
2641 printk("%s: %s Read Streaming\n", ahd_name(ahd),
2642 rdstrm ? "enabling" : "disabling");
2643#endif
2644
2645 if (rdstrm && spi_max_width(starget))
2646 ppr_options |= MSG_EXT_PPR_RD_STRM;
2647
2648 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2649 starget->channel + 'A', ROLE_INITIATOR);
2650 ahd_find_syncrate(ahd, &period, &ppr_options,
2651 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2652
2653 ahd_lock(ahd, &flags);
2654 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2655 ppr_options, AHD_TRANS_GOAL, FALSE);
2656 ahd_unlock(ahd, &flags);
2657}
2658
2659static void ahd_linux_set_wr_flow(struct scsi_target *starget, int wrflow)
2660{
2661 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2662 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2663 struct ahd_tmode_tstate *tstate;
2664 struct ahd_initiator_tinfo *tinfo
2665 = ahd_fetch_transinfo(ahd,
2666 starget->channel + 'A',
2667 shost->this_id, starget->id, &tstate);
2668 struct ahd_devinfo devinfo;
2669 unsigned int ppr_options = tinfo->goal.ppr_options
2670 & ~MSG_EXT_PPR_WR_FLOW;
2671 unsigned int period = tinfo->goal.period;
2672 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2673 unsigned long flags;
2674
2675#ifdef AHD_DEBUG
2676 if ((ahd_debug & AHD_SHOW_DV) != 0)
2677 printk("%s: %s Write Flow Control\n", ahd_name(ahd),
2678 wrflow ? "enabling" : "disabling");
2679#endif
2680
2681 if (wrflow && spi_max_width(starget))
2682 ppr_options |= MSG_EXT_PPR_WR_FLOW;
2683
2684 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2685 starget->channel + 'A', ROLE_INITIATOR);
2686 ahd_find_syncrate(ahd, &period, &ppr_options,
2687 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2688
2689 ahd_lock(ahd, &flags);
2690 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2691 ppr_options, AHD_TRANS_GOAL, FALSE);
2692 ahd_unlock(ahd, &flags);
2693}
2694
2695static void ahd_linux_set_rti(struct scsi_target *starget, int rti)
2696{
2697 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2698 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2699 struct ahd_tmode_tstate *tstate;
2700 struct ahd_initiator_tinfo *tinfo
2701 = ahd_fetch_transinfo(ahd,
2702 starget->channel + 'A',
2703 shost->this_id, starget->id, &tstate);
2704 struct ahd_devinfo devinfo;
2705 unsigned int ppr_options = tinfo->goal.ppr_options
2706 & ~MSG_EXT_PPR_RTI;
2707 unsigned int period = tinfo->goal.period;
2708 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2709 unsigned long flags;
2710
2711 if ((ahd->features & AHD_RTI) == 0) {
2712#ifdef AHD_DEBUG
2713 if ((ahd_debug & AHD_SHOW_DV) != 0)
2714 printk("%s: RTI not available\n", ahd_name(ahd));
2715#endif
2716 return;
2717 }
2718
2719#ifdef AHD_DEBUG
2720 if ((ahd_debug & AHD_SHOW_DV) != 0)
2721 printk("%s: %s RTI\n", ahd_name(ahd),
2722 rti ? "enabling" : "disabling");
2723#endif
2724
2725 if (rti && spi_max_width(starget))
2726 ppr_options |= MSG_EXT_PPR_RTI;
2727
2728 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2729 starget->channel + 'A', ROLE_INITIATOR);
2730 ahd_find_syncrate(ahd, &period, &ppr_options,
2731 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2732
2733 ahd_lock(ahd, &flags);
2734 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2735 ppr_options, AHD_TRANS_GOAL, FALSE);
2736 ahd_unlock(ahd, &flags);
2737}
2738
2739static void ahd_linux_set_pcomp_en(struct scsi_target *starget, int pcomp)
2740{
2741 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2742 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2743 struct ahd_tmode_tstate *tstate;
2744 struct ahd_initiator_tinfo *tinfo
2745 = ahd_fetch_transinfo(ahd,
2746 starget->channel + 'A',
2747 shost->this_id, starget->id, &tstate);
2748 struct ahd_devinfo devinfo;
2749 unsigned int ppr_options = tinfo->goal.ppr_options
2750 & ~MSG_EXT_PPR_PCOMP_EN;
2751 unsigned int period = tinfo->goal.period;
2752 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2753 unsigned long flags;
2754
2755#ifdef AHD_DEBUG
2756 if ((ahd_debug & AHD_SHOW_DV) != 0)
2757 printk("%s: %s Precompensation\n", ahd_name(ahd),
2758 pcomp ? "Enable" : "Disable");
2759#endif
2760
2761 if (pcomp && spi_max_width(starget)) {
2762 uint8_t precomp;
2763
2764 if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) {
2765 const struct ahd_linux_iocell_opts *iocell_opts;
2766
2767 iocell_opts = &aic79xx_iocell_info[ahd->unit];
2768 precomp = iocell_opts->precomp;
2769 } else {
2770 precomp = AIC79XX_DEFAULT_PRECOMP;
2771 }
2772 ppr_options |= MSG_EXT_PPR_PCOMP_EN;
2773 AHD_SET_PRECOMP(ahd, precomp);
2774 } else {
2775 AHD_SET_PRECOMP(ahd, 0);
2776 }
2777
2778 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2779 starget->channel + 'A', ROLE_INITIATOR);
2780 ahd_find_syncrate(ahd, &period, &ppr_options,
2781 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2782
2783 ahd_lock(ahd, &flags);
2784 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2785 ppr_options, AHD_TRANS_GOAL, FALSE);
2786 ahd_unlock(ahd, &flags);
2787}
2788
2789static void ahd_linux_set_hold_mcs(struct scsi_target *starget, int hold)
2790{
2791 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2792 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2793 struct ahd_tmode_tstate *tstate;
2794 struct ahd_initiator_tinfo *tinfo
2795 = ahd_fetch_transinfo(ahd,
2796 starget->channel + 'A',
2797 shost->this_id, starget->id, &tstate);
2798 struct ahd_devinfo devinfo;
2799 unsigned int ppr_options = tinfo->goal.ppr_options
2800 & ~MSG_EXT_PPR_HOLD_MCS;
2801 unsigned int period = tinfo->goal.period;
2802 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2803 unsigned long flags;
2804
2805 if (hold && spi_max_width(starget))
2806 ppr_options |= MSG_EXT_PPR_HOLD_MCS;
2807
2808 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2809 starget->channel + 'A', ROLE_INITIATOR);
2810 ahd_find_syncrate(ahd, &period, &ppr_options,
2811 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2812
2813 ahd_lock(ahd, &flags);
2814 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2815 ppr_options, AHD_TRANS_GOAL, FALSE);
2816 ahd_unlock(ahd, &flags);
2817}
2818
2819static void ahd_linux_get_signalling(struct Scsi_Host *shost)
2820{
2821 struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata;
2822 unsigned long flags;
2823 u8 mode;
2824
2825 ahd_lock(ahd, &flags);
2826 ahd_pause(ahd);
2827 mode = ahd_inb(ahd, SBLKCTL);
2828 ahd_unpause(ahd);
2829 ahd_unlock(ahd, &flags);
2830
2831 if (mode & ENAB40)
2832 spi_signalling(shost) = SPI_SIGNAL_LVD;
2833 else if (mode & ENAB20)
2834 spi_signalling(shost) = SPI_SIGNAL_SE;
2835 else
2836 spi_signalling(shost) = SPI_SIGNAL_UNKNOWN;
2837}
2838
2839static struct spi_function_template ahd_linux_transport_functions = {
2840 .set_offset = ahd_linux_set_offset,
2841 .show_offset = 1,
2842 .set_period = ahd_linux_set_period,
2843 .show_period = 1,
2844 .set_width = ahd_linux_set_width,
2845 .show_width = 1,
2846 .set_dt = ahd_linux_set_dt,
2847 .show_dt = 1,
2848 .set_iu = ahd_linux_set_iu,
2849 .show_iu = 1,
2850 .set_qas = ahd_linux_set_qas,
2851 .show_qas = 1,
2852 .set_rd_strm = ahd_linux_set_rd_strm,
2853 .show_rd_strm = 1,
2854 .set_wr_flow = ahd_linux_set_wr_flow,
2855 .show_wr_flow = 1,
2856 .set_rti = ahd_linux_set_rti,
2857 .show_rti = 1,
2858 .set_pcomp_en = ahd_linux_set_pcomp_en,
2859 .show_pcomp_en = 1,
2860 .set_hold_mcs = ahd_linux_set_hold_mcs,
2861 .show_hold_mcs = 1,
2862 .get_signalling = ahd_linux_get_signalling,
2863};
2864
2865static int __init
2866ahd_linux_init(void)
2867{
2868 int error = 0;
2869
2870
2871
2872
2873 if (aic79xx)
2874 aic79xx_setup(aic79xx);
2875
2876 ahd_linux_transport_template =
2877 spi_attach_transport(&ahd_linux_transport_functions);
2878 if (!ahd_linux_transport_template)
2879 return -ENODEV;
2880
2881 scsi_transport_reserve_device(ahd_linux_transport_template,
2882 sizeof(struct ahd_linux_device));
2883
2884 error = ahd_linux_pci_init();
2885 if (error)
2886 spi_release_transport(ahd_linux_transport_template);
2887 return error;
2888}
2889
2890static void __exit
2891ahd_linux_exit(void)
2892{
2893 ahd_linux_pci_exit();
2894 spi_release_transport(ahd_linux_transport_template);
2895}
2896
2897module_init(ahd_linux_init);
2898module_exit(ahd_linux_exit);
2899