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