main.c 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /*
  2. * PC Speaker Driver
  3. * main.c
  4. *
  5. * Copyright (C) 2016 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU Affero General Public License as
  9. * published by the Free Software Foundation, either version 3 of the
  10. * License, or (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 Affero General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include "speaker.h"
  21. #include <timer.h>
  22. #include <device.h>
  23. const char driver_name[] = "speaker";
  24. static dword_t speaker_init(void);
  25. static dword_t speaker_cleanup(void);
  26. static dword_t speaker_ioctl(device_t *device,
  27. dword_t control_code,
  28. const void *in_buffer,
  29. size_t in_length,
  30. void *out_buffer,
  31. size_t out_length);
  32. static char_dev_driver_t speaker_driver =
  33. {
  34. .init_proc = speaker_init,
  35. .cleanup_proc = speaker_cleanup,
  36. .ioctl_proc = speaker_ioctl
  37. };
  38. static void speaker_on(dword_t frequency)
  39. {
  40. dword_t divisor = TIMER_BASE_FREQUENCY / frequency;
  41. outportb(TIMER_CMD_PORT, TIMER_SQUARE_WAVE(2));
  42. outportb(TIMER_CHANNEL_PORT(2), (byte_t) (divisor & 0xFF));
  43. outportb(TIMER_CHANNEL_PORT(2), (byte_t) (divisor >> 8));
  44. outportb(0x61, inportb(0x61) | 3);
  45. }
  46. static void speaker_off()
  47. {
  48. outportb(0x61, inportb(0x61) & 0xFC);
  49. }
  50. static dword_t speaker_init(void)
  51. {
  52. return ERR_SUCCESS;
  53. }
  54. static dword_t speaker_cleanup(void)
  55. {
  56. speaker_off();
  57. return ERR_SUCCESS;
  58. }
  59. static dword_t speaker_ioctl(device_t *device,
  60. dword_t control_code,
  61. const void *in_buffer,
  62. size_t in_length,
  63. void *out_buffer,
  64. size_t out_length)
  65. {
  66. switch (control_code)
  67. {
  68. case SPEAKER_IOCTL_ON:
  69. if (in_length < sizeof(dword_t)) return ERR_SMALLBUF;
  70. speaker_on(*(dword_t*)in_buffer);
  71. return ERR_SUCCESS;
  72. case SPEAKER_IOCTL_OFF:
  73. speaker_off();
  74. return ERR_SUCCESS;
  75. default:
  76. return ERR_INVALID;
  77. }
  78. }
  79. dword_t driver_load(const char *parameters)
  80. {
  81. return register_char_dev_driver(&speaker_driver);
  82. }