t_stat set_iobase(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { DEVICE* dptr; PNP_INFO* pnp; t_stat rc; uint16 newbase; if (!cptr) return SCPE_ARG; if (!uptr) return SCPE_IERR; if (!(dptr = find_dev_from_unit(uptr))) return SCPE_IERR; if (!(pnp = (PNP_INFO*)dptr->ctxt)) return SCPE_IERR; newbase = get_uint (cptr, 16, 0xFF, &rc); if (rc != SCPE_OK) return rc; if (dptr->flags & DEV_DIS) { printf("Device not enabled yet.\n"); pnp->io_base = newbase; } else { dptr->flags |= DEV_DIS; dptr->reset(dptr); pnp->io_base = newbase; dptr->flags &= ~DEV_DIS; dptr->reset(dptr); } return SCPE_OK; }
bool dvd_close_job(DCR *dcr) { DEVICE *dev = dcr->dev; JCR *jcr = dcr->jcr; bool ok = true; /* * If the device is a dvd and WritePartAfterJob * is set to yes, open the next part, so, in case of a device * that requires mount, it will be written to the device. */ if (dev->is_dvd() && jcr->write_part_after_job && (dev->part_size > 0)) { Dmsg1(400, "Writing last part=%d write_partafter_job is set.\n", dev->part); if (dev->part < dev->num_dvd_parts+1) { Jmsg3(jcr, M_FATAL, 0, _("Error writing. Current part less than total number of parts (%d/%d, device=%s)\n"), dev->part, dev->num_dvd_parts, dev->print_name()); dev->dev_errno = EIO; ok = false; } if (ok && !dvd_write_part(dcr)) { Jmsg2(jcr, M_FATAL, 0, _("Unable to write last on %s: ERR=%s\n"), dev->print_name(), dev->bstrerror()); dev->dev_errno = EIO; ok = false; } } return ok; }
/* * Free memory allocated for the device */ void DEVICE::term(void) { DEVICE *dev = NULL; Dmsg1(900, "term dev: %s\n", print_name()); close(); if (dev_name) { free_memory(dev_name); dev_name = NULL; } if (prt_name) { free_memory(prt_name); prt_name = NULL; } if (errmsg) { free_pool_memory(errmsg); errmsg = NULL; } pthread_mutex_destroy(&m_mutex); pthread_cond_destroy(&wait); pthread_cond_destroy(&wait_next_vol); pthread_mutex_destroy(&spool_mutex); pthread_mutex_destroy(&freespace_mutex); if (attached_dcrs) { delete attached_dcrs; attached_dcrs = NULL; } /* We let the DEVRES pointer if not our device */ if (device && device->dev == this) { device->dev = NULL; } delete this; if (dev) { dev->term(); } }
void dvd_remove_empty_part(DCR *dcr) { DEVICE *dev = dcr->dev; /* Remove the last part file if it is empty */ if (dev->is_dvd() && dev->num_dvd_parts > 0) { struct stat statp; uint32_t part_save = dev->part; POOL_MEM archive_name(PM_FNAME); int status; dev->part = dev->num_dvd_parts; make_spooled_dvd_filename(dev, archive_name); /* Check that the part file is empty */ status = stat(archive_name.c_str(), &statp); if (status == 0 && statp.st_size == 0) { Dmsg3(100, "Unlink empty part in close call make_dvd_filename. part=%d num=%d vol=%s\n", part_save, dev->num_dvd_parts, dev->getVolCatName()); Dmsg1(100, "unlink(%s)\n", archive_name.c_str()); unlink(archive_name.c_str()); if (part_save == dev->part) { dev->set_part_spooled(false); /* no spooled part left */ } } else if (status < 0) { if (part_save == dev->part) { dev->set_part_spooled(false); /* spool doesn't exit */ } } dev->part = part_save; /* restore part number */ } }
void VM::reset() { // reset all devices for(DEVICE* device = first_device; device; device = device->next_device) { device->reset(); } }
VM::VM(EMU* parent_emu) : emu(parent_emu) { // create devices first_device = last_device = NULL; dummy = new DEVICE(this, emu); // must be 1st device event = new EVENT(this, emu); // must be 2nd device drec = new DATAREC(this, emu); sio = new I8251(this, emu); pio_k = new I8255(this, emu); pio_f = new I8255(this, emu); io = new IO(this, emu); psg = new SN76489AN(this, emu); vdp = new TMS9918A(this, emu); fdc = new UPD765A(this, emu); cpu = new Z80(this, emu); key = new KEYBOARD(this, emu); memory = new MEMORY(this, emu); // set contexts event->set_context_cpu(cpu); event->set_context_sound(psg); drec->set_context_out(pio_k, SIG_I8255_PORT_B, 0x80); pio_k->set_context_port_c(key, SIG_KEYBOARD_COLUMN, 0x07, 0); pio_k->set_context_port_c(drec, SIG_DATAREC_REMOTE, 0x08, 0); pio_k->set_context_port_c(drec, SIG_DATAREC_OUT, 0x10, 0); pio_f->set_context_port_c(fdc, SIG_UPD765A_MOTOR_NEG, 2, 0); pio_f->set_context_port_c(fdc, SIG_UPD765A_TC, 4, 0); pio_f->set_context_port_c(fdc, SIG_UPD765A_RESET, 8, 0); pio_f->set_context_port_c(memory, SIG_MEMORY_SEL, 0x40, 0); vdp->set_context_irq(cpu, SIG_CPU_IRQ, 1); fdc->set_context_irq(pio_f, SIG_I8255_PORT_A, 1); fdc->set_context_index(pio_f, SIG_I8255_PORT_A, 4); #ifdef _FDC_DEBUG_LOG fdc->set_context_cpu(cpu); #endif key->set_context_cpu(cpu); key->set_context_pio(pio_k); // cpu bus cpu->set_context_mem(memory); cpu->set_context_io(io); cpu->set_context_intr(dummy); // i/o bus io->set_iomap_range_rw(0x40, 0x7f, psg); io->set_iomap_range_rw(0x80, 0xbf, vdp); io->set_iomap_range_rw(0xc0, 0xdf, pio_k); io->set_iomap_range_rw(0xe0, 0xe3, fdc); io->set_iomap_range_rw(0xe4, 0xe7, pio_f); io->set_iomap_range_rw(0xe8, 0xeb, sio); // initialize all devices for(DEVICE* device = first_device; device; device = device->next_device) { device->initialize(); } }
/* * Put a volume label into the block * * Returns: false on failure * true on success */ static bool write_volume_label_to_block(DCR *dcr) { DEVICE *dev = dcr->dev; DEV_BLOCK *block = dcr->block; DEV_RECORD rec; JCR *jcr = dcr->jcr; Dmsg0(130, "write Label in write_volume_label_to_block()\n"); memset(&rec, 0, sizeof(rec)); rec.data = get_memory(SER_LENGTH_Volume_Label); empty_block(block); /* Volume label always at beginning */ create_volume_label_record(dcr, dev, &rec); block->BlockNumber = 0; if (!write_record_to_block(dcr, &rec)) { free_pool_memory(rec.data); Jmsg1(jcr, M_FATAL, 0, _("Cannot write Volume label to block for device %s\n"), dev->print_name()); return false; } else { Dmsg2(130, "Wrote label of %d bytes to block. Vol=%s\n", rec.data_len, dcr->VolumeName); } free_pool_memory(rec.data); return true; }
VM::VM(EMU* parent_emu) : emu(parent_emu) { // create devices first_device = last_device = NULL; dummy = new DEVICE(this, emu); // must be 1st device event = new EVENT(this, emu); // must be 2nd device sio = new I8251(this, emu); drec = new CMT(this, emu); io = new IO(this, emu); vdp = new MC6847(this, emu); not = new NOT(this, emu); psg = new YM2203(this, emu); cpu = new Z80(this, emu); joystick = new JOYSTICK(this, emu); keyboard = new KEYBOARD(this, emu); memory = new MEMORY(this, emu); system = new SYSTEM(this, emu); // set contexts event->set_context_cpu(cpu); event->set_context_sound(psg); vdp->set_vram_ptr(memory->get_vram(), 0x1800); vdp->set_font_ptr(memory->get_cgrom(), memory->get_pcgram()); vdp->set_context_vsync(not, SIG_NOT_INPUT, 1); not->set_context_out(cpu, SIG_CPU_IRQ, 1); joystick->set_context_psg(psg); system->set_context_drec(drec); system->set_context_vdp(vdp); drec->set_context_sio(sio); // cpu bus cpu->set_context_mem(memory); cpu->set_context_io(io); cpu->set_context_intr(dummy); sio->set_context_out(drec, SIG_CMT_OUT); // i/o bus io->set_iomap_range_r(0x00, 0x0f, keyboard); io->set_iomap_range_w(0x10, 0x1f, system); io->set_iomap_range_w(0x30, 0x3f, system); for(int i = 0x20; i < 0x30; i += 4) { io->set_iomap_alias_w(i+1, psg, 1); io->set_iomap_alias_r(i+2, psg, 1); io->set_iomap_alias_w(i+3, psg, 0); } io->set_iomap_range_w(0x60, 0x7f, memory); io->set_iomap_alias_rw(0xb0, sio, 0); io->set_iomap_alias_rw(0xb8, sio, 1); // initialize all devices for(DEVICE* device = first_device; device; device = device->next_device) { device->initialize(); } }
VM::VM(EMU* parent_emu) : emu(parent_emu) { // create devices first_device = last_device = NULL; dummy = new DEVICE(this, emu); // must be 1st device event = new EVENT(this, emu); // must be 2nd device drec = new DATAREC(this, emu); io = new IO(this, emu); vdp = new MC6847(this, emu); not = new NOT(this, emu); psg = new YM2203(this, emu); cpu = new Z80(this, emu); joystick = new JOYSTICK(this, emu); keyboard = new KEYBOARD(this, emu); memory = new MEMORY(this, emu); system = new SYSTEM(this, emu); // set contexts event->set_context_cpu(cpu); event->set_context_sound(psg); vdp->set_vram_ptr(memory->get_vram(), 0x1800); vdp->set_context_vsync(not, SIG_NOT_INPUT, 1); not->set_context_out(cpu, SIG_CPU_IRQ, 1); vdp->set_context_vsync(system, SIG_SYSTEM_PORT, 0x10); drec->set_context_out(system, SIG_SYSTEM_PORT, 0x20); // bit6: printer busy vdp->set_context_hsync(system, SIG_SYSTEM_PORT, 0x80); joystick->set_context_psg(psg); #ifdef _MAP1010 memory->set_context_keyboard(keyboard); #endif system->set_context_drec(drec); system->set_context_vdp(vdp); // cpu bus cpu->set_context_mem(memory); cpu->set_context_io(io); cpu->set_context_intr(dummy); // i/o bus io->set_iomap_single_rw(0x40, system); #ifndef _MAP1010 io->set_iomap_range_r(0x80, 0x88, keyboard); #endif io->set_iomap_alias_w(0xc0, psg, 1); // PSG data io->set_iomap_alias_w(0xc1, psg, 0); // PSG ch // io->set_iomap_alias_r(0xc0, psg, 1); io->set_iomap_alias_r(0xc1, psg, 1); // PSG data // initialize all devices for(DEVICE* device = first_device; device; device = device->next_device) { device->initialize(); } }
void VM::reset() { memory->readrom(config.device_type); // reset all devices for(DEVICE* device = first_device; device; device = device->next_device) { device->reset(); } }
void VM::special_reset() { // system reset for(DEVICE* device = first_device; device; device = device->next_device) { device->reset(); } io->sysreset(); }
VM::VM(EMU* parent_emu) : emu(parent_emu) { // create devices first_device = last_device = NULL; dummy = new DEVICE(this, emu); // must be 1st device event = new EVENT(this, emu); // must be 2nd device // cmt = new DATAREC(this, emu); cpu = new I8080(this, emu); pio = new I8155(this, emu); io = new IO(this, emu); buzzer = new PCM1BIT(this, emu); rtc = new UPD1990A(this, emu); keyboard = new KEYBOARD(this, emu); lcd = new LCD(this, emu); memory = new MEMORY(this, emu); // set contexts event->set_context_cpu(cpu); event->set_context_sound(buzzer); // cmt->set_context_out(cpu, SIG_I8085_SID, 1); // cpu->set_context_sod(cmt, SIG_DATAREC_OUT, 1); pio->set_context_port_a(rtc, SIG_UPD1990A_C0, 1, 0); pio->set_context_port_a(rtc, SIG_UPD1990A_C1, 2, 0); pio->set_context_port_a(rtc, SIG_UPD1990A_C2, 4, 0); pio->set_context_port_a(rtc, SIG_UPD1990A_CLK, 8, 0); pio->set_context_port_a(rtc, SIG_UPD1990A_DIN, 0x10, 0); pio->set_context_port_a(keyboard, SIG_KEYBOARD_COLUMN_L, 0xff, 0); pio->set_context_port_a(lcd, SIG_LCD_CHIPSEL_L, 0xff, 0); pio->set_context_port_b(keyboard, SIG_KEYBOARD_COLUMN_H, 1, 0); pio->set_context_port_b(lcd, SIG_LCD_CHIPSEL_H, 3, 0); pio->set_context_port_b(buzzer, SIG_PCM1BIT_MUTE, 0x20, 0); pio->set_context_timer(buzzer, SIG_PCM1BIT_SIGNAL, 1); pio->set_constant_clock(CPU_CLOCKS); rtc->set_context_dout(pio, SIG_I8155_PORT_C, 1); rtc->set_context_tp(cpu, SIG_I8085_RST7, 1); // memory->set_context_cmt(cmt); memory->set_context_rtc(rtc); // cpu bus cpu->set_context_mem(memory); cpu->set_context_io(io); // i/o bus io->set_iomap_range_w(0x90, 0x9f, memory); io->set_iomap_range_rw(0xa0, 0xaf, memory); io->set_iomap_range_rw(0xb0, 0xbf, pio); io->set_iomap_range_r(0xe0, 0xef, keyboard); io->set_iomap_range_rw(0xf0, 0xff, lcd); // initialize all devices for(DEVICE* device = first_device; device; device = device->next_device) { device->initialize(); } }
void VM::save_state(FILEIO* state_fio) { state_fio->FputUint32(STATE_VERSION); for(DEVICE* device = first_device; device; device = device->next_device) { device->save_state(state_fio); } state_fio->Fwrite(ram, sizeof(ram), 1); }
bool dir_ask_sysop_to_mount_volume(DCR *dcr, int /*mode*/) { DEVICE *dev = dcr->dev; fprintf(stderr, _("Mount Volume \"%s\" on device %s and press return when ready: "), dcr->VolumeName, dev->print_name()); dev->close(dcr); getchar(); return true; }
VM::~VM() { // delete all devices for(DEVICE* device = first_device; device;) { DEVICE *next_device = device->next_device; device->release(); delete device; device = next_device; } }
static bRC do_clear_scsi_encryption_key(void *value) { DCR *dcr; DEVICE *dev; DEVRES *device; bool need_to_clear; /* * Unpack the arguments passed in. */ dcr = (DCR *)value; if (!dcr) { return bRC_Error; } dev = dcr->dev; if (!dev) { return bRC_Error; } device = dev->device; if (!device) { return bRC_Error; } /* * See if device supports hardware encryption. */ if (!device->drive_crypto_enabled) { return bRC_OK; } P(crypto_operation_mutex); /* * See if we need to query the drive or use the tracked encryption status of the stored. */ if (device->query_crypto_status) { need_to_clear = is_scsi_encryption_enabled(dev->fd(), dev->dev_name); } else { need_to_clear = dev->is_crypto_enabled(); } if (need_to_clear) { Dmsg0(dbglvl, "scsicrypto-sd: Clearing crypto key\n"); if (clear_scsi_encryption_key(dev->fd(), dev->dev_name)) { dev->clear_crypto_enabled(); V(crypto_operation_mutex); return bRC_OK; } else { V(crypto_operation_mutex); return bRC_Error; } } else { Dmsg0(dbglvl, "scsicrypto-sd: Not clearing crypto key because encryption is currently not enabled on drive\n"); V(crypto_operation_mutex); return bRC_OK; } }
VM::VM(EMU* parent_emu) : emu(parent_emu) { // create devices first_device = last_device = NULL; dummy = new DEVICE(this, emu); // must be 1st device event = new EVENT(this, emu); // must be 2nd device drec = new DATAREC(this, emu); cpu = new I8080(this, emu); // i8085 memory = new MEMORY(this, emu); rtc = new RP5C01(this, emu); io = new IO(this, emu); // set contexts event->set_context_cpu(cpu); event->set_context_sound(drec); drec->set_context_ear(io, SIG_IO_CMT, 1); cpu->set_context_sod(io, SIG_IO_SOD, 1); io->set_context_cpu(cpu); io->set_context_drec(drec); io->set_context_rtc(rtc); // cpu bus cpu->set_context_mem(memory); cpu->set_context_io(io); cpu->set_context_intr(io); #ifdef USE_DEBUGGER cpu->set_context_debugger(new DEBUGGER(this, emu)); #endif // memory bus memset(rom, 0xff, sizeof(rom)); memset(ram, 0, sizeof(ram)); memory->read_bios(_T("BIOS.ROM"), rom, sizeof(rom)); FILEIO* fio = new FILEIO(); if(fio->Fopen(create_local_path(_T("RAM.BIN")), FILEIO_READ_BINARY)) { fio->Fread(ram, sizeof(ram), 1); fio->Fclose(); } delete fio; memory->set_memory_r(0x0000, 0x7fff, rom); memory->set_memory_rw(0x8000, 0xffff, ram); memory->set_wait_rw(0x0000, 0xffff, 1); // initialize all devices for(DEVICE* device = first_device; device; device = device->next_device) { device->initialize(); } }
/** * \brief Open a device. * \param name Name of the device file. * \param tmo Device alloc time out. * \note This function will lock the device. It can be released * using BermudaDeviceClose. * \see BermudaDeviceClose * \return 0 on success, -1 when tmo expires or when a device file named <b>name</b> is not found. * * Open a device with a device file named <b>name</b>. If no file is found, -1 is returned. */ PUBLIC int BermudaDeviceOpen(const char *name, unsigned int tmo) { DEVICE *dev = BermudaDeviceLoopup(name); int rc = -1; if(dev) { rc = dev->alloc(dev, tmo); } return rc; }
void VM::reset() { // reset all devices for(DEVICE* device = first_device; device; device = device->next_device) { device->reset(); } and_int->write_signal(SIG_AND_BIT_0, 0, 1); // CLOCK = L and_int->write_signal(SIG_AND_BIT_1, 1, 1); // INTMASK = H #if defined(_MZ800) || defined(_MZ1500) and_snd->write_signal(SIG_AND_BIT_1, 1, 1); // SNDMASK = H #endif }
bool VM::load_state(FILEIO* state_fio) { if(state_fio->FgetUint32() != STATE_VERSION) { return false; } for(DEVICE* device = first_device; device; device = device->next_device) { if(!device->load_state(state_fio)) { return false; } } state_fio->Fread(ram, sizeof(ram), 1); return true; }
void VM::update_config() { #if defined(_PC98DO) || defined(_PC98DOPLUS) if(boot_mode != config.boot_mode) { // boot mode is changed !!! boot_mode = config.boot_mode; reset(); } else #endif for(DEVICE* device = first_device; device; device = device->next_device) { device->update_config(); } }
void VM::save_state(FILEIO* state_fio) { state_fio->FputUint32(STATE_VERSION); for(DEVICE* device = first_device; device; device = device->next_device) { device->save_state(state_fio); } state_fio->Fwrite(ram, sizeof(ram), 1); state_fio->FputBool(pit_clock_8mhz); #if defined(_PC98DO) || defined(_PC98DOPLUS) state_fio->FputInt32(boot_mode); #endif state_fio->FputInt32(sound_device_type); }
VM::VM(EMU* parent_emu) : emu(parent_emu) { // create devices first_device = last_device = NULL; dummy = new DEVICE(this, emu); // must be 1st device event = new EVENT(this, emu); // must be 2nd device io = new IO(this, emu); memory = new MEMORY(this, emu); cpu = new Z80(this, emu); joystick = new JOYSTICK(this, emu); psg = new PSG(this, emu); vdp = new VDP(this, emu); // set contexts event->set_context_cpu(cpu); event->set_context_sound(psg); vdp->set_context_cpu(cpu); vdp->set_memory_ptr(mem); // cpu bus cpu->set_context_mem(memory); cpu->set_context_io(io); cpu->set_context_intr(dummy); #ifdef USE_DEBUGGER cpu->set_context_debugger(new DEBUGGER(this, emu)); #endif // memory bus memset(mem, 0xff, 0x8000); memset(mem + 0x8000, 0, 0x8000); memory->set_memory_r(0x0000, 0x7fff, mem); memory->set_memory_rw(0xb800, 0xbfff, mem + 0xb800); // i/o bus io->set_iomap_range_w(0xf8, 0xfa, psg); io->set_iomap_range_rw(0xfc, 0xfd, joystick); io->set_iomap_range_w(0xfe, 0xff, vdp); // initialize all devices for(DEVICE* device = first_device; device; device = device->next_device) { device->initialize(); } inserted = false; }
static bRC handle_tapealert_readout(void *value) { DCR *dcr; DEVICE *dev; DEVRES *device; uint64_t flags; /* * Unpack the arguments passed in. */ dcr = (DCR *)value; if (!dcr) { return bRC_Error; } dev = dcr->dev; if (!dev) { return bRC_Error; } device = dev->device; if (!device) { return bRC_Error; } /* * See if drive tapealert is enabled. */ if (!device->drive_tapealert_enabled) { Dmsg1(dbglvl, "scsitapealert-sd: tapealert is not enabled on device %s\n", dev->dev_name); return bRC_OK; } Dmsg1(dbglvl, "scsitapealert-sd: checking for tapealerts on device %s\n", dev->dev_name); P(tapealert_operation_mutex); get_tapealert_flags(dev->fd(), dev->dev_name, &flags); V(tapealert_operation_mutex); Dmsg1(dbglvl, "scsitapealert-sd: checking for tapealerts on device %s DONE\n", dev->dev_name); Dmsg1(dbglvl, "scsitapealert-sd: flags: %ld \n", flags); if (flags) { Dmsg1(dbglvl, "scsitapealert-sd: tapealerts on device %s, calling UpdateTapeAlerts\n", dev->dev_name); bfuncs->UpdateTapeAlert(dcr, flags); } return bRC_OK; }
VM::~VM() { FILEIO* fio = new FILEIO(); if(fio->Fopen(create_local_path(_T("RAM.BIN")), FILEIO_WRITE_BINARY)) { fio->Fwrite(ram, sizeof(ram), 1); fio->Fclose(); } delete fio; // delete all devices for(DEVICE* device = first_device; device;) { DEVICE *next_device = device->next_device; device->release(); delete device; device = next_device; } }
void VM::update_config() { #if defined(_MZ800) if(boot_mode != config.boot_mode) { // boot mode is changed !!! boot_mode = config.boot_mode; reset(); } else { #endif for(DEVICE* device = first_device; device; device = device->next_device) { device->update_config(); } #if defined(_MZ800) } #endif }
bool VM::load_state(FILEIO* state_fio) { if(state_fio->FgetUint32() != STATE_VERSION) { return false; } for(DEVICE* device = first_device; device; device = device->next_device) { if(!device->load_state(state_fio)) { return false; } } state_fio->Fread(ram, sizeof(ram), 1); pit_clock_8mhz = state_fio->FgetBool(); #if defined(_PC98DO) || defined(_PC98DOPLUS) boot_mode = state_fio->FgetInt32(); #endif sound_device_type = state_fio->FgetInt32(); return true; }
/* * Create a new Device Control Record and attach * it to the device (if this is a real job). * Note, this has been updated so that it can be called first * without a DEVICE, then a second or third time with a DEVICE, * and each time, it should cleanup and point to the new device. * This should facilitate switching devices. * Note, each dcr must point to the controlling job (jcr). However, * a job can have multiple dcrs, so we must not store in the jcr's * structure as previously. The higher level routine must store * this dcr in the right place * */ DCR *new_dcr(JCR *jcr, DCR *dcr, DEVICE *dev, bool writing) { DEVICE *odev; if (!dcr) { dcr = (DCR *)malloc(sizeof(DCR)); memset(dcr, 0, sizeof(DCR)); dcr->tid = pthread_self(); dcr->spool_fd = -1; } dcr->jcr = jcr; /* point back to jcr */ odev = dcr->dev; if (dcr->attached_to_dev && odev) { Dmsg2(100, "Detach 0x%x from olddev %s\n", dcr, odev->print_name()); odev->detach_dcr_from_dev(dcr); } ASSERT2(!dcr->attached_to_dev, "DCR is attached. Wrong!"); /* Set device information, possibly change device */ if (dev) { dcr->free_blocks(); dcr->block = new_block(dev); dcr->ameta_block = dcr->block; if (dcr->rec) { free_record(dcr->rec); } dcr->rec = new_record(); /* Use job spoolsize prior to device spoolsize */ if (jcr && jcr->spool_size) { dcr->max_job_spool_size = jcr->spool_size; } else { dcr->max_job_spool_size = dev->device->max_job_spool_size; } dcr->device = dev->device; dcr->set_dev(dev); Dmsg2(100, "Attach 0x%x to dev %s\n", dcr, dev->print_name()); dev->attach_dcr_to_dev(dcr); } if (writing) { dcr->set_writing(); } else { dcr->clear_writing(); } return dcr; }
/* * DCR is locked before calling this routine */ static void locked_detach_dcr_from_dev(DCR *dcr) { DEVICE *dev = dcr->dev; Dmsg0(500, "Enter detach_dcr_from_dev\n"); /* jcr is NULL in some cases */ /* Detach this dcr only if attached */ if (dcr->attached_to_dev && dev) { dcr->unreserve_device(); dev->Lock(); Dmsg4(200, "Detach Jid=%d dcr=%p size=%d to dev=%s\n", (uint32_t)dcr->jcr->JobId, dcr, dev->attached_dcrs->size(), dev->print_name()); dcr->attached_to_dev = false; if (dev->attached_dcrs->size()) { dev->attached_dcrs->remove(dcr); /* detach dcr from device */ } // remove_dcr_from_dcrs(dcr); /* remove dcr from jcr list */ dev->Unlock(); } dcr->attached_to_dev = false; }
static void attach_dcr_to_dev(DCR *dcr) { DEVICE *dev; JCR *jcr; P(dcr->m_mutex); dev = dcr->dev; jcr = dcr->jcr; if (jcr) Dmsg1(500, "JobId=%u enter attach_dcr_to_dev\n", (uint32_t)jcr->JobId); /* ***FIXME*** return error if dev not initiated */ if (!dcr->attached_to_dev && dev->initiated && jcr && jcr->getJobType() != JT_SYSTEM) { dev->Lock(); Dmsg4(200, "Attach Jid=%d dcr=%p size=%d dev=%s\n", (uint32_t)jcr->JobId, dcr, dev->attached_dcrs->size(), dev->print_name()); dev->attached_dcrs->append(dcr); /* attach dcr to device */ dev->Unlock(); dcr->attached_to_dev = true; } V(dcr->m_mutex); }