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