📄 dasd.c
字号:
return; } asm volatile ("STCK %0":"=m" (cqr->stopclk)); if ( ( stat->cstat == 0x00 && stat->dstat == (DEV_STAT_CHN_END|DEV_STAT_DEV_END) ) || dasd_erp_examine ( cqr ) == dasd_era_none ) { dasd_debug (0xc4c89692); /* DHok */ if (atomic_compare_and_swap (CQR_STATUS_IN_IO, CQR_STATUS_DONE, &cqr->status)) { PRINT_WARN ("handler: cqrstat changed%d\n", atomic_read (&cqr->status)); atomic_set(&cqr->status, CQR_STATUS_DONE); } if ( ! ( dasd_info[cqr->devindex]-> flags & DASD_INFO_FLAGS_INITIALIZED ) ) { int rc = register_dasd_last ( cqr->devindex ); dasd_info[cqr->devindex]-> flags |= DASD_INFO_FLAGS_INITIALIZED; if ( rc ) { dasd_info[cqr->devindex]->flags &= ~DASD_INFO_FLAGS_NOT_FORMATTED; } else { dasd_info[cqr->devindex]->flags |= DASD_INFO_FLAGS_NOT_FORMATTED; } } if (cqr->next) { dasd_debug (0xc4c8e2e3); /* DHST */ if (dasd_start_IO (cqr->next) == 0) { done_fast_io = 1; } else { atomic_inc (&chanq_tasks); } } break; } /* only visited in case of error ! */ dasd_debug (0xc4c8c5d9); /* DHER */ if (!cqr->dstat) cqr->dstat = kmalloc (sizeof (devstat_t), GFP_ATOMIC); if (cqr->dstat) { memcpy (cqr->dstat, stat, sizeof (devstat_t)); } else { PRINT_ERR ("no memory for dstat\n"); } /* errorprocessing */ atomic_set (&cqr->status, CQR_STATUS_ERROR); atomic_inc (&dasd_info[cqr->devindex]->queue.dirty_requests); } if (done_fast_io == 0) atomic_clear_mask (DASD_CHANQ_BUSY, &dasd_info[cqr->devindex]->queue.flags); if (cqr->flags & DASD_DO_IO_SLEEP) { dasd_debug (0xc4c8a6a4); /* DHwu */ dasd_wakeup (); } else if (! (cqr->options & DOIO_WAIT_FOR_INTERRUPT) ){ dasd_debug (0xc4c8a293); /* DHsl */ atomic_inc (&chanq_tasks); schedule_bh (dasd_do_chanq); } else { dasd_debug (0x64686f6f); /* DH_g */ dasd_debug (cqr->flags); /* DH_g */ } dasd_debug (0xc4c86d6d); /* DHwu */}static intdasd_format (int dev, format_data_t * fdata){ int rc; int devindex = DEVICE_NR (dev); dasd_chanq_t *q; cqr_t *cqr; int irq; long flags; PRINT_INFO ("Format called with devno %x\n", dev); if (MINOR (dev) & (0xff >> (8 - PARTN_BITS))) { PRINT_WARN ("Can't format partition! minor %x %x\n", MINOR (dev), 0xff >> (8 - PARTN_BITS)); return -EINVAL; } down (&dasd_info[devindex]->sem); if (dasd_info[devindex]->open_count == 1) { rc = dasd_disciplines[dasd_info[devindex]->type]-> dasd_format (devindex, fdata); if (rc) { PRINT_WARN ("Formatting failed rc=%d\n", rc); } } else { PRINT_WARN ("device is open! %d\n", dasd_info[devindex]->open_count); rc = -EINVAL; } if (!rc) {#if DASD_PARANOIA > 1 if (!dasd_disciplines[dasd_info[devindex]->type]->fill_sizes_first) { INTERNAL_CHECK ("No fill_sizes for dt=%d\n", dasd_info[devindex]->type); } else#endif /* DASD_PARANOIA */ { dasd_info[devindex]->flags &= ~DASD_INFO_FLAGS_INITIALIZED; irq = dasd_info[devindex]->info.irq; PRINT_INFO ("Trying to access DASD %x, irq %x, index %d\n", get_devno_by_irq(irq), irq, devindex); s390irq_spin_lock_irqsave (irq, flags); q = &dasd_info[devindex]->queue; cqr = dasd_disciplines[dasd_info[devindex]->type]-> fill_sizes_first (devindex); dasd_chanq_enq (q, cqr); schedule_bh(dasd_do_chanq); s390irq_spin_unlock_irqrestore (irq, flags); } } up (&dasd_info[devindex]->sem); return rc;}static intregister_dasd (int irq, dasd_type_t dt, dev_info_t * info){ int rc = 0; int di; unsigned long flags; dasd_chanq_t *q; cqr_t * cqr; static spinlock_t register_lock = SPIN_LOCK_UNLOCKED; spin_lock (®ister_lock); FUNCTION_ENTRY ("register_dasd"); di = devindex_from_devno (info->devno); if (di < 0) { INTERNAL_CHECK ("Can't get index for devno %d\n", info->devno); return -ENODEV; } if (dasd_info[di]) { /* devindex is not free */ INTERNAL_CHECK ("reusing allocated deviceindex %d\n", di); return -ENODEV; } dasd_info[di] = (dasd_information_t *) kmalloc (sizeof (dasd_information_t), GFP_ATOMIC); if (dasd_info[di] == NULL) { PRINT_WARN ("No memory for dasd_info_t on irq %d\n", irq); return -ENOMEM; } memset (dasd_info[di], 0, sizeof (dasd_information_t)); memcpy (&(dasd_info[di]->info), info, sizeof (dev_info_t)); spin_lock_init (&dasd_info[di]->queue.f_lock); spin_lock_init (&dasd_info[di]->queue.q_lock); dasd_info[di]->type = dt; dasd_info[di]->irq = irq; init_MUTEX (&dasd_info[di]->sem); rc = dasd_read_characteristics (dasd_info[di]); if (rc) { PRINT_WARN ("RDC returned error %d\n", rc); rc = -ENODEV; goto unalloc; }#if DASD_PARANOIA > 1 if (dasd_disciplines[dt]->ck_characteristics)#endif /* DASD_PARANOIA */ rc = dasd_disciplines[dt]-> ck_characteristics (dasd_info[di]->rdc_data); if (rc) { INTERNAL_CHECK ("Discipline returned non-zero when" "checking device characteristics%s\n", ""); rc = -ENODEV; goto unalloc; } rc = request_irq (irq, dasd_handler, 0, "dasd", &(dasd_info[di]->dev_status)); if (rc) {#if DASD_PARANOIA > 0 printk (KERN_WARNING PRINTK_HEADER "Cannot register irq %d, rc=%d\n", irq, rc);#endif /* DASD_PARANOIA */ rc = -ENODEV; goto unalloc; }#if DASD_PARANOIA > 1 if (!dasd_disciplines[dt]->fill_sizes_first) { INTERNAL_CHECK ("No fill_sizes for dt=%d\n", dt); goto unregister; }#endif /* DASD_PARANOIA */ irq = dasd_info[di]->info.irq; PRINT_INFO ("Trying to access DASD %x, irq %x, index %d\n", get_devno_by_irq(irq), irq, di); s390irq_spin_lock_irqsave (irq, flags); q = &dasd_info[di]->queue; cqr = dasd_disciplines[dt]->fill_sizes_first (di); dasd_chanq_enq (q, cqr); cql_enq_head(q); if (dasd_start_IO(cqr) != 0) { atomic_inc(&chanq_tasks); } s390irq_spin_unlock_irqrestore (irq, flags); goto exit; unregister: free_irq (irq, &(dasd_info[di]->dev_status)); unalloc: kfree (dasd_info[di]); exit: spin_unlock (®ister_lock); FUNCTION_EXIT ("register_dasd"); return rc;}static intprobe_for_dasd (int irq){ int rc; dev_info_t info; dasd_type_t dt; FUNCTION_ENTRY ("probe_for_dasd"); rc = get_dev_info_by_irq (irq, &info); if (rc == -ENODEV) { /* end of device list */ return rc; }#if DASD_PARANOIA > 2 if (rc) { INTERNAL_CHECK ("unknown rc %d of get_dev_info", rc); return rc; }#endif /* DASD_PARANOIA */ if ((info.status & DEVSTAT_NOT_OPER)) { return -ENODEV; } dt = check_type (&info); switch (dt) {#ifdef CONFIG_DASD_ECKD case dasd_eckd:#endif /* CONFIG_DASD_ECKD */ FUNCTION_CONTROL ("Probing devno %d...\n", info.devno); if (!dasd_is_accessible (info.devno)) { FUNCTION_CONTROL ("out of range...skip%s\n", ""); return -ENODEV; } if (dasd_disciplines[dt]->ck_devinfo) { rc = dasd_disciplines[dt]->ck_devinfo (&info); }#if DASD_PARANOIA > 1 else { INTERNAL_ERROR ("no ck_devinfo function%s\n", ""); return -ENODEV; }#endif /* DASD_PARANOIA */ if (rc == -ENODEV) { return rc; }#if DASD_PARANOIA > 2 if (rc) { INTERNAL_CHECK ("unknown error rc=%d\n", rc); return -ENODEV; }#endif /* DASD_PARANOIA */ rc = register_dasd (irq, dt, &info); if (rc) { PRINT_INFO ("devno %x not enabled as minor %d due to errors\n", info.devno, devindex_from_devno (info.devno) << PARTN_BITS); } else { PRINT_INFO ("devno %x added as minor %d (%s)\n", info.devno, devindex_from_devno (info.devno) << PARTN_BITS, dasd_name[dt]); } case dasd_none: break; default: PRINT_DEBUG ("unknown device type\n"); break; } FUNCTION_EXIT ("probe_for_dasd"); return rc;}static intregister_major (int major){ request_queue_t *q; int rc = 0; FUNCTION_ENTRY ("register_major"); rc = devfs_register_blkdev (major, DASD_NAME, &dasd_device_operations);#if DASD_PARANOIA > 1 if (rc) { PRINT_WARN ("registering major -> rc=%d aborting... \n", rc); return rc; }#endif /* DASD_PARANOIA */ q = BLK_DEFAULT_QUEUE(major); blk_init_queue(q, do_dasd_request); blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0); FUNCTION_CONTROL ("successfully registered major: %d\n", major); FUNCTION_EXIT ("register_major"); return rc;}/* Below you find functions which are called from outside. Some of them may be static, because they are called by their function pointers only. Thus static modifier is to make sure, that they are only called via the kernel's methods */static intdasd_ioctl (struct inode *inp, struct file *filp, unsigned int no, unsigned long data){ int rc = 0; FUNCTION_ENTRY ("dasd_ioctl"); if ((!inp) || !(inp->i_rdev)) { return -EINVAL; } rc = do_dasd_ioctl (inp, no, data); FUNCTION_EXIT ("dasd_ioctl"); return rc;}static intdasd_open (struct inode *inp, struct file *filp){ int rc = 0; dasd_information_t *dev; FUNCTION_ENTRY ("dasd_open"); if ((!inp) || !(inp->i_rdev)) { return -EINVAL; } dev = dasd_info[DEVICE_NR (inp->i_rdev)]; if (!dev) { PRINT_DEBUG ("No device registered as %d (%d)\n", inp->i_rdev, DEVICE_NR (inp->i_rdev)); return -EINVAL; } down (&dev->sem); up (&dev->sem);#ifdef MODULE MOD_INC_USE_COUNT;#endif /* MODULE */#if DASD_PARANOIA > 2 if (dev->open_count < 0) { INTERNAL_ERROR ("open count cannot be less than 0: %d", dev->open_count); return -EINVAL; }#endif /* DASD_PARANOIA */ dev->open_count++; FUNCTION_EXIT ("dasd_open"); return rc;}static intdasd_release (struct inode *inp, struct file *filp){ int rc = 0; dasd_information_t *dev; FUNCTION_ENTRY ("dasd_release"); if ((!inp) || !(inp->i_rdev)) { return -EINVAL; } dev = dasd_info[DEVICE_NR (inp->i_rdev)]; if (!dev) { PRINT_WARN ("No device registered as %d\n", inp->i_rdev); return -EINVAL; }#ifdef MODULE MOD_DEC_USE_COUNT;#endif /* MODULE */#if DASD_PARANOIA > 2 if (!dev->open_count) { PRINT_WARN ("device %d has not been opened before:\n", inp->i_rdev); }#endif /* DASD_PARANOIA */ dev->open_count--;#if DASD_PARANOIA > 2 if (dev->open_count < 0) { INTERNAL_ERROR ("open count cannot be less than 0: %d", dev->open_count); return -EINVAL; }#endif /* DASD_PARANOIA */ FUNCTION_EXIT ("dasd_release"); return rc;}static structblock_device_operations dasd_device_operations ={ ioctl: dasd_ioctl, open: dasd_open, release: dasd_release,};intdasd_init (void){ int rc = 0; int i; FUNCTION_ENTRY ("dasd_init"); PRINT_INFO ("initializing...\n"); atomic_set (&chanq_tasks, 0); atomic_set (&bh_scheduled, 0); spin_lock_init (&dasd_lock); init_waitqueue_head(&dasd_waitq); /* First register to the major number */ rc = register_major (MAJOR_NR);#if DASD_PARANOIA > 1 if (rc) { PRINT_WARN ("registering major_nr returned rc=%d\n", rc); return rc; }#endif /* DASD_PARANOIA */ read_ahead[MAJOR_NR] = 8; blk_size[MAJOR_NR] = dasd_blks; hardsect_size[MAJOR_NR] = dasd_secsize; blksize_size[MAJOR_NR] = dasd_blksize; max_sectors[MAJOR_NR] = dasd_maxsecs;#ifdef CONFIG_PROC_FS dasd_proc_init ();#endif /* CONFIG_PROC_FS */ /* Now scan the device list for DASDs */ FUNCTION_CONTROL ("entering detection loop%s\n", ""); for (i = 0; i < NR_IRQS; i++) { int irc; /* Internal return code */ LOOP_CONTROL ("Probing irq %d...\n", i); irc = probe_for_dasd (i); switch (irc) { case 0: LOOP_CONTROL ("Added DASD%s\n", ""); break; case -ENODEV: LOOP_CONTROL ("No DASD%s\n", ""); break; case -EMEDIUMTYPE: PRINT_WARN ("DASD not formatted%s\n", ""); break; default: INTERNAL_CHECK ("probe_for_dasd: unknown rc=%d", irc); break; } } FUNCTION_CONTROL ("detection loop completed %s partn check...\n", "");/* Finally do the genhd stuff */ dd_gendisk.next = gendisk_head; gendisk_head = &dd_gendisk; for ( i = 0; i < DASD_MAX_DEVICES; i ++ ) if ( dasd_info[i] ) dasd_partn_detect ( i ); FUNCTION_EXIT ("dasd_init"); return rc;}#ifdef MODULEintinit_module (void){ int rc = 0; FUNCTION_ENTRY ("init_module"); PRINT_INFO ("trying to load module\n"); rc = dasd_init (); if (rc == 0) { PRINT_INFO ("module loaded successfully\n"); } else { PRINT_WARN ("warning: Module load returned rc=%d\n", rc); } FUNCTION_EXIT ("init_module"); return rc;}voidcleanup_module (void){ int rc = 0; FUNCTION_ENTRY ("cleanup_module"); PRINT_INFO ("trying to unload module \n"); /* FIXME: replace by proper unload functionality */ INTERNAL_ERROR ("Modules not yet implemented %s", ""); if (rc == 0) { PRINT_INFO ("module unloaded successfully\n"); } else { PRINT_WARN ("module unloaded with errors\n"); } FUNCTION_EXIT ("cleanup_module");}#endif /* MODULE *//* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only. This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * c-indent-level: 4 * c-brace-imaginary-offset: 0 * c-brace-offset: -4 * c-argdecl-indent: 4 * c-label-offset: -4 * c-continued-statement-offset: 4 * c-continued-brace-offset: 0 * indent-tabs-mode: nil * tab-width: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -