]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/scsi/aic7xxx/aic79xx_osm.h
853998be1474f4059deb2251bef1ec7bb10a182c
[linux-2.6-omap-h63xx.git] / drivers / scsi / aic7xxx / aic79xx_osm.h
1 /*
2  * Adaptec AIC79xx device driver for Linux.
3  *
4  * Copyright (c) 2000-2001 Adaptec Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions, and the following disclaimer,
12  *    without modification.
13  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
14  *    substantially similar to the "NO WARRANTY" disclaimer below
15  *    ("Disclaimer") and any redistribution must be conditioned upon
16  *    including a substantially similar Disclaimer requirement for further
17  *    binary redistribution.
18  * 3. Neither the names of the above-listed copyright holders nor the names
19  *    of any contributors may be used to endorse or promote products derived
20  *    from this software without specific prior written permission.
21  *
22  * Alternatively, this software may be distributed under the terms of the
23  * GNU General Public License ("GPL") version 2 as published by the Free
24  * Software Foundation.
25  *
26  * NO WARRANTY
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
30  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
36  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGES.
38  *
39  * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#166 $
40  *
41  */
42 #ifndef _AIC79XX_LINUX_H_
43 #define _AIC79XX_LINUX_H_
44
45 #include <linux/types.h>
46 #include <linux/blkdev.h>
47 #include <linux/delay.h>
48 #include <linux/ioport.h>
49 #include <linux/pci.h>
50 #include <linux/interrupt.h>
51 #include <linux/module.h>
52 #include <linux/slab.h>
53 #include <asm/byteorder.h>
54 #include <asm/io.h>
55
56 #include <scsi/scsi.h>
57 #include <scsi/scsi_cmnd.h>
58 #include <scsi/scsi_eh.h>
59 #include <scsi/scsi_device.h>
60 #include <scsi/scsi_host.h>
61 #include <scsi/scsi_tcq.h>
62 #include <scsi/scsi_transport.h>
63 #include <scsi/scsi_transport_spi.h>
64
65 /* Core SCSI definitions */
66 #define AIC_LIB_PREFIX ahd
67
68 /* Name space conflict with BSD queue macros */
69 #ifdef LIST_HEAD
70 #undef LIST_HEAD
71 #endif
72
73 #include "cam.h"
74 #include "queue.h"
75 #include "scsi_message.h"
76 #include "scsi_iu.h"
77 #include "aiclib.h"
78
79 /*********************************** Debugging ********************************/
80 #ifdef CONFIG_AIC79XX_DEBUG_ENABLE
81 #ifdef CONFIG_AIC79XX_DEBUG_MASK
82 #define AHD_DEBUG 1
83 #define AHD_DEBUG_OPTS CONFIG_AIC79XX_DEBUG_MASK
84 #else
85 /*
86  * Compile in debugging code, but do not enable any printfs.
87  */
88 #define AHD_DEBUG 1
89 #define AHD_DEBUG_OPTS 0
90 #endif
91 /* No debugging code. */
92 #endif
93
94 /********************************** Misc Macros *******************************/
95 #define powerof2(x)     ((((x)-1)&(x))==0)
96
97 /************************* Forward Declarations *******************************/
98 struct ahd_softc;
99 typedef struct pci_dev *ahd_dev_softc_t;
100 typedef struct scsi_cmnd      *ahd_io_ctx_t;
101
102 /******************************* Byte Order ***********************************/
103 #define ahd_htobe16(x)  cpu_to_be16(x)
104 #define ahd_htobe32(x)  cpu_to_be32(x)
105 #define ahd_htobe64(x)  cpu_to_be64(x)
106 #define ahd_htole16(x)  cpu_to_le16(x)
107 #define ahd_htole32(x)  cpu_to_le32(x)
108 #define ahd_htole64(x)  cpu_to_le64(x)
109
110 #define ahd_be16toh(x)  be16_to_cpu(x)
111 #define ahd_be32toh(x)  be32_to_cpu(x)
112 #define ahd_be64toh(x)  be64_to_cpu(x)
113 #define ahd_le16toh(x)  le16_to_cpu(x)
114 #define ahd_le32toh(x)  le32_to_cpu(x)
115 #define ahd_le64toh(x)  le64_to_cpu(x)
116
117 /************************* Configuration Data *********************************/
118 extern uint32_t aic79xx_allow_memio;
119 extern struct scsi_host_template aic79xx_driver_template;
120
121 /***************************** Bus Space/DMA **********************************/
122
123 typedef uint32_t bus_size_t;
124
125 typedef enum {
126         BUS_SPACE_MEMIO,
127         BUS_SPACE_PIO
128 } bus_space_tag_t;
129
130 typedef union {
131         u_long            ioport;
132         volatile uint8_t __iomem *maddr;
133 } bus_space_handle_t;
134
135 typedef struct bus_dma_segment
136 {
137         dma_addr_t      ds_addr;
138         bus_size_t      ds_len;
139 } bus_dma_segment_t;
140
141 struct ahd_linux_dma_tag
142 {
143         bus_size_t      alignment;
144         bus_size_t      boundary;
145         bus_size_t      maxsize;
146 };
147 typedef struct ahd_linux_dma_tag* bus_dma_tag_t;
148
149 typedef dma_addr_t bus_dmamap_t;
150
151 typedef int bus_dma_filter_t(void*, dma_addr_t);
152 typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
153
154 #define BUS_DMA_WAITOK          0x0
155 #define BUS_DMA_NOWAIT          0x1
156 #define BUS_DMA_ALLOCNOW        0x2
157 #define BUS_DMA_LOAD_SEGS       0x4     /*
158                                          * Argument is an S/G list not
159                                          * a single buffer.
160                                          */
161
162 #define BUS_SPACE_MAXADDR       0xFFFFFFFF
163 #define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
164 #define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
165
166 int     ahd_dma_tag_create(struct ahd_softc *, bus_dma_tag_t /*parent*/,
167                            bus_size_t /*alignment*/, bus_size_t /*boundary*/,
168                            dma_addr_t /*lowaddr*/, dma_addr_t /*highaddr*/,
169                            bus_dma_filter_t*/*filter*/, void */*filterarg*/,
170                            bus_size_t /*maxsize*/, int /*nsegments*/,
171                            bus_size_t /*maxsegsz*/, int /*flags*/,
172                            bus_dma_tag_t */*dma_tagp*/);
173
174 void    ahd_dma_tag_destroy(struct ahd_softc *, bus_dma_tag_t /*tag*/);
175
176 int     ahd_dmamem_alloc(struct ahd_softc *, bus_dma_tag_t /*dmat*/,
177                          void** /*vaddr*/, int /*flags*/,
178                          bus_dmamap_t* /*mapp*/);
179
180 void    ahd_dmamem_free(struct ahd_softc *, bus_dma_tag_t /*dmat*/,
181                         void* /*vaddr*/, bus_dmamap_t /*map*/);
182
183 void    ahd_dmamap_destroy(struct ahd_softc *, bus_dma_tag_t /*tag*/,
184                            bus_dmamap_t /*map*/);
185
186 int     ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t /*dmat*/,
187                         bus_dmamap_t /*map*/, void * /*buf*/,
188                         bus_size_t /*buflen*/, bus_dmamap_callback_t *,
189                         void */*callback_arg*/, int /*flags*/);
190
191 int     ahd_dmamap_unload(struct ahd_softc *, bus_dma_tag_t, bus_dmamap_t);
192
193 /*
194  * Operations performed by ahd_dmamap_sync().
195  */
196 #define BUS_DMASYNC_PREREAD     0x01    /* pre-read synchronization */
197 #define BUS_DMASYNC_POSTREAD    0x02    /* post-read synchronization */
198 #define BUS_DMASYNC_PREWRITE    0x04    /* pre-write synchronization */
199 #define BUS_DMASYNC_POSTWRITE   0x08    /* post-write synchronization */
200
201 /*
202  * XXX
203  * ahd_dmamap_sync is only used on buffers allocated with
204  * the pci_alloc_consistent() API.  Although I'm not sure how
205  * this works on architectures with a write buffer, Linux does
206  * not have an API to sync "coherent" memory.  Perhaps we need
207  * to do an mb()?
208  */
209 #define ahd_dmamap_sync(ahd, dma_tag, dmamap, offset, len, op)
210
211 /************************** Timer DataStructures ******************************/
212 typedef struct timer_list ahd_timer_t;
213
214 /********************************** Includes **********************************/
215 #ifdef CONFIG_AIC79XX_REG_PRETTY_PRINT
216 #define AIC_DEBUG_REGISTERS 1
217 #else
218 #define AIC_DEBUG_REGISTERS 0
219 #endif
220 #include "aic79xx.h"
221
222 /***************************** Timer Facilities *******************************/
223 #define ahd_timer_init init_timer
224 #define ahd_timer_stop del_timer_sync
225 typedef void ahd_linux_callback_t (u_long);  
226 static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec,
227                                      ahd_callback_t *func, void *arg);
228
229 static __inline void
230 ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
231 {
232         struct ahd_softc *ahd;
233
234         ahd = (struct ahd_softc *)arg;
235         del_timer(timer);
236         timer->data = (u_long)arg;
237         timer->expires = jiffies + (usec * HZ)/1000000;
238         timer->function = (ahd_linux_callback_t*)func;
239         add_timer(timer);
240 }
241
242 /***************************** SMP support ************************************/
243 #include <linux/spinlock.h>
244
245 #define AIC79XX_DRIVER_VERSION "3.0"
246
247 /*************************** Device Data Structures ***************************/
248 /*
249  * A per probed device structure used to deal with some error recovery
250  * scenarios that the Linux mid-layer code just doesn't know how to
251  * handle.  The structure allocated for a device only becomes persistent
252  * after a successfully completed inquiry command to the target when
253  * that inquiry data indicates a lun is present.
254  */
255
256 typedef enum {
257         AHD_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */
258         AHD_DEV_Q_BASIC          = 0x10, /* Allow basic device queuing */
259         AHD_DEV_Q_TAGGED         = 0x20, /* Allow full SCSI2 command queueing */
260         AHD_DEV_PERIODIC_OTAG    = 0x40, /* Send OTAG to prevent starvation */
261 } ahd_linux_dev_flags;
262
263 struct ahd_linux_device {
264         TAILQ_ENTRY(ahd_linux_device) links;
265
266         /*
267          * The number of transactions currently
268          * queued to the device.
269          */
270         int                     active;
271
272         /*
273          * The currently allowed number of 
274          * transactions that can be queued to
275          * the device.  Must be signed for
276          * conversion from tagged to untagged
277          * mode where the device may have more
278          * than one outstanding active transaction.
279          */
280         int                     openings;
281
282         /*
283          * A positive count indicates that this
284          * device's queue is halted.
285          */
286         u_int                   qfrozen;
287         
288         /*
289          * Cumulative command counter.
290          */
291         u_long                  commands_issued;
292
293         /*
294          * The number of tagged transactions when
295          * running at our current opening level
296          * that have been successfully received by
297          * this device since the last QUEUE FULL.
298          */
299         u_int                   tag_success_count;
300 #define AHD_TAG_SUCCESS_INTERVAL 50
301
302         ahd_linux_dev_flags     flags;
303
304         /*
305          * Per device timer.
306          */
307         struct timer_list       timer;
308
309         /*
310          * The high limit for the tags variable.
311          */
312         u_int                   maxtags;
313
314         /*
315          * The computed number of tags outstanding
316          * at the time of the last QUEUE FULL event.
317          */
318         u_int                   tags_on_last_queuefull;
319
320         /*
321          * How many times we have seen a queue full
322          * with the same number of tags.  This is used
323          * to stop our adaptive queue depth algorithm
324          * on devices with a fixed number of tags.
325          */
326         u_int                   last_queuefull_same_count;
327 #define AHD_LOCK_TAGS_COUNT 50
328
329         /*
330          * How many transactions have been queued
331          * without the device going idle.  We use
332          * this statistic to determine when to issue
333          * an ordered tag to prevent transaction
334          * starvation.  This statistic is only updated
335          * if the AHD_DEV_PERIODIC_OTAG flag is set
336          * on this device.
337          */
338         u_int                   commands_since_idle_or_otag;
339 #define AHD_OTAG_THRESH 500
340 };
341
342 /********************* Definitions Required by the Core ***********************/
343 /*
344  * Number of SG segments we require.  So long as the S/G segments for
345  * a particular transaction are allocated in a physically contiguous
346  * manner and are allocated below 4GB, the number of S/G segments is
347  * unrestricted.
348  */
349 #define AHD_NSEG 128
350
351 /*
352  * Per-SCB OSM storage.
353  */
354 struct scb_platform_data {
355         struct ahd_linux_device *dev;
356         dma_addr_t               buf_busaddr;
357         uint32_t                 xfer_len;
358         uint32_t                 sense_resid;   /* Auto-Sense residual */
359 };
360
361 /*
362  * Define a structure used for each host adapter.  All members are
363  * aligned on a boundary >= the size of the member to honor the
364  * alignment restrictions of the various platforms supported by
365  * this driver.
366  */
367 struct ahd_platform_data {
368         /*
369          * Fields accessed from interrupt context.
370          */
371         struct scsi_target *starget[AHD_NUM_TARGETS]; 
372
373         spinlock_t               spin_lock;
374         struct completion       *eh_done;
375         struct Scsi_Host        *host;          /* pointer to scsi host */
376 #define AHD_LINUX_NOIRQ ((uint32_t)~0)
377         uint32_t                 irq;           /* IRQ for this adapter */
378         uint32_t                 bios_address;
379         uint32_t                 mem_busaddr;   /* Mem Base Addr */
380 };
381
382 /************************** OS Utility Wrappers *******************************/
383 #define printf printk
384 #define M_NOWAIT GFP_ATOMIC
385 #define M_WAITOK 0
386 #define malloc(size, type, flags) kmalloc(size, flags)
387 #define free(ptr, type) kfree(ptr)
388
389 static __inline void ahd_delay(long);
390 static __inline void
391 ahd_delay(long usec)
392 {
393         /*
394          * udelay on Linux can have problems for
395          * multi-millisecond waits.  Wait at most
396          * 1024us per call.
397          */
398         while (usec > 0) {
399                 udelay(usec % 1024);
400                 usec -= 1024;
401         }
402 }
403
404
405 /***************************** Low Level I/O **********************************/
406 static __inline uint8_t ahd_inb(struct ahd_softc * ahd, long port);
407 static __inline uint16_t ahd_inw_atomic(struct ahd_softc * ahd, long port);
408 static __inline void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val);
409 static __inline void ahd_outw_atomic(struct ahd_softc * ahd,
410                                      long port, uint16_t val);
411 static __inline void ahd_outsb(struct ahd_softc * ahd, long port,
412                                uint8_t *, int count);
413 static __inline void ahd_insb(struct ahd_softc * ahd, long port,
414                                uint8_t *, int count);
415
416 static __inline uint8_t
417 ahd_inb(struct ahd_softc * ahd, long port)
418 {
419         uint8_t x;
420
421         if (ahd->tags[0] == BUS_SPACE_MEMIO) {
422                 x = readb(ahd->bshs[0].maddr + port);
423         } else {
424                 x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
425         }
426         mb();
427         return (x);
428 }
429
430 static __inline uint16_t
431 ahd_inw_atomic(struct ahd_softc * ahd, long port)
432 {
433         uint8_t x;
434
435         if (ahd->tags[0] == BUS_SPACE_MEMIO) {
436                 x = readw(ahd->bshs[0].maddr + port);
437         } else {
438                 x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
439         }
440         mb();
441         return (x);
442 }
443
444 static __inline void
445 ahd_outb(struct ahd_softc * ahd, long port, uint8_t val)
446 {
447         if (ahd->tags[0] == BUS_SPACE_MEMIO) {
448                 writeb(val, ahd->bshs[0].maddr + port);
449         } else {
450                 outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
451         }
452         mb();
453 }
454
455 static __inline void
456 ahd_outw_atomic(struct ahd_softc * ahd, long port, uint16_t val)
457 {
458         if (ahd->tags[0] == BUS_SPACE_MEMIO) {
459                 writew(val, ahd->bshs[0].maddr + port);
460         } else {
461                 outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
462         }
463         mb();
464 }
465
466 static __inline void
467 ahd_outsb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
468 {
469         int i;
470
471         /*
472          * There is probably a more efficient way to do this on Linux
473          * but we don't use this for anything speed critical and this
474          * should work.
475          */
476         for (i = 0; i < count; i++)
477                 ahd_outb(ahd, port, *array++);
478 }
479
480 static __inline void
481 ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
482 {
483         int i;
484
485         /*
486          * There is probably a more efficient way to do this on Linux
487          * but we don't use this for anything speed critical and this
488          * should work.
489          */
490         for (i = 0; i < count; i++)
491                 *array++ = ahd_inb(ahd, port);
492 }
493
494 /**************************** Initialization **********************************/
495 int             ahd_linux_register_host(struct ahd_softc *,
496                                         struct scsi_host_template *);
497
498 /*************************** Pretty Printing **********************************/
499 struct info_str {
500         char *buffer;
501         int length;
502         off_t offset;
503         int pos;
504 };
505
506 /******************************** Locking *************************************/
507 static __inline void
508 ahd_lockinit(struct ahd_softc *ahd)
509 {
510         spin_lock_init(&ahd->platform_data->spin_lock);
511 }
512
513 static __inline void
514 ahd_lock(struct ahd_softc *ahd, unsigned long *flags)
515 {
516         spin_lock_irqsave(&ahd->platform_data->spin_lock, *flags);
517 }
518
519 static __inline void
520 ahd_unlock(struct ahd_softc *ahd, unsigned long *flags)
521 {
522         spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags);
523 }
524
525 /******************************* PCI Definitions ******************************/
526 /*
527  * PCIM_xxx: mask to locate subfield in register
528  * PCIR_xxx: config register offset
529  * PCIC_xxx: device class
530  * PCIS_xxx: device subclass
531  * PCIP_xxx: device programming interface
532  * PCIV_xxx: PCI vendor ID (only required to fixup ancient devices)
533  * PCID_xxx: device ID
534  */
535 #define PCIR_DEVVENDOR          0x00
536 #define PCIR_VENDOR             0x00
537 #define PCIR_DEVICE             0x02
538 #define PCIR_COMMAND            0x04
539 #define PCIM_CMD_PORTEN         0x0001
540 #define PCIM_CMD_MEMEN          0x0002
541 #define PCIM_CMD_BUSMASTEREN    0x0004
542 #define PCIM_CMD_MWRICEN        0x0010
543 #define PCIM_CMD_PERRESPEN      0x0040
544 #define PCIM_CMD_SERRESPEN      0x0100
545 #define PCIR_STATUS             0x06
546 #define PCIR_REVID              0x08
547 #define PCIR_PROGIF             0x09
548 #define PCIR_SUBCLASS           0x0a
549 #define PCIR_CLASS              0x0b
550 #define PCIR_CACHELNSZ          0x0c
551 #define PCIR_LATTIMER           0x0d
552 #define PCIR_HEADERTYPE         0x0e
553 #define PCIM_MFDEV              0x80
554 #define PCIR_BIST               0x0f
555 #define PCIR_CAP_PTR            0x34
556
557 /* config registers for header type 0 devices */
558 #define PCIR_MAPS       0x10
559 #define PCIR_SUBVEND_0  0x2c
560 #define PCIR_SUBDEV_0   0x2e
561
562 /****************************** PCI-X definitions *****************************/
563 #define PCIXR_COMMAND   0x96
564 #define PCIXR_DEVADDR   0x98
565 #define PCIXM_DEVADDR_FNUM      0x0003  /* Function Number */
566 #define PCIXM_DEVADDR_DNUM      0x00F8  /* Device Number */
567 #define PCIXM_DEVADDR_BNUM      0xFF00  /* Bus Number */
568 #define PCIXR_STATUS    0x9A
569 #define PCIXM_STATUS_64BIT      0x0001  /* Active 64bit connection to device. */
570 #define PCIXM_STATUS_133CAP     0x0002  /* Device is 133MHz capable */
571 #define PCIXM_STATUS_SCDISC     0x0004  /* Split Completion Discarded */
572 #define PCIXM_STATUS_UNEXPSC    0x0008  /* Unexpected Split Completion */
573 #define PCIXM_STATUS_CMPLEXDEV  0x0010  /* Device Complexity (set == bridge) */
574 #define PCIXM_STATUS_MAXMRDBC   0x0060  /* Maximum Burst Read Count */
575 #define PCIXM_STATUS_MAXSPLITS  0x0380  /* Maximum Split Transactions */
576 #define PCIXM_STATUS_MAXCRDS    0x1C00  /* Maximum Cumulative Read Size */
577 #define PCIXM_STATUS_RCVDSCEM   0x2000  /* Received a Split Comp w/Error msg */
578
579 typedef enum
580 {
581         AHD_POWER_STATE_D0,
582         AHD_POWER_STATE_D1,
583         AHD_POWER_STATE_D2,
584         AHD_POWER_STATE_D3
585 } ahd_power_state;
586
587 void ahd_power_state_change(struct ahd_softc *ahd,
588                             ahd_power_state new_state);
589
590 /******************************* PCI Routines *********************************/
591 int                      ahd_linux_pci_init(void);
592 void                     ahd_linux_pci_exit(void);
593 int                      ahd_pci_map_registers(struct ahd_softc *ahd);
594 int                      ahd_pci_map_int(struct ahd_softc *ahd);
595
596 static __inline uint32_t ahd_pci_read_config(ahd_dev_softc_t pci,
597                                              int reg, int width);
598
599 static __inline uint32_t
600 ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width)
601 {
602         switch (width) {
603         case 1:
604         {
605                 uint8_t retval;
606
607                 pci_read_config_byte(pci, reg, &retval);
608                 return (retval);
609         }
610         case 2:
611         {
612                 uint16_t retval;
613                 pci_read_config_word(pci, reg, &retval);
614                 return (retval);
615         }
616         case 4:
617         {
618                 uint32_t retval;
619                 pci_read_config_dword(pci, reg, &retval);
620                 return (retval);
621         }
622         default:
623                 panic("ahd_pci_read_config: Read size too big");
624                 /* NOTREACHED */
625                 return (0);
626         }
627 }
628
629 static __inline void ahd_pci_write_config(ahd_dev_softc_t pci,
630                                           int reg, uint32_t value,
631                                           int width);
632
633 static __inline void
634 ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width)
635 {
636         switch (width) {
637         case 1:
638                 pci_write_config_byte(pci, reg, value);
639                 break;
640         case 2:
641                 pci_write_config_word(pci, reg, value);
642                 break;
643         case 4:
644                 pci_write_config_dword(pci, reg, value);
645                 break;
646         default:
647                 panic("ahd_pci_write_config: Write size too big");
648                 /* NOTREACHED */
649         }
650 }
651
652 static __inline int ahd_get_pci_function(ahd_dev_softc_t);
653 static __inline int
654 ahd_get_pci_function(ahd_dev_softc_t pci)
655 {
656         return (PCI_FUNC(pci->devfn));
657 }
658
659 static __inline int ahd_get_pci_slot(ahd_dev_softc_t);
660 static __inline int
661 ahd_get_pci_slot(ahd_dev_softc_t pci)
662 {
663         return (PCI_SLOT(pci->devfn));
664 }
665
666 static __inline int ahd_get_pci_bus(ahd_dev_softc_t);
667 static __inline int
668 ahd_get_pci_bus(ahd_dev_softc_t pci)
669 {
670         return (pci->bus->number);
671 }
672
673 static __inline void ahd_flush_device_writes(struct ahd_softc *);
674 static __inline void
675 ahd_flush_device_writes(struct ahd_softc *ahd)
676 {
677         /* XXX Is this sufficient for all architectures??? */
678         ahd_inb(ahd, INTSTAT);
679 }
680
681 /**************************** Proc FS Support *********************************/
682 int     ahd_linux_proc_info(struct Scsi_Host *, char *, char **,
683                             off_t, int, int);
684
685 /*********************** Transaction Access Wrappers **************************/
686 static __inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
687 static __inline void ahd_set_transaction_status(struct scb *, uint32_t);
688 static __inline void ahd_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t);
689 static __inline void ahd_set_scsi_status(struct scb *, uint32_t);
690 static __inline uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd);
691 static __inline uint32_t ahd_get_transaction_status(struct scb *);
692 static __inline uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd);
693 static __inline uint32_t ahd_get_scsi_status(struct scb *);
694 static __inline void ahd_set_transaction_tag(struct scb *, int, u_int);
695 static __inline u_long ahd_get_transfer_length(struct scb *);
696 static __inline int ahd_get_transfer_dir(struct scb *);
697 static __inline void ahd_set_residual(struct scb *, u_long);
698 static __inline void ahd_set_sense_residual(struct scb *scb, u_long resid);
699 static __inline u_long ahd_get_residual(struct scb *);
700 static __inline u_long ahd_get_sense_residual(struct scb *);
701 static __inline int ahd_perform_autosense(struct scb *);
702 static __inline uint32_t ahd_get_sense_bufsize(struct ahd_softc *,
703                                                struct scb *);
704 static __inline void ahd_notify_xfer_settings_change(struct ahd_softc *,
705                                                      struct ahd_devinfo *);
706 static __inline void ahd_platform_scb_free(struct ahd_softc *ahd,
707                                            struct scb *scb);
708 static __inline void ahd_freeze_scb(struct scb *scb);
709
710 static __inline
711 void ahd_cmd_set_transaction_status(struct scsi_cmnd *cmd, uint32_t status)
712 {
713         cmd->result &= ~(CAM_STATUS_MASK << 16);
714         cmd->result |= status << 16;
715 }
716
717 static __inline
718 void ahd_set_transaction_status(struct scb *scb, uint32_t status)
719 {
720         ahd_cmd_set_transaction_status(scb->io_ctx,status);
721 }
722
723 static __inline
724 void ahd_cmd_set_scsi_status(struct scsi_cmnd *cmd, uint32_t status)
725 {
726         cmd->result &= ~0xFFFF;
727         cmd->result |= status;
728 }
729
730 static __inline
731 void ahd_set_scsi_status(struct scb *scb, uint32_t status)
732 {
733         ahd_cmd_set_scsi_status(scb->io_ctx, status);
734 }
735
736 static __inline
737 uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd)
738 {
739         return ((cmd->result >> 16) & CAM_STATUS_MASK);
740 }
741
742 static __inline
743 uint32_t ahd_get_transaction_status(struct scb *scb)
744 {
745         return (ahd_cmd_get_transaction_status(scb->io_ctx));
746 }
747
748 static __inline
749 uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd)
750 {
751         return (cmd->result & 0xFFFF);
752 }
753
754 static __inline
755 uint32_t ahd_get_scsi_status(struct scb *scb)
756 {
757         return (ahd_cmd_get_scsi_status(scb->io_ctx));
758 }
759
760 static __inline
761 void ahd_set_transaction_tag(struct scb *scb, int enabled, u_int type)
762 {
763         /*
764          * Nothing to do for linux as the incoming transaction
765          * has no concept of tag/non tagged, etc.
766          */
767 }
768
769 static __inline
770 u_long ahd_get_transfer_length(struct scb *scb)
771 {
772         return (scb->platform_data->xfer_len);
773 }
774
775 static __inline
776 int ahd_get_transfer_dir(struct scb *scb)
777 {
778         return (scb->io_ctx->sc_data_direction);
779 }
780
781 static __inline
782 void ahd_set_residual(struct scb *scb, u_long resid)
783 {
784         scsi_set_resid(scb->io_ctx, resid);
785 }
786
787 static __inline
788 void ahd_set_sense_residual(struct scb *scb, u_long resid)
789 {
790         scb->platform_data->sense_resid = resid;
791 }
792
793 static __inline
794 u_long ahd_get_residual(struct scb *scb)
795 {
796         return scsi_get_resid(scb->io_ctx);
797 }
798
799 static __inline
800 u_long ahd_get_sense_residual(struct scb *scb)
801 {
802         return (scb->platform_data->sense_resid);
803 }
804
805 static __inline
806 int ahd_perform_autosense(struct scb *scb)
807 {
808         /*
809          * We always perform autosense in Linux.
810          * On other platforms this is set on a
811          * per-transaction basis.
812          */
813         return (1);
814 }
815
816 static __inline uint32_t
817 ahd_get_sense_bufsize(struct ahd_softc *ahd, struct scb *scb)
818 {
819         return (sizeof(struct scsi_sense_data));
820 }
821
822 static __inline void
823 ahd_notify_xfer_settings_change(struct ahd_softc *ahd,
824                                 struct ahd_devinfo *devinfo)
825 {
826         /* Nothing to do here for linux */
827 }
828
829 static __inline void
830 ahd_platform_scb_free(struct ahd_softc *ahd, struct scb *scb)
831 {
832         ahd->flags &= ~AHD_RESOURCE_SHORTAGE;
833 }
834
835 int     ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg);
836 void    ahd_platform_free(struct ahd_softc *ahd);
837 void    ahd_platform_init(struct ahd_softc *ahd);
838 void    ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb);
839
840 static __inline void
841 ahd_freeze_scb(struct scb *scb)
842 {
843         if ((scb->io_ctx->result & (CAM_DEV_QFRZN << 16)) == 0) {
844                 scb->io_ctx->result |= CAM_DEV_QFRZN << 16;
845                 scb->platform_data->dev->qfrozen++;
846         }
847 }
848
849 void    ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev,
850                               struct ahd_devinfo *devinfo, ahd_queue_alg);
851 int     ahd_platform_abort_scbs(struct ahd_softc *ahd, int target,
852                                 char channel, int lun, u_int tag,
853                                 role_t role, uint32_t status);
854 irqreturn_t
855         ahd_linux_isr(int irq, void *dev_id);
856 void    ahd_done(struct ahd_softc*, struct scb*);
857 void    ahd_send_async(struct ahd_softc *, char channel,
858                        u_int target, u_int lun, ac_code);
859 void    ahd_print_path(struct ahd_softc *, struct scb *);
860
861 #ifdef CONFIG_PCI
862 #define AHD_PCI_CONFIG 1
863 #else
864 #define AHD_PCI_CONFIG 0
865 #endif
866 #define bootverbose aic79xx_verbose
867 extern uint32_t aic79xx_verbose;
868
869 #endif /* _AIC79XX_LINUX_H_ */