aacvar.h revision 198593
141502Swpaul/*-
241502Swpaul * Copyright (c) 2000 Michael Smith
341502Swpaul * Copyright (c) 2001 Scott Long
441502Swpaul * Copyright (c) 2000 BSDi
541502Swpaul * Copyright (c) 2001 Adaptec, Inc.
641502Swpaul * All rights reserved.
741502Swpaul *
841502Swpaul * Redistribution and use in source and binary forms, with or without
941502Swpaul * modification, are permitted provided that the following conditions
1041502Swpaul * are met:
1141502Swpaul * 1. Redistributions of source code must retain the above copyright
1241502Swpaul *    notice, this list of conditions and the following disclaimer.
1341502Swpaul * 2. Redistributions in binary form must reproduce the above copyright
1441502Swpaul *    notice, this list of conditions and the following disclaimer in the
1541502Swpaul *    documentation and/or other materials provided with the distribution.
1641502Swpaul *
1741502Swpaul * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1841502Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1941502Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2041502Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2141502Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2241502Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2341502Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2441502Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2541502Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2641502Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2741502Swpaul * SUCH DAMAGE.
2841502Swpaul *
2941502Swpaul *	$FreeBSD: head/sys/dev/aac/aacvar.h 198593 2009-10-29 14:53:45Z emaste $
3041502Swpaul */
3141502Swpaul
3243515Swpaul#include <sys/bio.h>
3341502Swpaul#include <sys/callout.h>
3441502Swpaul#include <sys/lock.h>
3541502Swpaul#include <sys/mutex.h>
3641502Swpaul#include <sys/taskqueue.h>
3741502Swpaul#include <sys/selinfo.h>
3841502Swpaul#include <geom/geom_disk.h>
3941502Swpaul
4041502Swpaul#ifndef AAC_DRIVER_BUILD
4141502Swpaul# define AAC_DRIVER_BUILD 1
4241502Swpaul#endif
4341502Swpaul
4441502Swpaul/*
4541502Swpaul * Driver Parameter Definitions
4641502Swpaul */
4741502Swpaul
4841502Swpaul/*
4941502Swpaul * The firmware interface allows for a 16-bit s/g list length.  We limit
5041502Swpaul * ourselves to a reasonable maximum and ensure alignment.
5141502Swpaul */
5241502Swpaul#define AAC_MAXSGENTRIES	64	/* max S/G entries, limit 65535 */
5341502Swpaul
5441502Swpaul/*
5541502Swpaul * We allocate a small set of FIBs for the adapter to use to send us messages.
5641502Swpaul */
5741502Swpaul#define AAC_ADAPTER_FIBS	8
5841502Swpaul
5941502Swpaul/*
6041502Swpaul * FIBs are allocated in page-size chunks and can grow up to the 512
6141502Swpaul * limit imposed by the hardware.
6241502Swpaul */
6341502Swpaul#define AAC_PREALLOCATE_FIBS	128
6441502Swpaul#define AAC_NUM_MGT_FIB		8
6541502Swpaul
6641502Swpaul/*
6741502Swpaul * The controller reports status events in AIFs.  We hang on to a number of
6841502Swpaul * these in order to pass them out to user-space management tools.
6941502Swpaul */
7041502Swpaul#define AAC_AIFQ_LENGTH		64
7141502Swpaul
7241502Swpaul/*
7341502Swpaul * Firmware messages are passed in the printf buffer.
7441502Swpaul */
7541502Swpaul#define AAC_PRINTF_BUFSIZE	256
7641502Swpaul
7741502Swpaul/*
7841502Swpaul * We wait this many seconds for the adapter to come ready if it is still
7941502Swpaul * booting
8041502Swpaul */
8141502Swpaul#define AAC_BOOT_TIMEOUT	(3 * 60)
8241502Swpaul
8341502Swpaul/*
8441502Swpaul * Timeout for immediate commands.
8541502Swpaul */
8641502Swpaul#define AAC_IMMEDIATE_TIMEOUT	30		/* seconds */
8741502Swpaul
8841502Swpaul/*
8941502Swpaul * Timeout for normal commands
9041502Swpaul */
9141502Swpaul#define AAC_CMD_TIMEOUT		120		/* seconds */
9241502Swpaul
9341502Swpaul/*
9441502Swpaul * Rate at which we periodically check for timed out commands and kick the
9541502Swpaul * controller.
9641502Swpaul */
9741502Swpaul#define AAC_PERIODIC_INTERVAL	20		/* seconds */
9841502Swpaul
9941502Swpaul/*
10041502Swpaul * Per-container data structure
10141502Swpaul */
10241502Swpaulstruct aac_container
10341502Swpaul{
10441502Swpaul	struct aac_mntobj		co_mntobj;
10541502Swpaul	device_t			co_disk;
10641502Swpaul	int				co_found;
10741502Swpaul	TAILQ_ENTRY(aac_container)	co_link;
10841502Swpaul};
10941502Swpaul
11041502Swpaul/*
11141502Swpaul * Per-SIM data structure
11241502Swpaul */
11341502Swpaulstruct aac_sim
11441502Swpaul{
11541502Swpaul	device_t		sim_dev;
11641502Swpaul	int			TargetsPerBus;
11741502Swpaul	int			BusNumber;
11841502Swpaul	int			InitiatorBusId;
11941502Swpaul	struct aac_softc	*aac_sc;
12041502Swpaul	TAILQ_ENTRY(aac_sim)	sim_link;
12141502Swpaul};
12241502Swpaul
12341633Sarchie/*
12443515Swpaul * Per-disk structure
12541502Swpaul */
12641502Swpaulstruct aac_disk
12741502Swpaul{
12841502Swpaul	device_t			ad_dev;
12941502Swpaul	struct aac_softc		*ad_controller;
13041502Swpaul	struct aac_container		*ad_container;
13141502Swpaul	struct disk			*ad_disk;
13241502Swpaul	int				ad_flags;
13341502Swpaul#define AAC_DISK_OPEN	(1<<0)
13441502Swpaul	int				ad_cylinders;
13541502Swpaul	int				ad_heads;
13641502Swpaul	int				ad_sectors;
13741502Swpaul	u_int64_t			ad_size;
13841502Swpaul	int				unit;
13941502Swpaul};
14041502Swpaul
14141502Swpaul/*
14241502Swpaul * Per-command control structure.
14341502Swpaul */
14441502Swpaulstruct aac_command
14541502Swpaul{
14641502Swpaul	TAILQ_ENTRY(aac_command) cm_link;	/* list linkage */
14741502Swpaul
14841502Swpaul	struct aac_softc	*cm_sc;		/* controller that owns us */
14941502Swpaul
15041502Swpaul	struct aac_fib		*cm_fib;	/* FIB associated with this
15141502Swpaul						 * command */
15241502Swpaul	u_int64_t		cm_fibphys;	/* bus address of the FIB */
15341502Swpaul	struct bio		*cm_data;	/* pointer to data in kernel
15441502Swpaul						 * space */
15541771Sdillon	u_int32_t		cm_datalen;	/* data length */
15641502Swpaul	bus_dmamap_t		cm_datamap;	/* DMA map for bio data */
15741502Swpaul	struct aac_sg_table	*cm_sgtable;	/* pointer to s/g table in
15841502Swpaul						 * command */
15941502Swpaul	int			cm_flags;
16041502Swpaul#define AAC_CMD_MAPPED		(1<<0)		/* command has had its data
16141502Swpaul						 * mapped */
16241502Swpaul#define AAC_CMD_DATAIN		(1<<1)		/* command involves data moving
16341502Swpaul						 * from controller to host */
16441502Swpaul#define AAC_CMD_DATAOUT		(1<<2)		/* command involves data moving
16541502Swpaul						 * from host to controller */
16641502Swpaul#define AAC_CMD_COMPLETED	(1<<3)		/* command has been completed */
16741502Swpaul#define AAC_CMD_TIMEDOUT	(1<<4)		/* command taken too long */
16841502Swpaul#define AAC_ON_AACQ_FREE	(1<<5)
16941502Swpaul#define AAC_ON_AACQ_READY	(1<<6)
17041502Swpaul#define AAC_ON_AACQ_BUSY	(1<<7)
17141502Swpaul#define AAC_ON_AACQ_AIF		(1<<8)
17241502Swpaul#define AAC_ON_AACQ_NORM	(1<<10)
17341502Swpaul#define AAC_ON_AACQ_MASK	((1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<10))
17441502Swpaul#define AAC_QUEUE_FRZN		(1<<9)		/* Freeze the processing of
17541502Swpaul						 * commands on the queue. */
17641502Swpaul
17742718Swpaul	void			(* cm_complete)(struct aac_command *cm);
17842718Swpaul	void			*cm_private;
17941502Swpaul	time_t			cm_timestamp;	/* command creation time */
18041502Swpaul	int			cm_queue;
18141502Swpaul	int			cm_index;
18241502Swpaul};
18341502Swpaul
18441502Swpaulstruct aac_fibmap {
18541502Swpaul	TAILQ_ENTRY(aac_fibmap) fm_link;	/* list linkage */
18642718Swpaul	struct aac_fib		*aac_fibs;
18741502Swpaul	bus_dmamap_t		aac_fibmap;
18841502Swpaul	struct aac_command	*aac_commands;
18941502Swpaul};
19041502Swpaul
19141502Swpaul/*
19242718Swpaul * We gather a number of adapter-visible items into a single structure.
19342718Swpaul *
19441502Swpaul * The ordering of this strucure may be important; we copy the Linux driver:
19541502Swpaul *
19641502Swpaul * Adapter FIBs
19741502Swpaul * Init struct
19841502Swpaul * Queue headers (Comm Area)
19941502Swpaul * Printf buffer
20041502Swpaul *
20141502Swpaul * In addition, we add:
20241502Swpaul * Sync Fib
20341502Swpaul */
20441502Swpaulstruct aac_common {
20541502Swpaul	/* fibs for the controller to send us messages */
20641502Swpaul	struct aac_fib		ac_fibs[AAC_ADAPTER_FIBS];
20741502Swpaul
20841502Swpaul	/* the init structure */
20941502Swpaul	struct aac_adapter_init	ac_init;
21041502Swpaul
21141502Swpaul	/* arena within which the queue structures are kept */
21241502Swpaul	u_int8_t		ac_qbuf[sizeof(struct aac_queue_table) +
21341502Swpaul				AAC_QUEUE_ALIGN];
21441502Swpaul
21541502Swpaul	/* buffer for text messages from the controller */
21641502Swpaul	char		       	ac_printf[AAC_PRINTF_BUFSIZE];
21741502Swpaul
21841502Swpaul	/* fib for synchronous commands */
21941502Swpaul	struct aac_fib		ac_sync_fib;
22042718Swpaul};
22141502Swpaul
22241502Swpaul/*
22341502Swpaul * Interface operations
22441502Swpaul */
22541502Swpaulstruct aac_interface
22641502Swpaul{
22741502Swpaul	int	(*aif_get_fwstatus)(struct aac_softc *sc);
22841502Swpaul	void	(*aif_qnotify)(struct aac_softc *sc, int qbit);
22941502Swpaul	int	(*aif_get_istatus)(struct aac_softc *sc);
23041502Swpaul	void	(*aif_clr_istatus)(struct aac_softc *sc, int mask);
23141502Swpaul	void	(*aif_set_mailbox)(struct aac_softc *sc, u_int32_t command,
23241502Swpaul				   u_int32_t arg0, u_int32_t arg1,
23341502Swpaul				   u_int32_t arg2, u_int32_t arg3);
23441502Swpaul	int	(*aif_get_mailbox)(struct aac_softc *sc, int mb);
23541502Swpaul	void	(*aif_set_interrupts)(struct aac_softc *sc, int enable);
23641502Swpaul	int (*aif_send_command)(struct aac_softc *sc, struct aac_command *cm);
23741502Swpaul	int (*aif_get_outb_queue)(struct aac_softc *sc);
23841502Swpaul	void (*aif_set_outb_queue)(struct aac_softc *sc, int index);
23941502Swpaul};
24041502Swpaulextern struct aac_interface	aac_rx_interface;
24141502Swpaulextern struct aac_interface	aac_sa_interface;
24241502Swpaulextern struct aac_interface	aac_fa_interface;
24341502Swpaulextern struct aac_interface	aac_rkt_interface;
24441502Swpaul
24541502Swpaul#define AAC_GET_FWSTATUS(sc)		((sc)->aac_if.aif_get_fwstatus((sc)))
24641502Swpaul#define AAC_QNOTIFY(sc, qbit)		((sc)->aac_if.aif_qnotify((sc), (qbit)))
24741502Swpaul#define AAC_GET_ISTATUS(sc)		((sc)->aac_if.aif_get_istatus((sc)))
24841502Swpaul#define AAC_CLEAR_ISTATUS(sc, mask)	((sc)->aac_if.aif_clr_istatus((sc), \
24941502Swpaul					(mask)))
25042718Swpaul#define AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3) \
25141502Swpaul	((sc)->aac_if.aif_set_mailbox((sc), (command), (arg0), (arg1), (arg2), \
25241502Swpaul	(arg3)))
25341502Swpaul#define AAC_GET_MAILBOX(sc, mb)		((sc)->aac_if.aif_get_mailbox((sc), \
25441502Swpaul					(mb)))
25541502Swpaul#define	AAC_MASK_INTERRUPTS(sc)		((sc)->aac_if.aif_set_interrupts((sc), \
25641502Swpaul					0))
25741502Swpaul#define AAC_UNMASK_INTERRUPTS(sc)	((sc)->aac_if.aif_set_interrupts((sc), \
25841502Swpaul					1))
25941502Swpaul#define AAC_SEND_COMMAND(sc, cm)	((sc)->aac_if.aif_send_command((sc), (cm)))
26041502Swpaul#define AAC_GET_OUTB_QUEUE(sc)		((sc)->aac_if.aif_get_outb_queue((sc)))
26141502Swpaul#define AAC_SET_OUTB_QUEUE(sc, idx)	((sc)->aac_if.aif_set_outb_queue((sc), (idx)))
26241502Swpaul
26341502Swpaul#define AAC_MEM0_SETREG4(sc, reg, val)	bus_space_write_4(sc->aac_btag0, \
26441502Swpaul					sc->aac_bhandle0, reg, val)
26541502Swpaul#define AAC_MEM0_GETREG4(sc, reg)	bus_space_read_4(sc->aac_btag0, \
26641502Swpaul					sc->aac_bhandle0, reg)
26741502Swpaul#define AAC_MEM0_SETREG2(sc, reg, val)	bus_space_write_2(sc->aac_btag0, \
26841502Swpaul					sc->aac_bhandle0, reg, val)
26941502Swpaul#define AAC_MEM0_GETREG2(sc, reg)	bus_space_read_2(sc->aac_btag0, \
27041502Swpaul					sc->aac_bhandle0, reg)
27141502Swpaul#define AAC_MEM0_SETREG1(sc, reg, val)	bus_space_write_1(sc->aac_btag0, \
27241502Swpaul					sc->aac_bhandle0, reg, val)
27341502Swpaul#define AAC_MEM0_GETREG1(sc, reg)	bus_space_read_1(sc->aac_btag0, \
27441502Swpaul					sc->aac_bhandle0, reg)
27541502Swpaul
27641502Swpaul#define AAC_MEM1_SETREG4(sc, reg, val)	bus_space_write_4(sc->aac_btag1, \
27741502Swpaul					sc->aac_bhandle1, reg, val)
27841502Swpaul#define AAC_MEM1_GETREG4(sc, reg)	bus_space_read_4(sc->aac_btag1, \
27941502Swpaul					sc->aac_bhandle1, reg)
28041502Swpaul#define AAC_MEM1_SETREG2(sc, reg, val)	bus_space_write_2(sc->aac_btag1, \
28141502Swpaul					sc->aac_bhandle1, reg, val)
28241502Swpaul#define AAC_MEM1_GETREG2(sc, reg)	bus_space_read_2(sc->aac_btag1, \
28341502Swpaul					sc->aac_bhandle1, reg)
28441502Swpaul#define AAC_MEM1_SETREG1(sc, reg, val)	bus_space_write_1(sc->aac_btag1, \
28541502Swpaul					sc->aac_bhandle1, reg, val)
28641502Swpaul#define AAC_MEM1_GETREG1(sc, reg)	bus_space_read_1(sc->aac_btag1, \
28741502Swpaul					sc->aac_bhandle1, reg)
28841502Swpaul
28941502Swpaul/* fib context (IOCTL) */
29041502Swpaulstruct aac_fib_context {
29141502Swpaul	u_int32_t		unique;
29241502Swpaul	int			ctx_idx;
29341502Swpaul	int			ctx_wrap;
29441502Swpaul	struct aac_fib_context *next, *prev;
29541502Swpaul};
29641502Swpaul
29741502Swpaul/*
29841502Swpaul * Per-controller structure.
29941502Swpaul */
30041502Swpaulstruct aac_softc
30141502Swpaul{
30241502Swpaul	/* bus connections */
30341502Swpaul	device_t		aac_dev;
30441502Swpaul	struct resource		*aac_regs_res0, *aac_regs_res1; /* reg. if. window */
30541502Swpaul	int			aac_regs_rid0, aac_regs_rid1;		/* resource ID */
30641502Swpaul	bus_space_handle_t	aac_bhandle0, aac_bhandle1;		/* bus space handle */
30741502Swpaul	bus_space_tag_t		aac_btag0, aac_btag1;		/* bus space tag */
30841502Swpaul	bus_dma_tag_t		aac_parent_dmat;	/* parent DMA tag */
30941502Swpaul	bus_dma_tag_t		aac_buffer_dmat;	/* data buffer/command
31041502Swpaul							 * DMA tag */
31141502Swpaul	struct resource		*aac_irq;		/* interrupt */
31241502Swpaul	int			aac_irq_rid;
31341502Swpaul	void			*aac_intr;		/* interrupt handle */
31441502Swpaul	eventhandler_tag	eh;
31541502Swpaul
31641502Swpaul	/* controller features, limits and status */
31741502Swpaul	int			aac_state;
31841502Swpaul#define AAC_STATE_SUSPEND	(1<<0)
31941502Swpaul#define	AAC_STATE_OPEN		(1<<1)
32041502Swpaul#define AAC_STATE_INTERRUPTS_ON	(1<<2)
32141502Swpaul#define AAC_STATE_AIF_SLEEPER	(1<<3)
32241502Swpaul	int			aac_open_cnt;
32341502Swpaul	struct FsaRevision		aac_revision;
32441502Swpaul
32541502Swpaul	/* controller hardware interface */
32641502Swpaul	int			aac_hwif;
32741502Swpaul#define AAC_HWIF_I960RX		0
32841502Swpaul#define AAC_HWIF_STRONGARM	1
32941502Swpaul#define AAC_HWIF_FALCON		2
33041502Swpaul#define AAC_HWIF_RKT		3
33141502Swpaul#define	AAC_HWIF_NARK		4
33241502Swpaul#define AAC_HWIF_UNKNOWN	-1
33341502Swpaul	bus_dma_tag_t		aac_common_dmat;	/* common structure
33441502Swpaul							 * DMA tag */
33541502Swpaul	bus_dmamap_t		aac_common_dmamap;	/* common structure
33641502Swpaul							 * DMA map */
33741502Swpaul	struct aac_common	*aac_common;
33841502Swpaul	u_int32_t		aac_common_busaddr;
33941502Swpaul	struct aac_interface	aac_if;
34041502Swpaul
34141502Swpaul	/* command/fib resources */
34241502Swpaul	bus_dma_tag_t		aac_fib_dmat;	/* DMA tag for allocing FIBs */
34341502Swpaul	TAILQ_HEAD(,aac_fibmap)	aac_fibmap_tqh;
34441502Swpaul	u_int			total_fibs;
34541502Swpaul	struct aac_command	*aac_commands;
34641502Swpaul
34741502Swpaul	/* command management */
34841502Swpaul	TAILQ_HEAD(,aac_command) aac_free;	/* command structures
34941502Swpaul						 * available for reuse */
35041502Swpaul	TAILQ_HEAD(,aac_command) aac_ready;	/* commands on hold for
35141502Swpaul						 * controller resources */
35241502Swpaul	TAILQ_HEAD(,aac_command) aac_busy;
35341502Swpaul	TAILQ_HEAD(,aac_event)	aac_ev_cmfree;
35441502Swpaul	struct bio_queue_head	aac_bioq;
35541502Swpaul	struct aac_queue_table	*aac_queues;
35641502Swpaul	struct aac_queue_entry	*aac_qentries[AAC_QUEUE_COUNT];
35741502Swpaul
35841502Swpaul	struct aac_qstat	aac_qstat[AACQ_COUNT];	/* queue statistics */
35941502Swpaul
36041502Swpaul	/* connected containters */
36141502Swpaul	TAILQ_HEAD(,aac_container)	aac_container_tqh;
36241502Swpaul	struct mtx		aac_container_lock;
36341502Swpaul
36441502Swpaul	/*
36541502Swpaul	 * The general I/O lock.  This protects the sync fib, the lists, the
36641502Swpaul	 * queues, and the registers.
36741502Swpaul	 */
36841502Swpaul	struct mtx		aac_io_lock;
36941502Swpaul
37041502Swpaul	/* delayed activity infrastructure */
37141502Swpaul	struct task		aac_task_complete;	/* deferred-completion
37241502Swpaul							 * task */
37341502Swpaul	struct intr_config_hook	aac_ich;
37441502Swpaul
37541502Swpaul	/* management interface */
37641502Swpaul	struct cdev *aac_dev_t;
37741502Swpaul	struct mtx		aac_aifq_lock;
37841502Swpaul	struct aac_fib		aac_aifq[AAC_AIFQ_LENGTH];
37941502Swpaul	int			aifq_idx;
38041502Swpaul	int			aifq_filled;
38141502Swpaul	struct aac_fib_context *fibctx;
38241502Swpaul	struct selinfo		rcv_select;
38341502Swpaul	struct proc		*aifthread;
38441502Swpaul	int			aifflags;
38541502Swpaul#define AAC_AIFFLAGS_RUNNING	(1 << 0)
38641502Swpaul#define AAC_AIFFLAGS_AIF	(1 << 1)
38741502Swpaul#define	AAC_AIFFLAGS_EXIT	(1 << 2)
38841502Swpaul#define AAC_AIFFLAGS_EXITED	(1 << 3)
38941502Swpaul#define AAC_AIFFLAGS_PRINTF	(1 << 4)
39041502Swpaul#define	AAC_AIFFLAGS_ALLOCFIBS	(1 << 5)
39141502Swpaul#define AAC_AIFFLAGS_PENDING	(AAC_AIFFLAGS_AIF | AAC_AIFFLAGS_PRINTF | \
39241502Swpaul				 AAC_AIFFLAGS_ALLOCFIBS)
39341502Swpaul	u_int32_t		flags;
39441502Swpaul#define AAC_FLAGS_PERC2QC	(1 << 0)
39541502Swpaul#define	AAC_FLAGS_ENABLE_CAM	(1 << 1)	/* No SCSI passthrough */
39641502Swpaul#define	AAC_FLAGS_CAM_NORESET	(1 << 2)	/* Fake SCSI resets */
39741502Swpaul#define	AAC_FLAGS_CAM_PASSONLY	(1 << 3)	/* Only create pass devices */
39841502Swpaul#define	AAC_FLAGS_SG_64BIT	(1 << 4)	/* Use 64-bit S/G addresses */
39941502Swpaul#define	AAC_FLAGS_4GB_WINDOW	(1 << 5)	/* Device can access host mem
40041502Swpaul						 * 2GB-4GB range */
40141502Swpaul#define	AAC_FLAGS_NO4GB		(1 << 6)	/* Can't access host mem >2GB */
40241502Swpaul#define	AAC_FLAGS_256FIBS	(1 << 7)	/* Can only do 256 commands */
40341502Swpaul#define	AAC_FLAGS_BROKEN_MEMMAP (1 << 8)	/* Broken HostPhysMemPages */
40441502Swpaul#define AAC_FLAGS_SLAVE	(1 << 9)
40541502Swpaul#define AAC_FLAGS_MASTER	(1 << 10)
40641502Swpaul#define AAC_FLAGS_NEW_COMM	(1 << 11)	/* New comm. interface supported */
40741502Swpaul#define AAC_FLAGS_RAW_IO	(1 << 12)	/* Raw I/O interface */
40841502Swpaul#define AAC_FLAGS_ARRAY_64BIT	(1 << 13)	/* 64-bit array size */
40941502Swpaul#define	AAC_FLAGS_LBA_64BIT	(1 << 14)	/* 64-bit LBA support */
41041502Swpaul
41141502Swpaul	u_int32_t		supported_options;
41241502Swpaul	u_int32_t		scsi_method_id;
41341502Swpaul	TAILQ_HEAD(,aac_sim)	aac_sim_tqh;
41441502Swpaul
41541502Swpaul	struct callout	aac_daemontime;		/* clock daemon callout */
41641502Swpaul
41741502Swpaul	u_int32_t	aac_max_fibs;           /* max. FIB count */
41841502Swpaul	u_int32_t	aac_max_fibs_alloc;		/* max. alloc. per alloc_commands() */
41941502Swpaul	u_int32_t	aac_max_fib_size;		/* max. FIB size */
42041502Swpaul	u_int32_t	aac_sg_tablesize;		/* max. sg count from host */
42141502Swpaul	u_int32_t	aac_max_sectors;		/* max. I/O size from host (blocks) */
42241502Swpaul};
42341502Swpaul
42441502Swpaul/*
42541502Swpaul * Event callback mechanism for the driver
42641502Swpaul */
42741502Swpaul#define AAC_EVENT_NONE		0x00
42841502Swpaul#define AAC_EVENT_CMFREE	0x01
42941502Swpaul#define	AAC_EVENT_MASK		0xff
43041502Swpaul#define AAC_EVENT_REPEAT	0x100
43141502Swpaul
43241502Swpaultypedef void aac_event_cb_t(struct aac_softc *sc, struct aac_event *event,
43341502Swpaul    void *arg);
43441502Swpaulstruct aac_event {
43541502Swpaul	TAILQ_ENTRY(aac_event)	ev_links;
43641502Swpaul	int			ev_type;
43741502Swpaul	aac_event_cb_t		*ev_callback;
43841502Swpaul	void			*ev_arg;
43941502Swpaul};
44041502Swpaul
44141502Swpaul/*
44241502Swpaul * Public functions
44341502Swpaul */
44441502Swpaulextern void		aac_free(struct aac_softc *sc);
44541502Swpaulextern int		aac_attach(struct aac_softc *sc);
44641502Swpaulextern int		aac_detach(device_t dev);
44741502Swpaulextern int		aac_shutdown(device_t dev);
44841502Swpaulextern int		aac_suspend(device_t dev);
44941502Swpaulextern int		aac_resume(device_t dev);
45041502Swpaulextern void		aac_new_intr(void *arg);
45141502Swpaulextern int		aac_filter(void *arg);
45241502Swpaulextern void		aac_submit_bio(struct bio *bp);
45341502Swpaulextern void		aac_biodone(struct bio *bp);
45441502Swpaulextern void		aac_startio(struct aac_softc *sc);
45541502Swpaulextern int		aac_alloc_command(struct aac_softc *sc,
45641502Swpaul					  struct aac_command **cmp);
45741502Swpaulextern void		aac_release_command(struct aac_command *cm);
45841502Swpaulextern int		aac_sync_fib(struct aac_softc *sc, u_int32_t command,
45941502Swpaul				     u_int32_t xferstate, struct aac_fib *fib,
46041502Swpaul				     u_int16_t datasize);
46141502Swpaulextern void		aac_add_event(struct aac_softc *sc, struct aac_event
46241502Swpaul				      *event);
46341502Swpaul
46441502Swpaul#ifdef AAC_DEBUG
46541502Swpaulextern int	aac_debug_enable;
46641502Swpaul# define fwprintf(sc, flags, fmt, args...)				\
46741502Swpauldo {									\
46841502Swpaul	if (!aac_debug_enable)						\
46941502Swpaul		break;							\
47041502Swpaul	if (sc != NULL)							\
47141502Swpaul		device_printf(((struct aac_softc *)sc)->aac_dev,	\
47241502Swpaul		    "%s: " fmt "\n", __func__, ##args);			\
47341502Swpaul	else								\
47441502Swpaul		printf("%s: " fmt "\n", __func__, ##args);		\
47541502Swpaul} while(0)
47641502Swpaul
47741502Swpaulextern void	aac_print_queues(struct aac_softc *sc);
47841502Swpaulextern void	aac_panic(struct aac_softc *sc, char *reason);
47941502Swpaulextern void	aac_print_fib(struct aac_softc *sc, struct aac_fib *fib,
48041502Swpaul			      const char *caller);
48141502Swpaulextern void	aac_print_aif(struct aac_softc *sc,
48241502Swpaul			      struct aac_aif_command *aif);
48341502Swpaul
48441502Swpaul#define AAC_PRINT_FIB(sc, fib)	aac_print_fib(sc, fib, __func__)
48541502Swpaul
48641502Swpaul#else
48741502Swpaul# define fwprintf(sc, flags, fmt, args...)
48841502Swpaul
48941502Swpaul# define aac_print_queues(sc)
49041502Swpaul# define aac_panic(sc, reason)
49141502Swpaul
49241502Swpaul# define AAC_PRINT_FIB(sc, fib)
49341502Swpaul# define aac_print_aif(sc, aac_aif_command)
49441502Swpaul#endif
49541502Swpaul
49641502Swpaulstruct aac_code_lookup {
49741502Swpaul	char	*string;
49841502Swpaul	u_int32_t	code;
49941502Swpaul};
50041502Swpaul
50141502Swpaul/*
50241502Swpaul * Queue primitives for driver queues.
50341502Swpaul */
50441502Swpaul#define AACQ_ADD(sc, qname)					\
50541502Swpaul	do {							\
50641502Swpaul		struct aac_qstat *qs;				\
50741502Swpaul								\
50841502Swpaul		qs = &(sc)->aac_qstat[qname];			\
50941502Swpaul								\
51041502Swpaul		qs->q_length++;					\
51141502Swpaul		if (qs->q_length > qs->q_max)			\
51241502Swpaul			qs->q_max = qs->q_length;		\
51341502Swpaul	} while (0)
51441502Swpaul
51541502Swpaul#define AACQ_REMOVE(sc, qname)    (sc)->aac_qstat[qname].q_length--
51641502Swpaul#define AACQ_INIT(sc, qname)				\
51741502Swpaul	do {						\
51842718Swpaul		sc->aac_qstat[qname].q_length = 0;	\
51942718Swpaul		sc->aac_qstat[qname].q_max = 0;		\
52041502Swpaul	} while (0)
52141502Swpaul
52241502Swpaul
52341502Swpaul#define AACQ_COMMAND_QUEUE(name, index)					\
52441502Swpaulstatic __inline void							\
52541502Swpaulaac_initq_ ## name (struct aac_softc *sc)				\
52641502Swpaul{									\
52741502Swpaul	TAILQ_INIT(&sc->aac_ ## name);					\
52841502Swpaul	AACQ_INIT(sc, index);						\
52941502Swpaul}									\
53041502Swpaulstatic __inline void							\
53141502Swpaulaac_enqueue_ ## name (struct aac_command *cm)				\
53241502Swpaul{									\
53341502Swpaul	if ((cm->cm_flags & AAC_ON_AACQ_MASK) != 0) {			\
53441502Swpaul		printf("command %p is on another queue, flags = %#x\n",	\
53542718Swpaul		       cm, cm->cm_flags);				\
53641502Swpaul		panic("command is on another queue");			\
53741502Swpaul	}								\
53841502Swpaul	TAILQ_INSERT_TAIL(&cm->cm_sc->aac_ ## name, cm, cm_link);	\
53941502Swpaul	cm->cm_flags |= AAC_ON_ ## index;				\
54041502Swpaul	AACQ_ADD(cm->cm_sc, index);					\
54141502Swpaul}									\
54241502Swpaulstatic __inline void							\
54341502Swpaulaac_requeue_ ## name (struct aac_command *cm)				\
54441502Swpaul{									\
54541502Swpaul	if ((cm->cm_flags & AAC_ON_AACQ_MASK) != 0) {			\
54641502Swpaul		printf("command %p is on another queue, flags = %#x\n",	\
54741502Swpaul		       cm, cm->cm_flags);				\
54841502Swpaul		panic("command is on another queue");			\
54941502Swpaul	}								\
55041502Swpaul	TAILQ_INSERT_HEAD(&cm->cm_sc->aac_ ## name, cm, cm_link);	\
55141502Swpaul	cm->cm_flags |= AAC_ON_ ## index;				\
55241502Swpaul	AACQ_ADD(cm->cm_sc, index);					\
55341502Swpaul}									\
55441502Swpaulstatic __inline struct aac_command *					\
55541502Swpaulaac_dequeue_ ## name (struct aac_softc *sc)				\
55641502Swpaul{									\
55741502Swpaul	struct aac_command *cm;						\
55841502Swpaul									\
55941502Swpaul	if ((cm = TAILQ_FIRST(&sc->aac_ ## name)) != NULL) {		\
56041502Swpaul		if ((cm->cm_flags & AAC_ON_ ## index) == 0) {		\
56141502Swpaul			printf("command %p not in queue, flags = %#x, "	\
56241502Swpaul		       	       "bit = %#x\n", cm, cm->cm_flags,		\
56341502Swpaul			       AAC_ON_ ## index);			\
56441502Swpaul			panic("command not in queue");			\
56541502Swpaul		}							\
56641502Swpaul		TAILQ_REMOVE(&sc->aac_ ## name, cm, cm_link);		\
56741502Swpaul		cm->cm_flags &= ~AAC_ON_ ## index;			\
56841502Swpaul		AACQ_REMOVE(sc, index);					\
56941502Swpaul	}								\
57041502Swpaul	return(cm);							\
57141502Swpaul}									\
57241502Swpaulstatic __inline void							\
57341502Swpaulaac_remove_ ## name (struct aac_command *cm)				\
57441502Swpaul{									\
57541502Swpaul	if ((cm->cm_flags & AAC_ON_ ## index) == 0) {			\
57641502Swpaul		printf("command %p not in queue, flags = %#x, "		\
57741502Swpaul		       "bit = %#x\n", cm, cm->cm_flags, 		\
57841502Swpaul		       AAC_ON_ ## index);				\
57941502Swpaul		panic("command not in queue");				\
58041502Swpaul	}								\
58141502Swpaul	TAILQ_REMOVE(&cm->cm_sc->aac_ ## name, cm, cm_link);		\
58241502Swpaul	cm->cm_flags &= ~AAC_ON_ ## index;				\
58341502Swpaul	AACQ_REMOVE(cm->cm_sc, index);					\
58441502Swpaul}									\
58541502Swpaulstruct hack
58641502Swpaul
58741502SwpaulAACQ_COMMAND_QUEUE(free, AACQ_FREE);
58841502SwpaulAACQ_COMMAND_QUEUE(ready, AACQ_READY);
58941502SwpaulAACQ_COMMAND_QUEUE(busy, AACQ_BUSY);
59041502Swpaul
59141502Swpaul/*
59241502Swpaul * outstanding bio queue
59341502Swpaul */
59441502Swpaulstatic __inline void
59541502Swpaulaac_initq_bio(struct aac_softc *sc)
59641502Swpaul{
59741502Swpaul	bioq_init(&sc->aac_bioq);
59841502Swpaul	AACQ_INIT(sc, AACQ_BIO);
59941502Swpaul}
60041502Swpaul
60141502Swpaulstatic __inline void
60241502Swpaulaac_enqueue_bio(struct aac_softc *sc, struct bio *bp)
60341502Swpaul{
60441502Swpaul	bioq_insert_tail(&sc->aac_bioq, bp);
60541502Swpaul	AACQ_ADD(sc, AACQ_BIO);
60641502Swpaul}
60741502Swpaul
60841502Swpaulstatic __inline struct bio *
60941502Swpaulaac_dequeue_bio(struct aac_softc *sc)
61041502Swpaul{
61141502Swpaul	struct bio *bp;
61241502Swpaul
61341502Swpaul	if ((bp = bioq_first(&sc->aac_bioq)) != NULL) {
61441502Swpaul		bioq_remove(&sc->aac_bioq, bp);
61541502Swpaul		AACQ_REMOVE(sc, AACQ_BIO);
61641502Swpaul	}
61741502Swpaul	return(bp);
61841502Swpaul}
61941502Swpaul
62041502Swpaulstatic __inline void
62141502Swpaulaac_print_printf(struct aac_softc *sc)
62241502Swpaul{
62341502Swpaul	/*
62441502Swpaul	 * XXX We have the ability to read the length of the printf string
62541502Swpaul	 * from out of the mailboxes.
62641502Swpaul	 */
62741502Swpaul	device_printf(sc->aac_dev, "**Monitor** %.*s", AAC_PRINTF_BUFSIZE,
62841502Swpaul		      sc->aac_common->ac_printf);
62941502Swpaul	sc->aac_common->ac_printf[0] = 0;
63041502Swpaul	AAC_QNOTIFY(sc, AAC_DB_PRINTF);
63141502Swpaul}
63241502Swpaul
63341502Swpaulstatic __inline int
63441502Swpaulaac_alloc_sync_fib(struct aac_softc *sc, struct aac_fib **fib)
63541502Swpaul{
63641502Swpaul
63741502Swpaul	mtx_assert(&sc->aac_io_lock, MA_OWNED);
63841502Swpaul	*fib = &sc->aac_common->ac_sync_fib;
63941502Swpaul	return (0);
64041502Swpaul}
64141502Swpaul
64241502Swpaulstatic __inline void
64341502Swpaulaac_release_sync_fib(struct aac_softc *sc)
64441502Swpaul{
64541502Swpaul
64641502Swpaul	mtx_assert(&sc->aac_io_lock, MA_OWNED);
64741502Swpaul}
64841502Swpaul
64941502Swpaul