To be used with ~/Courses/C4029/ACPI/call*

Kernel Considerations:
  - The kernel provides basic services including:
      a. process management - supplies resources, schedules process time
      b. memory management - provides virtual memory, efficient operation
      c. file system management - all entities look like file systems
      d. device drivers - peripherals connected to computer
      e. communication with remote devices
  - The interface to the kernel is via system calls (System Call Interface)
    (the gnu c library is usually an intermediary)
  - If an process performs a system call, a software interrupt is sent
    to the kernel, which then dispatches the appropriate interrupt
    handler and continues its work after the handler has finished.
  - If the handler takes too long, a system crash is likely
  - The kernel is limited to about 1GB of virtual and physical memory.
  - The kernel's memory is not pageable.
  - The kernel usually wants physically contiguous memory.
  - Often, the kernel must allocate the memory without sleeping.
  - Mistakes in the kernel have a much higher cost than they do elsewhere.

Hence:
  kernel memory allocation is handled by 
    void *kmalloc(size_t size, int flags)
    void kfree(const void *obj)

  where 'flags' controls the behavior of memory allocation. 
  There are three groups of flags:
    1. action modifiers:
         tell the kernel how to allocate memory. They specify, for
         example, whether the call to kmalloc() can block in order 
         to satisfy the allocation.
    2. zone modifiers:
         tell the kernel from where the request should be satisfied. 
         For example, some requests may need to be satisfied from
         memory that hardware can access through direct memory access (DMA). 
    3. types:
         specify a type of allocation. They group together relevant
         action and zone modifiers into a single mnemonic.
         GFP = Get Free Page

           GFP_ATOMIC 
              - The allocation is high-priority and does not
                sleep.  This is the flag to use in interrupt handlers, 
                bottom halves and other situations where you cannot sleep.
           GFP_DMA    
              - This is an allocation of DMA-capable memory. 
                Device drivers that need DMA-capable memory use this flag.
           GFP_KERNEL
              - This is a normal allocation and may block. This is the
                flag to use in process context code when it is safe to sleep.
           GFP_NOFS
              - This allocation might block and might initiate disk
                I/O, but it does not initiate a filesystem operation. 
                This is the flag to use in filesystem code when you
                cannot start another filesystem operation.
           GFP_NOIO
              - This allocation might block, but it does not initiate 
                block I/O. This is the flag to use in block layer code 
                when you cannot start more block I/O.
           GFP_USER
              - This is a normal allocation and might block. This flag
                is used to allocate memory for user-space processes.

  If contiguous memory is not necessary, use
    void *vmalloc(unsigned long size)

acpi_root_dir:
  a pointer to proc_dir_entry 
     (in /usr/src/kernels/linux-3.10.2/include/acpi/acpi_bus.h)

  struct proc_dir_entry {
     unsigned int low_ino;
     umode_t mode;
     nlink_t nlink;
     kuid_t uid;
     kgid_t gid;
     loff_t size;
     const struct inode_operations *proc_iops;
     const struct file_operations *proc_fops;
     struct proc_dir_entry *next, *parent, *subdir;
     void *data;
     read_proc_t *read_proc;
     write_proc_t *write_proc;
     atomic_t count;      /* use count */
     int pde_users; /* number of callers into module in progress */
     struct completion *pde_unload_completion;
     struct list_head pde_openers; /* who did ->open, but not ->release */
     spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
     u8 namelen;
     char name[];
  };

acpi_object:
  defined in /usr/src/kernels/linux-3.10.2/include/acpi/actypes.h
  
  union acpi_object {
     acpi_object_type type;  /* u32 */
     struct {
        acpi_object_type type;  /* ACPI_TYPE_INTEGER */
        u64 value;  /* The actual number */
     } integer;

     struct {
        acpi_object_type type;  /* ACPI_TYPE_STRING */
        u32 length; /* # of bytes in string, excluding trailing null */
        char *pointer; /* points to the string value */
     } string;

     struct {
        acpi_object_type type;  /* ACPI_TYPE_BUFFER */
        u32 length; /* # of bytes in buffer */
        u8 *pointer;   /* points to the buffer */
     } buffer;

     struct {
        acpi_object_type type;  /* ACPI_TYPE_PACKAGE */
        u32 count;  /* # of elements in package */
        union acpi_object *elements;  /* Pointer to an array of ACPI_OBJECTs */
     } package;

     struct {
        acpi_object_type type;  /* ACPI_TYPE_LOCAL_REFERENCE */
        acpi_object_type actual_type; /* Type associated with the Handle */
        acpi_handle handle;  /* object reference */
     } reference;

     struct {
        acpi_object_type type;  /* ACPI_TYPE_PROCESSOR */
        u32 proc_id;
        acpi_io_address pblk_address;
        u32 pblk_length;
     } processor;

     struct {
        acpi_object_type type;  /* ACPI_TYPE_POWER */
        u32 system_level;
        u32 resource_order;
     } power_resource;
  };

printk: the kernel print utility
  - Callable from just about anywhere in the kernel at any time. 
  - Can be called from interrupt or process context. 
  - Can be called while a lock is held. 
  - Can be called simultaneously on multiple processors, yet it does 
    not require the caller to hold a lock.
  - It's important that printk() is always there and always works.
  - But it is unusable before a certain point in the kernel boot
    process, prior to console initialization (use early_printk)
  - Log levels can be specified - e.g. printk(KERN_INFO "trust me\n");
    Log levels are as follows:
       KERN_EMERG   - An emergency condition; the system is probably dead
       KERN_ALERT   - A problem that requires immediate attention
       KERN_CRIT    - A critical condition
       KERN_ERR     - An error
       KERN_WARNING - A warning
       KERN_NOTICE  - A normal, but perhaps noteworthy, condition
       KERN_INFO    - An informational message
       KERN_DEBUG   - A debug messagetypically superfluous

acpi_size   - type is u32
acpi_status - type is u32
acpi_handle - type is void*
acpi_name   - type is u32
acpi_string - type is char*
acpi_buffer - type is struct { acpi_size, void* }

acpi_get_handle - defined in drivers/acpi/acpica/nsxfname.c
  function: Searches for a caller specified name in the name space.  
            The caller can restrict the search region by specifying 
            a non NULL parent.  The parent value is itself a namespace 
            handle.
  parameters: parent     - Object to search under (search scope).
              pathname   - Pointer to an asciiz string containing the name
              ret_handle - Where the return handle is returned

acpi_evaluate_object - defined in drivers/acpi/acpica/nsxfeval.c
  function: Finds and evaluates the given object, passing the given
            parameters if necessary.  One of "handle" or "pathname" must
            be valid (non-null)
  parameters:  handle   - Object handle (optional)
               pathname - Object pathname (optional)
               external_params - List of parameters to pass to method,
                                 terminated by NULL.  May be NULL if
                                 no parameters are being passed.
               return_buffer - Where to put method's return value (if
                               any).  If NULL, no value is returned.