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

Last change on this file since 84 was 84, checked in by chris, 14 years ago
  • Added ioctl.c, ioctl.h and apm.c to repository
File size: 5.0 KB
Line 
1/******************************************************************************
2 * apm.c - Functions to interface with the APM driver.
3 *
4 * Copyright (c) 2010 Christian Mueller, Markus Thielen.
5 * Parts copied from/inspired by the LINUX ahci driver;
6 * those parts are (c) Linux AHCI/ATA maintainers
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include "os2ahci.h"
24
25#include <apmcalls.h>
26
27/* -------------------------- macros and constants ------------------------- */
28
29/* ------------------------ typedefs and structures ------------------------ */
30
31/* -------------------------- function prototypes -------------------------- */
32
33/* ------------------------ global/static variables ------------------------ */
34
35USHORT _far _cdecl apm_event (APMEVENT _far *evt);
36
37/* ----------------------------- start of code ----------------------------- */
38
39/******************************************************************************
40 * Connect to APM driver and register for power state change events.
41 */
42void apm_init(void)
43{
44 USHORT rc;
45
46 /* connect to APM driver */
47 if ((rc = APMAttach()) != 0) {
48 dprintf("couldn't connect to APM driver (rc = %d)\n", rc);
49 return;
50 }
51
52 /* register for suspend/resume events */
53 if ((rc = APMRegister(apm_event, APM_NOTIFYSETPWR |
54 APM_NOTIFYNORMRESUME |
55 APM_NOTIFYCRITRESUME, 0)) != 0) {
56 dprintf("couldn't register for power event notificatins (rc = %d)\n", rc);
57 return;
58 }
59}
60
61/******************************************************************************
62 * APM event handler
63 */
64USHORT _far _cdecl apm_event(APMEVENT _far *evt)
65{
66 USHORT msg = (USHORT) evt->ulParm1;
67
68 dprintf("received APM event: 0x%lx/0x%lx\n");
69
70 switch (msg) {
71
72 case APM_SETPWRSTATE:
73 if (evt->ulParm2 >> 16 != APM_PWRSTATEREADY) {
74 /* we're suspending */
75 apm_suspend();
76 }
77 break;
78
79 case APM_NORMRESUMEEVENT:
80 case APM_CRITRESUMEEVENT:
81 /* we're resuming */
82 apm_resume();
83 break;
84
85 default:
86 dprintf("unknown APM event; ignoring...\n");
87 break;
88 }
89
90 return(0);
91}
92
93/******************************************************************************
94 * APM suspend handler. In a nutshell, it'll turn of interrupts and flush all
95 * write caches.
96 */
97void apm_suspend(void)
98{
99 int a;
100 int p;
101 int d;
102
103 dprintf("apm_suspend()\n");
104
105 /* restart all ports with interrupts disabled */
106 for (a = 0; a < ad_info_cnt; a++) {
107 AD_INFO *ai = ad_infos + a;
108
109 lock_adapter(ai);
110 for (p = 0; p <= ai->port_max; p++) {
111 /* wait until all active commands have completed on this port */
112 while (ahci_port_busy(ai, p)) {
113 msleep(250);
114 }
115
116 /* restart port with interrupts disabled */
117 ahci_stop_port(ai, p);
118 ahci_start_port(ai, p, 0);
119
120 /* flush cache on all attached devices */
121 for (d = 0; d <= ai->ports[p].dev_max; d++) {
122 if (ai->ports[p].devs[d].present) {
123 ahci_flush_cache(ai, p, d);
124 }
125 }
126 }
127 }
128
129 /* reset init_complete so that we can process IORBs without interrupts */
130 init_complete = 0;
131
132 /* restore BIOS configuration for each adapter and release the adapter */
133 for (a = 0; a < ad_info_cnt; a++) {
134 ahci_restore_bios_config(ad_infos + a);
135 unlock_adapter(ad_infos + a);
136 }
137
138 dprintf("apm_suspend() finished\n");
139}
140
141/******************************************************************************
142 * APM resume handler. All ports are restarted with interrupts enabled using
143 * the same function as the IOCM_COMPLETE_INIT handler does.
144 */
145void apm_resume(void)
146{
147 int a;
148
149 dprintf("apm_resume()\n");
150
151 for (a = 0; a < ad_info_cnt; a++) {
152 AD_INFO *ai = ad_infos + a;
153
154 /* Complete initialization of this adapter; this will restart the ports
155 * with interrupts enabled and take care of whatever else needs to be
156 * done to get the adapter and its ports up and running.
157 */
158 lock_adapter(ai);
159 ahci_complete_init(ai);
160 }
161
162 /* tell the driver we're again fully operational */
163 init_complete = 1;
164
165 /* unlock all adapters now that we have set the init_complete flag */
166 for (a = 0; a < ad_info_cnt; a++) {
167 unlock_adapter(ad_infos + a);
168 }
169
170 dprintf("apm_resume() finished\n");
171}
Note: See TracBrowser for help on using the repository browser.