next up previous contents
Next: 4.3 Processors Up: 4.2.2 Timer server navigation Previous: 4.2.2.1 Timer server navigation

4.2.2.2 Freezing timer servers

<Other protected methods of off_TmrSrv. >+= (<-U) [<-D->]
// These are for freeze:
// Freeze dynamic resource state at curbuf in buf with avail bytes. 
virtual err_t freeze_state(char *buf, char *&curbuf, size_t &avail,
                           char *&curto, size_t &toavail,
                           const off_prtl_id_t &frozen_domain) {
  return ENOSYS;
}

// Copy static resource state in curbuf with toavail bytes. 
virtual err_t copy_state(char *&curto, size_t &toavail) const {
  return ENOSYS;
}

<Other protected methods of off_TmrSrv. >+= (<-U) [<-D]
// These are for melt:
// Does resource cleanup. No external resource should be used after 
// return. 
virtual err_t cleanup(void) { return ENOSYS; }
// Restores the static state from a user supplied buffer. 
virtual err_t restore_state(char *&buf, size_t &bsize) { return ENOSYS; }
// Restores dynamic resource state. 
virtual err_t melt_state(char *&buf, size_t &bsize, char *&from, size_t &size,
                         const off_prtl_id_t &melted_domain) {
  return ENOSYS;
}

\subsubsection{Freezing timers}

<Other protected methods of off_Tmr. >+= (<-U) [<-D->]
// These are for freeze:
// Freeze dynamic resource state at curbuf in buf with avail bytes. 
virtual err_t freeze_state(char *buf, char *&curbuf, size_t &avail,
                           char *&curto, size_t &toavail,
                           const off_prtl_id_t &frozen_domain) {
  return ENOSYS;
}

// Copy static resource state in curbuf with toavail bytes. 
virtual err_t copy_state(char *&curto, size_t &toavail) const {
  return ENOSYS;
}

<Other protected methods of off_Tmr. >+= (<-U) [<-D]
// These are for melt:
// Does resource cleanup. No external resource should be used after 
// return. 
virtual err_t cleanup(void) { return ENOSYS; }
// Restores the static state from a user supplied buffer. 
virtual err_t restore_state(char *&buf, size_t &bsize) { return ENOSYS; }
// Restores dynamic resource state. 
virtual err_t melt_state(char *&buf, size_t &bsize, char *&from, size_t &size,
                         const off_prtl_id_t &melted_domain) {
  return ENOSYS;
}

\subsection{Dumping timers. }

To dump a Timer server we use this operator.

<Other public methods of off_TmrSrv. >+= (<-U) [<-D]
// Dumps tmrsrv state. 
friend OStr &operator<<(OStr &s,  off_TmrSrv &t);

<off_TmrSrv::operator<< implementation. >= (U->)
// Dumps tmrsrv state. 
OStr &operator<<(OStr &s,  off_TmrSrv &t)
{
  s << *(off_HWCompResource*)&t;
  s << "name=" << t.nameof() << " url=" << t.get_url() << nl;
  return s;
}

<Off timer server implementation dependencies. >+= (U->) [<-D]
#include <klib/str.h>           // for OStr et al.

\subsection{Timer \cpp{} source files}

Timer server code is kept in hw/TmrSrv.h and hw/TmrSrv.C.

<TmrSrv.h*>=
<Read the literate code instead warning. >
#ifndef __OFF_TMR_SRV_H
#define __OFF_TMR_SRV_H 1

<Off timer server dependencies. >

#ifdef __KERNEL__
<Off timer server. >
#endif // __KERNEL__

#ifdef __KERNEL__
// Timer server inline methods
//
<off_TmrSrv::get_allocator implementation. >
<off_TmrSrv::is_local implementation. >
<off_TmrSrv::operator+ implementation. >
#endif // __KERNEL__
#endif // __OFF_TMR_SRV_H

<TmrSrv.C*>=
<Read the literate code instead warning. >

#include <hw/TmrSrv.h>          // Exported interface.
<Off timer server implementation dependencies. >

<Off timer server static members. >

<off_TmrSrv::off_TmrSrv implementation. >
<off_TmrSrv::start implementation. >
<off_TmrSrv::alloc and free implementation. >
<off_TmrSrv::get_url implementation. >
<off_TmrSrv::nameof implementation. >
<off_TmrSrv::expired implementation. >
<off_TmrSrv::activate implementation. >
<off_TmrSrv::clock_handler implementation. >
<off_TmrSrv::alloc_pclk implementation. >
<off_TmrSrv::operator<< implementation. >

