void Fish::collision_tile(uint32_t tile_attributes) { if(tile_attributes & Tile::WATER) { start_waiting(); movement = Vector(0, 0); } }
/*! Start waiting for DMA to be finished */ void start_dma_wait(ide_device_info *device, ide_qrequest *qrequest) { ide_bus_info *bus = device->bus; bus->controller->start_dma(bus->channel_cookie); start_waiting(bus, qrequest->request->timeout > 0 ? qrequest->request->timeout : IDE_STD_TIMEOUT, ide_state_async_waiting); }
void Fish::collision_tile(uint32_t tile_attributes) { if ((tile_attributes & Tile::WATER) && (physic.get_velocity_y() >= 0)) { // initialize stop position if uninitialized if (stop_y == 0) stop_y = get_pos().y + bbox.get_height(); // stop when we have reached the stop position if (get_pos().y >= stop_y) { if(!frozen) start_waiting(); movement = Vector(0, 0); } } }
void Fish::unfreeze() { // does this happen at all? (or do fishes die when they fall frozen?) BadGuy::unfreeze(); start_waiting(); }
bool send_command(ide_device_info *device, ide_qrequest *qrequest, bool need_drdy, uint32 timeout, ide_bus_state new_state) { ide_bus_info *bus = device->bus; bigtime_t irq_disabled_at = 0; // make compiler happy uint8 num_retries = 0; bool irq_guard; retry: irq_guard = bus->num_running_reqs > 1; SHOW_FLOW(3, "qrequest=%p, request=%p", qrequest, qrequest ? qrequest->request : NULL); // if there are pending requests, IRQs must be disabled to // not mix up IRQ reasons // XXX can we avoid that with the IDE_LOCK trick? It would // save some work and the bug workaround! if (irq_guard) { if (bus->controller->write_device_control(bus->channel_cookie, ide_devctrl_nien | ide_devctrl_bit3) != B_OK) goto err; irq_disabled_at = system_time(); } // select device if (bus->controller->write_command_block_regs(bus->channel_cookie, &device->tf, ide_mask_device_head) != B_OK) goto err; bus->active_device = device; if (!ide_wait(device, 0, ide_status_bsy | ide_status_drq, false, 50000)) { uint8 status; SHOW_FLOW0(1, "device is not ready"); status = bus->controller->get_altstatus(bus->channel_cookie); if (status == 0xff) { // there is no device (should happen during detection only) SHOW_FLOW0(1, "there is no device"); // device detection recognizes this code as "all hope lost", so // neither replace it nor use it anywhere else device->subsys_status = SCSI_TID_INVALID; return false; } // reset device and retry if (reset_device(device, qrequest) && ++num_retries <= MAX_FAILED_SEND) { SHOW_FLOW0(1, "retrying"); goto retry; } SHOW_FLOW0(1, "giving up"); // reset to often - abort request device->subsys_status = SCSI_SEL_TIMEOUT; return false; } if (need_drdy && (bus->controller->get_altstatus(bus->channel_cookie) & ide_status_drdy) == 0) { SHOW_FLOW0(3, "drdy not set"); device->subsys_status = SCSI_SEQUENCE_FAIL; return false; } // write parameters if (bus->controller->write_command_block_regs(bus->channel_cookie, &device->tf, device->tf_param_mask) != B_OK) goto err; if (irq_guard) { // IRQ may be fired by service requests and by the process of disabling(!) // them (I heard this is caused by edge triggered PCI IRQs) // wait at least 50 µs to catch all pending irq's // (at my system, up to 30 µs elapsed) // additionally, old drives (at least my IBM-DTTA-351010) loose // sync if they are pushed too hard - on heavy overlapped write // stress this drive tends to forget outstanding requests, // waiting at least 50 µs seems(!) to solve this while (system_time() - irq_disabled_at < MAX_IRQ_DELAY) spin(1); } // if we will start waiting once the command is sent, we have to // lock the bus before sending; this way, IRQs that are fired // shortly before/after sending of command are delayed until the // command is really sent (start_waiting unlocks the bus) and then // the IRQ handler can check savely whether the IRQ really signals // finishing of command or not by testing the busy-signal of the device if (new_state != ide_state_accessing) { IDE_LOCK(bus); } if (irq_guard) { // now it's clear why IRQs gets fired, so we can enable them again if (bus->controller->write_device_control(bus->channel_cookie, ide_devctrl_bit3) != B_OK) goto err1; } // write command code - this will start the actual command SHOW_FLOW(3, "Writing command 0x%02x", (int)device->tf.write.command); if (bus->controller->write_command_block_regs(bus->channel_cookie, &device->tf, ide_mask_command) != B_OK) goto err1; // start waiting now; also un-blocks IRQ handler (see above) if (new_state != ide_state_accessing) start_waiting(bus, timeout, new_state); return true; err1: if (timeout > 0) { bus->state = ide_state_accessing; IDE_UNLOCK(bus); } err: device->subsys_status = SCSI_HBA_ERR; return false; }
// new_state must be either accessing, async_waiting or sync_waiting // param_mask must not include command register bool send_command( ide_device_info *device, bool need_drdy, bigtime_t timeout, ide_bus_state new_state ) { ide_bus_info *bus = device->bus; bigtime_t irq_disabled_at = 0; // make compiler happy bool irq_guard = bus->num_running_reqs > 1; SHOW_FLOW0( 3, "" ); reset_timeouts( device ); if( irq_guard ) { if( bus->controller->write_device_control( bus->channel, ide_devctrl_nien | ide_devctrl_bit3 ) != NO_ERROR ) goto err; irq_disabled_at = system_time(); } if( bus->controller->write_command_block_regs( bus->channel, &device->tf, ide_mask_device_head ) != NO_ERROR ) goto err; SHOW_FLOW0( 3, "1" ); bus->active_device = device; if( !ide_wait( device, 0, ide_status_bsy | ide_status_drq, false, 50000 )) { uint8 status; SHOW_FLOW0( 1, "device is not ready" ); status = bus->controller->get_altstatus( bus->channel ); if( status == 0xff ) { // this shouldn't happen unless the device has died // as we only submit commands to existing devices // (only detection routines shoot at will) set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_INTERNAL_FAILURE ); return false; } if( !reset_bus( device )) return false; SHOW_FLOW0( 1, "retrying" ); if( bus->controller->write_command_block_regs( bus->channel, &device->tf, ide_mask_device_head ) != NO_ERROR ) goto err; bus->active_device = device; if( !ide_wait( device, 0, ide_status_bsy | ide_status_drq, false, 50000 )) { // XXX this is not a device but a bus error, we should return // CAM_SEL_TIMEOUT instead SHOW_FLOW0( 1, "device is dead" ); set_sense( device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_LUN_SEL_FAILED ); return false; } } SHOW_FLOW0( 3, "3" ); if( need_drdy && (bus->controller->get_altstatus( bus->channel ) & ide_status_drdy) == 0 ) { SHOW_FLOW0( 3, "drdy not set" ); set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_TIMEOUT ); return false; } SHOW_FLOW0( 3, "4" ); if( bus->controller->write_command_block_regs( bus->channel, &device->tf, device->tf_param_mask ) != NO_ERROR ) goto err; SHOW_FLOW0( 3, "5" ); if( irq_guard ) { // enable IRQs now // IRQ may be fired by service requests and by the process of disabling(!) // them (I heard this is caused by edge triggered PCI IRQs) // wait at least 50 µs to catch all pending irq's // (at my system, up to 30 µs elapsed) // additionally, old drives (at least my IBM-DTTA-351010) loose // sync if they are pushed too hard - on heavy overlapped write // stress this drive tends to forget outstanding requests, // waiting at least 50 µs seems(!) to solve this while( system_time() - irq_disabled_at < MAX_IRQ_DELAY ) cpu_spin( 1 ); } SHOW_FLOW0( 3, "6" ); if( new_state != ide_state_accessing ) { IDE_LOCK( bus ); } SHOW_FLOW( 3, "Writing command %x", (int)device->tf.write.command ); if( bus->controller->write_command_block_regs( bus->channel, &device->tf, ide_mask_command ) != NO_ERROR ) goto err2; SHOW_FLOW0( 3, "7" ); if( irq_guard ) { if( bus->controller->write_device_control( bus->channel, ide_devctrl_bit3 ) != NO_ERROR ) goto err1; } SHOW_FLOW0( 3, "8" ); if( new_state != ide_state_accessing ) { start_waiting( bus, timeout, new_state ); } SHOW_FLOW0( 3, "9" ); return true; err2: if( irq_guard ) bus->controller->write_device_control( bus->channel, ide_devctrl_bit3 ); err1: if( timeout > 0 ) { bus->state = ide_state_accessing; IDE_UNLOCK( bus ); } err: set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_INTERNAL_FAILURE ); return false; }