source: trunk/src/os2ahci/apm.c@ 157

Last change on this file since 157 was 157, checked in by David Azarewicz, 12 years ago

Fixed up timer functions

File size: 5.2 KB
Line 
1/******************************************************************************
2 * apm.c - Functions to interface with the APM 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 "os2ahci.h"
28
29#include <apmcalls.h>
30
31/* -------------------------- macros and constants ------------------------- */
32
33/* ------------------------ typedefs and structures ------------------------ */
34
35/* -------------------------- function prototypes -------------------------- */
36
37/* ------------------------ global/static variables ------------------------ */
38
39USHORT _far _cdecl apm_event (APMEVENT _far *evt);
40
41/* ----------------------------- start of code ----------------------------- */
42
43/******************************************************************************
44 * Connect to APM driver and register for power state change events.
45 */
46void apm_init(void)
47{
48 USHORT rc;
49
50 /* connect to APM driver */
51 if ((rc = APMAttach()) != 0) {
52 dprintf("couldn't connect to APM driver (rc = %d)\n", rc);
53 return;
54 }
55
56 /* register for suspend/resume events */
57 if ((rc = APMRegister(apm_event, APM_NOTIFYSETPWR |
58 APM_NOTIFYNORMRESUME |
59 APM_NOTIFYCRITRESUME, 0)) != 0) {
60 dprintf("couldn't register for power event notificatins (rc = %d)\n", rc);
61 return;
62 }
63}
64
65/******************************************************************************
66 * APM event handler
67 */
68USHORT _far _cdecl apm_event(APMEVENT _far *evt)
69{
70 USHORT msg = (USHORT) evt->ulParm1;
71
72 dprintf("received APM event: 0x%lx/0x%lx\n");
73
74 switch (msg) {
75
76 case APM_SETPWRSTATE:
77 if (evt->ulParm2 >> 16 != APM_PWRSTATEREADY) {
78 /* we're suspending */
79 apm_suspend();
80 }
81 break;
82
83 case APM_NORMRESUMEEVENT:
84 case APM_CRITRESUMEEVENT:
85 /* we're resuming */
86 apm_resume();
87 break;
88
89 default:
90 dprintf("unknown APM event; ignoring...\n");
91 break;
92 }
93
94 return(0);
95}
96
97/******************************************************************************
98 * APM suspend handler. In a nutshell, it'll turn of interrupts and flush all
99 * write caches.
100 */
101void apm_suspend(void)
102{
103 int a;
104 int p;
105 int d;
106 TIMER Timer;
107
108 if (suspended) return;
109 dprintf("apm_suspend()\n");
110
111 /* restart all ports with interrupts disabled */
112 for (a = 0; a < ad_info_cnt; a++) {
113 AD_INFO *ai = ad_infos + a;
114
115 lock_adapter(ai);
116 for (p = 0; p <= ai->port_max; p++) {
117 /* wait until all active commands have completed on this port */
118 timer_init(&Timer, 250);
119 while (ahci_port_busy(ai, p)) {
120 if (timer_check_and_block(&Timer)) break;
121 }
122
123 /* restart port with interrupts disabled */
124 ahci_stop_port(ai, p);
125 ahci_start_port(ai, p, 0);
126
127 /* flush cache on all attached devices */
128 for (d = 0; d <= ai->ports[p].dev_max; d++) {
129 if (ai->ports[p].devs[d].present) {
130 ahci_flush_cache(ai, p, d);
131 }
132 }
133 }
134 }
135
136 /* reset init_complete so that we can process IORBs without interrupts */
137 init_complete = 0;
138
139 /* restore BIOS configuration for each adapter and release the adapter */
140 for (a = 0; a < ad_info_cnt; a++) {
141 ahci_restore_bios_config(ad_infos + a);
142 unlock_adapter(ad_infos + a);
143 }
144
145 suspended = 1;
146 dprintf("apm_suspend() finished\n");
147}
148
149/******************************************************************************
150 * APM resume handler. All ports are restarted with interrupts enabled using
151 * the same function as the IOCM_COMPLETE_INIT handler does.
152 */
153void apm_resume(void)
154{
155 int a;
156
157 if (!suspended) return;
158 dprintf("apm_resume()\n");
159
160 for (a = 0; a < ad_info_cnt; a++) {
161 AD_INFO *ai = ad_infos + a;
162
163 /* Complete initialization of this adapter; this will restart the ports
164 * with interrupts enabled and take care of whatever else needs to be
165 * done to get the adapter and its ports up and running.
166 */
167 lock_adapter(ai);
168 ahci_complete_init(ai);
169 }
170
171 /* tell the driver we're again fully operational */
172 init_complete = 1;
173
174 /* unlock all adapters now that we have set the init_complete flag */
175 for (a = 0; a < ad_info_cnt; a++) {
176 unlock_adapter(ad_infos + a);
177 }
178
179 suspended = 0;
180 dprintf("apm_resume() finished\n");
181}
Note: See TracBrowser for help on using the repository browser.