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