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

Last change on this file since 145 was 145, checked in by rousseau, 13 years ago

Possibly fixed VirtualBox trap #8/reset problem (TRAC ticket #15)

Depending on kernel (W4/SMP) and ACPI (enabled or not), massive copying of
files produced a trap #8 or reset when using OS2AHCI in VirtualBox.

Causes & Fixes

o Interrupts were not disabled before doing DevHelp_EOI().

Since the AHCI controller in VirtualBox is a software implementation,
it cannot process requests as fast as a true hardware controller.
This caused stacked interrupts to a level that exhausted the interrupt
stack, resulting in a trap #8 on W4 or a reset on SMP with ACPI.
Interrupts are now disabled before doing the EOI.
The "Physycal Device Driver Reference" mentions this in:
?:\IBMDDK\DOCS\PDDREF.INF->Device Helper (DevHlp) Services)->EOI
and cross-referencing with DANIS506 shows she does the same in:
s506m.c (state machine) around line 244.

To investigate

o SMP safety

The disable() function in lib.c (around line 793) mentions that SMP systems
should use spinlocks. Possibly because a CLI is only executed on the
current CPU and a new interrupt could come from another CPU where
interrupts are still enabled. However, doing the EOI before unlocking did
not solve the VBox issue, possibly because spin_unlock() enables
interrupts again. So, at least in the case of VBox, the interrupt handler
has to return with interrupts disabled.
This will only be an issue in VBox if it realy can receive interrupts from
multiple CPU's in it's software implementation.

o Real hardware

As far as I can tell this patch has no influence on performance when
using real hardware. Also, since real hardware can handle requests in a
much shorter timespan, the likeliness of stacked interrupts occuring is
much less.

Performance measurements in VirtualBox

VirtualBox is a virtual machine and therefore subjected to any system load
on the host OS. Even comparing DANIS506 with OS2AHCI makes no real sense
since with DANI the SATA-contoller will run in ATA-compatibility and with
OS2AHCI it will run in AHCI-mode. Also, I have experienced that when my CPU
get's hot, the duty-cycle throttling goes active, reducing performance and
thus impacting any benchmarks in VBox. (or real hardware)
The only way to compare DANIS506 with OS2AHCI is on real hardware, on the
same controller, with the same disks and doing the same tests.
And most importantly, with the same CPU core-temperature.

Note

Diff's may show changed lines that are actually the same.
That's because my editor is configured to strip trailing white space.

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