X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Fmn10300%2Fdv-mn103tim.c;h=53e49cd61f69a6e1413a30ff878c6770bf6d3570;hb=7fed4b0be6aa0d0794b8536e9f80d128f0d9bbdb;hp=6347db6b26ebf5561e015aa3b356312d30b004ec;hpb=e98fe4f7b54cbdf29aef9287bbb1bea8801dd05a;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/mn10300/dv-mn103tim.c b/sim/mn10300/dv-mn103tim.c index 6347db6b26..53e49cd61f 100644 --- a/sim/mn10300/dv-mn103tim.c +++ b/sim/mn10300/dv-mn103tim.c @@ -1,26 +1,26 @@ /* This file is part of the program GDB, the GNU debugger. - Copyright (C) 1998 Free Software Foundation, Inc. + Copyright (C) 1998-2015 Free Software Foundation, Inc. Contributed by Cygnus Solutions. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + along with this program. If not, see . */ #include "sim-main.h" #include "hw-main.h" +#include "sim-assert.h" /* DEVICE @@ -83,29 +83,35 @@ enum timer_register_types { TM6MDB, TM6CA, TM6CB, + LAST_TIMER_REG = TM6BC, }; /* Don't include timer 6 because it's handled specially. */ #define NR_8BIT_TIMERS 4 #define NR_16BIT_TIMERS 2 -#define NR_TIMERS 6 +#define NR_REG_TIMERS 6 /* Exclude timer 6 - it's handled specially. */ +#define NR_TIMERS 7 -typedef struct _mn10300_timer { - unsigned32 div_ratio, start, base; +typedef struct _mn10300_timer_regs { + unsigned32 base; unsigned8 mode; +} mn10300_timer_regs; + +typedef struct _mn10300_timer { + unsigned32 div_ratio, start; struct hw_event *event; } mn10300_timer; struct mn103tim { struct mn103tim_block block[NR_TIMER_BLOCKS]; + mn10300_timer_regs reg[NR_REG_TIMERS]; mn10300_timer timer[NR_TIMERS]; /* treat timer 6 registers specially. */ - unsigned16 tm6md, tm6bc, tm6mca, tm6mcb; + unsigned16 tm6md0, tm6md1, tm6bc, tm6ca, tm6cb; unsigned8 tm6mda, tm6mdb; /* compare/capture mode regs for timer 6 */ - struct hw_event *event6; }; /* output port ID's */ @@ -141,6 +147,7 @@ static const struct hw_port_descriptor mn103tim_ports[] = { }; #define bits2to5_mask 0x3c +#define bits0to2_mask 0x07 #define load_mask 0x40 #define count_mask 0x80 #define count_and_load_mask (load_mask | count_mask) @@ -203,18 +210,22 @@ mn103tim_finish (struct hw *me) attach_mn103tim_regs (me, timers); /* Initialize the timers */ + for ( i=0; i < NR_REG_TIMERS; ++i ) + { + timers->reg[i].mode = 0x00; + timers->reg[i].base = 0; + } for ( i=0; i < NR_TIMERS; ++i ) { timers->timer[i].event = NULL; - timers->timer[i].mode = 0x00; - timers->timer[i].base = 0; timers->timer[i].div_ratio = 0; timers->timer[i].start = 0; } - timers->tm6md = 0x0000; + timers->tm6md0 = 0x00; + timers->tm6md1 = 0x00; timers->tm6bc = 0x0000; - timers->tm6mca = 0x0000; - timers->tm6mcb = 0x0000; + timers->tm6ca = 0x0000; + timers->tm6cb = 0x0000; timers->tm6mda = 0x00; timers->tm6mdb = 0x00; } @@ -247,7 +258,8 @@ decode_addr (struct hw *me, case 0x23: return TM3BC; case 0x80: return TM4MD; case 0x82: return TM5MD; - case 0x84: return TM6MD; + case 0x84: /* fall through */ + case 0x85: return TM6MD; case 0x90: return TM4BR; case 0x92: return TM5BR; case 0xa0: return TM4BC; @@ -279,18 +291,25 @@ read_mode_reg (struct hw *me, { case 1: /* Accessing 1 byte is ok for all mode registers. */ - *(unsigned8*)dest = timers->timer[timer_nr].mode; + if ( timer_nr == 6 ) + { + *(unsigned8*)dest = timers->tm6md0; + } + else + { + *(unsigned8*)dest = timers->reg[timer_nr].mode; + } break; case 2: if ( timer_nr == 6 ) { - *(unsigned16 *)dest = timers->tm6md; + *(unsigned16 *)dest = (timers->tm6md0 << 8) | timers->tm6md1; } else if ( timer_nr == 0 || timer_nr == 2 ) { - val16 = (timers->timer[timer_nr].mode << 8) - | timers->timer[timer_nr+1].mode; + val16 = (timers->reg[timer_nr].mode << 8) + | timers->reg[timer_nr+1].mode; *(unsigned16*)dest = val16; } else @@ -302,10 +321,10 @@ read_mode_reg (struct hw *me, case 4: if ( timer_nr == 0 ) { - val32 = (timers->timer[0].mode << 24 ) - | (timers->timer[1].mode << 16) - | (timers->timer[2].mode << 8) - | timers->timer[3].mode; + val32 = (timers->reg[0].mode << 24 ) + | (timers->reg[1].mode << 16) + | (timers->reg[2].mode << 8) + | timers->reg[3].mode; *(unsigned32*)dest = val32; } else @@ -338,7 +357,7 @@ read_base_reg (struct hw *me, /* Reading 1 byte is ok for all registers. */ if ( timer_nr < NR_8BIT_TIMERS ) { - *(unsigned8*)dest = timers->timer[timer_nr].base; + *(unsigned8*)dest = timers->reg[timer_nr].base; } break; @@ -351,12 +370,12 @@ read_base_reg (struct hw *me, { if ( timer_nr < NR_8BIT_TIMERS ) { - val16 = (timers->timer[timer_nr].base<<8) - | timers->timer[timer_nr+1].base; + val16 = (timers->reg[timer_nr].base<<8) + | timers->reg[timer_nr+1].base; } else { - val16 = timers->timer[timer_nr].base; + val16 = timers->reg[timer_nr].base; } *(unsigned16*)dest = val16; } @@ -365,13 +384,13 @@ read_base_reg (struct hw *me, case 4: if ( timer_nr == 0 ) { - val32 = (timers->timer[0].base << 24) | (timers->timer[1].base << 16) - | (timers->timer[2].base << 8) | timers->timer[3].base; + val32 = (timers->reg[0].base << 24) | (timers->reg[1].base << 16) + | (timers->reg[2].base << 8) | timers->reg[3].base; *(unsigned32*)dest = val32; } else if ( timer_nr == 4 ) { - val32 = (timers->timer[4].base << 16) | timers->timer[5].base; + val32 = (timers->reg[4].base << 16) | timers->reg[5].base; *(unsigned32*)dest = val32; } else @@ -399,16 +418,30 @@ read_counter (struct hw *me, if ( NULL == timers->timer[timer_nr].event ) { /* Timer is not counting, use value in base register. */ - val = timers->timer[timer_nr].base; + if ( timer_nr == 6 ) + { + val = 0; /* timer 6 is an up counter */ + } + else + { + val = timers->reg[timer_nr].base; + } } else { - /* ticks left = start time + div ratio - curr time */ - /* Cannot use base register because it can be written during counting and it - doesn't affect counter until underflow occurs. */ - - val = timers->timer[timer_nr].start + timers->timer[timer_nr].div_ratio - - hw_event_queue_time(me); + if ( timer_nr == 6 ) /* timer 6 is an up counter. */ + { + val = hw_event_queue_time(me) - timers->timer[timer_nr].start; + } + else + { + /* ticks left = start time + div ratio - curr time */ + /* Cannot use base register because it can be written during counting and it + doesn't affect counter until underflow occurs. */ + + val = timers->timer[timer_nr].start + timers->timer[timer_nr].div_ratio + - hw_event_queue_time(me); + } } switch (nr_bytes) { @@ -431,6 +464,63 @@ read_counter (struct hw *me, } +static void +read_special_timer6_reg (struct hw *me, + struct mn103tim *timers, + int timer_nr, + void *dest, + unsigned nr_bytes) +{ + unsigned32 val; + + switch (nr_bytes) { + case 1: + { + switch ( timer_nr ) { + case TM6MDA: + *(unsigned8 *)dest = timers->tm6mda; + break; + + case TM6MDB: + *(unsigned8 *)dest = timers->tm6mdb; + break; + + case TM6CA: + *(unsigned8 *)dest = timers->tm6ca; + break; + + case TM6CB: + *(unsigned8 *)dest = timers->tm6cb; + break; + + default: + break; + } + break; + } + + case 2: + if ( timer_nr == TM6CA ) + { + *(unsigned16 *)dest = timers->tm6ca; + } + else if ( timer_nr == TM6CB ) + { + *(unsigned16 *)dest = timers->tm6cb; + } + else + { + hw_abort(me, "bad read size for timer 6 mode A/B register"); + } + break; + + default: + hw_abort(me, "bad read size for timer 6 register"); + } + +} + + static unsigned mn103tim_io_read_buffer (struct hw *me, void *dest, @@ -445,8 +535,8 @@ mn103tim_io_read_buffer (struct hw *me, timer_reg = decode_addr (me, timers, base); - /* It can be either a mode register, a base register or a binary counter. */ - /* Check in that order. */ + /* It can be either a mode register, a base register, a binary counter, */ + /* or a special timer 6 register. Check in that order. */ if ( timer_reg >= FIRST_MODE_REG && timer_reg <= LAST_MODE_REG ) { read_mode_reg(me, timers, timer_reg-FIRST_MODE_REG, dest, nr_bytes); @@ -459,6 +549,10 @@ mn103tim_io_read_buffer (struct hw *me, { read_counter(me, timers, timer_reg-FIRST_COUNTER, dest, nr_bytes); } + else if ( timer_reg <= LAST_TIMER_REG ) + { + read_special_timer6_reg(me, timers, timer_reg, dest, nr_bytes); + } else { hw_abort(me, "invalid timer register address."); @@ -473,22 +567,67 @@ do_counter_event (struct hw *me, void *data) { struct mn103tim *timers = hw_data(me); - int timer_nr = (int) data; + long timer_nr = (long) data; + int next_timer; /* Check if counting is still enabled. */ - if ( (timers->timer[timer_nr].mode & count_mask) != 0 ) + if ( (timers->reg[timer_nr].mode & count_mask) != 0 ) { /* Generate an interrupt for the timer underflow (TIMERn_UFLOW). */ - hw_port_event (me, timer_nr /*uflow_port[timer_nr]*/, 1 /* level */); - /* Schedule next timeout. */ + /* Port event occurs on port of last cascaded timer. */ + /* This works across timer range from 0 to NR_REG_TIMERS because */ + /* the first 16 bit timer (timer 4) is not allowed to be set as */ + /* a cascading timer. */ + for ( next_timer = timer_nr+1; next_timer < NR_REG_TIMERS; ++next_timer ) + { + if ( (timers->reg[next_timer].mode & clock_mask) != clk_cascaded ) + { + break; + } + } + hw_port_event (me, next_timer-1, 1); + /* Schedule next timeout. */ timers->timer[timer_nr].start = hw_event_queue_time(me); - /* FIX: Check if div_ ratio has changed and if it's now 0. */ + /* FIX: Check if div_ratio has changed and if it's now 0. */ timers->timer[timer_nr].event = hw_event_queue_schedule (me, timers->timer[timer_nr].div_ratio, do_counter_event, (void *)timer_nr); } + else + { + timers->timer[timer_nr].event = NULL; + } + +} + + +static void +do_counter6_event (struct hw *me, + void *data) +{ + struct mn103tim *timers = hw_data(me); + long timer_nr = (long) data; + int next_timer; + + /* Check if counting is still enabled. */ + if ( (timers->reg[timer_nr].mode & count_mask) != 0 ) + { + /* Generate an interrupt for the timer underflow (TIMERn_UFLOW). */ + hw_port_event (me, timer_nr, 1); + + /* Schedule next timeout. */ + timers->timer[timer_nr].start = hw_event_queue_time(me); + /* FIX: Check if div_ratio has changed and if it's now 0. */ + timers->timer[timer_nr].event + = hw_event_queue_schedule (me, timers->timer[timer_nr].div_ratio, + do_counter6_event, (void *)timer_nr); + } + else + { + timers->timer[timer_nr].event = NULL; + } } @@ -502,7 +641,6 @@ write_base_reg (struct hw *me, unsigned i; const unsigned8 *buf8 = source; const unsigned16 *buf16 = source; - unsigned8 mode_val; /* If TMnCNE == 0 (counting is off), writing to the base register (TMnBR) causes a simultaneous write to the counter reg (TMnBC). @@ -510,14 +648,12 @@ write_base_reg (struct hw *me, underflow occurs. Since the counter register is not explicitly maintained, this functionality is handled in read_counter. */ - mode_val = timers->timer[timer_nr].mode; - /* Check nr_bytes: write of 1, 2 or 4 bytes allowed depending on timer. */ switch ( nr_bytes ) { case 1: /* Storing 1 byte is ok for all registers. */ - timers->timer[timer_nr].base = buf8[0]; + timers->reg[timer_nr].base = buf8[0]; break; case 2: @@ -529,12 +665,12 @@ write_base_reg (struct hw *me, { if ( timer_nr < NR_8BIT_TIMERS ) { - timers->timer[timer_nr].base = buf8[0]; - timers->timer[timer_nr+1].base = buf8[1]; + timers->reg[timer_nr].base = buf8[0]; + timers->reg[timer_nr+1].base = buf8[1]; } else { - timers->timer[timer_nr].base = buf16[0]; + timers->reg[timer_nr].base = buf16[0]; } } break; @@ -542,16 +678,15 @@ write_base_reg (struct hw *me, case 4: if ( timer_nr == 0 ) { - ASSERT(0); - timers->timer[0].base = buf8[0]; - timers->timer[1].base = buf8[1]; - timers->timer[2].base = buf8[2]; - timers->timer[3].base = buf8[3]; + timers->reg[0].base = buf8[0]; + timers->reg[1].base = buf8[1]; + timers->reg[2].base = buf8[2]; + timers->reg[3].base = buf8[3]; } else if ( timer_nr == 4 ) { - timers->timer[4].base = buf16[0]; - timers->timer[5].base = buf16[1]; + timers->reg[4].base = buf16[0]; + timers->reg[5].base = buf16[1]; } else { @@ -567,12 +702,12 @@ write_base_reg (struct hw *me, } static void -write_8bit_mode_reg (struct hw *me, - struct mn103tim *timers, - int timer_nr, - const void *source, - unsigned nr_bytes) - /* for timers 0 to 3 */ +write_mode_reg (struct hw *me, + struct mn103tim *timers, + long timer_nr, + const void *source, + unsigned nr_bytes) + /* for timers 0 to 5 */ { unsigned i; unsigned8 mode_val, next_mode_val; @@ -580,11 +715,12 @@ write_8bit_mode_reg (struct hw *me, if ( nr_bytes != 1 ) { - hw_abort (me, "bad write size of %d bytes to TM%dMD.", nr_bytes, timer_nr); + hw_abort (me, "bad write size of %d bytes to TM%ldMD.", nr_bytes, + timer_nr); } mode_val = *(unsigned8 *)source; - timers->timer[timer_nr].mode = mode_val; + timers->reg[timer_nr].mode = mode_val; if ( ( mode_val & count_and_load_mask ) == count_and_load_mask ) { @@ -594,7 +730,7 @@ write_8bit_mode_reg (struct hw *me, { hw_abort(me, "Cannot write to bits 2 to 5 of mode register"); } - + if ( mode_val & count_mask ) { /* - de-schedule any previous event. */ @@ -604,27 +740,54 @@ write_8bit_mode_reg (struct hw *me, /* For cascaded timers, */ if ( (mode_val & clock_mask) == clk_cascaded ) { - if ( timer_nr == 0 ) + if ( timer_nr == 0 || timer_nr == 4 ) { - hw_abort(me, "Timer 0 cannot be cascaded."); + hw_abort(me, "Timer %ld cannot be cascaded.", timer_nr); } } else { - div_ratio = timers->timer[timer_nr].base; + div_ratio = timers->reg[timer_nr].base; /* Check for cascading. */ - next_mode_val = timers->timer[timer_nr+1].mode; - if ( ( next_mode_val & clock_mask ) == clk_cascaded ) + if ( timer_nr < NR_8BIT_TIMERS ) + { + for ( i = timer_nr + 1; i <= 3; ++i ) + { + next_mode_val = timers->reg[i].mode; + if ( ( next_mode_val & clock_mask ) == clk_cascaded ) + { + /* Check that CNE is on. */ + if ( ( next_mode_val & count_mask ) == 0 ) + { + hw_abort (me, "cascaded timer not ready for counting"); + } + ASSERT(timers->timer[i].event == NULL); + ASSERT(timers->timer[i].div_ratio == 0); + div_ratio = div_ratio + | (timers->reg[i].base << (8*(i-timer_nr))); + } + else + { + break; + } + } + } + else { - /* Check that CNE is on. */ - if ( ( next_mode_val & count_mask ) == 0 ) + /* Mode register for a 16 bit timer */ + next_mode_val = timers->reg[timer_nr+1].mode; + if ( ( next_mode_val & clock_mask ) == clk_cascaded ) { - hw_abort (me, "cascaded timer not ready for counting"); + /* Check that CNE is on. */ + if ( ( next_mode_val & count_mask ) == 0 ) + { + hw_abort (me, "cascaded timer not ready for counting"); + } + ASSERT(timers->timer[timer_nr+1].event == NULL); + ASSERT(timers->timer[timer_nr+1].div_ratio == 0); + div_ratio = div_ratio | (timers->reg[timer_nr+1].base << 16); } - ASSERT(timers->timer[timer_nr+1].event == NULL); - ASSERT(timers->timer[timer_nr+1].div_ratio == 0); - div_ratio = div_ratio | (timers->timer[timer_nr+1].base << 8); } timers->timer[timer_nr].div_ratio = div_ratio; @@ -639,7 +802,6 @@ write_8bit_mode_reg (struct hw *me, { /* Set start time. */ timers->timer[timer_nr].start = hw_event_queue_time(me); - timers->timer[timer_nr].event = hw_event_queue_schedule(me, div_ratio, do_counter_event, @@ -652,13 +814,13 @@ write_8bit_mode_reg (struct hw *me, /* Turn off counting */ if ( NULL != timers->timer[timer_nr].event ) { - ASSERT((timers->timer[timer_nr].mode & clock_mask) != clk_cascaded); + ASSERT((timers->reg[timer_nr].mode & clock_mask) != clk_cascaded); hw_event_queue_deschedule (me, timers->timer[timer_nr].event); timers->timer[timer_nr].event = NULL; } else { - if ( (timers->timer[timer_nr].mode & clock_mask) == clk_cascaded ) + if ( (timers->reg[timer_nr].mode & clock_mask) == clk_cascaded ) { ASSERT(timers->timer[timer_nr].event == NULL); } @@ -669,84 +831,81 @@ write_8bit_mode_reg (struct hw *me, } static void -write_16bit_mode_reg (struct hw *me, - struct mn103tim *timers, - int timer_nr, - const void *source, - unsigned nr_bytes) - /* for timers 4 and 5, not 6 */ +write_tm6md (struct hw *me, + struct mn103tim *timers, + unsigned_word address, + const void *source, + unsigned nr_bytes) { - unsigned i; - unsigned8 mode_val, next_mode_val; + unsigned8 mode_val0 = 0x00, mode_val1 = 0x00; unsigned32 div_ratio; + long timer_nr = 6; - if ( nr_bytes != 1 ) + unsigned_word offset = address - timers->block[0].base; + + if ((offset != 0x84 && nr_bytes > 1) || nr_bytes > 2 ) { - hw_abort (me, "bad write size of %d bytes to TM%dMD.", nr_bytes, timer_nr); + hw_abort (me, "Bad write size of %d bytes to TM6MD", nr_bytes); } - mode_val = *(unsigned8 *)source; - timers->timer[timer_nr].mode = mode_val; - - if ( ( mode_val & count_and_load_mask ) == count_and_load_mask ) + if ( offset == 0x84 ) /* address of TM6MD */ { - hw_abort(me, "Cannot load base reg and start counting simultaneously."); + /* Fill in first byte of mode */ + mode_val0 = *(unsigned8 *)source; + timers->tm6md0 = mode_val0; + + if ( ( mode_val0 & 0x26 ) != 0 ) + { + hw_abort(me, "Cannot write to bits 5, 3, and 2 of TM6MD"); + } } - if ( ( mode_val & bits2to5_mask ) != 0 ) + + if ( offset == 0x85 || nr_bytes == 2 ) { - hw_abort(me, "Cannot write to bits 2 to 5 of mode register"); + /* Fill in second byte of mode */ + if ( nr_bytes == 2 ) + { + mode_val1 = *(unsigned8 *)source+1; + } + else + { + mode_val1 = *(unsigned8 *)source; + } + + timers->tm6md1 = mode_val1; + + if ( ( mode_val1 & count_and_load_mask ) == count_and_load_mask ) + { + hw_abort(me, "Cannot load base reg and start counting simultaneously."); + } + if ( ( mode_val1 & bits0to2_mask ) != 0 ) + { + hw_abort(me, "Cannot write to bits 8 to 10 of TM6MD"); + } } - - if ( mode_val & count_mask ) + if ( mode_val1 & count_mask ) { /* - de-schedule any previous event. */ /* - add new event to queue to start counting. */ /* - assert that counter == base reg? */ - /* For cascaded timers, */ - if ( (mode_val & clock_mask) == clk_cascaded ) + div_ratio = timers->tm6ca; /* binary counter for timer 6 */ + timers->timer[timer_nr].div_ratio = div_ratio; + if ( NULL != timers->timer[timer_nr].event ) { - if ( timer_nr == 4 ) - { - hw_abort(me, "Timer 4 cannot be cascaded."); - } + hw_event_queue_deschedule (me, timers->timer[timer_nr].event); + timers->timer[timer_nr].event = NULL; } - else - { - div_ratio = timers->timer[timer_nr].base; - - /* Check for cascading. */ - next_mode_val = timers->timer[timer_nr+1].mode; - if ( ( next_mode_val & clock_mask ) == clk_cascaded ) - { - /* Check that CNE is on. */ - if ( ( next_mode_val & count_mask ) == 0 ) - { - hw_abort (me, "cascaded timer not ready for counting"); - } - ASSERT(timers->timer[timer_nr+1].event == NULL); - ASSERT(timers->timer[timer_nr+1].div_ratio == 0); - div_ratio = div_ratio | (timers->timer[timer_nr+1].base << 16); - } - - timers->timer[timer_nr].div_ratio = div_ratio; - - if ( NULL != timers->timer[timer_nr].event ) - { - hw_event_queue_deschedule (me, timers->timer[timer_nr].event); - timers->timer[timer_nr].event = NULL; - } - if ( div_ratio > 0 ) - { - /* Set start time. */ - timers->timer[timer_nr].start = hw_event_queue_time(me); - - timers->timer[timer_nr].event - = hw_event_queue_schedule(me, div_ratio, do_counter_event, - (void *)(timer_nr)); - } + if ( div_ratio > 0 ) + { + /* Set start time. */ + timers->timer[timer_nr].start = hw_event_queue_time(me); + timers->timer[timer_nr].event + = hw_event_queue_schedule(me, div_ratio, + do_counter6_event, + (void *)(timer_nr)); } } else @@ -754,22 +913,71 @@ write_16bit_mode_reg (struct hw *me, /* Turn off counting */ if ( NULL != timers->timer[timer_nr].event ) { - ASSERT((timers->timer[timer_nr].mode & clock_mask) != clk_cascaded); hw_event_queue_deschedule (me, timers->timer[timer_nr].event); timers->timer[timer_nr].event = NULL; } - else - { - if ( (timers->timer[timer_nr].mode & clock_mask) == clk_cascaded ) - { - ASSERT(timers->timer[timer_nr].event == NULL); - } - } + } +} + + + +static void +write_special_timer6_reg (struct hw *me, + struct mn103tim *timers, + int timer_nr, + const void *source, + unsigned nr_bytes) +{ + unsigned32 val; + + switch (nr_bytes) { + case 1: + { + switch ( timer_nr ) { + case TM6MDA: + timers->tm6mda = *(unsigned8 *)source; + break; + + case TM6MDB: + timers->tm6mdb = *(unsigned8 *)source; + break; + + case TM6CA: + timers->tm6ca = *(unsigned8 *)source; + break; + + case TM6CB: + timers->tm6cb = *(unsigned8 *)source; + break; + default: + break; + } + break; } + + case 2: + if ( timer_nr == TM6CA ) + { + timers->tm6ca = *(unsigned16 *)source; + } + else if ( timer_nr == TM6CB ) + { + timers->tm6cb = *(unsigned16 *)source; + } + else + { + hw_abort(me, "bad read size for timer 6 mode A/B register"); + } + break; + default: + hw_abort(me, "bad read size for timer 6 register"); + } + } + static unsigned mn103tim_io_write_buffer (struct hw *me, const void *source, @@ -785,19 +993,18 @@ mn103tim_io_write_buffer (struct hw *me, timer_reg = decode_addr (me, timers, base); - /* It can be either a mode register, a base register or a binary counter. */ - /* Check in that order. */ + /* It can be either a mode register, a base register, a binary counter, */ + /* or a special timer 6 register. Check in that order. */ if ( timer_reg <= LAST_MODE_REG ) { - if ( timer_reg > 3 ) + if ( timer_reg == 6 ) { - write_16bit_mode_reg(me, timers, timer_reg-FIRST_MODE_REG, - source, nr_bytes); + write_tm6md(me, timers, base, source, nr_bytes); } else { - write_8bit_mode_reg(me, timers, timer_reg-FIRST_MODE_REG, - source, nr_bytes); + write_mode_reg(me, timers, timer_reg-FIRST_MODE_REG, + source, nr_bytes); } } else if ( timer_reg <= LAST_BASE_REG ) @@ -808,6 +1015,10 @@ mn103tim_io_write_buffer (struct hw *me, { hw_abort(me, "cannot write to counter"); } + else if ( timer_reg <= LAST_TIMER_REG ) + { + write_special_timer6_reg(me, timers, timer_reg, source, nr_bytes); + } else { hw_abort(me, "invalid reg type");