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