Home | History | Annotate | Line # | Download | only in mn10300
dv-mn103tim.c revision 1.1
      1  1.1  christos /*  This file is part of the program GDB, the GNU debugger.
      2  1.1  christos 
      3  1.1  christos     Copyright (C) 1998, 2003, 2007, 2008, 2009, 2010, 2011
      4  1.1  christos     Free Software Foundation, Inc.
      5  1.1  christos     Contributed by Cygnus Solutions.
      6  1.1  christos 
      7  1.1  christos     This program is free software; you can redistribute it and/or modify
      8  1.1  christos     it under the terms of the GNU General Public License as published by
      9  1.1  christos     the Free Software Foundation; either version 3 of the License, or
     10  1.1  christos     (at your option) any later version.
     11  1.1  christos 
     12  1.1  christos     This program is distributed in the hope that it will be useful,
     13  1.1  christos     but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  1.1  christos     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  1.1  christos     GNU General Public License for more details.
     16  1.1  christos 
     17  1.1  christos     You should have received a copy of the GNU General Public License
     18  1.1  christos     along with this program.  If not, see <http://www.gnu.org/licenses/>.
     19  1.1  christos 
     20  1.1  christos     */
     21  1.1  christos 
     22  1.1  christos #include "sim-main.h"
     23  1.1  christos #include "hw-main.h"
     24  1.1  christos #include "sim-assert.h"
     25  1.1  christos 
     26  1.1  christos /* DEVICE
     27  1.1  christos 
     28  1.1  christos 
     29  1.1  christos    mn103tim - mn103002 timers (8 and 16 bit)
     30  1.1  christos 
     31  1.1  christos 
     32  1.1  christos    DESCRIPTION
     33  1.1  christos 
     34  1.1  christos    Implements the mn103002 8 and 16 bit timers as described in the mn103002 user guide.
     35  1.1  christos 
     36  1.1  christos 
     37  1.1  christos    PROPERTIES
     38  1.1  christos 
     39  1.1  christos    reg = <8bit-timers-addr> <8bit-timers-size> <16bit-timers-addr> <16bit-timers-size>
     40  1.1  christos 
     41  1.1  christos 
     42  1.1  christos    BUGS
     43  1.1  christos 
     44  1.1  christos    */
     45  1.1  christos 
     46  1.1  christos 
     47  1.1  christos /* The timers' register address blocks */
     48  1.1  christos 
     49  1.1  christos struct mn103tim_block {
     50  1.1  christos   unsigned_word base;
     51  1.1  christos   unsigned_word bound;
     52  1.1  christos };
     53  1.1  christos 
     54  1.1  christos enum { TIMER8_BLOCK, TIMER16_BLOCK, NR_TIMER_BLOCKS };
     55  1.1  christos 
     56  1.1  christos enum timer_register_types {
     57  1.1  christos   FIRST_MODE_REG = 0,
     58  1.1  christos   TM0MD = FIRST_MODE_REG,
     59  1.1  christos   TM1MD,
     60  1.1  christos   TM2MD,
     61  1.1  christos   TM3MD,
     62  1.1  christos   TM4MD,
     63  1.1  christos   TM5MD,
     64  1.1  christos   TM6MD,
     65  1.1  christos   LAST_MODE_REG = TM6MD,
     66  1.1  christos   FIRST_BASE_REG,
     67  1.1  christos   TM0BR = FIRST_BASE_REG,
     68  1.1  christos   TM1BR,
     69  1.1  christos   TM2BR,
     70  1.1  christos   TM3BR,
     71  1.1  christos   TM4BR,
     72  1.1  christos   TM5BR,
     73  1.1  christos   LAST_BASE_REG = TM5BR,
     74  1.1  christos   FIRST_COUNTER,
     75  1.1  christos   TM0BC = FIRST_COUNTER,
     76  1.1  christos   TM1BC,
     77  1.1  christos   TM2BC,
     78  1.1  christos   TM3BC,
     79  1.1  christos   TM4BC,
     80  1.1  christos   TM5BC,
     81  1.1  christos   TM6BC,
     82  1.1  christos   LAST_COUNTER = TM6BC,
     83  1.1  christos   TM6MDA,
     84  1.1  christos   TM6MDB,
     85  1.1  christos   TM6CA,
     86  1.1  christos   TM6CB,
     87  1.1  christos   LAST_TIMER_REG = TM6BC,
     88  1.1  christos };
     89  1.1  christos 
     90  1.1  christos 
     91  1.1  christos /* Don't include timer 6 because it's handled specially. */
     92  1.1  christos #define NR_8BIT_TIMERS 4
     93  1.1  christos #define NR_16BIT_TIMERS 2
     94  1.1  christos #define NR_REG_TIMERS 6 /* Exclude timer 6 - it's handled specially. */
     95  1.1  christos #define NR_TIMERS 7
     96  1.1  christos 
     97  1.1  christos typedef struct _mn10300_timer_regs {
     98  1.1  christos   unsigned32 base;
     99  1.1  christos   unsigned8  mode;
    100  1.1  christos } mn10300_timer_regs;
    101  1.1  christos 
    102  1.1  christos typedef struct _mn10300_timer {
    103  1.1  christos   unsigned32 div_ratio, start;
    104  1.1  christos   struct hw_event *event;
    105  1.1  christos } mn10300_timer;
    106  1.1  christos 
    107  1.1  christos 
    108  1.1  christos struct mn103tim {
    109  1.1  christos   struct mn103tim_block block[NR_TIMER_BLOCKS];
    110  1.1  christos   mn10300_timer_regs reg[NR_REG_TIMERS];
    111  1.1  christos   mn10300_timer timer[NR_TIMERS];
    112  1.1  christos 
    113  1.1  christos   /* treat timer 6 registers specially. */
    114  1.1  christos   unsigned16   tm6md0, tm6md1, tm6bc, tm6ca, tm6cb;
    115  1.1  christos   unsigned8  tm6mda, tm6mdb;  /* compare/capture mode regs for timer 6 */
    116  1.1  christos };
    117  1.1  christos 
    118  1.1  christos /* output port ID's */
    119  1.1  christos 
    120  1.1  christos /* for mn103002 */
    121  1.1  christos enum {
    122  1.1  christos   TIMER0_UFLOW,
    123  1.1  christos   TIMER1_UFLOW,
    124  1.1  christos   TIMER2_UFLOW,
    125  1.1  christos   TIMER3_UFLOW,
    126  1.1  christos   TIMER4_UFLOW,
    127  1.1  christos   TIMER5_UFLOW,
    128  1.1  christos   TIMER6_UFLOW,
    129  1.1  christos   TIMER6_CMPA,
    130  1.1  christos   TIMER6_CMPB,
    131  1.1  christos };
    132  1.1  christos 
    133  1.1  christos 
    134  1.1  christos static const struct hw_port_descriptor mn103tim_ports[] = {
    135  1.1  christos 
    136  1.1  christos   { "timer-0-underflow", TIMER0_UFLOW, 0, output_port, },
    137  1.1  christos   { "timer-1-underflow", TIMER1_UFLOW, 0, output_port, },
    138  1.1  christos   { "timer-2-underflow", TIMER2_UFLOW, 0, output_port, },
    139  1.1  christos   { "timer-3-underflow", TIMER3_UFLOW, 0, output_port, },
    140  1.1  christos   { "timer-4-underflow", TIMER4_UFLOW, 0, output_port, },
    141  1.1  christos   { "timer-5-underflow", TIMER5_UFLOW, 0, output_port, },
    142  1.1  christos 
    143  1.1  christos   { "timer-6-underflow", TIMER6_UFLOW, 0, output_port, },
    144  1.1  christos   { "timer-6-compare-a", TIMER6_CMPA, 0, output_port, },
    145  1.1  christos   { "timer-6-compare-b", TIMER6_CMPB, 0, output_port, },
    146  1.1  christos 
    147  1.1  christos   { NULL, },
    148  1.1  christos };
    149  1.1  christos 
    150  1.1  christos #define bits2to5_mask 0x3c
    151  1.1  christos #define bits0to2_mask 0x07
    152  1.1  christos #define load_mask     0x40
    153  1.1  christos #define count_mask    0x80
    154  1.1  christos #define count_and_load_mask (load_mask | count_mask)
    155  1.1  christos #define clock_mask    0x03
    156  1.1  christos #define clk_ioclk    0x00
    157  1.1  christos #define clk_cascaded 0x03
    158  1.1  christos 
    159  1.1  christos 
    160  1.1  christos /* Finish off the partially created hw device.  Attach our local
    161  1.1  christos    callbacks.  Wire up our port names etc */
    162  1.1  christos 
    163  1.1  christos static hw_io_read_buffer_method mn103tim_io_read_buffer;
    164  1.1  christos static hw_io_write_buffer_method mn103tim_io_write_buffer;
    165  1.1  christos 
    166  1.1  christos static void
    167  1.1  christos attach_mn103tim_regs (struct hw *me,
    168  1.1  christos 		      struct mn103tim *timers)
    169  1.1  christos {
    170  1.1  christos   int i;
    171  1.1  christos   if (hw_find_property (me, "reg") == NULL)
    172  1.1  christos     hw_abort (me, "Missing \"reg\" property");
    173  1.1  christos   for (i = 0; i < NR_TIMER_BLOCKS; i++)
    174  1.1  christos     {
    175  1.1  christos       unsigned_word attach_address;
    176  1.1  christos       int attach_space;
    177  1.1  christos       unsigned attach_size;
    178  1.1  christos       reg_property_spec reg;
    179  1.1  christos       if (!hw_find_reg_array_property (me, "reg", i, &reg))
    180  1.1  christos 	hw_abort (me, "\"reg\" property must contain three addr/size entries");
    181  1.1  christos       hw_unit_address_to_attach_address (hw_parent (me),
    182  1.1  christos 					 &reg.address,
    183  1.1  christos 					 &attach_space,
    184  1.1  christos 					 &attach_address,
    185  1.1  christos 					 me);
    186  1.1  christos       timers->block[i].base = attach_address;
    187  1.1  christos       hw_unit_size_to_attach_size (hw_parent (me),
    188  1.1  christos 				   &reg.size,
    189  1.1  christos 				   &attach_size, me);
    190  1.1  christos       timers->block[i].bound = attach_address + (attach_size - 1);
    191  1.1  christos       hw_attach_address (hw_parent (me),
    192  1.1  christos 			 0,
    193  1.1  christos 			 attach_space, attach_address, attach_size,
    194  1.1  christos 			 me);
    195  1.1  christos     }
    196  1.1  christos }
    197  1.1  christos 
    198  1.1  christos static void
    199  1.1  christos mn103tim_finish (struct hw *me)
    200  1.1  christos {
    201  1.1  christos   struct mn103tim *timers;
    202  1.1  christos   int i;
    203  1.1  christos 
    204  1.1  christos   timers = HW_ZALLOC (me, struct mn103tim);
    205  1.1  christos   set_hw_data (me, timers);
    206  1.1  christos   set_hw_io_read_buffer (me, mn103tim_io_read_buffer);
    207  1.1  christos   set_hw_io_write_buffer (me, mn103tim_io_write_buffer);
    208  1.1  christos   set_hw_ports (me, mn103tim_ports);
    209  1.1  christos 
    210  1.1  christos   /* Attach ourself to our parent bus */
    211  1.1  christos   attach_mn103tim_regs (me, timers);
    212  1.1  christos 
    213  1.1  christos   /* Initialize the timers */
    214  1.1  christos   for ( i=0; i < NR_REG_TIMERS; ++i )
    215  1.1  christos     {
    216  1.1  christos       timers->reg[i].mode = 0x00;
    217  1.1  christos       timers->reg[i].base = 0;
    218  1.1  christos     }
    219  1.1  christos   for ( i=0; i < NR_TIMERS; ++i )
    220  1.1  christos     {
    221  1.1  christos       timers->timer[i].event = NULL;
    222  1.1  christos       timers->timer[i].div_ratio = 0;
    223  1.1  christos       timers->timer[i].start = 0;
    224  1.1  christos     }
    225  1.1  christos   timers->tm6md0 = 0x00;
    226  1.1  christos   timers->tm6md1 = 0x00;
    227  1.1  christos   timers->tm6bc = 0x0000;
    228  1.1  christos   timers->tm6ca = 0x0000;
    229  1.1  christos   timers->tm6cb = 0x0000;
    230  1.1  christos   timers->tm6mda = 0x00;
    231  1.1  christos   timers->tm6mdb = 0x00;
    232  1.1  christos }
    233  1.1  christos 
    234  1.1  christos 
    235  1.1  christos 
    236  1.1  christos /* read and write */
    237  1.1  christos 
    238  1.1  christos static int
    239  1.1  christos decode_addr (struct hw *me,
    240  1.1  christos 	     struct mn103tim *timers,
    241  1.1  christos 	     unsigned_word address)
    242  1.1  christos {
    243  1.1  christos   unsigned_word offset;
    244  1.1  christos   offset = address - timers->block[0].base;
    245  1.1  christos 
    246  1.1  christos   switch (offset)
    247  1.1  christos     {
    248  1.1  christos     case 0x00: return TM0MD;
    249  1.1  christos     case 0x01: return TM1MD;
    250  1.1  christos     case 0x02: return TM2MD;
    251  1.1  christos     case 0x03: return TM3MD;
    252  1.1  christos     case 0x10: return TM0BR;
    253  1.1  christos     case 0x11: return TM1BR;
    254  1.1  christos     case 0x12: return TM2BR;
    255  1.1  christos     case 0x13: return TM3BR;
    256  1.1  christos     case 0x20: return TM0BC;
    257  1.1  christos     case 0x21: return TM1BC;
    258  1.1  christos     case 0x22: return TM2BC;
    259  1.1  christos     case 0x23: return TM3BC;
    260  1.1  christos     case 0x80: return TM4MD;
    261  1.1  christos     case 0x82: return TM5MD;
    262  1.1  christos     case 0x84: /* fall through */
    263  1.1  christos     case 0x85: return TM6MD;
    264  1.1  christos     case 0x90: return TM4BR;
    265  1.1  christos     case 0x92: return TM5BR;
    266  1.1  christos     case 0xa0: return TM4BC;
    267  1.1  christos     case 0xa2: return TM5BC;
    268  1.1  christos     case 0xa4: return TM6BC;
    269  1.1  christos     case 0xb4: return TM6MDA;
    270  1.1  christos     case 0xb5: return TM6MDB;
    271  1.1  christos     case 0xc4: return TM6CA;
    272  1.1  christos     case 0xd4: return TM6CB;
    273  1.1  christos     default:
    274  1.1  christos       {
    275  1.1  christos 	hw_abort (me, "bad address");
    276  1.1  christos 	return -1;
    277  1.1  christos       }
    278  1.1  christos     }
    279  1.1  christos }
    280  1.1  christos 
    281  1.1  christos static void
    282  1.1  christos read_mode_reg (struct hw *me,
    283  1.1  christos 	       struct mn103tim *timers,
    284  1.1  christos 	       int timer_nr,
    285  1.1  christos 	       void *dest,
    286  1.1  christos 	       unsigned nr_bytes)
    287  1.1  christos {
    288  1.1  christos   unsigned16 val16;
    289  1.1  christos   unsigned32 val32;
    290  1.1  christos 
    291  1.1  christos   switch ( nr_bytes )
    292  1.1  christos     {
    293  1.1  christos     case 1:
    294  1.1  christos       /* Accessing 1 byte is ok for all mode registers. */
    295  1.1  christos       if ( timer_nr == 6 )
    296  1.1  christos 	{
    297  1.1  christos 	  *(unsigned8*)dest = timers->tm6md0;
    298  1.1  christos 	}
    299  1.1  christos       else
    300  1.1  christos 	{
    301  1.1  christos 	  *(unsigned8*)dest = timers->reg[timer_nr].mode;
    302  1.1  christos 	}
    303  1.1  christos       break;
    304  1.1  christos 
    305  1.1  christos     case 2:
    306  1.1  christos       if ( timer_nr == 6 )
    307  1.1  christos 	{
    308  1.1  christos 	  *(unsigned16 *)dest = (timers->tm6md0 << 8) | timers->tm6md1;
    309  1.1  christos 	}
    310  1.1  christos       else if ( timer_nr == 0 || timer_nr == 2 )
    311  1.1  christos 	{
    312  1.1  christos 	  val16 = (timers->reg[timer_nr].mode << 8)
    313  1.1  christos 	    | timers->reg[timer_nr+1].mode;
    314  1.1  christos 	  *(unsigned16*)dest = val16;
    315  1.1  christos 	}
    316  1.1  christos       else
    317  1.1  christos 	{
    318  1.1  christos 	  hw_abort (me, "bad read size of 2 bytes to TM%dMD.", timer_nr);
    319  1.1  christos 	}
    320  1.1  christos       break;
    321  1.1  christos 
    322  1.1  christos     case 4:
    323  1.1  christos       if ( timer_nr == 0 )
    324  1.1  christos 	{
    325  1.1  christos 	  val32 = (timers->reg[0].mode << 24 )
    326  1.1  christos 	    | (timers->reg[1].mode << 16)
    327  1.1  christos 	    | (timers->reg[2].mode << 8)
    328  1.1  christos 	    | timers->reg[3].mode;
    329  1.1  christos 	  *(unsigned32*)dest = val32;
    330  1.1  christos 	}
    331  1.1  christos       else
    332  1.1  christos 	{
    333  1.1  christos 	  hw_abort (me, "bad read size of 4 bytes to TM%dMD.", timer_nr);
    334  1.1  christos 	}
    335  1.1  christos       break;
    336  1.1  christos 
    337  1.1  christos     default:
    338  1.1  christos       hw_abort (me, "bad read size of %d bytes to TM%dMD.",
    339  1.1  christos 		nr_bytes, timer_nr);
    340  1.1  christos     }
    341  1.1  christos }
    342  1.1  christos 
    343  1.1  christos 
    344  1.1  christos static void
    345  1.1  christos read_base_reg (struct hw *me,
    346  1.1  christos 	       struct mn103tim *timers,
    347  1.1  christos 	       int timer_nr,
    348  1.1  christos 	       void *dest,
    349  1.1  christos 	       unsigned  nr_bytes)
    350  1.1  christos {
    351  1.1  christos   unsigned16 val16;
    352  1.1  christos   unsigned32 val32;
    353  1.1  christos 
    354  1.1  christos   /* Check nr_bytes: accesses of 1, 2 and 4 bytes allowed depending on timer. */
    355  1.1  christos   switch ( nr_bytes )
    356  1.1  christos     {
    357  1.1  christos     case 1:
    358  1.1  christos       /* Reading 1 byte is ok for all registers. */
    359  1.1  christos       if ( timer_nr < NR_8BIT_TIMERS )
    360  1.1  christos 	{
    361  1.1  christos 	  *(unsigned8*)dest = timers->reg[timer_nr].base;
    362  1.1  christos 	}
    363  1.1  christos       break;
    364  1.1  christos 
    365  1.1  christos     case 2:
    366  1.1  christos       if ( timer_nr == 1 || timer_nr == 3 )
    367  1.1  christos 	{
    368  1.1  christos 	  hw_abort (me, "bad read size of 2 bytes to TM%dBR.", timer_nr);
    369  1.1  christos 	}
    370  1.1  christos       else
    371  1.1  christos 	{
    372  1.1  christos 	  if ( timer_nr < NR_8BIT_TIMERS )
    373  1.1  christos 	    {
    374  1.1  christos 	      val16 = (timers->reg[timer_nr].base<<8)
    375  1.1  christos 		| timers->reg[timer_nr+1].base;
    376  1.1  christos 	    }
    377  1.1  christos 	  else
    378  1.1  christos 	    {
    379  1.1  christos 	      val16 = timers->reg[timer_nr].base;
    380  1.1  christos 	    }
    381  1.1  christos 	  *(unsigned16*)dest = val16;
    382  1.1  christos 	}
    383  1.1  christos       break;
    384  1.1  christos 
    385  1.1  christos     case 4:
    386  1.1  christos       if ( timer_nr == 0 )
    387  1.1  christos 	{
    388  1.1  christos 	  val32 = (timers->reg[0].base << 24) | (timers->reg[1].base << 16)
    389  1.1  christos 	    | (timers->reg[2].base << 8) | timers->reg[3].base;
    390  1.1  christos 	  *(unsigned32*)dest = val32;
    391  1.1  christos 	}
    392  1.1  christos       else if ( timer_nr == 4 )
    393  1.1  christos 	{
    394  1.1  christos 	  val32 = (timers->reg[4].base << 16) | timers->reg[5].base;
    395  1.1  christos 	  *(unsigned32*)dest = val32;
    396  1.1  christos 	}
    397  1.1  christos       else
    398  1.1  christos 	{
    399  1.1  christos 	  hw_abort (me, "bad read size of 4 bytes to TM%dBR.", timer_nr);
    400  1.1  christos 	}
    401  1.1  christos       break;
    402  1.1  christos 
    403  1.1  christos     default:
    404  1.1  christos       hw_abort (me, "bad read size must of %d bytes to TM%dBR.",
    405  1.1  christos 		nr_bytes, timer_nr);
    406  1.1  christos     }
    407  1.1  christos }
    408  1.1  christos 
    409  1.1  christos 
    410  1.1  christos static void
    411  1.1  christos read_counter (struct hw *me,
    412  1.1  christos 	      struct mn103tim *timers,
    413  1.1  christos 	      int timer_nr,
    414  1.1  christos 	      void *dest,
    415  1.1  christos 	      unsigned  nr_bytes)
    416  1.1  christos {
    417  1.1  christos   unsigned32 val;
    418  1.1  christos 
    419  1.1  christos   if ( NULL == timers->timer[timer_nr].event )
    420  1.1  christos     {
    421  1.1  christos       /* Timer is not counting, use value in base register. */
    422  1.1  christos       if ( timer_nr == 6 )
    423  1.1  christos 	{
    424  1.1  christos 	  val = 0;  /* timer 6 is an up counter */
    425  1.1  christos 	}
    426  1.1  christos       else
    427  1.1  christos 	{
    428  1.1  christos 	  val = timers->reg[timer_nr].base;
    429  1.1  christos 	}
    430  1.1  christos     }
    431  1.1  christos   else
    432  1.1  christos     {
    433  1.1  christos       if ( timer_nr == 6 )  /* timer 6 is an up counter. */
    434  1.1  christos 	{
    435  1.1  christos 	  val = hw_event_queue_time(me) - timers->timer[timer_nr].start;
    436  1.1  christos 	}
    437  1.1  christos       else
    438  1.1  christos 	{
    439  1.1  christos 	  /* ticks left = start time + div ratio - curr time */
    440  1.1  christos 	  /* Cannot use base register because it can be written during counting and it
    441  1.1  christos 	     doesn't affect counter until underflow occurs. */
    442  1.1  christos 
    443  1.1  christos 	  val = timers->timer[timer_nr].start + timers->timer[timer_nr].div_ratio
    444  1.1  christos 	    - hw_event_queue_time(me);
    445  1.1  christos 	}
    446  1.1  christos     }
    447  1.1  christos 
    448  1.1  christos   switch (nr_bytes) {
    449  1.1  christos   case 1:
    450  1.1  christos     *(unsigned8 *)dest = val;
    451  1.1  christos     break;
    452  1.1  christos 
    453  1.1  christos   case 2:
    454  1.1  christos     *(unsigned16 *)dest = val;
    455  1.1  christos     break;
    456  1.1  christos 
    457  1.1  christos   case 4:
    458  1.1  christos     *(unsigned32 *)dest = val;
    459  1.1  christos     break;
    460  1.1  christos 
    461  1.1  christos   default:
    462  1.1  christos     hw_abort(me, "bad read size for reading counter");
    463  1.1  christos   }
    464  1.1  christos 
    465  1.1  christos }
    466  1.1  christos 
    467  1.1  christos 
    468  1.1  christos static void
    469  1.1  christos read_special_timer6_reg (struct hw *me,
    470  1.1  christos 			 struct mn103tim *timers,
    471  1.1  christos 			 int timer_nr,
    472  1.1  christos 			 void *dest,
    473  1.1  christos 			 unsigned  nr_bytes)
    474  1.1  christos {
    475  1.1  christos   unsigned32 val;
    476  1.1  christos 
    477  1.1  christos   switch (nr_bytes) {
    478  1.1  christos   case 1:
    479  1.1  christos     {
    480  1.1  christos       switch ( timer_nr ) {
    481  1.1  christos       case TM6MDA:
    482  1.1  christos 	*(unsigned8 *)dest = timers->tm6mda;
    483  1.1  christos 	break;
    484  1.1  christos 
    485  1.1  christos       case TM6MDB:
    486  1.1  christos 	*(unsigned8 *)dest = timers->tm6mdb;
    487  1.1  christos 	break;
    488  1.1  christos 
    489  1.1  christos       case TM6CA:
    490  1.1  christos 	*(unsigned8 *)dest = timers->tm6ca;
    491  1.1  christos 	break;
    492  1.1  christos 
    493  1.1  christos       case TM6CB:
    494  1.1  christos 	*(unsigned8 *)dest = timers->tm6cb;
    495  1.1  christos 	break;
    496  1.1  christos 
    497  1.1  christos       default:
    498  1.1  christos 	break;
    499  1.1  christos       }
    500  1.1  christos       break;
    501  1.1  christos     }
    502  1.1  christos 
    503  1.1  christos   case 2:
    504  1.1  christos     if ( timer_nr == TM6CA )
    505  1.1  christos       {
    506  1.1  christos 	*(unsigned16 *)dest = timers->tm6ca;
    507  1.1  christos       }
    508  1.1  christos     else if ( timer_nr == TM6CB )
    509  1.1  christos       {
    510  1.1  christos 	*(unsigned16 *)dest = timers->tm6cb;
    511  1.1  christos       }
    512  1.1  christos     else
    513  1.1  christos       {
    514  1.1  christos 	hw_abort(me, "bad read size for timer 6 mode A/B register");
    515  1.1  christos       }
    516  1.1  christos     break;
    517  1.1  christos 
    518  1.1  christos   default:
    519  1.1  christos     hw_abort(me, "bad read size for timer 6 register");
    520  1.1  christos   }
    521  1.1  christos 
    522  1.1  christos }
    523  1.1  christos 
    524  1.1  christos 
    525  1.1  christos static unsigned
    526  1.1  christos mn103tim_io_read_buffer (struct hw *me,
    527  1.1  christos 			 void *dest,
    528  1.1  christos 			 int space,
    529  1.1  christos 			 unsigned_word base,
    530  1.1  christos 			 unsigned nr_bytes)
    531  1.1  christos {
    532  1.1  christos   struct mn103tim *timers = hw_data (me);
    533  1.1  christos   enum timer_register_types timer_reg;
    534  1.1  christos 
    535  1.1  christos   HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
    536  1.1  christos 
    537  1.1  christos   timer_reg = decode_addr (me, timers, base);
    538  1.1  christos 
    539  1.1  christos   /* It can be either a mode register, a base register, a binary counter, */
    540  1.1  christos   /* or a special timer 6 register.  Check in that order. */
    541  1.1  christos   if ( timer_reg >= FIRST_MODE_REG && timer_reg <= LAST_MODE_REG )
    542  1.1  christos     {
    543  1.1  christos       read_mode_reg(me, timers, timer_reg-FIRST_MODE_REG, dest, nr_bytes);
    544  1.1  christos     }
    545  1.1  christos   else if ( timer_reg <= LAST_BASE_REG )
    546  1.1  christos     {
    547  1.1  christos       read_base_reg(me, timers, timer_reg-FIRST_BASE_REG, dest, nr_bytes);
    548  1.1  christos     }
    549  1.1  christos   else if ( timer_reg <= LAST_COUNTER )
    550  1.1  christos     {
    551  1.1  christos       read_counter(me, timers, timer_reg-FIRST_COUNTER, dest, nr_bytes);
    552  1.1  christos     }
    553  1.1  christos   else if ( timer_reg <= LAST_TIMER_REG )
    554  1.1  christos     {
    555  1.1  christos       read_special_timer6_reg(me, timers, timer_reg, dest, nr_bytes);
    556  1.1  christos     }
    557  1.1  christos   else
    558  1.1  christos     {
    559  1.1  christos       hw_abort(me, "invalid timer register address.");
    560  1.1  christos     }
    561  1.1  christos 
    562  1.1  christos   return nr_bytes;
    563  1.1  christos }
    564  1.1  christos 
    565  1.1  christos 
    566  1.1  christos static void
    567  1.1  christos do_counter_event (struct hw *me,
    568  1.1  christos 		  void *data)
    569  1.1  christos {
    570  1.1  christos   struct mn103tim *timers = hw_data(me);
    571  1.1  christos   long timer_nr = (long) data;
    572  1.1  christos   int next_timer;
    573  1.1  christos 
    574  1.1  christos   /* Check if counting is still enabled. */
    575  1.1  christos   if ( (timers->reg[timer_nr].mode & count_mask) != 0 )
    576  1.1  christos     {
    577  1.1  christos       /* Generate an interrupt for the timer underflow (TIMERn_UFLOW). */
    578  1.1  christos 
    579  1.1  christos       /* Port event occurs on port of last cascaded timer. */
    580  1.1  christos       /* This works across timer range from 0 to NR_REG_TIMERS because */
    581  1.1  christos       /* the first 16 bit timer (timer 4) is not allowed to be set as  */
    582  1.1  christos       /* a cascading timer. */
    583  1.1  christos       for ( next_timer = timer_nr+1; next_timer < NR_REG_TIMERS; ++next_timer )
    584  1.1  christos 	{
    585  1.1  christos 	  if ( (timers->reg[next_timer].mode & clock_mask) != clk_cascaded )
    586  1.1  christos 	    {
    587  1.1  christos 	      break;
    588  1.1  christos 	    }
    589  1.1  christos 	}
    590  1.1  christos       hw_port_event (me, next_timer-1, 1);
    591  1.1  christos 
    592  1.1  christos       /* Schedule next timeout.  */
    593  1.1  christos       timers->timer[timer_nr].start = hw_event_queue_time(me);
    594  1.1  christos       /* FIX: Check if div_ratio has changed and if it's now 0. */
    595  1.1  christos       timers->timer[timer_nr].event
    596  1.1  christos 	= hw_event_queue_schedule (me, timers->timer[timer_nr].div_ratio,
    597  1.1  christos 				   do_counter_event, (void *)timer_nr);
    598  1.1  christos     }
    599  1.1  christos   else
    600  1.1  christos     {
    601  1.1  christos       timers->timer[timer_nr].event = NULL;
    602  1.1  christos     }
    603  1.1  christos 
    604  1.1  christos }
    605  1.1  christos 
    606  1.1  christos 
    607  1.1  christos static void
    608  1.1  christos do_counter6_event (struct hw *me,
    609  1.1  christos 		  void *data)
    610  1.1  christos {
    611  1.1  christos   struct mn103tim *timers = hw_data(me);
    612  1.1  christos   long timer_nr = (long) data;
    613  1.1  christos   int next_timer;
    614  1.1  christos 
    615  1.1  christos   /* Check if counting is still enabled. */
    616  1.1  christos   if ( (timers->reg[timer_nr].mode & count_mask) != 0 )
    617  1.1  christos     {
    618  1.1  christos       /* Generate an interrupt for the timer underflow (TIMERn_UFLOW). */
    619  1.1  christos       hw_port_event (me, timer_nr, 1);
    620  1.1  christos 
    621  1.1  christos       /* Schedule next timeout.  */
    622  1.1  christos       timers->timer[timer_nr].start = hw_event_queue_time(me);
    623  1.1  christos       /* FIX: Check if div_ratio has changed and if it's now 0. */
    624  1.1  christos       timers->timer[timer_nr].event
    625  1.1  christos 	= hw_event_queue_schedule (me, timers->timer[timer_nr].div_ratio,
    626  1.1  christos 				   do_counter6_event, (void *)timer_nr);
    627  1.1  christos     }
    628  1.1  christos   else
    629  1.1  christos     {
    630  1.1  christos       timers->timer[timer_nr].event = NULL;
    631  1.1  christos     }
    632  1.1  christos 
    633  1.1  christos }
    634  1.1  christos 
    635  1.1  christos static void
    636  1.1  christos write_base_reg (struct hw *me,
    637  1.1  christos 		struct mn103tim *timers,
    638  1.1  christos 		int timer_nr,
    639  1.1  christos 		const void *source,
    640  1.1  christos 		unsigned  nr_bytes)
    641  1.1  christos {
    642  1.1  christos   unsigned i;
    643  1.1  christos   const unsigned8 *buf8 = source;
    644  1.1  christos   const unsigned16 *buf16 = source;
    645  1.1  christos 
    646  1.1  christos   /* If TMnCNE == 0 (counting is off),  writing to the base register
    647  1.1  christos      (TMnBR) causes a simultaneous write to the counter reg (TMnBC).
    648  1.1  christos      Else, the TMnBC is reloaded with the value from TMnBR when
    649  1.1  christos      underflow occurs.  Since the counter register is not explicitly
    650  1.1  christos      maintained, this functionality is handled in read_counter. */
    651  1.1  christos 
    652  1.1  christos   /* Check nr_bytes: write of 1, 2 or 4 bytes allowed depending on timer. */
    653  1.1  christos   switch ( nr_bytes )
    654  1.1  christos     {
    655  1.1  christos     case 1:
    656  1.1  christos       /* Storing 1 byte is ok for all registers. */
    657  1.1  christos       timers->reg[timer_nr].base = buf8[0];
    658  1.1  christos       break;
    659  1.1  christos 
    660  1.1  christos     case 2:
    661  1.1  christos       if ( timer_nr == 1 || timer_nr == 3 )
    662  1.1  christos 	{
    663  1.1  christos 	  hw_abort (me, "bad write size of 2 bytes to TM%dBR.", timer_nr);
    664  1.1  christos 	}
    665  1.1  christos       else
    666  1.1  christos 	{
    667  1.1  christos 	  if ( timer_nr < NR_8BIT_TIMERS )
    668  1.1  christos 	    {
    669  1.1  christos 	      timers->reg[timer_nr].base = buf8[0];
    670  1.1  christos 	      timers->reg[timer_nr+1].base = buf8[1];
    671  1.1  christos 	    }
    672  1.1  christos 	  else
    673  1.1  christos 	    {
    674  1.1  christos 	      timers->reg[timer_nr].base = buf16[0];
    675  1.1  christos 	    }
    676  1.1  christos 	}
    677  1.1  christos       break;
    678  1.1  christos 
    679  1.1  christos     case 4:
    680  1.1  christos       if ( timer_nr == 0 )
    681  1.1  christos 	{
    682  1.1  christos 	  timers->reg[0].base = buf8[0];
    683  1.1  christos 	  timers->reg[1].base = buf8[1];
    684  1.1  christos 	  timers->reg[2].base = buf8[2];
    685  1.1  christos 	  timers->reg[3].base = buf8[3];
    686  1.1  christos 	}
    687  1.1  christos       else if ( timer_nr == 4 )
    688  1.1  christos 	{
    689  1.1  christos 	  timers->reg[4].base = buf16[0];
    690  1.1  christos 	  timers->reg[5].base = buf16[1];
    691  1.1  christos 	}
    692  1.1  christos       else
    693  1.1  christos 	{
    694  1.1  christos 	  hw_abort (me, "bad write size of 4 bytes to TM%dBR.", timer_nr);
    695  1.1  christos 	}
    696  1.1  christos       break;
    697  1.1  christos 
    698  1.1  christos     default:
    699  1.1  christos       hw_abort (me, "bad write size must of %d bytes to TM%dBR.",
    700  1.1  christos 		nr_bytes, timer_nr);
    701  1.1  christos     }
    702  1.1  christos 
    703  1.1  christos }
    704  1.1  christos 
    705  1.1  christos static void
    706  1.1  christos write_mode_reg (struct hw *me,
    707  1.1  christos 		struct mn103tim *timers,
    708  1.1  christos 		long timer_nr,
    709  1.1  christos 		const void *source,
    710  1.1  christos 		unsigned nr_bytes)
    711  1.1  christos      /* for timers 0 to 5 */
    712  1.1  christos {
    713  1.1  christos   unsigned i;
    714  1.1  christos   unsigned8 mode_val, next_mode_val;
    715  1.1  christos   unsigned32 div_ratio;
    716  1.1  christos 
    717  1.1  christos   if ( nr_bytes != 1 )
    718  1.1  christos     {
    719  1.1  christos       hw_abort (me, "bad write size of %d bytes to TM%ldMD.", nr_bytes,
    720  1.1  christos 		timer_nr);
    721  1.1  christos     }
    722  1.1  christos 
    723  1.1  christos   mode_val = *(unsigned8 *)source;
    724  1.1  christos   timers->reg[timer_nr].mode = mode_val;
    725  1.1  christos 
    726  1.1  christos   if ( ( mode_val & count_and_load_mask ) == count_and_load_mask )
    727  1.1  christos     {
    728  1.1  christos       hw_abort(me, "Cannot load base reg and start counting simultaneously.");
    729  1.1  christos     }
    730  1.1  christos   if ( ( mode_val & bits2to5_mask ) != 0 )
    731  1.1  christos     {
    732  1.1  christos       hw_abort(me, "Cannot write to bits 2 to 5 of mode register");
    733  1.1  christos     }
    734  1.1  christos 
    735  1.1  christos   if ( mode_val & count_mask )
    736  1.1  christos     {
    737  1.1  christos       /* - de-schedule any previous event. */
    738  1.1  christos       /* - add new event to queue to start counting. */
    739  1.1  christos       /* - assert that counter == base reg? */
    740  1.1  christos 
    741  1.1  christos       /* For cascaded timers, */
    742  1.1  christos       if ( (mode_val & clock_mask) == clk_cascaded )
    743  1.1  christos 	{
    744  1.1  christos 	  if ( timer_nr == 0 || timer_nr == 4 )
    745  1.1  christos 	    {
    746  1.1  christos 	      hw_abort(me, "Timer %ld cannot be cascaded.", timer_nr);
    747  1.1  christos 	    }
    748  1.1  christos 	}
    749  1.1  christos       else
    750  1.1  christos 	{
    751  1.1  christos 	  div_ratio = timers->reg[timer_nr].base;
    752  1.1  christos 
    753  1.1  christos 	  /* Check for cascading. */
    754  1.1  christos 	  if ( timer_nr < NR_8BIT_TIMERS )
    755  1.1  christos 	    {
    756  1.1  christos 	      for ( i = timer_nr + 1; i <= 3; ++i )
    757  1.1  christos 		{
    758  1.1  christos 		  next_mode_val = timers->reg[i].mode;
    759  1.1  christos 		  if ( ( next_mode_val & clock_mask ) == clk_cascaded )
    760  1.1  christos 		    {
    761  1.1  christos 		      /* Check that CNE is on. */
    762  1.1  christos 		      if ( ( next_mode_val & count_mask ) == 0 )
    763  1.1  christos 			{
    764  1.1  christos 			  hw_abort (me, "cascaded timer not ready for counting");
    765  1.1  christos 			}
    766  1.1  christos 		      ASSERT(timers->timer[i].event == NULL);
    767  1.1  christos 		      ASSERT(timers->timer[i].div_ratio == 0);
    768  1.1  christos 		      div_ratio = div_ratio
    769  1.1  christos 			| (timers->reg[i].base << (8*(i-timer_nr)));
    770  1.1  christos 		    }
    771  1.1  christos 		  else
    772  1.1  christos 		    {
    773  1.1  christos 		      break;
    774  1.1  christos 		    }
    775  1.1  christos 		}
    776  1.1  christos 	    }
    777  1.1  christos 	  else
    778  1.1  christos 	    {
    779  1.1  christos 	      /* Mode register for a 16 bit timer */
    780  1.1  christos 	      next_mode_val = timers->reg[timer_nr+1].mode;
    781  1.1  christos 	      if ( ( next_mode_val & clock_mask ) == clk_cascaded )
    782  1.1  christos 		{
    783  1.1  christos 		  /* Check that CNE is on. */
    784  1.1  christos 		  if ( ( next_mode_val & count_mask ) == 0 )
    785  1.1  christos 		    {
    786  1.1  christos 		      hw_abort (me, "cascaded timer not ready for counting");
    787  1.1  christos 		    }
    788  1.1  christos 		  ASSERT(timers->timer[timer_nr+1].event == NULL);
    789  1.1  christos 		  ASSERT(timers->timer[timer_nr+1].div_ratio == 0);
    790  1.1  christos 		  div_ratio = div_ratio | (timers->reg[timer_nr+1].base << 16);
    791  1.1  christos 		}
    792  1.1  christos 	    }
    793  1.1  christos 
    794  1.1  christos 	  timers->timer[timer_nr].div_ratio = div_ratio;
    795  1.1  christos 
    796  1.1  christos 	  if ( NULL != timers->timer[timer_nr].event )
    797  1.1  christos 	    {
    798  1.1  christos 	      hw_event_queue_deschedule (me, timers->timer[timer_nr].event);
    799  1.1  christos 	      timers->timer[timer_nr].event = NULL;
    800  1.1  christos 	    }
    801  1.1  christos 
    802  1.1  christos 	  if ( div_ratio > 0 )
    803  1.1  christos 	    {
    804  1.1  christos 	      /* Set start time. */
    805  1.1  christos 	      timers->timer[timer_nr].start = hw_event_queue_time(me);
    806  1.1  christos 	      timers->timer[timer_nr].event
    807  1.1  christos 		= hw_event_queue_schedule(me, div_ratio,
    808  1.1  christos 					  do_counter_event,
    809  1.1  christos 					  (void *)(timer_nr));
    810  1.1  christos 	    }
    811  1.1  christos 	}
    812  1.1  christos     }
    813  1.1  christos   else
    814  1.1  christos     {
    815  1.1  christos       /* Turn off counting */
    816  1.1  christos       if ( NULL != timers->timer[timer_nr].event )
    817  1.1  christos 	{
    818  1.1  christos 	  ASSERT((timers->reg[timer_nr].mode & clock_mask) != clk_cascaded);
    819  1.1  christos 	  hw_event_queue_deschedule (me, timers->timer[timer_nr].event);
    820  1.1  christos 	  timers->timer[timer_nr].event = NULL;
    821  1.1  christos 	}
    822  1.1  christos       else
    823  1.1  christos 	{
    824  1.1  christos 	  if ( (timers->reg[timer_nr].mode & clock_mask) == clk_cascaded )
    825  1.1  christos 	    {
    826  1.1  christos 	      ASSERT(timers->timer[timer_nr].event == NULL);
    827  1.1  christos 	    }
    828  1.1  christos 	}
    829  1.1  christos 
    830  1.1  christos     }
    831  1.1  christos 
    832  1.1  christos }
    833  1.1  christos 
    834  1.1  christos static void
    835  1.1  christos write_tm6md (struct hw *me,
    836  1.1  christos 	     struct mn103tim *timers,
    837  1.1  christos 	     unsigned_word address,
    838  1.1  christos 	     const void *source,
    839  1.1  christos 	     unsigned nr_bytes)
    840  1.1  christos {
    841  1.1  christos   unsigned8 mode_val0 = 0x00, mode_val1 = 0x00;
    842  1.1  christos   unsigned32 div_ratio;
    843  1.1  christos   long timer_nr = 6;
    844  1.1  christos 
    845  1.1  christos   unsigned_word offset = address - timers->block[0].base;
    846  1.1  christos 
    847  1.1  christos   if ((offset != 0x84 && nr_bytes > 1) || nr_bytes > 2 )
    848  1.1  christos     {
    849  1.1  christos       hw_abort (me, "Bad write size of %d bytes to TM6MD", nr_bytes);
    850  1.1  christos     }
    851  1.1  christos 
    852  1.1  christos   if ( offset == 0x84 )  /* address of TM6MD */
    853  1.1  christos     {
    854  1.1  christos       /*  Fill in first byte of mode */
    855  1.1  christos       mode_val0 = *(unsigned8 *)source;
    856  1.1  christos       timers->tm6md0 = mode_val0;
    857  1.1  christos 
    858  1.1  christos       if ( ( mode_val0 & 0x26 ) != 0 )
    859  1.1  christos 	{
    860  1.1  christos 	  hw_abort(me, "Cannot write to bits 5, 3, and 2 of TM6MD");
    861  1.1  christos 	}
    862  1.1  christos     }
    863  1.1  christos 
    864  1.1  christos   if ( offset == 0x85 || nr_bytes == 2 )
    865  1.1  christos     {
    866  1.1  christos       /*  Fill in second byte of mode */
    867  1.1  christos       if ( nr_bytes == 2 )
    868  1.1  christos 	{
    869  1.1  christos 	  mode_val1 = *(unsigned8 *)source+1;
    870  1.1  christos 	}
    871  1.1  christos       else
    872  1.1  christos 	{
    873  1.1  christos 	  mode_val1 = *(unsigned8 *)source;
    874  1.1  christos 	}
    875  1.1  christos 
    876  1.1  christos       timers->tm6md1 = mode_val1;
    877  1.1  christos 
    878  1.1  christos       if ( ( mode_val1 & count_and_load_mask ) == count_and_load_mask )
    879  1.1  christos 	{
    880  1.1  christos 	  hw_abort(me, "Cannot load base reg and start counting simultaneously.");
    881  1.1  christos 	}
    882  1.1  christos       if ( ( mode_val1 & bits0to2_mask ) != 0 )
    883  1.1  christos 	{
    884  1.1  christos 	  hw_abort(me, "Cannot write to bits 8 to 10 of TM6MD");
    885  1.1  christos 	}
    886  1.1  christos     }
    887  1.1  christos 
    888  1.1  christos   if ( mode_val1 & count_mask )
    889  1.1  christos     {
    890  1.1  christos       /* - de-schedule any previous event. */
    891  1.1  christos       /* - add new event to queue to start counting. */
    892  1.1  christos       /* - assert that counter == base reg? */
    893  1.1  christos 
    894  1.1  christos       div_ratio = timers->tm6ca;  /* binary counter for timer 6 */
    895  1.1  christos       timers->timer[timer_nr].div_ratio = div_ratio;
    896  1.1  christos       if ( NULL != timers->timer[timer_nr].event )
    897  1.1  christos 	{
    898  1.1  christos 	  hw_event_queue_deschedule (me, timers->timer[timer_nr].event);
    899  1.1  christos 	  timers->timer[timer_nr].event = NULL;
    900  1.1  christos 	}
    901  1.1  christos 
    902  1.1  christos       if ( div_ratio > 0 )
    903  1.1  christos 	{
    904  1.1  christos 	  /* Set start time. */
    905  1.1  christos 	  timers->timer[timer_nr].start = hw_event_queue_time(me);
    906  1.1  christos 	  timers->timer[timer_nr].event
    907  1.1  christos 	    = hw_event_queue_schedule(me, div_ratio,
    908  1.1  christos 				      do_counter6_event,
    909  1.1  christos 				      (void *)(timer_nr));
    910  1.1  christos 	}
    911  1.1  christos     }
    912  1.1  christos   else
    913  1.1  christos     {
    914  1.1  christos       /* Turn off counting */
    915  1.1  christos       if ( NULL != timers->timer[timer_nr].event )
    916  1.1  christos 	{
    917  1.1  christos 	  hw_event_queue_deschedule (me, timers->timer[timer_nr].event);
    918  1.1  christos 	  timers->timer[timer_nr].event = NULL;
    919  1.1  christos 	}
    920  1.1  christos     }
    921  1.1  christos }
    922  1.1  christos 
    923  1.1  christos 
    924  1.1  christos 
    925  1.1  christos static void
    926  1.1  christos write_special_timer6_reg (struct hw *me,
    927  1.1  christos 			  struct mn103tim *timers,
    928  1.1  christos 			  int timer_nr,
    929  1.1  christos 			  const void *source,
    930  1.1  christos 			  unsigned  nr_bytes)
    931  1.1  christos {
    932  1.1  christos   unsigned32 val;
    933  1.1  christos 
    934  1.1  christos   switch (nr_bytes) {
    935  1.1  christos   case 1:
    936  1.1  christos     {
    937  1.1  christos       switch ( timer_nr ) {
    938  1.1  christos       case TM6MDA:
    939  1.1  christos 	timers->tm6mda = *(unsigned8 *)source;
    940  1.1  christos 	break;
    941  1.1  christos 
    942  1.1  christos       case TM6MDB:
    943  1.1  christos 	timers->tm6mdb = *(unsigned8 *)source;
    944  1.1  christos 	break;
    945  1.1  christos 
    946  1.1  christos       case TM6CA:
    947  1.1  christos 	timers->tm6ca = *(unsigned8 *)source;
    948  1.1  christos 	break;
    949  1.1  christos 
    950  1.1  christos       case TM6CB:
    951  1.1  christos 	timers->tm6cb = *(unsigned8 *)source;
    952  1.1  christos 	break;
    953  1.1  christos 
    954  1.1  christos       default:
    955  1.1  christos 	break;
    956  1.1  christos       }
    957  1.1  christos       break;
    958  1.1  christos     }
    959  1.1  christos 
    960  1.1  christos   case 2:
    961  1.1  christos     if ( timer_nr == TM6CA )
    962  1.1  christos       {
    963  1.1  christos 	timers->tm6ca = *(unsigned16 *)source;
    964  1.1  christos       }
    965  1.1  christos     else if ( timer_nr == TM6CB )
    966  1.1  christos       {
    967  1.1  christos 	timers->tm6cb = *(unsigned16 *)source;
    968  1.1  christos       }
    969  1.1  christos     else
    970  1.1  christos       {
    971  1.1  christos 	hw_abort(me, "bad read size for timer 6 mode A/B register");
    972  1.1  christos       }
    973  1.1  christos     break;
    974  1.1  christos 
    975  1.1  christos   default:
    976  1.1  christos     hw_abort(me, "bad read size for timer 6 register");
    977  1.1  christos   }
    978  1.1  christos 
    979  1.1  christos }
    980  1.1  christos 
    981  1.1  christos 
    982  1.1  christos static unsigned
    983  1.1  christos mn103tim_io_write_buffer (struct hw *me,
    984  1.1  christos 			  const void *source,
    985  1.1  christos 			  int space,
    986  1.1  christos 			  unsigned_word base,
    987  1.1  christos 			  unsigned nr_bytes)
    988  1.1  christos {
    989  1.1  christos   struct mn103tim *timers = hw_data (me);
    990  1.1  christos   enum timer_register_types timer_reg;
    991  1.1  christos 
    992  1.1  christos   HW_TRACE ((me, "write to 0x%08lx length %d with 0x%x", (long) base,
    993  1.1  christos 	     (int) nr_bytes, *(unsigned32 *)source));
    994  1.1  christos 
    995  1.1  christos   timer_reg = decode_addr (me, timers, base);
    996  1.1  christos 
    997  1.1  christos   /* It can be either a mode register, a base register, a binary counter, */
    998  1.1  christos   /* or a special timer 6 register.  Check in that order. */
    999  1.1  christos   if ( timer_reg <= LAST_MODE_REG )
   1000  1.1  christos     {
   1001  1.1  christos       if ( timer_reg == 6 )
   1002  1.1  christos 	{
   1003  1.1  christos 	  write_tm6md(me, timers, base, source, nr_bytes);
   1004  1.1  christos 	}
   1005  1.1  christos       else
   1006  1.1  christos 	{
   1007  1.1  christos 	  write_mode_reg(me, timers, timer_reg-FIRST_MODE_REG,
   1008  1.1  christos 			 source, nr_bytes);
   1009  1.1  christos 	}
   1010  1.1  christos     }
   1011  1.1  christos   else if ( timer_reg <= LAST_BASE_REG )
   1012  1.1  christos     {
   1013  1.1  christos       write_base_reg(me, timers, timer_reg-FIRST_BASE_REG, source, nr_bytes);
   1014  1.1  christos     }
   1015  1.1  christos   else if ( timer_reg <= LAST_COUNTER )
   1016  1.1  christos     {
   1017  1.1  christos       hw_abort(me, "cannot write to counter");
   1018  1.1  christos     }
   1019  1.1  christos   else if ( timer_reg <= LAST_TIMER_REG )
   1020  1.1  christos     {
   1021  1.1  christos       write_special_timer6_reg(me, timers, timer_reg, source, nr_bytes);
   1022  1.1  christos     }
   1023  1.1  christos   else
   1024  1.1  christos     {
   1025  1.1  christos       hw_abort(me, "invalid reg type");
   1026  1.1  christos     }
   1027  1.1  christos 
   1028  1.1  christos   return nr_bytes;
   1029  1.1  christos }
   1030  1.1  christos 
   1031  1.1  christos 
   1032  1.1  christos const struct hw_descriptor dv_mn103tim_descriptor[] = {
   1033  1.1  christos   { "mn103tim", mn103tim_finish, },
   1034  1.1  christos   { NULL },
   1035  1.1  christos };
   1036