📄 tape.c
字号:
#endif /* Register IRQ */#ifdef CONFIG_S390_TAPE_DYNAMIC rc = s390_request_irq_special (irq, tape_irq, tape_noper_handler,0, "tape", &(ti->devstat));#else rc = s390_request_irq (irq, tape_irq, 0, "tape", &(ti->devstat));#endif s390irq_spin_lock_irqsave (irq, lockflags); ti->next = NULL; if (rc) PRINT_WARN ("Cannot register irq %d, rc=%d\n", irq, rc); init_waitqueue_head (&ti->wq); ti->kernbuf = ti->userbuf = ti->discdata = NULL; tapestate_set (ti, TS_UNUSED); ti->discdata=NULL; ti->discipline->setup_assist (ti); ti->wanna_wakeup=0; s390irq_spin_unlock_irqrestore (irq, lockflags); return rc;}/* * tape_init will register the driver for each tape. */inttape_init (void){ long lockflags; s390_dev_info_t dinfo; tape_discipline_t *disc; tape_info_t *ti = NULL, *tempti = NULL; char *opt_char,*opt_block,*opt_3490,*opt_3480; int irq = 0, rc, retries = 0, tape_num = 0; static int initialized=0; if (initialized) // Only init the devices once return 0; initialized=1;#ifdef TAPE_DEBUG tape_debug_area = debug_register ( "tape", 3, 2, 10); debug_register_view(tape_debug_area,&debug_hex_ascii_view); debug_text_event (tape_debug_area,3,"begin init");#endif /* TAPE_DEBUG */ /* print banner */ PRINT_WARN ("IBM S/390 Tape Device Driver (v1.01).\n"); PRINT_WARN ("(C) IBM Deutschland Entwicklung GmbH, 2000\n"); opt_char=opt_block=opt_3480=opt_3490="not present";#ifdef CONFIG_S390_TAPE_CHAR opt_char="built in";#endif#ifdef CONFIG_S390_TAPE_BLOCK opt_block="built in";#endif#ifdef CONFIG_S390_TAPE_3480 opt_3480="built in";#endif#ifdef CONFIG_S390_TAPE_3490 opt_3490="built in";#endif /* print feature info */ PRINT_WARN ("character device frontend : %s\n",opt_char); PRINT_WARN ("block device frontend : %s\n",opt_block); PRINT_WARN ("support for 3480 compatible : %s\n",opt_3480); PRINT_WARN ("support for 3490 compatible : %s\n",opt_3490); #ifndef MODULE tape_split_parm_string(tape_parm_string);#endif if (*tape) PRINT_INFO ("Using ranges supplied in parameters, disabling autoprobe mode.\n"); else PRINT_INFO ("No parameters supplied, enabling autoprobe mode for all supported devices.\n");#ifdef CONFIG_S390_TAPE_3490 if (*tape) first_discipline = tape3490_init (0); // no autoprobe for devices else first_discipline = tape3490_init (1); // do autoprobe since no parm specified first_discipline->next = NULL;#endif#ifdef CONFIG_S390_TAPE_3480 if (first_discipline == NULL) { if (*tape) first_discipline = tape3480_init (0); // no autoprobe for devices else first_discipline = tape3480_init (1); // do autoprobe since no parm specified first_discipline->next = NULL; } else { if (*tape) first_discipline->next = tape3480_init (0); // no autoprobe for devices else first_discipline->next = tape3480_init (1); // do autoprobe since no parm specified ((tape_discipline_t*) (first_discipline->next))->next=NULL; }#endif#ifdef CONFIG_DEVFS_FS tape_devfs_root_entry=devfs_mk_dir (NULL, "tape", NULL);#endif CONFIG_DEVFS_FS#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,3,"dev detect");#endif /* TAPE_DEBUG */ /* Allocate the tape structures */ if (*tape!=NULL) { // we have parameters, continue with parsing the parameters and set the devices online tape_parm_parse (tape); } else { // we are running in autodetect mode, search all devices for compatibles for (irq = get_irq_first(); irq!=-ENODEV; irq=get_irq_next(irq)) { rc = get_dev_info_by_irq (irq, &dinfo); disc = first_discipline; while ((disc != NULL) && (disc->cu_type != dinfo.sid_data.cu_type)) disc = (tape_discipline_t *) (disc->next); if ((disc == NULL) || (rc == -ENODEV)) continue;#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,3,"det irq: "); debug_int_event (tape_debug_area,3,irq); debug_text_event (tape_debug_area,3,"cu: "); debug_int_event (tape_debug_area,3,disc->cu_type);#endif /* TAPE_DEBUG */ PRINT_INFO ("using devno %04x with discipline %04x on irq %d as tape device %d\n",dinfo.devno,dinfo.sid_data.cu_type,irq,tape_num/2); /* Allocate tape structure */ ti = kmalloc (sizeof (tape_info_t), GFP_ATOMIC); if (ti == NULL) {#ifdef TAPE_DEBUG debug_text_exception (tape_debug_area,3,"ti:no mem ");#endif /* TAPE_DEBUG */ PRINT_INFO ("tape: can't allocate memory for " "tape info structure\n"); continue; } memset(ti,0,sizeof(tape_info_t)); ti->discipline = disc; disc->tape = ti; rc = tape_setup (ti, irq, tape_num); if (rc) {#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,3,"tsetup err"); debug_int_exception (tape_debug_area,3,rc);#endif /* TAPE_DEBUG */ kfree (ti); } else { s390irq_spin_lock_irqsave (irq, lockflags); if (first_tape_info == NULL) { first_tape_info = ti; } else { tempti = first_tape_info; while (tempti->next != NULL) tempti = tempti->next; tempti->next = ti; } tape_num += 2; s390irq_spin_unlock_irqrestore (irq, lockflags); } } } /* Allocate local buffer for the ccwcache */ tape_init_emergency_req ();#ifdef CONFIG_PROC_FS#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98)) tape_devices_entry = create_proc_entry ("tapedevices", S_IFREG | S_IRUGO | S_IWUSR, &proc_root); tape_devices_entry->proc_fops = &tape_devices_file_ops; tape_devices_entry->proc_iops = &tape_devices_inode_ops;#else tape_devices_entry = (struct proc_dir_entry *) kmalloc (sizeof (struct proc_dir_entry), GFP_ATOMIC); if (tape_devices_entry) { memset (tape_devices_entry, 0, sizeof (struct proc_dir_entry)); tape_devices_entry->name = "tapedevices"; tape_devices_entry->namelen = strlen ("tapedevices"); tape_devices_entry->low_ino = 0; tape_devices_entry->mode = (S_IFREG | S_IRUGO | S_IWUSR); tape_devices_entry->nlink = 1; tape_devices_entry->uid = 0; tape_devices_entry->gid = 0; tape_devices_entry->size = 0; tape_devices_entry->get_info = NULL; tape_devices_entry->ops = &tape_devices_inode_ops; proc_register (&proc_root, tape_devices_entry); }#endif#endif /* CONFIG_PROC_FS */ return 0;}#ifdef MODULEMODULE_AUTHOR("(C) 2001 IBM Deutschland Entwicklung GmbH by Carsten Otte (cotte@de.ibm.com)");MODULE_DESCRIPTION("Linux for S/390 channel attached tape device driver");MODULE_PARM (tape, "1-" __MODULE_STRING (256) "s");intinit_module (void){#ifdef CONFIG_S390_TAPE_CHAR tapechar_init ();#endif#ifdef CONFIG_S390_TAPE_BLOCK tapeblock_init ();#endif return 0;}voidcleanup_module (void){ tape_info_t *ti ,*temp; tape_frontend_t* frontend, *tempfe; tape_discipline_t* disc ,*tempdi; int i;#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"cleaup mod");#endif /* TAPE_DEBUG */ if (*tape) { // we are running with parameters. we'll now deregister from our devno's for (i=0;i<devregct;i++) { s390_device_unregister(tape_devreg[devregct]); } } ti = first_tape_info; while (ti != NULL) { temp = ti; ti = ti->next; //cleanup a device #ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"free irq:"); debug_int_event (tape_debug_area,6,temp->devinfo.irq);#endif /* TAPE_DEBUG */ free_irq (temp->devinfo.irq, &(temp->devstat)); if (temp->discdata) kfree (temp->discdata); if (temp->kernbuf) kfree (temp->kernbuf); if (temp->cqr) tape_free_request(temp->cqr);#ifdef CONFIG_DEVFS_FS for (frontend=first_frontend;frontend!=NULL;frontend=frontend->next) frontend->rmdevfstree(temp); tape_rmdevfsroots(temp);#endif kfree (temp); }#ifdef CONFIG_DEVFS_FS devfs_unregister (tape_devfs_root_entry);#endif CONFIG_DEVFS_FS#ifdef CONFIG_PROC_FS#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98)) remove_proc_entry ("tapedevices", &proc_root);#else proc_unregister (&proc_root, tape_devices_entry->low_ino); kfree (tape_devices_entry);#endif /* LINUX_IS_24 */#endif #ifdef CONFIG_S390_TAPE_CHAR tapechar_uninit();#endif#ifdef CONFIG_S390_TAPE_BLOCK tapeblock_uninit();#endif frontend=first_frontend; while (frontend != NULL) { tempfe = frontend; frontend = frontend->next; kfree (tempfe); } disc=first_discipline; while (disc != NULL) { if (*tape) disc->shutdown(0); else disc->shutdown(1); tempdi = disc; disc = disc->next; kfree (tempdi); } /* Deallocate the local buffer for the ccwcache */ tape_cleanup_emergency_req ();#ifdef TAPE_DEBUG debug_unregister (tape_debug_area);#endif /* TAPE_DEBUG */}#endif /* MODULE */inline voidtapestate_set (tape_info_t * ti, int newstate){ if (ti->tape_state == TS_NOT_OPER) {#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,3,"ts_set err"); debug_text_exception (tape_debug_area,3,"dev n.oper");#endif /* TAPE_DEBUG */ } else {#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,4,"ts. dev: "); debug_int_event (tape_debug_area,4,ti->blk_minor); debug_text_event (tape_debug_area,4,"old ts: "); debug_text_event (tape_debug_area,4,(((tapestate_get (ti) < TS_SIZE) && (tapestate_get (ti) >=0 )) ? state_verbose[tapestate_get (ti)] : "UNKNOWN TS")); debug_text_event (tape_debug_area,4,"new ts: "); debug_text_event (tape_debug_area,4,(((newstate < TS_SIZE) && (newstate >= 0)) ? state_verbose[newstate] : "UNKNOWN TS"));#endif /* TAPE_DEBUG */ ti->tape_state = newstate; }}inline inttapestate_get (tape_info_t * ti){ return (ti->tape_state);}voidtapestate_event (tape_info_t * ti, int event){#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"te! dev: "); debug_int_event (tape_debug_area,6,ti->blk_minor); debug_text_event (tape_debug_area,6,"event:"); debug_text_event (tape_debug_area,6,((event >=0) && (event < TE_SIZE)) ? event_verbose[event] : "TE UNKNOWN"); debug_text_event (tape_debug_area,6,"state:"); debug_text_event (tape_debug_area,6,((tapestate_get(ti) >= 0) && (tapestate_get(ti) < TS_SIZE)) ? state_verbose[tapestate_get (ti)] : "TS UNKNOWN");#endif /* TAPE_DEBUG */ if (event == TE_ERROR) { ti->discipline->error_recovery(ti); } else { if ((event >= 0) && (event < TE_SIZE) && (tapestate_get (ti) >= 0) && (tapestate_get (ti) < TS_SIZE) && ((*(ti->discipline->event_table))[tapestate_get (ti)][event] != NULL)) ((*(ti->discipline->event_table))[tapestate_get (ti)][event]) (ti); else {#ifdef TAPE_DEBUG debug_text_exception (tape_debug_area,3,"TE UNEXPEC");#endif /* TAPE_DEBUG */ ti->discipline->default_handler (ti); } }}/* * 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 + -