<off_clock_handler implementation. >

Timers are kept in hw/Tmr.h and hw/Tmr.C.

<Tmr.h*>=
<Read the literate code instead warning. >
#ifndef __OFF_TMR_H
#define __OFF_TMR_H 1

<Off timer dependencies. >

<Off timer flags. >

#ifdef __KERNEL__
<Off timer. >
#endif // __KERNEL__

#ifdef __KERNEL__
// Timer inline methods
//
<off_Tmr::is_periodic implementation. >
<off_Tmr::get_irqline implementation. >
<off_Tmr::get_ticks implementation. >
<off_Tmr::get_rticks implementation. >
#endif // __KERNEL__
#endif // __OFF_TMR_H

<Tmr.C*>=
<Read the literate code instead warning. >

#include <hw/Tmr.h>          // Exported interface.
<Off timer implementation dependencies. >

<Off timer static members. >

<off_Tmr::off_Tmr implementation. >
<off_Tmr::operator new implementation. >
<off_Tmr::operator delete implementation. >
<off_Tmr::get_url_holder implementation. >
<off_Tmr::activate implementation. >

The timer allocator can be found in hw/TmrAllocator.h and hw/TmrAllocator.C.

<TmrAllocator.h*>=
<Read the literate code instead warning. >
#ifndef __OFF_TMR_ALLOCATOR_H
#define __OFF_TMR_ALLOCATOR_H 1

<Off timer allocator dependencies. >

#ifdef __KERNEL__
<Off linkable timer. >
<Off timer allocator. >
#endif // __KERNEL__

#ifdef __KERNEL__
// Timer allocator inline methods
//
<off_TmrAllocator::operator + implementation. >
#endif // __KERNEL__

#endif // __OFF_TMR_ALLOCATOR_H

<TmrAllocator.C*>=
<Read the literate code instead warning. >

#include <hw/TmrAllocator.h>          // Exported interface.

<Off timer allocator static members. >

<off_TmrAllocator::off_TmrAllocator implementation. >

\subsection{Timers for ix86 based architectures}

On Intels, the machine dependent part of the timer server is responsible to handle the programmable interval timer (PIT) chipset. Thus, it allocates PIT IO ports and the actual clock interrupt.

<Off machine dependent timer server. >= (U->)
// An ix86 timer server
//
class off_mdepTmrSrv {
public: 
  static natural_t get_ntmrs(void)  { return OFF_MDEP_NVINT_MAX; }
  <Other public methods of off_mdepTmrSrv. >
};

Defines off_mdepTmrSrv (links are to index).

<Off machine dependent timer server dependencies. >= (U->)
#include <flux/types.h>         // for boolean_t natural_t et al.
#include <klib/limits.h>

PIT is initialized when the machine dependent server is started.

<Other public methods of off_mdepTmrSrv. >= (<-U)
// Starts the PIT
// Interrupts must be cleared!
static void start(natural_t hz);

<off_mdepTmrSrv::start implementation. >= (U->)
// Starts the PIT
void off_mdepTmrSrv::start(natural_t hz)
{
  // XXX use APIC instead for SMP.
  {
    off_io_id_t io(nd.get_iobank(0).get_id(),PITCTL_PORT);
    new(&nd.get_iobank(0),io) 
      off_IOPort(nd.get_proc(0).get_tmr().get_protection(),
                 nd.get_proc(0).get_tmr().get_domain());
  }
  {
    off_io_id_t io(nd.get_iobank(0).get_id(),PITCTR0_PORT);
    new(&nd.get_iobank(0),io) 
      off_IOPort(nd.get_proc(0).get_tmr().get_protection(),
                 nd.get_proc(0).get_tmr().get_domain());
  }
  init_pit(hz);
}

To fully support SMP systems, this implementation has to be changed to program the local APIC instead and a timer server per processor must be created.

<Off machine dependent timer server implementation dependencies.>= (U->)
#include <hw/IOBank.h>      
#include <hw/IOPort.h>      
#include <node/Node.h>      
#include <hw/Processor.h>       // for clri seti et al.
#include <flux/machine/pc/pic.h> // for PIC settings  
#include <flux/machine/pc/pit.h> // for PIT settings 

