1/*
2 * Copyright (c) 2004-2005 HighPoint Technologies, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28#ifndef _COMMAND_H_
29#define _COMMAND_H_
30
31/***************************************************************************
32 * Description: Command
33 ***************************************************************************/
34typedef struct _AtaCommand
35{
36	LBA_T            Lba;          /* Current Logic Disk command: LBA   */
37	USHORT           nSectors;     /* sector count. May great than 0x80 */
38	UCHAR            Command;      /* IDE_COMMAND_READ, _WRITE, _VERIFY */
39	UCHAR            QueueTag;
40} AtaComm, *PAtaComm;
41
42typedef struct _PassthroughCmd {
43	BYTE     bFeaturesReg;     /* feature register */
44	BYTE     bSectorCountReg;  /* IDE sector count register. */
45	BYTE     bLbaLowReg; /* IDE sector number register. */
46	BYTE     bLbaMidReg;       /* IDE low order cylinder value. */
47	BYTE     bLbaHighReg;      /* IDE high order cylinder value. */
48	BYTE     bDriveHeadReg;    /* IDE drive/head register. */
49	BYTE     bCommandReg;      /* Actual IDE command. Checked for validity by driver. */
50	BYTE     nSectors;         /* data transfer */
51	ADDRESS  pDataBuffer;      /* data buffer */
52}
53PassthroughCmd;
54
55/* control commands */
56#define CTRL_CMD_REBUILD 1
57#define CTRL_CMD_VERIFY  2
58#define CTRL_CMD_INIT    3
59
60/*
61 * RAID5 rebuild/verify
62 *   Rebuild/verify one stripe line.
63 *   The caller needn't supply a buffer for rebuild.
64 *   RebuildSectors member will be updated if its previous location is the
65 *   begin of this stripe line.
66 */
67typedef struct _R5ControlCmd {
68	LBA_T  StripeLine;   /* _physical_ stripe line on array */
69	USHORT Offset;       /* internal use, don't set */
70	UCHAR  Command;      /* CTRL_CMD_XXX */
71	UCHAR  reserve1;
72}
73R5ControlCmd, *PR5ControlCmd;
74
75/*
76 * RAID1 rebuild/verify
77 *   Rebuild/verify specified sectors.
78 *   The caller must supply a valid buffer and a physical SG table (or a
79 *   pfnBuildSgl routine).
80 *   For rebuild/initialize, the buffer size should be nSectors<<9;
81 *   For verify, the buffer size should be (nSectors*2)<<9.
82 *   RebuildSectors member will be updated if its previous value equals Lba.
83 */
84typedef struct _R1ControlCmd {
85	LBA_T  Lba;
86	USHORT nSectors;
87	UCHAR  Command;      /* CTRL_CMD_XXX */
88	UCHAR  reserve1;
89	ADDRESS Buffer;  /* buffer logical address */
90#ifdef _MACOSX_
91	ADDRESS PhysicalAddress;
92#endif
93}
94R1ControlCmd, *PR1ControlCmd;
95
96typedef struct _Command
97{
98	PVDevice pVDevice;
99	union{
100		/* Ide Command */
101		AtaComm Ide;
102		PassthroughCmd Passthrough;
103		/* Atapi Command */
104		UCHAR Atapi[12];
105		/* Control command */
106		R5ControlCmd R5Control;
107		R1ControlCmd R1Control;
108	} uCmd;
109
110	USHORT	cf_physical_sg: 1;
111	USHORT	cf_data_in: 1;
112	USHORT	cf_data_out: 1;
113	USHORT	cf_atapi: 1;
114	USHORT	cf_ide_passthrough: 1;
115	USHORT  cf_control: 1;
116
117	/* return status */
118	UCHAR	Result;
119	/* retry count */
120	UCHAR   RetryCount;
121
122	/* S/G table address, if already prepared */
123	FPSCAT_GATH pSgTable;
124
125	/* called if pSgTable is invalid. */
126	int (* HPTLIBAPI pfnBuildSgl)(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical);
127
128	/* called when this command is finished */
129	void (* HPTLIBAPI pfnCompletion)(_VBUS_ARG PCommand pCmd);
130
131	/* pointer to original command */
132	void *pOrgCommand;
133
134
135	/* scratch data area */
136	union {
137		struct {
138			LBA_T      StartLBA;
139			UCHAR      FirstMember;    /* the sequence number of the first member */
140			UCHAR      LastMember;     /* the sequence number of the last member */
141			USHORT     LastSectors;    /* the number of sectors for the last member */
142			USHORT     FirstSectors;   /* the number of sectors for the first member */
143			USHORT     FirstOffset;    /* the offset from the StartLBA for the first member */
144			USHORT     AllMemberBlocks;/* the number of sectors for all member */
145			USHORT     WaitInterrupt;  /* bit map the members who wait interrupt */
146			UCHAR      InSameLine;     /* if the start and end on the same line */
147			UCHAR      pad1;
148		} array;
149		struct {
150			LBA_T      StartLBA;
151			USHORT     FirstSectors;   /* the number of sectors for the first member */
152			USHORT     FirstOffset;    /* the offset from the StartLBA for the first member */
153			USHORT     WaitInterrupt;  /* bit map the members who wait interrupt */
154			USHORT     r5_gap;         /* see raid5.c */
155			UCHAR      ParDiskNo;      /* parity for startLba */
156			UCHAR      BadDiskNo;
157			UCHAR      FirstMember;
158			UCHAR      pad1;
159		} r5;
160		struct {
161			PCommand pCmd1;
162			PCommand pCmd2;
163		} r5split;
164#ifdef _RAID5N_
165		struct {
166			ULONG dummy[2]; /* uScratch.wait shall be moved out uScratch.
167							   now just fix it thisway */
168			struct range_lock *range_lock;
169			struct stripe *stripes[5];
170			UCHAR nstripes;
171			UCHAR finished_stripes;
172			USHORT pad2;
173			/* for direct-read: */
174			struct {
175				UCHAR  cmds;
176				UCHAR  finished;
177				UCHAR  first;
178				UCHAR  parity;
179				LBA_T  base;
180				USHORT firstoffset;
181				USHORT firstsectors;
182			} dr;
183		} r5n2;
184#endif
185		struct {
186			ULONG WordsLeft;
187			FPSCAT_GATH pPIOSg;
188			void (* HPTLIBAPI pfnOrgDone)(_VBUS_ARG PCommand pCmd);
189#ifdef SUPPORT_HPT584
190			UCHAR cmd;
191#endif
192		} disk;
193		struct {
194			PCommand pNext;
195			void (* HPTLIBAPI WaitEntry)(_VBUS_ARG PCommand pCmd);
196		} wait;
197
198		struct {
199			PVOID prdAddr;
200			ULONG cmd_priv;
201			USHORT responseFlags;
202			UCHAR  bIdeStatus;
203			UCHAR  errorRegister;
204		} sata_param;
205	} uScratch;
206} Command;
207
208/***************************************************************************
209 * command return value
210 ***************************************************************************/
211#define   RETURN_PENDING             0
212#define   RETURN_SUCCESS             1
213#define   RETURN_BAD_DEVICE          2
214#define   RETURN_BAD_PARAMETER       3
215#define   RETURN_WRITE_NO_DRQ        4
216#define   RETURN_DEVICE_BUSY         5
217#define   RETURN_INVALID_REQUEST     6
218#define   RETURN_SELECTION_TIMEOUT   7
219#define   RETURN_IDE_ERROR           8
220#define   RETURN_NEED_LOGICAL_SG     9
221#define   RETURN_NEED_PHYSICAL_SG    10
222#define   RETURN_RETRY               11
223#define   RETURN_DATA_ERROR          12
224#define   RETURN_BUS_RESET           13
225#define   RETURN_BAD_TRANSFER_LENGTH 14
226
227typedef void (* HPTLIBAPI DPC_PROC)(_VBUS_ARG void *);
228typedef struct _dpc_routine {
229	DPC_PROC proc;
230	void *arg;
231}
232DPC_ROUTINE;
233
234/*
235 * MAX_QUEUE_COMM is defined in platform related compiler.h
236 * to specify the maximum requests allowed (for each VBus) from system.
237 *
238 * Maximum command blocks needed for each VBus:
239 *   Each OS command requests 1+MAX_MEMBERS*2 command blocks (RAID1/0 case)
240 *   This space is allocated by platform dependent part, either static or
241 *   dynamic, continuous or non-continous.
242 *   The code only needs _vbus_(pFreeCommands) to be set.
243 *
244 * PendingRoutines[] size:
245 *   Each command may invoke CallAfterReturn once.
246 *
247 * IdleRoutines[] size:
248 *   Each command may invoke CallWhenIdle once.
249 */
250#define MAX_COMMAND_BLOCKS_FOR_EACH_VBUS (MAX_QUEUE_COMM * (1+MAX_MEMBERS*2) + 1)
251#define MAX_PENDING_ROUTINES  (MAX_COMMAND_BLOCKS_FOR_EACH_VBUS+1)
252#define MAX_IDLE_ROUTINES     (MAX_COMMAND_BLOCKS_FOR_EACH_VBUS+1)
253
254#define mWaitingForIdle(pVBus) ((pVBus)->IdleRoutinesFirst!=(pVBus)->IdleRoutinesLast)
255
256PCommand HPTLIBAPI AllocateCommand(_VBUS_ARG0);
257void FASTCALL FreeCommand(_VBUS_ARG PCommand pCmd);
258
259void FASTCALL CallAfterReturn(_VBUS_ARG DPC_PROC proc, void *arg);
260void HPTLIBAPI CheckPendingCall(_VBUS_ARG0);
261void FASTCALL CallWhenIdle(_VBUS_ARG DPC_PROC proc, void *arg);
262void HPTLIBAPI CheckIdleCall(_VBUS_ARG0);
263
264void HPTLIBAPI AddToWaitingList(PCommand *ppList, PCommand pCmd);
265void HPTLIBAPI DoWaitingList(_VBUS_ARG PCommand *ppList);
266
267#endif
268