sm_osl.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:20k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  *
  3.  * Module Name: sm_osl.c
  4.  *   $Revision: 16 $
  5.  *
  6.  *****************************************************************************/
  7. /*
  8.  *  Copyright (C) 2000, 2001 Andrew Grover
  9.  *
  10.  *  This program is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2 of the License, or
  13.  *  (at your option) any later version.
  14.  *
  15.  *  This program is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this program; if not, write to the Free Software
  22.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  23.  */
  24. #include <linux/kernel.h>
  25. #include <linux/module.h>
  26. #include <linux/init.h>
  27. #include <linux/types.h>
  28. #include <linux/proc_fs.h>
  29. #include <linux/pm.h>
  30. #include <asm/uaccess.h>
  31. #include <linux/acpi.h>
  32. #include <asm/io.h>
  33. #include <linux/mc146818rtc.h>
  34. #include <linux/delay.h>
  35. #include <acpi.h>
  36. #include "sm.h"
  37. MODULE_AUTHOR("Andrew Grover");
  38. MODULE_DESCRIPTION("ACPI Component Architecture (CA) - ACPI System Driver");
  39. MODULE_LICENSE("GPL");
  40. #define SM_PROC_INFO "info"
  41. #define SM_PROC_DSDT "dsdt"
  42. extern struct proc_dir_entry *bm_proc_root;
  43. struct proc_dir_entry *sm_proc_root = NULL;
  44. static void  (*sm_pm_power_off)(void) = NULL;
  45. static ssize_t sm_osl_read_dsdt(struct file *, char *, size_t, loff_t *);
  46. static struct file_operations proc_dsdt_operations = {
  47. read: sm_osl_read_dsdt,
  48. };
  49. static acpi_status sm_osl_suspend(u32 state);
  50. struct proc_dir_entry *bm_proc_sleep;
  51. struct proc_dir_entry *bm_proc_alarm;
  52. struct proc_dir_entry *bm_proc_gpe;
  53. static int
  54. sm_osl_proc_read_sleep (
  55.         char                    *page,
  56.         char                    **start,
  57.         off_t                   off,
  58.         int                     count,
  59.         int                     *eof,
  60.         void                    *context)
  61. {
  62. SM_CONTEXT    *system = (SM_CONTEXT*) context;
  63. char          *str = page;
  64. int           len;
  65. int           i;
  66. if (!system)
  67.                goto end;
  68. if (off != 0)
  69.                goto end;
  70. for (i = 0; i <= ACPI_S5; i++) {
  71. if (system->states[i])
  72. str += sprintf(str,"S%d ", i);
  73. }
  74. str += sprintf(str, "n");
  75. end:
  76. len = (str - page);
  77. if (len < (off + count))
  78. *eof = 1;
  79. *start = page + off;
  80. len -= off;
  81. if (len > count)
  82. len = count;
  83. if (len < 0)
  84. len = 0;
  85. return (len);
  86. }
  87. int sm_osl_proc_write_sleep (struct file *file,
  88.      const char *buffer,
  89.      unsigned long count,
  90.      void *data)
  91. {
  92. SM_CONTEXT    *system = (SM_CONTEXT*) data;
  93. char          str[10];
  94. char          *strend;
  95. unsigned long value;
  96. if (count > (sizeof(str) - 1))
  97. return -EINVAL;
  98. if (copy_from_user(str,buffer,count))
  99. return -EFAULT;
  100. str[count] = '';
  101. value = simple_strtoul(str,&strend,0);
  102. if (str == strend)
  103. return -EINVAL;
  104. if (value == 0 || value >= ACPI_S5)
  105. return -EINVAL;
  106. /*
  107.  * make sure that the sleep state is supported
  108.  */
  109. if (system->states[value] != TRUE)
  110. return -EINVAL;
  111. sm_osl_suspend(value);
  112. return (count);
  113. }
  114. /****************************************************************************
  115.  *
  116.  * FUNCTION: sm_osl_proc_read_info
  117.  *
  118.  ****************************************************************************/
  119. static int
  120. sm_osl_proc_read_info (
  121. char *page,
  122. char **start,
  123. off_t off,
  124. int  count,
  125. int  *eof,
  126. void *context)
  127. {
  128. acpi_status status = AE_OK;
  129. SM_CONTEXT *system = NULL;
  130. char *p = page;
  131. int len;
  132. acpi_system_info system_info;
  133. acpi_buffer buffer;
  134. u32 i = 0;
  135. if (!context) {
  136. goto end;
  137. }
  138. system = (SM_CONTEXT*) context;
  139. /* don't get status more than once for a single proc read */
  140. if (off != 0) {
  141. goto end;
  142. }
  143. /*
  144.  * Get ACPI CA Information.
  145.  */
  146. buffer.length  = sizeof(system_info);
  147. buffer.pointer = &system_info;
  148. status = acpi_get_system_info(&buffer);
  149. if (ACPI_FAILURE(status)) {
  150. p += sprintf(p, "ACPI-CA Version:         unknownn");
  151. }
  152. else {
  153. p += sprintf(p, "ACPI-CA Version:         %xn",
  154. system_info.acpi_ca_version);
  155. }
  156. p += sprintf(p, "Sx States Supported:     ");
  157. for (i=0; i<SM_MAX_SYSTEM_STATES; i++) {
  158. if (system->states[i]) {
  159. p += sprintf(p, "S%d ", i);
  160. }
  161. }
  162. p += sprintf(p, "n");
  163. end:
  164. len = (p - page);
  165. if (len <= off+count) *eof = 1;
  166. *start = page + off;
  167. len -= off;
  168. if (len>count) len = count;
  169. if (len<0) len = 0;
  170. return(len);
  171. }
  172. /****************************************************************************
  173.  *
  174.  * FUNCTION: sm_osl_read_dsdt
  175.  *
  176.  ****************************************************************************/
  177. static ssize_t
  178. sm_osl_read_dsdt(
  179. struct file *file,
  180. char *buf,
  181. size_t count,
  182. loff_t *ppos)
  183. {
  184. acpi_buffer acpi_buf;
  185. void *data;
  186. size_t size = 0;
  187. acpi_buf.length = 0;
  188. acpi_buf.pointer = NULL;
  189. /* determine what buffer size we will need */
  190. if (acpi_get_table(ACPI_TABLE_DSDT, 1, &acpi_buf) != AE_BUFFER_OVERFLOW) {
  191. return 0;
  192. }
  193. acpi_buf.pointer = kmalloc(acpi_buf.length, GFP_KERNEL);
  194. if (!acpi_buf.pointer) {
  195. return -ENOMEM;
  196. }
  197. /* get the table for real */
  198. if (!ACPI_SUCCESS(acpi_get_table(ACPI_TABLE_DSDT, 1, &acpi_buf))) {
  199. kfree(acpi_buf.pointer);
  200. return 0;
  201. }
  202. if (*ppos < acpi_buf.length) {
  203. data = acpi_buf.pointer + file->f_pos;
  204. size = acpi_buf.length - file->f_pos;
  205. if (size > count)
  206. size = count;
  207. if (copy_to_user(buf, data, size)) {
  208. kfree(acpi_buf.pointer);
  209. return -EFAULT;
  210. }
  211. }
  212. kfree(acpi_buf.pointer);
  213. *ppos += size;
  214. return size;
  215. }
  216. static int
  217. sm_osl_proc_read_alarm (
  218. char                    *page,
  219. char                    **start,
  220. off_t                   off,
  221. int                     count,
  222. int                     *eof,
  223. void                    *context)
  224. {
  225. char *str = page;
  226. int len;
  227. u32 sec,min,hr;
  228. u32 day,mo,yr;
  229. if (off != 0) goto out;
  230. spin_lock(&rtc_lock);
  231. sec = CMOS_READ(RTC_SECONDS_ALARM);
  232. min = CMOS_READ(RTC_MINUTES_ALARM);
  233. hr = CMOS_READ(RTC_HOURS_ALARM);
  234. #if 0
  235. /* if I ever get an FACP with proper values, maybe I'll enable this code */
  236. if (acpi_gbl_FADT->day_alrm)
  237. day = CMOS_READ(acpi_gbl_FADT->day_alrm);
  238. else
  239. day =  CMOS_READ(RTC_DAY_OF_MONTH);
  240. if (acpi_gbl_FADT->mon_alrm)
  241. mo = CMOS_READ(acpi_gbl_FADT->mon_alrm);
  242. else
  243. mo = CMOS_READ(RTC_MONTH);;
  244. if (acpi_gbl_FADT->century)
  245. yr = CMOS_READ(acpi_gbl_FADT->century) * 100 + CMOS_READ(RTC_YEAR);
  246. else
  247. yr = CMOS_READ(RTC_YEAR);
  248. #else
  249. day = CMOS_READ(RTC_DAY_OF_MONTH);
  250. mo = CMOS_READ(RTC_MONTH);
  251. yr = CMOS_READ(RTC_YEAR);
  252. #endif
  253. spin_unlock(&rtc_lock);
  254. BCD_TO_BIN(sec);
  255. BCD_TO_BIN(min);
  256. BCD_TO_BIN(hr);
  257. BCD_TO_BIN(day);
  258. BCD_TO_BIN(mo);
  259. BCD_TO_BIN(yr);
  260. str += sprintf(str,"%4.4u-",yr);
  261. str += (mo > 12) ?
  262. sprintf(str,"**-") :
  263. sprintf(str,"%2.2u-",mo);
  264. str += (day > 31) ?
  265. sprintf(str,"** ") :
  266. sprintf(str,"%2.2u ",day);
  267. str += (hr > 23) ?
  268. sprintf(str,"**:") :
  269. sprintf(str,"%2.2u:",hr);
  270. str += (min > 59) ?
  271. sprintf(str,"**:") :
  272. sprintf(str,"%2.2u:",min);
  273. str += (sec > 59) ?
  274. sprintf(str,"**n") :
  275. sprintf(str,"%2.2un",sec);
  276.  out:
  277. len = str - page;
  278. if (len < count) *eof = 1;
  279. else if (len > count) len = count;
  280. if (len < 0) len = 0;
  281. *start = page;
  282. return len;
  283. }
  284. static int get_date_field(char **str, u32 *value)
  285. {
  286. char *next,*strend;
  287. int error = -EINVAL;
  288. /* try to find delimeter, only to insert null;
  289.  *  the end of string won't have one, but is still valid
  290.  */
  291. next = strpbrk(*str,"- :");
  292. if (next) *next++ = '';
  293. *value = simple_strtoul(*str,&strend,10);
  294. /* signal success if we got a good digit */
  295. if (strend != *str) error = 0;
  296. if (next) *str = next;
  297. return error;
  298. }
  299. int sm_osl_proc_write_alarm (
  300. struct file *file,
  301. const char *buffer,
  302. unsigned long count,
  303. void *data)
  304. {
  305. char buf[30];
  306. char *str = buf;
  307. u32 sec,min,hr;
  308. u32 day,mo,yr;
  309. int adjust = 0;
  310. unsigned char rtc_control;
  311. int error = -EINVAL;
  312. if (count > sizeof(buf) - 1) return -EINVAL;
  313. if (copy_from_user(str,buffer,count)) return -EFAULT;
  314. str[count] = '';
  315. /* check for time adjustment */
  316. if (str[0] == '+') {
  317. str++;
  318. adjust = 1;
  319. }
  320. if ((error = get_date_field(&str,&yr)))  goto out;
  321. if ((error = get_date_field(&str,&mo)))  goto out;
  322. if ((error = get_date_field(&str,&day))) goto out;
  323. if ((error = get_date_field(&str,&hr)))  goto out;
  324. if ((error = get_date_field(&str,&min))) goto out;
  325. if ((error = get_date_field(&str,&sec))) goto out;
  326. if (sec > 59) {
  327. min += 1;
  328. sec -= 60;
  329. }
  330. if (min > 59) {
  331. hr += 1;
  332. min -= 60;
  333. if (hr > 23) {
  334. day += 1;
  335. hr -= 24;
  336. }
  337. if (day > 31) { 
  338. mo += 1;
  339. day -= 31;
  340. }
  341. if (mo > 12) {
  342. yr += 1;
  343. mo -= 12;
  344. }
  345. spin_lock_irq(&rtc_lock);
  346. rtc_control = CMOS_READ(RTC_CONTROL);
  347. if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
  348. BIN_TO_BCD(yr);
  349. BIN_TO_BCD(mo);
  350. BIN_TO_BCD(day);
  351. BIN_TO_BCD(hr);
  352. BIN_TO_BCD(min);
  353. BIN_TO_BCD(sec);
  354. }
  355. if (adjust) {
  356. yr  += CMOS_READ(RTC_YEAR);
  357. mo  += CMOS_READ(RTC_MONTH);
  358. day += CMOS_READ(RTC_DAY_OF_MONTH);
  359. hr  += CMOS_READ(RTC_HOURS);
  360. min += CMOS_READ(RTC_MINUTES);
  361. sec += CMOS_READ(RTC_SECONDS);
  362. }
  363. spin_unlock_irq(&rtc_lock);
  364. if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
  365. BCD_TO_BIN(yr);
  366. BCD_TO_BIN(mo);
  367. BCD_TO_BIN(day);
  368. BCD_TO_BIN(hr);
  369. BCD_TO_BIN(min);
  370. BCD_TO_BIN(sec);
  371. }
  372. if (sec > 59) {
  373. min++;
  374. sec -= 60;
  375. }
  376. if (min > 59) {
  377. hr++;
  378. min -= 60;
  379. }
  380. if (hr > 23) {
  381. day++;
  382. hr -= 24;
  383. }
  384. if (day > 31) {
  385. mo++;
  386. day -= 31;
  387. }
  388. if (mo > 12) {
  389. yr++;
  390. mo -= 12;
  391. }
  392. if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
  393. BIN_TO_BCD(yr);
  394. BIN_TO_BCD(mo);
  395. BIN_TO_BCD(day);
  396. BIN_TO_BCD(hr);
  397. BIN_TO_BCD(min);
  398. BIN_TO_BCD(sec);
  399. }
  400. spin_lock_irq(&rtc_lock);
  401. /* write the fields the rtc knows about */
  402. CMOS_WRITE(hr,RTC_HOURS_ALARM);
  403. CMOS_WRITE(min,RTC_MINUTES_ALARM);
  404. CMOS_WRITE(sec,RTC_SECONDS_ALARM);
  405. /* If the system supports an enhanced alarm, it will have non-zero
  406.  * offsets into the CMOS RAM here.
  407.  * Which for some reason are pointing to the RTC area of memory.
  408.  */
  409. #if 0
  410. if (acpi_gbl_FADT->day_alrm) CMOS_WRITE(day,acpi_gbl_FADT->day_alrm);
  411. if (acpi_gbl_FADT->mon_alrm) CMOS_WRITE(mo,acpi_gbl_FADT->mon_alrm);
  412. if (acpi_gbl_FADT->century)  CMOS_WRITE(yr / 100,acpi_gbl_FADT->century);
  413. #endif
  414. /* enable the rtc alarm interrupt */
  415. if (!(rtc_control & RTC_AIE)) {
  416. rtc_control |= RTC_AIE;
  417. CMOS_WRITE(rtc_control,RTC_CONTROL);
  418. CMOS_READ(RTC_INTR_FLAGS);
  419. }
  420. /* unlock the lock on the rtc now that we're done with it */
  421. spin_unlock_irq(&rtc_lock);
  422. acpi_hw_register_bit_access(ACPI_WRITE,ACPI_MTX_LOCK, RTC_EN, 1);
  423. file->f_pos += count;
  424. error = 0;
  425.  out:
  426. return error ? error : count;
  427. }
  428. static int 
  429. sm_osl_proc_read_gpe(
  430. char                    *page,
  431. char                    **start,
  432. off_t                   off,
  433. int                     count,
  434. int                     *eof,
  435. void                    *context)
  436. {
  437. char *str = page;
  438. int size;
  439. int length;
  440. int i;
  441. u32 addr,data;
  442. if (off) goto out;
  443. if (acpi_gbl_FADT->V1_gpe0blk) {
  444. length = acpi_gbl_FADT->gpe0blk_len / 2;
  445. str += sprintf(str,"GPE0: ");
  446. for (i = length; i > 0; i--) {
  447. addr = GPE0_EN_BLOCK | (i - 1);
  448. data = acpi_hw_register_read(ACPI_MTX_LOCK,addr);
  449. str += sprintf(str,"%2.2x ",data);
  450. }
  451. str += sprintf(str,"n");
  452. str += sprintf(str,"Status: ");
  453. for (i = length; i > 0; i--) {
  454. addr = GPE0_STS_BLOCK | (i - 1);
  455. data = acpi_hw_register_read(ACPI_MTX_LOCK,addr);
  456. str += sprintf(str,"%2.2x ",data);
  457. }
  458. str += sprintf(str,"n");
  459. }
  460. if (acpi_gbl_FADT->V1_gpe1_blk) {
  461. length = acpi_gbl_FADT->gpe1_blk_len / 2;
  462. str += sprintf(str,"GPE1: ");
  463. for (i = length; i > 0; i--) {
  464. addr = GPE1_EN_BLOCK | (i - 1);
  465. data = acpi_hw_register_read(ACPI_MTX_LOCK,addr);
  466. str += sprintf(str,"%2.2x",data);
  467. }
  468. str += sprintf(str,"n");
  469. str += sprintf(str,"Status: ");
  470. for (i = length; i > 0; i--) {
  471. addr = GPE1_STS_BLOCK | (i - 1);
  472. data = acpi_hw_register_read(ACPI_MTX_LOCK,addr);
  473. str += sprintf(str,"%2.2x",data);
  474. }
  475. str += sprintf(str,"n");
  476. }
  477.  out:
  478. size = str - page;
  479. if (size < count) *eof = 1;
  480. else if (size > count) size = count;
  481. if (size < 0) size = 0;
  482. *start = page;
  483. return size;
  484. }
  485. static int
  486. sm_osl_proc_write_gpe (
  487. struct file *file,
  488. const char *buffer,
  489. unsigned long count,
  490. void *data)
  491. {
  492. char buf[256];
  493. char *str = buf;
  494. char *next;
  495. int error = -EINVAL;
  496. u32 addr,value = 0;
  497. if (count > sizeof(buf) + 1) return -EINVAL;
  498. if (copy_from_user(str,buffer,count)) return -EFAULT;
  499. str[count] = '';
  500. /* set addr to which block to refer to */
  501. if (!strncmp(str,"GPE0 ",5))      addr = GPE0_EN_BLOCK;
  502. else if (!strncmp(str,"GPE1 ",5)) addr = GPE1_EN_BLOCK;
  503. else goto out;
  504. str += 5;
  505. /* set low order bits to index of bit to set */
  506. addr |= simple_strtoul(str,&next,0);
  507. if (next == str) goto out;
  508. if (next) {
  509. str = ++next;
  510. value = simple_strtoul(str,&next,0);
  511. if (next == str) value = 1;
  512. }
  513. value = acpi_hw_register_bit_access(ACPI_WRITE,ACPI_MTX_LOCK,addr,(value ? 1 : 0));
  514. error = 0;
  515.  out:
  516. return error ? error : count;
  517. }
  518. /****************************************************************************
  519.  *
  520.  * FUNCTION:    sm_osl_suspend
  521.  *
  522.  * PARAMETERS:  %state: Sleep state to enter. Assumed that caller has filtered
  523.  *              out bogus values, so it's one of S1, S2, S3 or S4
  524.  *
  525.  * RETURN:      ACPI_STATUS, whether or not we successfully entered and
  526.  *              exited sleep.
  527.  *
  528.  * DESCRIPTION:
  529.  * This function is the meat of the sleep routine, as far as the ACPI-CA is
  530.  * concerned.
  531.  *
  532.  * See Chapter 9 of the ACPI 2.0 spec for details concerning the methodology here.
  533.  *
  534.  * It will do the following things:
  535.  * - Call arch-specific routines to save the processor and kernel state
  536.  * - Call acpi_enter_sleep_state to actually go to sleep
  537.  * ....
  538.  * When we wake back up, we will:
  539.  * - Restore the processor and kernel state
  540.  * - Return to the user
  541.  *
  542.  * By having this routine in here, it hides it from every part of the CA,
  543.  * so it can remain OS-independent. The only function that calls this is
  544.  * sm_proc_write_sleep, which gets the sleep state to enter from the user.
  545.  *
  546.  ****************************************************************************/
  547. static acpi_status
  548. sm_osl_suspend(u32 state)
  549. {
  550. acpi_status status = AE_ERROR;
  551. unsigned long wakeup_address;
  552. /* get out if state is invalid */
  553. if (state < ACPI_S1 || state > ACPI_S5) 
  554. goto acpi_sleep_done;
  555. /* make sure we don't get any suprises */
  556. disable();
  557. /* TODO: save device state and suspend them */
  558. /* save the processor state to memory if going into S2 or S3;
  559.  * save it to disk if going into S4.
  560.  * Also, set the FWV if going into an STR state
  561.  */
  562. if (state == ACPI_S2 || state == ACPI_S3) {
  563. #ifdef DONT_USE_UNTIL_LOWLEVEL_CODE_EXISTS
  564. wakeup_address = acpi_save_state_mem((unsigned long)&&acpi_sleep_done);
  565. if (!wakeup_address) goto acpi_sleep_done;
  566. acpi_set_firmware_waking_vector(
  567. (ACPI_PHYSICAL_ADDRESS)wakeup_address);
  568. #endif
  569. } else if (state == ACPI_S4)
  570. #ifdef DONT_USE_UNTIL_LOWLEVEL_CODE_EXISTS
  571. if (acpi_save_state_disk((unsigned long)&&acpi_sleep_done)) 
  572. goto acpi_sleep_done;
  573. #endif
  574. /* set status, since acpi_enter_sleep_state won't return unless something
  575.  * goes wrong, or it's just S1.
  576.  */
  577. status = AE_OK;
  578. mdelay(10);
  579. status = acpi_enter_sleep_state(state);
  580.  acpi_sleep_done:
  581. /* pause for a bit to allow devices to come back on */
  582. mdelay(10);
  583. /* make sure that the firmware waking vector is reset */
  584. acpi_set_firmware_waking_vector((ACPI_PHYSICAL_ADDRESS)0);
  585. acpi_leave_sleep_state(state);
  586. /* TODO: resume devices and restore their state */
  587. enable();
  588. return status;
  589. }
  590. /****************************************************************************
  591.  *
  592.  * FUNCTION: sm_osl_power_down
  593.  *
  594.  ****************************************************************************/
  595. void
  596. sm_osl_power_down (void)
  597. {
  598. /* Power down the system (S5 = soft off). */
  599. sm_osl_suspend(ACPI_S5);
  600. }
  601. /****************************************************************************
  602.  *
  603.  * FUNCTION: sm_osl_add_device
  604.  *
  605.  ****************************************************************************/
  606. acpi_status
  607. sm_osl_add_device(
  608. SM_CONTEXT *system)
  609. {
  610. u32 i = 0;
  611. struct proc_dir_entry *bm_proc_dsdt;
  612. if (!system) {
  613. return(AE_BAD_PARAMETER);
  614. }
  615. printk("ACPI: System firmware supports");
  616. for (i=0; i<SM_MAX_SYSTEM_STATES; i++) {
  617. if (system->states[i]) {
  618. printk(" S%d", i);
  619. }
  620. }
  621. printk("n");
  622. if (system->states[ACPI_STATE_S5]) {
  623. sm_pm_power_off = pm_power_off;
  624. pm_power_off = sm_osl_power_down;
  625. }
  626. create_proc_read_entry(SM_PROC_INFO, S_IRUGO,
  627. sm_proc_root, sm_osl_proc_read_info, (void*)system);
  628. bm_proc_sleep = create_proc_read_entry("sleep", S_IFREG | S_IRUGO | S_IWUSR,
  629.     sm_proc_root, sm_osl_proc_read_sleep, (void*)system);
  630. if (bm_proc_sleep)
  631. bm_proc_sleep->write_proc = sm_osl_proc_write_sleep;
  632. bm_proc_alarm = create_proc_read_entry("alarm", S_IFREG | S_IRUGO | S_IWUSR,
  633.        sm_proc_root,sm_osl_proc_read_alarm, NULL);
  634. if (bm_proc_alarm)
  635. bm_proc_alarm->write_proc = sm_osl_proc_write_alarm;
  636. bm_proc_gpe = create_proc_read_entry("gpe", S_IFREG | S_IRUGO | S_IWUSR,
  637.      sm_proc_root,sm_osl_proc_read_gpe,NULL);
  638. if (bm_proc_gpe)
  639. bm_proc_gpe->write_proc = sm_osl_proc_write_gpe;
  640. /*
  641.  * Get a wakeup address for use when we come back from sleep.
  642.  * At least on IA-32, this needs to be in low memory.
  643.  * When sleep is supported on other arch's, then we may want
  644.  * to move this out to another place, but GFP_LOW should suffice
  645.  * for now.
  646.  */
  647. #if 0
  648. if (system->states[ACPI_S3] || system->states[ACPI_S4]) {
  649. acpi_wakeup_address = (unsigned long)virt_to_phys(get_free_page(GFP_LOWMEM));
  650. printk(KERN_INFO "ACPI: Have wakeup address 0x%8.8xn",acpi_wakeup_address);
  651. }
  652. #endif
  653. /*
  654.  * This returns more than a page, so we need to use our own file ops,
  655.  * not proc's generic ones
  656.  */
  657. bm_proc_dsdt = create_proc_entry(SM_PROC_DSDT, S_IRUSR, sm_proc_root);
  658. if (bm_proc_dsdt) {
  659. bm_proc_dsdt->proc_fops = &proc_dsdt_operations;
  660. }
  661. return(AE_OK);
  662. }
  663. /****************************************************************************
  664.  *
  665.  * FUNCTION: sm_osl_remove_device
  666.  *
  667.  ****************************************************************************/
  668. acpi_status
  669. sm_osl_remove_device (
  670. SM_CONTEXT *system)
  671. {
  672. if (!system) {
  673. return(AE_BAD_PARAMETER);
  674. }
  675. remove_proc_entry(SM_PROC_INFO, sm_proc_root);
  676. remove_proc_entry(SM_PROC_DSDT, sm_proc_root);
  677. return(AE_OK);
  678. }
  679. /****************************************************************************
  680.  *
  681.  * FUNCTION: sm_osl_generate_event
  682.  *
  683.  ****************************************************************************/
  684. acpi_status
  685. sm_osl_generate_event (
  686. u32 event,
  687. SM_CONTEXT *system)
  688. {
  689. acpi_status status = AE_OK;
  690. if (!system) {
  691. return(AE_BAD_PARAMETER);
  692. }
  693. switch (event) {
  694. default:
  695. return(AE_BAD_PARAMETER);
  696. break;
  697. }
  698. return(status);
  699. }
  700. /****************************************************************************
  701.  *
  702.  * FUNCTION: sm_osl_init
  703.  *
  704.  * PARAMETERS: <none>
  705.  *
  706.  * RETURN: 0: Success
  707.  *
  708.  * DESCRIPTION: Module initialization.
  709.  *
  710.  ****************************************************************************/
  711. static int __init
  712. sm_osl_init (void)
  713. {
  714. acpi_status status = AE_OK;
  715. /* abort if no busmgr */
  716. if (!bm_proc_root)
  717. return -ENODEV;
  718. sm_proc_root = bm_proc_root;
  719. if (!sm_proc_root) {
  720. status = AE_ERROR;
  721. }
  722. else {
  723. status = sm_initialize();
  724. }
  725. return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;
  726. }
  727. /****************************************************************************
  728.  *
  729.  * FUNCTION: sm_osl_cleanup
  730.  *
  731.  * PARAMETERS: <none>
  732.  *
  733.  * RETURN: <none>
  734.  *
  735.  * DESCRIPTION: Module cleanup.
  736.  *
  737.  ****************************************************************************/
  738. static void __exit
  739. sm_osl_cleanup (void)
  740. {
  741. sm_terminate();
  742. return;
  743. }
  744. module_init(sm_osl_init);
  745. module_exit(sm_osl_cleanup);