]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
2005-12-03 Vincent Pelletier <subdino2004@yahoo.fr>
authorsubdino <subdino@localhost>
Sat, 3 Dec 2005 16:18:27 +0000 (16:18 +0000)
committersubdino <subdino@localhost>
Sat, 3 Dec 2005 16:18:27 +0000 (16:18 +0000)
        * commands/i386/pc/play.c: New file.
        * conf/i386-pc.rmk (pkgdata_MODULES): Added play.mod.
        (play_mod_SOURCES, play_mod_CFLAGS, play_mod_LDFLAGS): New
        macros.

ChangeLog
commands/i386/pc/play.c [new file with mode: 0644]
conf/i386-pc.mk
conf/i386-pc.rmk

index 2af205e331df2225afdb2d066eeec5b46b1f47ba..a788355edf694f1bcbd8dce8777cfe63db031c31 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2005-12-03  Vincent Pelletier  <subdino2004@yahoo.fr>
+
+       * commands/i386/pc/play.c: New file.
+       * conf/i386-pc.rmk (pkgdata_MODULES): Added play.mod.
+       (play_mod_SOURCES, play_mod_CFLAGS, play_mod_LDFLAGS): New
+       macros.
+       
 2005-11-27  Marco Gerards  <mgerards@xs4all.nl>
 
        * include/grub/dl.h (GRUB_MOD_INIT): Use `__attribute__
diff --git a/commands/i386/pc/play.c b/commands/i386/pc/play.c
new file mode 100644 (file)
index 0000000..f3f524b
--- /dev/null
@@ -0,0 +1,233 @@
+/* play.c - command to play a tune  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Lots of this file is borrowed from GNU/Hurd generic-speaker driver.  */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/term.h>
+#include <grub/misc.h>
+
+#define BASE_TEMPO 120
+
+/* Read a byte from a port.  */
+static inline unsigned char
+inb (unsigned short port)
+{
+  unsigned char value;
+  asm volatile ("inb    %w1, %0" : "=a" (value) : "Nd" (port));
+  return value;
+}
+
+/* Write a byte to a port.  */
+static inline void
+outb (unsigned short port, unsigned char value)
+{
+  asm volatile ("outb   %b0, %w1" : : "a" (value), "Nd" (port));
+}
+
+/* The speaker port.  */
+#define SPEAKER                        0x61
+
+/* If 0, follow state of SPEAKER_DATA bit, otherwise enable output
+   from timer 2.  */
+#define SPEAKER_TMR2           0x01
+
+/* If SPEAKER_TMR2 is not set, this provides direct input into the
+   speaker.  Otherwise, this enables or disables the output from the
+   timer.  */
+#define SPEAKER_DATA           0x02
+
+/* The PIT channel value ports.  You can write to and read from them.
+   Do not mess with timer 0 or 1.  */
+#define PIT_COUNTER_0          0x40
+#define PIT_COUNTER_1          0x41
+#define PIT_COUNTER_2          0x42
+
+/* The frequency of the PIT clock.  */
+#define PIT_FREQUENCY          0x1234dd
+
+/* The PIT control port.  You can only write to it.  Do not mess with
+   timer 0 or 1.  */
+#define PIT_CTRL               0x43
+#define PIT_CTRL_SELECT_MASK   0xc0
+#define PIT_CTRL_SELECT_0      0x00
+#define PIT_CTRL_SELECT_1      0x40
+#define PIT_CTRL_SELECT_2      0x80
+
+/* Read and load control.  */
+#define PIT_CTRL_READLOAD_MASK 0x30
+#define PIT_CTRL_COUNTER_LATCH 0x00    /* Hold timer value until read.  */
+#define PIT_CTRL_READLOAD_LSB  0x10    /* Read/load the LSB.  */
+#define PIT_CTRL_READLOAD_MSB  0x20    /* Read/load the MSB.  */
+#define PIT_CTRL_READLOAD_WORD 0x30    /* Read/load the LSB then the MSB.  */
+
+/* Mode control.  */
+#define PIT_CTRL_MODE_MASK     0x0e
+
+/* Interrupt on terminal count.  Setting the mode sets output to low.
+   When counter is set and terminated, output is set to high.  */
+#define PIT_CTRL_INTR_ON_TERM  0x00
+
+/* Programmable one-shot.  When loading counter, output is set to
+   high.  When counter terminated, output is set to low.  Can be
+   triggered again from that point on by setting the gate pin to
+   high.  */
+#define PIT_CTRL_PROGR_ONE_SHOT        0x02
+
+/* Rate generator.  Output is low for one period of the counter, and
+   high for the other.  */
+#define PIT_CTRL_RATE_GEN      0x04
+
+/* Square wave generator.  Output is low for one half of the period,
+   and high for the other half.  */
+#define PIT_CTRL_SQUAREWAVE_GEN        0x06
+
+/* Software triggered strobe.  Setting the mode sets output to high.
+   When counter is set and terminated, output is set to low.  */
+#define PIT_CTRL_SOFTSTROBE    0x08
+
+/* Hardware triggered strobe.  Like software triggered strobe, but
+   only starts the counter when the gate pin is set to high.  */
+#define PIT_CTRL_HARDSTROBE    0x0a
+
+/* Count mode.  */
+#define PIT_CTRL_COUNT_MASK    0x01
+#define PIT_CTRL_COUNT_BINARY  0x00    /* 16-bit binary counter.  */
+#define PIT_CTRL_COUNT_BCD     0x01    /* 4-decade BCD counter.  */
+
+#define T_REST                 ((short) 0)
+#define T_FINE                 ((short) -1)
+
+struct note
+{
+  short pitch;
+  short duration;
+};
+
+static void
+beep_off (void)
+{
+  unsigned char status;
+
+  status = inb (SPEAKER);
+  outb (SPEAKER, status & ~(SPEAKER_TMR2 | SPEAKER_DATA));
+}
+
+static void
+beep_on (short pitch)
+{
+  unsigned char status;
+  unsigned int counter;
+
+  if (pitch < 20)
+    pitch = 20;
+  else if (pitch > 20000)
+    pitch = 20000;
+
+  counter = PIT_FREQUENCY / pitch;
+
+  /* Program timer 2.  */
+  outb (PIT_CTRL, PIT_CTRL_SELECT_2 | PIT_CTRL_READLOAD_WORD
+       | PIT_CTRL_SQUAREWAVE_GEN | PIT_CTRL_COUNT_BINARY);
+  outb (PIT_COUNTER_2, counter & 0xff);                /* LSB */
+  outb (PIT_COUNTER_2, (counter >> 8) & 0xff); /* MSB */
+
+  /* Start speaker.  */
+  status = inb (SPEAKER);
+  outb (SPEAKER, status | SPEAKER_TMR2 | SPEAKER_DATA);
+
+}
+
+static grub_err_t
+grub_cmd_play (struct grub_arg_list *state __attribute__ ((unused)),
+              int argc, char **args)
+{
+  grub_file_t file;
+  struct note buf;
+  int tempo;
+  unsigned int to;
+
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
+
+  file = grub_file_open (args[0]);
+  if (! file)
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+
+  if (grub_file_read (file, (void *) &tempo, sizeof(tempo)) != sizeof(tempo))
+    {
+      grub_file_close (file);
+      return grub_error (GRUB_ERR_FILE_READ_ERROR,
+                         "file doesn't even contains a full tempo record");
+    }
+
+  grub_dprintf ("play","tempo = %d\n", tempo);
+
+  while (grub_file_read (file, (void *) &buf,
+                         sizeof (struct note)) == sizeof (struct note)
+         && buf.pitch != T_FINE && grub_checkkey () < 0)
+    {
+      
+      grub_dprintf ("play", "pitch = %d, duration = %d\n", buf.pitch,
+                    buf.duration);
+
+      switch (buf.pitch)
+        {
+          case T_REST:
+            beep_off ();
+            break;
+
+          default:
+            beep_on (buf.pitch);
+            break;
+        }
+
+      to = grub_get_rtc () + BASE_TEMPO * buf.duration / tempo;
+      while (((unsigned int) grub_get_rtc () <= to) && (grub_checkkey () < 0))
+        ;
+
+    }
+
+  beep_off ();
+
+  grub_file_close (file);
+
+  while (grub_checkkey () > 0)
+    grub_getkey ();
+
+  return 0;
+}
+
+\f
+GRUB_MOD_INIT(play)
+{
+  (void)mod;                   /* To stop warning. */
+  grub_register_command ("play", grub_cmd_play, GRUB_COMMAND_FLAG_BOTH,
+                        "play FILE", "Play a tune", 0);
+}
+
+GRUB_MOD_FINI(play)
+{
+  grub_unregister_command ("play");
+}
index cb3f58491578c0066d1a4d8be1f3a6924fe2fd4a..05f60f81affd1d425c7861e7cf7e5875d4a43a1b 100644 (file)
@@ -1336,7 +1336,7 @@ grub-install: util/i386/pc/grub-install.in config.status
 # Modules.
 pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod vga.mod   \
        _multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod      \
-       vbe.mod vesafb.mod vbetest.mod vbeinfo.mod
+       vbe.mod vesafb.mod vbetest.mod vbeinfo.mod play.mod
 
 # For _chain.mod.
 _chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -2328,4 +2328,55 @@ fs-vbetest_mod-commands_i386_pc_vbetest.lst: commands/i386/pc/vbetest.c genfslis
 vbetest_mod_CFLAGS = $(COMMON_CFLAGS)
 vbetest_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For play.mod.
+play_mod_SOURCES = commands/i386/pc/play.c
+CLEANFILES += play.mod mod-play.o mod-play.c pre-play.o play_mod-commands_i386_pc_play.o def-play.lst und-play.lst
+MOSTLYCLEANFILES += play_mod-commands_i386_pc_play.d
+DEFSYMFILES += def-play.lst
+UNDSYMFILES += und-play.lst
+
+play.mod: pre-play.o mod-play.o
+       -rm -f $@
+       $(LD) $(play_mod_LDFLAGS) $(LDFLAGS) -r -d -o $@ $^
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@
+
+pre-play.o: play_mod-commands_i386_pc_play.o
+       -rm -f $@
+       $(LD) $(play_mod_LDFLAGS) -r -d -o $@ $^
+
+mod-play.o: mod-play.c
+       $(CC) $(CPPFLAGS) $(CFLAGS) $(play_mod_CFLAGS) -c -o $@ $<
+
+mod-play.c: moddep.lst genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'play' $< > $@ || (rm -f $@; exit 1)
+
+def-play.lst: pre-play.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 play/' > $@
+
+und-play.lst: pre-play.o
+       echo 'play' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+play_mod-commands_i386_pc_play.o: commands/i386/pc/play.c
+       $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(play_mod_CFLAGS) -c -o $@ $<
+
+play_mod-commands_i386_pc_play.d: commands/i386/pc/play.c
+       set -e;           $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(play_mod_CFLAGS) -M $<    | sed 's,play\.o[ :]*,play_mod-commands_i386_pc_play.o $@ : ,g' > $@;           [ -s $@ ] || rm -f $@
+
+-include play_mod-commands_i386_pc_play.d
+
+CLEANFILES += cmd-play_mod-commands_i386_pc_play.lst fs-play_mod-commands_i386_pc_play.lst
+COMMANDFILES += cmd-play_mod-commands_i386_pc_play.lst
+FSFILES += fs-play_mod-commands_i386_pc_play.lst
+
+cmd-play_mod-commands_i386_pc_play.lst: commands/i386/pc/play.c gencmdlist.sh
+       set -e;           $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(play_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh play > $@ || (rm -f $@; exit 1)
+
+fs-play_mod-commands_i386_pc_play.lst: commands/i386/pc/play.c genfslist.sh
+       set -e;           $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(play_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh play > $@ || (rm -f $@; exit 1)
+
+
+play_mod_CFLAGS = $(COMMON_CFLAGS)
+play_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
index ef971ad1c414d85caf642338e5ff570f3f508c33..4cf37dc54e82b8cd0b0bec76c395e86fa3fa82b1 100644 (file)
@@ -114,7 +114,7 @@ grub_install_SOURCES = util/i386/pc/grub-install.in
 # Modules.
 pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod vga.mod   \
        _multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod      \
-       vbe.mod vesafb.mod vbetest.mod vbeinfo.mod
+       vbe.mod vesafb.mod vbetest.mod vbeinfo.mod play.mod
 
 # For _chain.mod.
 _chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -196,4 +196,9 @@ vbetest_mod_SOURCES = commands/i386/pc/vbetest.c
 vbetest_mod_CFLAGS = $(COMMON_CFLAGS)
 vbetest_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For play.mod.
+play_mod_SOURCES = commands/i386/pc/play.c
+play_mod_CFLAGS = $(COMMON_CFLAGS)
+play_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk