Beispiel #1
0
Datei: main.c Projekt: duparq/hwa
/*  Service counter-overflow IRQ: turn the LED on and enable the compare IRQ
 *  that turns it off
 */
HW_ISR( COUNTER, overflow, non_interruptible )
{
  /*  No need to protect access to duty since interrupts are not allowed */

  if ( duty ) {
    hw( write, PIN_LED, 1 );
    if ( duty < COUNT_TOP ) {
      hw( write, (COUNTER,compare1), duty );
      hw( turn, irq(COUNTER,compare1), on );
    }
    else
      hw( turn, irq(COUNTER,compare1), off );
  }
  else {
    hw( write, PIN_LED, 0 );
    hw( turn, irq(COUNTER,compare1), off );
  }
}
IMPLEMENT
void
Timer::init(Cpu_number)
{
  printf("Using the PIT (i8254) on IRQ %d for scheduling\n", irq());

  // set up timer interrupt (~ 1ms)
  Pit::init();
}
Beispiel #3
0
void msm6242_device::update_rtc_registers()
{
	// get the absolute current time, in ticks
	UINT64 curtime = current_time();

	// how long as it been since we last updated?
	UINT64 delta = curtime - m_last_update_time;

	// set current time
	m_last_update_time = curtime;

	// no delta?  just return
	if (delta == 0)
		return;

	// ticks
	if ((m_tick % 200) != (int)((delta + m_tick) % 0x200))
		irq(IRQ_64THSECOND);
	delta = bump(RTC_TICKS, delta, 0, 0x8000);
	if (delta == 0)
		return;

	// seconds
	irq(IRQ_SECOND);
	delta = bump(RTC_SECOND, delta, 0, 60);
	if (delta == 0)
		return;

	// minutes
	irq(IRQ_MINUTE);
	delta = bump(RTC_MINUTE, delta, 0, 60);
	if (delta == 0)
		return;

	// hours
	irq(IRQ_HOUR);
	delta = bump(RTC_HOUR, delta, 0, 24);
	if (delta == 0)
		return;

	// days
	while(delta--)
		advance_days();
}
Beispiel #4
0
Datei: user.c Projekt: duparq/hwa
/*  The UART should be ready for reconfiguration. Configure timer1 too.
 */
void IROM user_init_2 ( )
{
  os_timer_disarm( &os_timer );

  /*  Install user IRQ handlers
   */
  os_set_isr( irq(timer1,irq), ev_timer );
  os_set_isr( irq(timer1,nmi), ev_timer );

  hwa( begin_from_reset );

  hwa( configure, PIN_LED, function, gpio, mode, digital_output );

  /*  Reconfigure the UART
   */
  hwa( configure, gpio15, function, (uart0,txd) );
  hwa( configure, gpio13, function, (uart0,rxd) );

  hwa( configure, uart0,
       baudrate,  115200,
       databits,  8,
       parity,    none,
       stopbits,  1 );

  /*  Configure the timer1 to trigger an interrupt every 10 ms
   */
  hwa( configure, timer1,
       clock,     apb/256,
       direction, down_loop,
       top,       0.5 + 0.1*HW_APBHZ/256,
       action,    irq );

  hwa( commit );

  os_printf("START with user configuration: RXD=GPIO13 TXD=GPIO15\n");

  /*  Trigger a function call every 100 ms (about)
   */
  os_timer_setfn( &os_timer, (os_timer_func_t *)every_100ms, NULL );
  os_timer_arm( &os_timer, 100, 1 );
}
Beispiel #5
0
/**
 * Initialise the timer
 */
void timer_initialise(void)
{
  asm volatile("sti");
  irq(IRQ_TIMER, timer_handler);
}
Beispiel #6
0
VirtioBlk::VirtioBlk(hw::PCI_Device& d)
  : Virtio(d), hw::Drive(), req(queue_size(0), 0, iobase()), inflight(0)
{
  INFO("VirtioBlk", "Driver initializing");
  {
    auto& reqs = Statman::get().create(
      Stat::UINT32, blkname() + ".requests");
    this->requests = &reqs.get_uint32();
    *this->requests = 0;

    auto& err = Statman::get().create(
      Stat::UINT32, blkname() + ".errors");
    this->errors = &err.get_uint32();
    *this->errors = 0;
  }

  uint32_t needed_features =
    FEAT(VIRTIO_BLK_F_BLK_SIZE);
  negotiate_features(needed_features);

  CHECK(features() & FEAT(VIRTIO_BLK_F_BARRIER),
        "Barrier is enabled");
  CHECK(features() & FEAT(VIRTIO_BLK_F_SIZE_MAX),
        "Size-max is known");
  CHECK(features() & FEAT(VIRTIO_BLK_F_SEG_MAX),
        "Seg-max is known");
  CHECK(features() & FEAT(VIRTIO_BLK_F_GEOMETRY),
        "Geometry structure is used");
  CHECK(features() & FEAT(VIRTIO_BLK_F_RO),
        "Device is read-only");
  CHECK(features() & FEAT(VIRTIO_BLK_F_BLK_SIZE),
        "Block-size is known");
  CHECK(features() & FEAT(VIRTIO_BLK_F_SCSI),
        "SCSI is enabled :(");
  CHECK(features() & FEAT(VIRTIO_BLK_F_FLUSH),
        "Flush enabled");

  CHECK ((features() & needed_features) == needed_features,
         "Negotiated needed features");

  // Step 1 - Initialize REQ queue
  auto success = assign_queue(0, (uint32_t) req.queue_desc());
  CHECK(success, "Request queue assigned (0x%x) to device",
        (uint32_t) req.queue_desc());

  // Step 3 - Fill receive queue with buffers
  // DEBUG: Disable
  INFO("VirtioBlk", "Queue size: %i\tRequest size: %u\n",
       req.size(), sizeof(request_t));

  // Get device configuration
  get_config();

  // Signal setup complete.
  setup_complete((features() & needed_features) == needed_features);
  CHECK((features() & needed_features) == needed_features, "Signalled driver OK");

  // Hook up IRQ handler (inherited from Virtio)
  if (is_msix())
  {
    // update IRQ subscriptions
    IRQ_manager::get().subscribe(irq() + 0, {this, &VirtioBlk::service_RX});
    IRQ_manager::get().subscribe(irq() + 1, {this, &VirtioBlk::msix_conf_handler});
  }
  else
  {
    auto del(delegate<void()>{this, &VirtioBlk::irq_handler});
    IRQ_manager::get().subscribe(irq(), del);
  }

  // Done
  INFO("VirtioBlk", "Block device with %llu sectors capacity", config.capacity);
}
Beispiel #7
0
void
trap(Ureg *ureg)
{
	int rem, itype, t;

	if(up != nil)
		rem = ((char*)ureg)-up->kstack;
	else rem = ((char*)ureg)-(char*)m->stack;

	if(ureg->type != PsrMfiq && rem < 256) {
		dumpregs(ureg);
		panic("trap %d stack bytes remaining (%s), "
			  "up=#%8.8lux ureg=#%8.8lux pc=#%8.8ux"
			  ,rem, up?up->text:"", up, ureg, ureg->pc);
		for(;;);
	}

	itype = ureg->type;
	/*	All interrupts/exceptions should be resumed at ureg->pc-4,
		except for Data Abort which resumes at ureg->pc-8. */
	if(itype == PsrMabt+1)
		ureg->pc -= 8;
	else ureg->pc -= 4;

	if(up){
		up->pc = ureg->pc;
		up->dbgreg = ureg;
	}

	switch(itype) {
	case PsrMirq:
		t = m->ticks;		/* CPU time per proc */
		up = nil;		/* no process at interrupt level */
		irq(ureg);
		up = m->proc;
		preemption(m->ticks - t);
		m->intr++;
		break;

	case PsrMund:
		if(*(ulong*)ureg->pc == BREAK && breakhandler) {
			int s;
			Proc *p;

			p = up;
			s = breakhandler(ureg, p);
			if(s == BrkSched) {
				p->preempted = 0;
				sched();
			} else if(s == BrkNoSched) {
				/* stop it being preempted until next instruction */
				p->preempted = 1;
				if(up)
					up->dbgreg = 0;
				return;
			}
			break;
		}
		if(up == nil) goto faultpanic;
		spllo();
		if(waserror()) {
			if(waslo(ureg->psr) && up->type == Interp)
				disfault(ureg, up->env->errstr);
			setpanic();
			dumpregs(ureg);
			panic("%s", up->env->errstr);
		}
		if(!fpiarm(ureg)) {
			dumpregs(ureg);
			sys_trap_error(ureg->type);
		}
		poperror();
		break;

	case PsrMsvc: /* Jump through 0 or SWI */
		if(waslo(ureg->psr) && up && up->type == Interp) {
			spllo();
			dumpregs(ureg);
			sys_trap_error(ureg->type);
		}
		setpanic();
		dumpregs(ureg);
		panic("SVC/SWI exception");
		break;

	case PsrMabt: /* Prefetch abort */
		if(catchdbg && catchdbg(ureg, 0))
			break;
		/* FALL THROUGH */
	case PsrMabt+1: /* Data abort */
		if(waslo(ureg->psr) && up && up->type == Interp) {
			spllo();
			faultarm(ureg);
		}
		print("Data Abort\n");
		/* FALL THROUGH */

	default:
faultpanic:
		setpanic();
		dumpregs(ureg);
		panic("exception %uX %s\n", ureg->type, trapname(ureg->type));
		break;
	}

	splhi();
	if(up)
		up->dbgreg = 0;		/* becomes invalid after return from trap */
}
Beispiel #8
0
Datei: main.c Projekt: duparq/hwa
int main ( )
{
  /*  Create a HWA context to collect the hardware configuration
   *  Preload this context with RESET values
   */
  hwa( begin_from_reset );

  /*  Have the CPU enter idle mode when the 'sleep' instruction is executed.
   */
  hwa( configure,  core0,
       sleep,	   enabled,
       sleep_mode, idle	     );

  /*  Configure LED pin
   */
  hwa( configure, PIN_LED,
       mode,     digital_output   );

  /*  Configure analog input pin in analog mode (disable digital input buffer)
   *  and enable the internal pull-up resistor
   */
  hwa( configure, PIN_ANALOG_INPUT,
       mode,      analog_input_pullup );

  /*  Check that the counter can handle the top value. This must be done
   *  here since the C preprocessor does not allow floats in expressions.
   */
  if ( COUNT_TOP > ((1UL<<HW_BITS(COUNTER))-1) )
    HWA_ERR("PWM_COUNTER can not afford PWM_PERIOD.") ;

  /*  Configure the counter prescaler
   */
  hwa( configure, (COUNTER,prescaler),
       clock,	  ioclk );

  /*  Configure the counter to overflow periodically and trigger an interrupt
   *  The counter overflow ISR manages the compare IRQ
   */
  hwa( configure, COUNTER,
       clock,	  ioclk / COUNTER_CLK_DIV,
       direction, up_loop,
       bottom,	  0,
       top,	  TOP_OBJ,
       //	    overflow,  after_top,
       );
  hwa( write, (COUNTER, TOP_OBJ), COUNT_TOP );
  hwa( turn, irq(COUNTER,overflow), on );

  /*  Configure the ADC to make a single conversion and trigger an
   *  IRQ. The ISR will start a new conversion after its hard job is done.
   */
  hwa( configure, adc0,
       clock,	  ioclk / ADC_CLK_DIV,
       trigger,	  manual,
       vref,	  vcc,
       align,	  right,
       input,	  PIN_ANALOG_INPUT );
  
  hwa( turn, irq(adc0), on );
  hwa( trigger, adc0 );

  /*  Write this configuration into the hardware
   */
  hwa( commit );

  hw( enable_interrupts );

  for(;;)
    hw( sleep_until_irq );

  return 0 ;
}
Beispiel #9
0
int CPU::execute_inst(Instruction inst) {
    //stringstream inststr;
    //inststr << HEX4(pc) << " " << inst << dump_regs();
    //log(inststr.str());
    byte t;
    byte a7, m7, r7;
    word result;
    switch(inst.op.op) {
    case NOP:
	case DOP:
    case TOP:
        break;
    case JMP:
        pc = inst.addr;
        break;
    case JSR:
        push2(pc-1);
        pc = inst.addr;
        break;
    case RTS:
		get_mem(0x100 | s);
        pc = pop2()+1;
		get_mem(pc);
        break;
    case RTI:
		get_mem(0x100 | s);
        p = (pop() | (1<<5)) & (~B);
        pc = pop2();
		if(get_flag(I))
			m->scheduled_irq = -1;
		else if(m->irq_waiting)
			m->scheduled_irq = 1;
        break;
    case BRK:
        pc += 1;
        p |= B;
        irq(); 
        break;
    case BCS:
        branch(get_flag(C), inst);
        break;
    case BCC:
        branch(!get_flag(C), inst);
        break;
    case BEQ:
        branch(get_flag(Z), inst);
        break;
    case BNE:
        branch(!get_flag(Z), inst);
        break;
    case BVS:
        branch(get_flag(V), inst);
        break;
    case BVC:
        branch(!get_flag(V), inst);
        break;
    case BPL:
        branch(!get_flag(N), inst);
        break;
    case BMI:
        branch(get_flag(N), inst);
        break;
    case BIT:
        t = inst.operand;
        set_flag(N, t & (1 << 7));
        set_flag(V, t & (1 << 6));
        set_flag(Z, (t & a) == 0);
        break;
    case CMP:
        compare(a, inst.operand);
        break;
    case CPY:
        compare(y, inst.operand);
        break;
    case CPX:
        compare(x, inst.operand);
        break;
    case CLC:
        set_flag(C, false);
        break;
    case CLD:
        set_flag(D, false);
        break;
    case CLV:
        set_flag(V, false);
        break;
    case CLI:
        set_flag(I, false);
        break;
    case SED:
        set_flag(D, true);
        break;
    case SEC:
        set_flag(C, true);
        break;
    case SEI:
        set_flag(I, true);
        break;
    case LDA:
        a = inst.operand;
        set_nz(a);
        break;
    case STA:
        set_mem(inst.addr, a);
        break;
    case LDX:
        x = inst.operand;
        set_nz(x);
        break;
    case STX:
        set_mem(inst.addr, x);
        break;
    case LDY:
        y = inst.operand;
        set_nz(y);
        break;
    case STY:
        set_mem(inst.addr, y);
        break;
    case LAX:
        a = inst.operand;
        x = inst.operand;
        set_nz(a);
        break;
    case SAX:
        set_mem(inst.addr, a & x);
        break;
    case PHP:
        push(p | B);
        break;
    case PLP:
		get_mem(0x100|s);
        p = (pop() | (1 << 5)) & (~B);
        break;
    case PLA:
		get_mem(0x100|s);
        a = pop();
        set_nz(a);
        break;
    case PHA:
        push(a);
        break;
    case AND:
        a &= inst.operand;
        set_nz(a);
        break;
	case AAC:
		a &= inst.operand;
		set_nz(a);
		set_flag(C, a & 0x80);
		break;
    case ORA:
        a |= inst.operand;
        set_nz(a);
        break;
    case EOR:
        a ^= inst.operand;
        set_nz(a);
        break;
    case ADC:
        a7 = a & (1 << 7);
        m7 = inst.operand & (1 << 7);
        result = a + inst.operand;
        if(get_flag(C)) {
            result += 1;
        }
        a = result & 0xff;
        set_flag(C, result > 0xff);
        set_nz(a);
        r7 = a & (1 << 7);
        set_flag(V, !((a7 != m7) || ((a7 == m7) && (m7 == r7))));
        break;
    case SBC:
        a7 = a & (1 << 7);
        m7 = inst.operand & (1 << 7);
        result = a - inst.operand;
        if(!get_flag(C)) {
            result -= 1;
        }
        a = result & 0xff;
        set_flag(C, result < 0x100);
        set_nz(a);
        r7 = a & (1 << 7);
        set_flag(V, !((a7 == m7) || ((a7 != m7) && (r7 == a7))));
        break;
    case INX:
        x += 1;
        set_nz(x);
        break;
    case INY:
        y += 1;
        set_nz(y);
        break;
    case DEX:
        x -= 1;
        set_nz(x);
        break;
    case DEY:
        y -= 1;
        set_nz(y);
        break;
    case INC:
		set_mem(inst.addr, inst.operand);
        inst.operand += 1;
        inst.operand &= 0xff;
        set_nz(inst.operand);
        set_mem(inst.addr, inst.operand);
        break;
    case DEC:
		set_mem(inst.addr, inst.operand);
        inst.operand -= 1;
        inst.operand &= 0xff;
        set_nz(inst.operand);
        set_mem(inst.addr, inst.operand);
        break;
    case DCP:
		set_mem(inst.addr, inst.operand);
        set_mem(inst.addr, (inst.operand -1) & 0xff);
        compare(a, (inst.operand-1)&0xff);
        break;
    case ISB:
		set_mem(inst.addr, inst.operand);
        inst.operand = (inst.operand + 1) & 0xff;
        set_mem(inst.addr, inst.operand);
		a7 = a & (1 << 7);
        m7 = inst.operand & (1 << 7);
        result = a - inst.operand;
        if(!get_flag(C)) {
            result -= 1;
        }
        a = result & 0xff;
        set_flag(C, result < 0x100);
        set_nz(a);
        r7 = a & (1 << 7);
        set_flag(V, !((a7 == m7) || ((a7 != m7) && (r7 == a7))));
        break;
    case LSR_A:
        set_flag(C, a & 1);
        a >>= 1;
        set_nz(a);
        break;
    case LSR:
        set_flag(C, inst.operand & 1);
		set_mem(inst.addr, inst.operand);
        inst.operand >>= 1;
        set_mem(inst.addr, inst.operand);
        set_nz(inst.operand);
        break;
    case ASL_A:
        set_flag(C, a & (1 << 7));
        a <<= 1;
        set_nz(a);
        break;
    case ASL:
        set_flag(C, inst.operand & (1 << 7));
		set_mem(inst.addr, inst.operand);
        inst.operand <<= 1;
        set_mem(inst.addr, inst.operand);
        set_nz(inst.operand);
        break;
	case ASR:
		a &= inst.operand;
		set_flag(C, a & 1);
		a >>= 1;
		set_nz(a);
		break;
	case ARR:
		a &= inst.operand;
		a >>= 1;
		if(get_flag(C))
			a |= 0x80;
		set_flag(C, a & (1<<6));
		set_flag(V, ((a & (1<<5))<<1)  ^ (a & (1<<6)));
		set_nz(a);
		break;
    case TSX:
        x = s;
        set_nz(x);
        break;
    case TXS:
        s = x;
        break;
    case TYA:
        a = y;
        set_nz(a);
        break;
    case TXA:
        a = x;
        set_nz(a);
        break;
	case ATX:
		a |= 0xff;
		a &= inst.operand;
		x = a;
		set_nz(x);
		break;
	case AXS:
		x = a & x;
		result = x - inst.operand;
		set_flag(C, result < 0x100);
		x = result & 0xff;
		set_nz(x);
		break;
	case SYA:
		t = y & (inst.args[1] + 1);
		if(!inst.extra_cycles)
			set_mem(inst.addr, t);
		else
			inst.extra_cycles = 0;
		break;
	case SXA:
		t = x & (inst.args[1] + 1);
		if(!inst.extra_cycles)
			set_mem(inst.addr, t);
		else
			inst.extra_cycles = 0;
		break;
    case ROR_A:
        t = a & 1;
        a >>= 1;
        if(get_flag(C))
            a |= 1 << 7;
        set_flag(C, t);
        set_nz(a);
        break;
    case ROR:
        t = inst.operand & 1;
		set_mem(inst.addr, inst.operand);
        inst.operand >>= 1;
        if(get_flag(C))
            inst.operand |= 1 << 7;
        set_flag(C, t);
        set_mem(inst.addr, inst.operand);
        set_nz(inst.operand);
        break;
    case ROL_A:
        t = a & (1 << 7);
        a <<= 1;
        if(get_flag(C))
            a |= 1;
        set_flag(C, t);
        set_nz(a);
        break;
    case ROL:
        t = inst.operand & (1 << 7);
		set_mem(inst.addr, inst.operand);
        inst.operand <<= 1;
        if(get_flag(C))
            inst.operand |= 1;
        set_flag(C, t);
        set_mem(inst.addr, inst.operand);
        set_nz(inst.operand);
        break;
    case TAY:
        y = a;
        set_nz(y);
        break;
    case TAX:
        x = a;
        set_nz(x);
        break;
    case RLA:
        t = inst.operand & (1 << 7);
		set_mem(inst.addr, inst.operand);
        inst.operand <<= 1;
        if(get_flag(C))
            inst.operand |= 1;
        set_flag(C, t);
        set_mem(inst.addr, inst.operand);
        a &= inst.operand;
        set_nz(a);
        break;
    case SLO:
        set_flag(C, inst.operand & (1 << 7));
		set_mem(inst.addr, inst.operand);
        inst.operand <<= 1;
        set_mem(inst.addr, inst.operand);
        a |= inst.operand;
        set_nz(a);
        break;
	case SRE:
		set_flag(C, inst.operand & 1);
		set_mem(inst.addr, inst.operand);
        inst.operand >>= 1;
        set_mem(inst.addr, inst.operand);
        a ^= inst.operand;
        set_nz(a);
		break;
    case RRA:
        t = inst.operand & 1;
		set_mem(inst.addr, inst.operand);
        inst.operand >>= 1;
        if(get_flag(C))
            inst.operand |= 1 << 7;
        set_mem(inst.addr, inst.operand);
		a7 = a & (1 << 7);
        m7 = inst.operand & (1 << 7);
        result = a + inst.operand;
        if(t) {
            result += 1;
        }
        a = result & 0xff;
        set_flag(C, result > 0xff);
        set_nz(a);
        r7 = a & (1 << 7);
        set_flag(V, !((a7 != m7) || ((a7 == m7) && (m7 == r7))));
		break;
    case XAA:
    case AXA:
    case XAS:
    case LAR:
        break;
    default:
        cout << "Unsupported opcode! " << int(inst.opcode) << endl;
        cout << inst.op.op << endl;
		cout << opnames[inst.op.op] << endl;
        throw new runtime_error("Unsupported opcode");
        break;
    }

    int inst_cycles = cycle_count - prev_cycles;
	prev_cycles = cycle_count;
	//cycle_count += inst.op.cycles + inst.extra_cycles;
	return inst_cycles;
}
Beispiel #10
0
static int __init mcdx_init_drive(int drive)
{
	struct s_version version;
	struct gendisk *disk;
	struct s_drive_stuff *stuffp;
	int size = sizeof(*stuffp);
	char msg[80];

	xtrace(INIT, "init() try drive %d\n", drive);

	xtrace(INIT, "kmalloc space for stuffpt's\n");
	xtrace(MALLOC, "init() malloc %d bytes\n", size);
	if (!(stuffp = kzalloc(size, GFP_KERNEL))) {
		xwarn("init() malloc failed\n");
		return 1;
	}

	disk = alloc_disk(1);
	if (!disk) {
		xwarn("init() malloc failed\n");
		kfree(stuffp);
		return 1;
	}

	xtrace(INIT, "init() got %d bytes for drive stuff @ %p\n",
	       sizeof(*stuffp), stuffp);

	/* set default values */
	stuffp->present = 0;	/* this should be 0 already */
	stuffp->toc = NULL;	/* this should be NULL already */

	/* setup our irq and i/o addresses */
	stuffp->irq = irq(mcdx_drive_map[drive]);
	stuffp->wreg_data = stuffp->rreg_data = port(mcdx_drive_map[drive]);
	stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1;
	stuffp->wreg_hcon = stuffp->wreg_reset + 1;
	stuffp->wreg_chn = stuffp->wreg_hcon + 1;

	init_waitqueue_head(&stuffp->busyq);
	init_waitqueue_head(&stuffp->lockq);
	init_waitqueue_head(&stuffp->sleepq);

	/* check if i/o addresses are available */
	if (!request_region(stuffp->wreg_data, MCDX_IO_SIZE, "mcdx")) {
		xwarn("0x%03x,%d: Init failed. "
		      "I/O ports (0x%03x..0x%03x) already in use.\n",
		      stuffp->wreg_data, stuffp->irq,
		      stuffp->wreg_data,
		      stuffp->wreg_data + MCDX_IO_SIZE - 1);
		xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
		kfree(stuffp);
		put_disk(disk);
		xtrace(INIT, "init() continue at next drive\n");
		return 0;	/* next drive */
	}

	xtrace(INIT, "init() i/o port is available at 0x%03x\n"
	       stuffp->wreg_data);
	xtrace(INIT, "init() hardware reset\n");
	mcdx_reset(stuffp, HARD, 1);

	xtrace(INIT, "init() get version\n");
	if (-1 == mcdx_requestversion(stuffp, &version, 4)) {
		/* failed, next drive */
		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
		xwarn("%s=0x%03x,%d: Init failed. Can't get version.\n",
		      MCDX, stuffp->wreg_data, stuffp->irq);
		xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
		kfree(stuffp);
		put_disk(disk);
		xtrace(INIT, "init() continue at next drive\n");
		return 0;
	}

	switch (version.code) {
	case 'D':
		stuffp->readcmd = READ2X;
		stuffp->present = DOUBLE | DOOR | MULTI;
		break;
	case 'F':
		stuffp->readcmd = READ1X;
		stuffp->present = SINGLE | DOOR | MULTI;
		break;
	case 'M':
		stuffp->readcmd = READ1X;
		stuffp->present = SINGLE;
		break;
	default:
		stuffp->present = 0;
		break;
	}

	stuffp->playcmd = READ1X;

	if (!stuffp->present) {
		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
		xwarn("%s=0x%03x,%d: Init failed. No Mitsumi CD-ROM?.\n",
		      MCDX, stuffp->wreg_data, stuffp->irq);
		kfree(stuffp);
		put_disk(disk);
		return 0;	/* next drive */
	}

	xtrace(INIT, "init() register blkdev\n");
	if (register_blkdev(MAJOR_NR, "mcdx")) {
		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
		kfree(stuffp);
		put_disk(disk);
		return 1;
	}

	mcdx_queue = blk_init_queue(do_mcdx_request, &mcdx_lock);
	if (!mcdx_queue) {
		unregister_blkdev(MAJOR_NR, "mcdx");
		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
		kfree(stuffp);
		put_disk(disk);
		return 1;
	}

	xtrace(INIT, "init() subscribe irq and i/o\n");
	if (request_irq(stuffp->irq, mcdx_intr, IRQF_DISABLED, "mcdx", stuffp)) {
		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
		xwarn("%s=0x%03x,%d: Init failed. Can't get irq (%d).\n",
		      MCDX, stuffp->wreg_data, stuffp->irq, stuffp->irq);
		stuffp->irq = 0;
		blk_cleanup_queue(mcdx_queue);
		kfree(stuffp);
		put_disk(disk);
		return 0;
	}

	xtrace(INIT, "init() get garbage\n");
	{
		int i;
		mcdx_delay(stuffp, HZ / 2);
		for (i = 100; i; i--)
			(void) inb(stuffp->rreg_status);
	}


#ifdef WE_KNOW_WHY
	/* irq 11 -> channel register */
	outb(0x50, stuffp->wreg_chn);
#endif

	xtrace(INIT, "init() set non dma but irq mode\n");
	mcdx_config(stuffp, 1);

	stuffp->info.ops = &mcdx_dops;
	stuffp->info.speed = 2;
	stuffp->info.capacity = 1;
	stuffp->info.handle = stuffp;
	sprintf(stuffp->info.name, "mcdx%d", drive);
	disk->major = MAJOR_NR;
	disk->first_minor = drive;
	strcpy(disk->disk_name, stuffp->info.name);
	disk->fops = &mcdx_bdops;
	disk->flags = GENHD_FL_CD;
	stuffp->disk = disk;

	sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%03x, irq %d."
		" (Firmware version %c %x)\n",
		stuffp->wreg_data, stuffp->irq, version.code, version.ver);
	mcdx_stuffp[drive] = stuffp;
	xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp);
	if (register_cdrom(&stuffp->info) != 0) {
		printk("Cannot register Mitsumi CD-ROM!\n");
		free_irq(stuffp->irq, NULL);
		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
		kfree(stuffp);
		put_disk(disk);
		if (unregister_blkdev(MAJOR_NR, "mcdx") != 0)
			xwarn("cleanup() unregister_blkdev() failed\n");
		blk_cleanup_queue(mcdx_queue);
		return 2;
	}
	disk->private_data = stuffp;
	disk->queue = mcdx_queue;
	add_disk(disk);
	printk(msg);
	return 0;
}
Beispiel #11
0
void timer_poll()
{
    irq(TIMER_IRQ);
}
u32 sdidCheckSDSpeed( u32 readCount )
{
    CIniFile ini( SFN_SDCARD_LIST );

    std::string name = sdidGetSDName();
    std::string manufacturerID = sdidGetSDManufacturerID();

    u32 ret = ini.GetInt( "SD Card Speed", manufacturerID + name, 0 );

    if( ret != 0 )
        return ret;

    u32 totalSectors;
    if(!ELM_SectorsFromDisk(ioSD(),&totalSectors))
    {
        dbg_printf("no sd card\n");
        return 0;
    }
    dbg_printf("total sectors %d, max addr %08x\n", totalSectors, (totalSectors << 9) - 0x200);

    // some sd card needs to be readed one time for initialization
    sddReadBlocks( 0, 1, NULL );

    irq().vblankStop();
    double maxAccessTime = 0.f;

    std::string tipText = LANG("progress window", "first use sd");
    progressWnd().setTipText( tipText );
    progressWnd().show();
    progressWnd().setPercent( 0 );

    vu64 tick1 = 0;
    vu64 tick2 = 0;
    for( size_t i = 0; i < readCount; ++i ) {
        u32 randAddr = ((rand() % totalSectors)<<(isSDHC()?0:9) ) & (~(0x200-1));

        u32 sdReadSingleBlock[2] = { 0xD5030011, randAddr }; // input read address here
        ioRpgSendCommand( sdReadSingleBlock, 0, 80, NULL );
        timer().initTimer();
        tick1 = timer().getTick();
        ioRpgWaitCmdBusy( true );
        tick2 = timer().getTick();

        u32 readSD[2] = { 0xB7000000, 0x00000000 | 0x00130000 }; // address dont care here
        ioRpgSendCommand( readSD, 512, 4, NULL );

        if( tick2 < tick1 ) {
            tick2 += 65536;
        }
        tick1 = tick2 - tick1;
        double timeCostUs = timer().tickToUs( tick1 );
        if( timeCostUs > maxAccessTime ) {
            maxAccessTime = timeCostUs;
        }

        u32 percent = i * 100 / readCount;
        if( (i & 0x1ff) == 0x1ff ) {
            dbg_printf( "%02d ", percent );
            progressWnd().setPercent( percent );
        }
    }
    progressWnd().hide();
    irq().vblankStart();


    maxAccessTime = ((u32)(maxAccessTime / 15 + 0.5)) * 15;

    ret = ((u32)(maxAccessTime * 1000 / 150));

    dbg_printf("max access time: max %4.2fus\n", maxAccessTime );

    ini.SetInt( "SD Card Speed", manufacturerID + name, ret );
    ini.SaveIniFile( SFN_SDCARD_LIST );

    return ret;
}