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_ */
870