source: trunk/src/os2ahci/os2ahci.h@ 23

Last change on this file since 23 was 20, checked in by markus, 15 years ago

fixed devhelp calls for Watcom compiler (added private, fixed copy of devhelp.h from DDK)

File size: 22.0 KB
Line 
1/******************************************************************************
2 * os2ahci.h - main header file for os2ahci driver
3 *
4 * Copyright (c) 2010 Christian Mueller. Parts copied from/inspired by the
5 * Linux AHCI driver; those parts are (c) Linux AHCI/ATA maintainers
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22/* ----------------------------- include files ----------------------------- */
23
24/* IMPORTANT NOTE: The DDK headers require tight structure packing and this
25 * is controlled via compiler parameters. Thus, all stuctures in os2ahci.sys
26 * are expected to be byte-aligned without the need of explicit pragma pack()
27 * directives. Where possible, the structures are layed out such that words
28 * and dwords are aligned at least on 2-byte boundaries.
29 */
30
31#define INCL_NOPMAPI
32#define INCL_DOSINFOSEG
33#define INCL_NO_SCB
34#define INCL_DOSERRORS
35#include <os2.h>
36#include <dos.h>
37#include <bseerr.h>
38#include <dskinit.h>
39#include <scb.h>
40
41#include <devhdr.h>
42#include <iorb.h>
43#include <strat2.h>
44#include <reqpkt.h>
45
46#ifdef __WATCOMC__
47#include <devhelp.h>
48#else
49#include <dhcalls.h>
50#endif
51
52#include <addcalls.h>
53#include <rmcalls.h>
54#include <devclass.h>
55#include <devcmd.h>
56#include <rmbase.h>
57
58#include "ahci.h"
59
60/* -------------------------- macros and constants ------------------------- */
61
62#define VERSION 100 /* driver version (2 implied decimals) */
63#define MAX_AD 8 /* maximum number of adapters */
64
65/* Timer pool size. In theory, we need one timer per outstanding command plus
66 * a few miscellaneous timers but it's unlikely we'll ever have outstanding
67 * commands on all devices on all ports on all apapters -- this would be
68 * 8 * 32 * 32 = 8192 outstanding commands on a maximum of 8 * 32 * 15 = 3840
69 * devices and that's a bit of an exaggeration. It should be more than enough
70 * to have 128 timers.
71 */
72#define TIMER_COUNT 128
73#define TIMER_POOL_SIZE (sizeof(ADD_TIMER_POOL) + \
74 TIMER_COUNT * sizeof(ADD_TIMER_DATA))
75
76/* default command timeout (can be overwritten in the IORB) */
77#define DEFAULT_TIMEOUT 30000
78
79/* debug output macros */
80#define dprintf if (debug > 0) printf
81#define dphex if (debug > 0) phex
82#define ddprintf if (debug > 1) printf
83#define ddphex if (debug > 1) phex
84#define dddprintf if (debug > 2) printf
85#define dddphex if (debug > 2) phex
86
87/* adapter number from AD_INFO pointer; mainly for dprintf() purposes */
88#define ad_no(ai) (((u16) ai - (u16) ad_infos) / sizeof(*ai))
89
90/* Convert far function address into NPFN (the DDK needs this all over the
91 * place and just casting to NPFN will produce a "segment lost in conversion"
92 * warning. Since casting to a u32 is a bit nasty for function pointers and
93 * might have to be revised for different compilers, we'll use a central
94 * macro for this crap.
95 */
96#define mk_NPFN(func) (NPFN) (u32) (func)
97
98/* stdarg.h macros with explicit far pointers
99 *
100 * NOTE: The compiler pushes fixed arguments with 16 bits minimum, thus
101 * the last fixed argument (i.e. the one passed to va_start) must
102 * have at least 16 bits. Otherwise, the address calculation in
103 * va_start() will fail.
104 */
105typedef char _far *va_list;
106#define va_start(va, last) va = (va_list) (&last + 1)
107#define va_arg(va, type) ((type _far *) (va += sizeof(type)))[-1]
108#define va_end(va) va = 0
109
110/* ctype macros */
111#define isupper(ch) ((ch) >= 'A' && (ch) <= 'Z')
112#define tolower(ch) (isupper(ch) ? (ch) - ('a' - 'A') : (ch))
113
114/* stddef macros */
115#define offsetof(s, e) ((u16) &((s *) 0)->e)
116
117/* SMP spinlock compatibility macros for older DDKs using CLI/STI */
118#ifndef OS2AHCI_SMP
119#define DevHelp_CreateSpinLock(sph) *(sph) = 0
120#define DevHelp_FreeSpinLock(sph) 0
121
122#define DevHelp_AquireSpinLock(sph) if ((sph) != 0) \
123 panic("recursive spinlock"); \
124 (sph) = disable()
125
126#define DevHelp_ReleaseSpinLock(sph) if (sph) { \
127 (sph) = 0; \
128 enable(); \
129 }
130#endif
131
132/* shortcut macros */
133#define spin_lock(sl) DevHelp_AquireSpinLock(sl)
134#define spin_unlock(sl) DevHelp_ReleaseSpinLock(sl)
135
136/* Get AHCI port MMIO base from AD_INFO and port number. For the time being,
137 * MMIO addresses are assumed to be valid 16:16 pointers which implies
138 * that one GDT selector is allocated per adapter.
139 */
140#define port_base(ai, p) ((u8 _far *) (ai)->mmio + 0x100 + (p) * 0x80)
141
142/* Get address of port-specific DMA scratch buffer. The total size of all DMA
143 * buffers required for 32 ports exceeds 65536 bytes, thus we need multiple
144 * GDT selectors to access all port DMA scratch buffers and some logic to map
145 * a port number to the corresponding DMA scratch buffer address.
146 */
147#define PORT_DMA_BUFS_PER_SEG ((size_t) (65536UL / AHCI_PORT_PRIV_DMA_SZ))
148#define PORT_DMA_BUF_SEGS ((AHCI_MAX_PORTS + PORT_DMA_BUFS_PER_SEG - 1) \
149 / PORT_DMA_BUFS_PER_SEG)
150#define PORT_DMA_SEG_SIZE ((u32) PORT_DMA_BUFS_PER_SEG * \
151 (u32) AHCI_PORT_PRIV_DMA_SZ)
152
153#define port_dma_base(ai, p) \
154 ((AHCI_PORT_DMA _far *) ((ai)->dma_buf[(p) / PORT_DMA_BUFS_PER_SEG] + \
155 ((p) % PORT_DMA_BUFS_PER_SEG) * AHCI_PORT_PRIV_DMA_SZ))
156
157#define port_dma_base_phys(ai, p) \
158 ((ai)->dma_buf_phys + (u32) (p) * AHCI_PORT_PRIV_DMA_SZ)
159
160/* Convert an SATA adapter/port/device address into a 16-bit IORB unit handle
161 * (and the other way round). The mapping looks like this:
162 *
163 * mapping comment
164 * -----------------------------------------------------------------------
165 * 4 bits for the adapter current max is 8 adapters
166 * 4 bits for the port AHCI spec defines up to 32 ports
167 * 4 bits for the device SATA spec defines up to 15 devices behind PMP
168 */
169#define iorb_unit(a, p, d) ((((u16) (a) & 0x0fU) << 8) | \
170 (((u16) (p) & 0x0fU) << 4) | \
171 (((u16) (d) & 0x0fU)))
172#define iorb_unit_adapter(iorb) (((u16) (iorb)->UnitHandle >> 8) & 0x07U)
173#define iorb_unit_port(iorb) (((u16) (iorb)->UnitHandle >> 4) & 0x0fU)
174#define iorb_unit_device(iorb) ((u16) (iorb)->UnitHandle & 0x0fU)
175
176/*******************************************************************************
177 * Convenience macros for IORB processing functions
178 */
179/* is this IORB on driver or port level? */
180#define iorb_driver_level(iorb) ((iorb)->CommandCode == IOCC_CONFIGURATION)
181
182/* is this IORB to be inserted at the beginnig of the IORB queue? */
183#define iorb_priority(iorb) ((iorb)->CommandCode == IOCC_DEVICE_CONTROL && \
184 (iorb)->CommandModifier == IOCM_ABORT))
185
186/* access IORB ADD workspace */
187#define add_workspace(iorb) ((ADD_WORKSPACE _far *) &(iorb)->ADDWorkSpace)
188
189/* free resources in ADD workspace (timer, buffer, ...) */
190#define aws_free(aws) if ((aws)->timer != 0) { \
191 ADD_CancelTimer((aws)->timer); \
192 (aws)->timer = 0; \
193 } \
194 if ((aws)->buf != NULL) { \
195 free((aws)->buf); \
196 (aws)->buf = NULL; \
197 }
198
199/******************************************************************************
200 * PCI generic IDs and macros
201 */
202#define PCI_ANY_ID 0xffffU
203#define PCI_VDEVICE(vendor, device) PCI_VENDOR_ID_##vendor, (device), \
204 PCI_ANY_ID, PCI_ANY_ID, 0, 0
205
206/******************************************************************************
207 * PCI vendor IDs for AHCI adapters known to this driver (copied from Linux
208 * pci_ids.h)
209 */
210#define PCI_VENDOR_ID_AL 0x10b9
211#define PCI_VENDOR_ID_AMD 0x1022
212#define PCI_VENDOR_ID_AT 0x1259
213#define PCI_VENDOR_ID_ATI 0x1002
214#define PCI_VENDOR_ID_ATT 0x11c1
215#define PCI_VENDOR_ID_CMD 0x1095
216#define PCI_VENDOR_ID_CT 0x102c
217#define PCI_VENDOR_ID_INTEL 0x8086
218#define PCI_VENDOR_ID_JMICRON 0x197B
219#define PCI_VENDOR_ID_MARVELL 0x11ab
220#define PCI_VENDOR_ID_NVIDIA 0x10de
221#define PCI_VENDOR_ID_PROMISE 0x105a
222#define PCI_VENDOR_ID_SI 0x1039
223#define PCI_VENDOR_ID_VIA 0x1106
224
225/******************************************************************************
226 * PCI class IDs we're interested in (copied from Linux pci_ids.h)
227 */
228#define PCI_BASE_CLASS_STORAGE 0x01
229#define PCI_CLASS_STORAGE_SCSI 0x0100
230#define PCI_CLASS_STORAGE_IDE 0x0101
231#define PCI_CLASS_STORAGE_FLOPPY 0x0102
232#define PCI_CLASS_STORAGE_IPI 0x0103
233#define PCI_CLASS_STORAGE_RAID 0x0104
234#define PCI_CLASS_STORAGE_SATA 0x0106
235#define PCI_CLASS_STORAGE_SATA_AHCI 0x010601
236#define PCI_CLASS_STORAGE_SAS 0x0107
237#define PCI_CLASS_STORAGE_OTHER 0x0180
238
239/* ------------------------ typedefs and structures ------------------------ */
240
241typedef unsigned int size_t;
242
243/* PCI device information structure; this is used both for scanning and for
244 * identification purposes in 'AD_INFO'; based on the Linux pci_device_id
245 * structure but hard-wired to use board_* constants for 'driver_data'
246 */
247typedef struct {
248 u16 vendor; /* PCI device vendor/manufacturer */
249 u16 device; /* PCI device ID inside vendor scope */
250 u16 subvendor; /* subsystem vendor (unused so far) */
251 u16 subdevice; /* subsystem device (unused so far) */
252 u32 class; /* PCI device class */
253 u32 class_mask; /* bits to match when scanning for 'class' */
254 u32 board; /* AHCI controller board type (board_* constants) */
255} PCI_ID;
256
257/* IORB queue; since IORB queues are updated at interrupt time, the
258 * corresponding pointers (not the data they point to) need to be volatile.
259 */
260typedef struct {
261 IORBH _far *volatile root; /* root of request list */
262 IORBH _far *volatile tail; /* tail of request list */
263} IORB_QUEUE;
264
265/* port information structure */
266typedef struct {
267 IORB_QUEUE iorb_queue; /* IORB queue for this port */
268 unsigned dev_max : 4; /* maximum device number on this port (0-15) */
269 unsigned cmd_slot : 5; /* current command slot index (using round-
270 * robin indexes to prevent starvation) */
271
272 volatile u32 ncq_cmds; /* bitmap for NCQ commands issued */
273 volatile u32 reg_cmds; /* bitmap for regular commands issued */
274
275 struct {
276 unsigned allocated : 1; /* if != 0, device is allocated */
277 unsigned present : 1; /* if != 0, device is present */
278 unsigned lba48 : 1; /* if != 0, device supports 48-bit LBA */
279 unsigned atapi : 1; /* if != 0, this is an ATAPI device */
280 unsigned atapi_16 : 1; /* if != 0, device suports 16-byte cmds */
281 unsigned removable : 1; /* if != 0, device has removable media */
282 unsigned dev_type : 5; /* device type (UIB_TYPE_* in iorb.h) */
283 unsigned ncq_max : 5; /* maximum tag number for queued commands */
284 UNITINFO _far *unit_info; /* pointer to modified unit info */
285 } devs[15];
286} P_INFO;
287
288/* adapter information structure */
289typedef struct {
290 PCI_ID *pci; /* pointer to corresponding PCI ID */
291
292 unsigned port_max : 5; /* maximum port number (0-31) */
293 unsigned cmd_max : 5; /* maximum cmd slot number (0-31) */
294 unsigned port_scan_done : 1; /* if != 0, port scan already done */
295 unsigned busy : 1; /* if != 0, adapter is busy */
296
297 u32 port_map; /* bitmap of active ports */
298
299 /* initial adapter configuration from BIOS */
300 u32 bios_config[HOST_CAP2 / sizeof(u32) + 1];
301
302 u32 cap; /* working copy of CAP register */
303 u32 cap2; /* working copy of CAP2 register */
304 u32 flags; /* adapter flags */
305
306 HRESOURCE rm_adh; /* resource handle for adapter */
307 HRESOURCE rm_mmio; /* resource handle for MMIO */
308 HRESOURCE rm_irq; /* resource handle for IRQ */
309
310 u8 bus; /* PCI bus number */
311 u8 dev_func; /* PCI device and function number */
312 u16 irq; /* interrupt number */
313
314 u32 mmio_phys; /* physical address of MMIO region */
315 u8 _far *mmio; /* pointer to this adapter's MMIO region */
316
317 u32 dma_buf_phys; /* physical address of DMA scratch buffer */
318 u8 _far *dma_buf[PORT_DMA_BUF_SEGS]; /* DMA scatch buffer */
319
320 P_INFO ports[AHCI_MAX_PORTS]; /* SATA ports on this adapter */
321} AD_INFO;
322
323/* ADD workspace in IORB (must not exceed 16 bytes) */
324typedef struct {
325 void (*ppfunc)(IORBH _far *iorb); /* post-processing function */
326 void *buf; /* response buffer (e.g. for identify cmds) */
327 ULONG timer; /* timer for timeout procesing */
328 USHORT blocks; /* number of blocks to be transferred */
329 unsigned processing : 1; /* IORB is being processd */
330 unsigned idempotent : 1; /* IORB is idempotent (can be retried) */
331 unsigned queued_hw : 1; /* IORB has been queued to hardware */
332 unsigned no_ncq : 1; /* must not use native command queuing */
333 unsigned is_ncq : 1; /* should use native command queueing */
334 unsigned complete : 1; /* IORB has completed processing */
335 unsigned cmd_slot : 5; /* AHCI command slot for this IORB */
336} ADD_WORKSPACE;
337
338/* -------------------------- function prototypes -------------------------- */
339
340/* init.asm */
341extern u32 readl (void _far *addr);
342extern u32 writel (void _far *addr, u32 val);
343extern void _far *memcpy (void _far *v_dst, void _far *v_src, int len);
344extern void _far *memset (void _far *p, int ch, size_t len);
345extern void _far restart_hook (void);
346extern void _far reset_hook (void);
347extern void _far engine_hook (void);
348
349/* os2ahci.c */
350extern USHORT init_drv (RPINITIN _far *req);
351extern void _far _loadds add_entry (IORBH _far *iorb);
352extern void trigger_engine (void);
353extern int trigger_engine_1 (void);
354extern void send_iorb (IORBH _far *iorb);
355extern void iocc_configuration (IORBH _far *iorb);
356extern void iocc_device_control (IORBH _far *iorb);
357extern void iocc_unit_control (IORBH _far *iorb);
358extern void iocm_device_table (IORBH _far *iorb);
359extern void iocc_geometry (IORBH _far *iorb);
360extern void iocc_execute_io (IORBH _far *iorb);
361extern void iocc_unit_status (IORBH _far *iorb);
362extern void iocc_adapter_passthru (IORBH _far *iorb);
363extern void iorb_queue_add (IORB_QUEUE _far *queue, IORBH _far *iorb);
364extern int iorb_queue_del (IORB_QUEUE _far *queue, IORBH _far *iorb);
365extern void iorb_seterr (IORBH _far *iorb, USHORT error_code);
366extern void iorb_done (IORBH _far *iorb);
367extern void iorb_requeue (IORBH _far *iorb);
368
369/* ahci.c */
370extern int ahci_save_bios_config (AD_INFO *ai);
371extern int ahci_restore_bios_config (AD_INFO *ai);
372extern int ahci_restore_initial_config (AD_INFO *ai);
373extern AHCI_PORT_CFG *ahci_save_port_config (AD_INFO *ai, int p);
374extern void ahci_restore_port_config (AD_INFO *ai, int p,
375 AHCI_PORT_CFG *pc);
376extern int ahci_enable_ahci (AD_INFO *ai);
377extern int ahci_scan_ports (AD_INFO *ai);
378extern int ahci_complete_init (AD_INFO *ai);
379extern int ahci_reset_port (AD_INFO *ai, int p, int ei);
380extern int ahci_start_port (AD_INFO *ai, int p, int ei);
381extern void ahci_start_fis_rx (AD_INFO *ai, int p);
382extern void ahci_start_engine (AD_INFO *ai, int p);
383extern int ahci_stop_port (AD_INFO *ai, int p);
384extern int ahci_stop_fis_rx (AD_INFO *ai, int p);
385extern int ahci_stop_engine (AD_INFO *ai, int p);
386extern void ahci_exec_iorb (IORBH _far *iorb, int ncq_capable,
387 int (*func)(IORBH _far *, int));
388extern void ahci_exec_polled_iorb (IORBH _far *iorb,
389 int (*func)(IORBH _far *, int),
390 ULONG timeout);
391extern int ahci_exec_polled_cmd (AD_INFO *ai, int p, int d,
392 int timeout, int cmd, ...);
393
394extern int ahci_intr (u16 irq);
395extern void ahci_port_intr (AD_INFO *ai, int p);
396extern void ahci_error_intr (AD_INFO *ai, int p, u32 irq_stat);
397
398extern void ahci_get_geometry (IORBH _far *iorb);
399extern void ahci_unit_ready (IORBH _far *iorb);
400extern void ahci_read (IORBH _far *iorb);
401extern void ahci_verify (IORBH _far *iorb);
402extern void ahci_write (IORBH _far *iorb);
403extern void ahci_execute_cdb (IORBH _far *iorb);
404extern void ahci_execute_ata (IORBH _far *iorb);
405
406/* libc.c */
407extern void init_com1 (void);
408extern int vsprintf (char _far *buf, const char *fmt, va_list va);
409extern int sprintf (char _far *buf, const char *fmt, ...);
410extern void vfprintf (const char *fmt, va_list va);
411extern void printf (const char *fmt, ...);
412extern void cprintf (const char *fmt, ...);
413extern void phex (const void _far *p, int len,
414 const char *fmt, ...);
415extern size_t strlen (const char _far *s);
416extern char _far *strcpy (char _far *dst, const char _far *src);
417extern int memcmp (void _far *p1, void _far *p2, size_t len);
418extern long strtol (const char _far *buf,
419 const char _far * _far *ep, int base);
420extern void *malloc (size_t len);
421extern void free (void *ptr);
422extern void mdelay_cal (void);
423extern void mdelay (u32 millies);
424extern void msleep (u32 millies);
425extern void panic (char *msg);
426extern int disable (void);
427extern void enable (void);
428
429/* pci.c */
430extern int add_pci_id (u16 vendor, u16 device);
431extern void scan_pci_bus (void);
432extern int pci_enable_int (UCHAR bus, UCHAR dev_func);
433extern void pci_hack_virtualbox(void);
434
435/* ctxhook.c */
436extern void restart_ctxhook (ULONG parm);
437extern void reset_ctxhook (ULONG parm);
438extern void engine_ctxhook (ULONG parm);
439
440/* ---------------------------- global variables --------------------------- */
441
442extern char end_of_data; /* label at the end of all data segments */
443extern void _near end_of_code(); /* label at the end of all code segments */
444
445extern int debug; /* if != 0, print debug messages to COM1 */
446extern int thorough_scan; /* if != 0, perform thorough PCI scan */
447extern int init_reset; /* if != 0, reset ports during init */
448
449extern HDRIVER rm_drvh; /* resource manager driver handle */
450extern USHORT add_handle; /* adapter device driver handle */
451extern UCHAR timer_pool[]; /* timer pool */
452
453extern PCI_ID pci_ids[]; /* SATA adapter PCI IDs */
454extern ULONG drv_lock; /* driver-level spinlock */
455extern IORB_QUEUE driver_queue; /* driver-level IORB queue */
456extern AD_INFO ad_infos[]; /* adapter information list */
457extern int ad_info_cnt; /* number of entries in ad_infos[] */
458extern int init_complete; /* if != 0, initialization has completed */
459
460extern u16 com_base; /* debug COM port base address */
461
462/* port restart context hook and input data */
463extern ULONG restart_ctxhook_h;
464extern volatile u32 ports_to_restart[MAX_AD];
465
466/* port reset context hook and input data */
467extern ULONG reset_ctxhook_h;
468extern volatile u32 ports_to_reset[MAX_AD];
469extern IORB_QUEUE abort_queue;
470
471/* trigger engine context hook and input data */
472extern ULONG engine_ctxhook_h;
473
474/* apapter/port-specific options saved when parsing the command line */
475extern u8 link_speed[MAX_AD][AHCI_MAX_PORTS];
476extern u8 disable_ncq[MAX_AD][AHCI_MAX_PORTS];
477
Note: See TracBrowser for help on using the repository browser.