\subsubsection{Machine dependent timer \cpp{} source files}

Machine dependent timers are kept in mdep/mTmrSrv.h and mdep/mTmrSrv.C.

<mdep mTmrSrv.h*>=
<Read the literate code instead warning. >
#ifndef __OFF_MDEP_TMR_SRV_H 
#define __OFF_MDEP_TMR_SRV_H 1

<Off machine dependent timer server dependencies. >

#ifdef __KERNEL__
<Off machine dependent timer server. >
#endif // __KERNEL__

#endif // __OFF_MDEP_TMR_SRV_H

<mdep mTmrSrv.C*>=
<Read the literate code instead warning. >

#include <hw/mdep/mTmrSrv.h>    // Exported interface
<Off machine dependent timer server implementation dependencies.>

<off_mdepTmrSrv::start implementation. >

%% --------------------------------------------------------------

\section{DMA lines}

DMA objects are used to allocate DMALines. Note that DMA lines are kept in the kernel although they could have been considered to be a device (and kept in userland). The reason is efficiency, because we do not want protection domain crossings just to program a DMA line. Also, we believe that no flexibility is lost by placing this small piece of code into the kernel.

<Off DMA table. >=
// Allocation of DMA lines
class off_DMA: public off_HWCompResource {
public:
  // Allocates n DMA lines. 
  off_DMALine *alloc(off_Protection *prot,natural_t n=1,
                     off_dma_id_t at=OFF_EU_ID_NULL );
  // Deallocates the n contiguous DMA lines starting at d. 
  void free( off_DMALine *d, natural_t n=1 );
  //Gets a DMA line from its  number.
  off_DMALine *operator [](natural_t n) const;

  // Starts operation in this memory bank.
  err_t start(const off_mdepDMA &dmainfo);

};
Defines off_DMA (links are to index).

NOTE: XXX must provide off_DMA::off_DMA(void).
\Note{XXX implement off_mdepDMA see off_mdepNode::get_dmainfo implementation in node.nw for methods used.

DMA lines are very not well modeled, instead we provided a model of DMA pretty close to that of Intel based machines. Future Off portings to different architectures should provide feedback on how should DMA lines be modeled.

<Off DMA line. >=
typedef off_mode_t dma_mode_t;
class off_DMAline: public off_HWResUnit {
public:
   // Enables/disables this dma line.
   void enable(void);
   void disable(void);
   // Programs a DMA operation. 
   void program(off_pg_id_t addr, vm_offset_t length, dma_mode_t mode);
   // Gets # of copied or pending bytes. 
   vm_offset_t get_copied(void);
   vm_offset_t get_pending(void);
};
Defines off_DMALine (links are to index).

where

<Off DMA line mode data type. >=
typedef natural_t dma_mode_t;
Defines dma_mode_t (links are to index).

\subsection{DMA lines for plain users}

DMA related wrappers are straightforward.

<Off DMA table for users. >=
ENTRY class off_uDMA : public off_uHWCompResource {
public:
 off_uDMALine *alloc(off_Protection *prot, 
                     natural_t n=1, off_dma_id_t at=OFF_EU_ID_NULL);
 void free(off_uDMALine *pf, const off_Rights &r, natural_t n=1 );
 off_uDMALine *fetch(off_dma_id_t d,const off_Rights &r) const;
};
Defines off_uDMA (links are to index).

<Off DMA line for users. >=
ENTRY class off_uDMALine : public off_uHWResUnit {
public:
   // Enables/disables this dma line.
   void enable(const off_Rights &r);
   void disable(const off_Rights &r);
   // Programs a DMA operation. 
   void program(off_pg_id_t addr, vm_offset_t length, dma_mode_t mode,
        const off_Rights &r);
   // Gets # of copied or pending bytes. 
   vm_offset_t get_copied(void,const off_Rights &r);
   vm_offset_t get_pending(void,const off_Rights &r);
};
Defines off_uDMALine (links are to index).

%% --------------------------------------------------------------

rawhtml2942#


next up previous contents
Next: 4.3 Processors Up: 4.2.2 Timer server navigation Previous: 4.2.2.1 Timer server navigation
Francisco J. Ballesteros
1998-05-25