tape_3590.c
来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 1,302 行 · 第 1/3 页
C
1,302 行
case 0x08: if (sense->fmt.f71.mdf == 0) PRINT_WARN("(%s): Repair will disable message " "display 0x%x on DV\n", device->cdev->dev.bus_id, sense->fmt.f71.md[1]); else PRINT_WARN("(%s): Repair will disable message " "displays (0x%x-0x%x) on DV\n", device->cdev->dev.bus_id, sense->fmt.f71.md[1], sense->fmt.f71.md[2]); break; case 0x09: PRINT_WARN("(%s): Clean DV\n", device->cdev->dev.bus_id); break; default: PRINT_WARN("(%s): DSIM ServiceMsg: 0x%02x\n", device->cdev->dev.bus_id, sense->fmt.f71.smc); }}/* * Print standard ERA Message */static voidtape_3590_print_era_msg(struct tape_device *device, struct irb *irb){ struct tape_3590_sense *sense; sense = (struct tape_3590_sense *) irb->ecw; if (sense->mc == 0) return; if ((sense->mc > 0) && (sense->mc < TAPE_3590_MAX_MSG)) { if (tape_3590_msg[sense->mc] != NULL) PRINT_WARN("(%s): %s\n", device->cdev->dev.bus_id, tape_3590_msg[sense->mc]); else { PRINT_WARN("(%s): Message Code 0x%x\n", device->cdev->dev.bus_id, sense->mc); } return; } if (sense->mc == 0xf0) { /* Standard Media Information Message */ PRINT_WARN("(%s): MIM SEV=%i, MC=%02x, ES=%x/%x, " "RC=%02x-%04x-%02x\n", device->cdev->dev.bus_id, sense->fmt.f70.sev, sense->mc, sense->fmt.f70.emc, sense->fmt.f70.smc, sense->fmt.f70.refcode, sense->fmt.f70.mid, sense->fmt.f70.fid); tape_3590_print_mim_msg_f0(device, irb); return; } if (sense->mc == 0xf1) { /* Standard I/O Subsystem Service Information Message */ PRINT_WARN("(%s): IOSIM SEV=%i, DEVTYPE=3590/%02x, " "MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n", device->cdev->dev.bus_id, sense->fmt.f71.sev, device->cdev->id.dev_model, sense->mc, sense->fmt.f71.emc, sense->fmt.f71.smc, sense->fmt.f71.refcode1, sense->fmt.f71.refcode2, sense->fmt.f71.refcode3); tape_3590_print_io_sim_msg_f1(device, irb); return; } if (sense->mc == 0xf2) { /* Standard Device Service Information Message */ PRINT_WARN("(%s): DEVSIM SEV=%i, DEVTYPE=3590/%02x, " "MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n", device->cdev->dev.bus_id, sense->fmt.f71.sev, device->cdev->id.dev_model, sense->mc, sense->fmt.f71.emc, sense->fmt.f71.smc, sense->fmt.f71.refcode1, sense->fmt.f71.refcode2, sense->fmt.f71.refcode3); tape_3590_print_dev_sim_msg_f2(device, irb); return; } if (sense->mc == 0xf3) { /* Standard Library Service Information Message */ return; } PRINT_WARN("(%s): Device Message(%x)\n", device->cdev->dev.bus_id, sense->mc);}/* * 3590 error Recovery routine: * If possible, it tries to recover from the error. If this is not possible, * inform the user about the problem. */static inttape_3590_unit_check(struct tape_device *device, struct tape_request *request, struct irb *irb){ struct tape_3590_sense *sense; int rc;#ifdef CONFIG_S390_TAPE_BLOCK if (request->op == TO_BLOCK) { /* * Recovery for block device requests. Set the block_position * to something invalid and retry. */ device->blk_data.block_position = -1; if (request->retries-- <= 0) return tape_3590_erp_failed(device, request, irb, -EIO); else return tape_3590_erp_retry(device, request, irb); }#endif sense = (struct tape_3590_sense *) irb->ecw; /* * First check all RC-QRCs where we want to do something special * - "break": basic error recovery is done * - "goto out:": just print error message if available */ rc = -EIO; switch (sense->rc_rqc) { case 0x1110: tape_3590_print_era_msg(device, irb); return tape_3590_erp_read_buf_log(device, request, irb); case 0x2011: tape_3590_print_era_msg(device, irb); return tape_3590_erp_read_alternate(device, request, irb); case 0x2230: case 0x2231: tape_3590_print_era_msg(device, irb); return tape_3590_erp_special_interrupt(device, request, irb); case 0x3010: DBF_EVENT(2, "(%08x): Backward at Beginning of Partition\n", device->cdev_id); return tape_3590_erp_basic(device, request, irb, -ENOSPC); case 0x3012: DBF_EVENT(2, "(%08x): Forward at End of Partition\n", device->cdev_id); return tape_3590_erp_basic(device, request, irb, -ENOSPC); case 0x3020: DBF_EVENT(2, "(%08x): End of Data Mark\n", device->cdev_id); return tape_3590_erp_basic(device, request, irb, -ENOSPC); case 0x3122: DBF_EVENT(2, "(%08x): Rewind Unload initiated\n", device->cdev_id); return tape_3590_erp_basic(device, request, irb, -EIO); case 0x3123: DBF_EVENT(2, "(%08x): Rewind Unload complete\n", device->cdev_id); tape_med_state_set(device, MS_UNLOADED); return tape_3590_erp_basic(device, request, irb, 0); case 0x4010: /* * print additional msg since default msg * "device intervention" is not very meaningfull */ PRINT_WARN("(%s): Tape operation when medium not loaded\n", device->cdev->dev.bus_id); tape_med_state_set(device, MS_UNLOADED); return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM); case 0x4012: /* Device Long Busy */ tape_3590_print_era_msg(device, irb); return tape_3590_erp_long_busy(device, request, irb); case 0x5010: if (sense->rac == 0xd0) { /* Swap */ tape_3590_print_era_msg(device, irb); return tape_3590_erp_swap(device, request, irb); } if (sense->rac == 0x26) { /* Read Opposite */ tape_3590_print_era_msg(device, irb); return tape_3590_erp_read_opposite(device, request, irb); } return tape_3590_erp_basic(device, request, irb, -EIO); case 0x5020: case 0x5021: case 0x5022: case 0x5040: case 0x5041: case 0x5042: tape_3590_print_era_msg(device, irb); return tape_3590_erp_swap(device, request, irb); case 0x5110: case 0x5111: return tape_3590_erp_basic(device, request, irb, -EMEDIUMTYPE); case 0x5120: case 0x1120: tape_med_state_set(device, MS_UNLOADED); return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM); case 0x6020: PRINT_WARN("(%s): Cartridge of wrong type ?\n", device->cdev->dev.bus_id); return tape_3590_erp_basic(device, request, irb, -EMEDIUMTYPE); case 0x8011: PRINT_WARN("(%s): Another host has reserved the tape device\n", device->cdev->dev.bus_id); return tape_3590_erp_basic(device, request, irb, -EPERM); case 0x8013: PRINT_WARN("(%s): Another host has priviliged access to the " "tape device\n", device->cdev->dev.bus_id); PRINT_WARN("(%s): To solve the problem unload the current " "cartridge!\n", device->cdev->dev.bus_id); return tape_3590_erp_basic(device, request, irb, -EPERM); default: return tape_3590_erp_basic(device, request, irb, -EIO); }}/* * 3590 interrupt handler: */static inttape_3590_irq(struct tape_device *device, struct tape_request *request, struct irb *irb){ if (request == NULL) return tape_3590_unsolicited_irq(device, irb); if ((irb->scsw.dstat & DEV_STAT_UNIT_EXCEP) && (irb->scsw.dstat & DEV_STAT_DEV_END) && (request->op == TO_WRI)) { /* Write at end of volume */ DBF_EVENT(2, "End of volume\n"); return tape_3590_erp_failed(device, request, irb, -ENOSPC); } if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) return tape_3590_unit_check(device, request, irb); if (irb->scsw.dstat & DEV_STAT_DEV_END) { if (irb->scsw.dstat == DEV_STAT_UNIT_EXCEP) { if (request->op == TO_FSB || request->op == TO_BSB) request->rescnt++; else DBF_EVENT(5, "Unit Exception!\n"); } return tape_3590_done(device, request); } if (irb->scsw.dstat & DEV_STAT_CHN_END) { DBF_EVENT(2, "cannel end\n"); return TAPE_IO_PENDING; } if (irb->scsw.dstat & DEV_STAT_ATTENTION) { DBF_EVENT(2, "Unit Attention when busy..\n"); return TAPE_IO_PENDING; } DBF_EVENT(6, "xunknownirq\n"); PRINT_ERR("Unexpected interrupt.\n"); PRINT_ERR("Current op is: %s", tape_op_verbose[request->op]); tape_dump_sense(device, request, irb); return TAPE_IO_STOP;}/* * Setup device function */static inttape_3590_setup_device(struct tape_device *device){ int rc; struct tape_3590_disc_data *data; DBF_EVENT(6, "3590 device setup\n"); data = kmalloc(sizeof(struct tape_3590_disc_data), GFP_KERNEL | GFP_DMA); if (data == NULL) return -ENOMEM; data->read_back_op = READ_PREVIOUS; device->discdata = data; if ((rc = tape_std_assign(device)) == 0) { /* Try to find out if medium is loaded */ if ((rc = tape_3590_sense_medium(device)) != 0) DBF_LH(3, "3590 medium sense returned %d\n", rc); } return rc;}/* * Cleanup device function */static voidtape_3590_cleanup_device(struct tape_device *device){ flush_scheduled_work(); tape_std_unassign(device); kfree(device->discdata); device->discdata = NULL;}/* * List of 3590 magnetic tape commands. */static tape_mtop_fn tape_3590_mtop[TAPE_NR_MTOPS] = { [MTRESET] = tape_std_mtreset, [MTFSF] = tape_std_mtfsf, [MTBSF] = tape_std_mtbsf, [MTFSR] = tape_std_mtfsr, [MTBSR] = tape_std_mtbsr, [MTWEOF] = tape_std_mtweof, [MTREW] = tape_std_mtrew, [MTOFFL] = tape_std_mtoffl, [MTNOP] = tape_std_mtnop, [MTRETEN] = tape_std_mtreten, [MTBSFM] = tape_std_mtbsfm, [MTFSFM] = tape_std_mtfsfm, [MTEOM] = tape_std_mteom, [MTERASE] = tape_std_mterase, [MTRAS1] = NULL, [MTRAS2] = NULL, [MTRAS3] = NULL, [MTSETBLK] = tape_std_mtsetblk, [MTSETDENSITY] = NULL, [MTSEEK] = tape_3590_mtseek, [MTTELL] = tape_3590_mttell, [MTSETDRVBUFFER] = NULL, [MTFSS] = NULL, [MTBSS] = NULL, [MTWSM] = NULL, [MTLOCK] = NULL, [MTUNLOCK] = NULL, [MTLOAD] = tape_std_mtload, [MTUNLOAD] = tape_std_mtunload, [MTCOMPRESSION] = tape_std_mtcompression, [MTSETPART] = NULL, [MTMKPART] = NULL};/* * Tape discipline structure for 3590. */static struct tape_discipline tape_discipline_3590 = { .owner = THIS_MODULE, .setup_device = tape_3590_setup_device, .cleanup_device = tape_3590_cleanup_device, .process_eov = tape_std_process_eov, .irq = tape_3590_irq, .read_block = tape_std_read_block, .write_block = tape_std_write_block,#ifdef CONFIG_S390_TAPE_BLOCK .bread = tape_3590_bread, .free_bread = tape_3590_free_bread, .check_locate = tape_3590_check_locate,#endif .ioctl_fn = tape_3590_ioctl, .mtop_array = tape_3590_mtop};static struct ccw_device_id tape_3590_ids[] = { {CCW_DEVICE_DEVTYPE(0x3590, 0, 0x3590, 0), .driver_info = tape_3590}, {CCW_DEVICE_DEVTYPE(0x3592, 0, 0x3592, 0), .driver_info = tape_3592}, { /* end of list */ }};static inttape_3590_online(struct ccw_device *cdev){ return tape_generic_online(cdev->dev.driver_data, &tape_discipline_3590);}static inttape_3590_offline(struct ccw_device *cdev){ return tape_generic_offline(cdev->dev.driver_data);}static struct ccw_driver tape_3590_driver = { .name = "tape_3590", .owner = THIS_MODULE, .ids = tape_3590_ids, .probe = tape_generic_probe, .remove = tape_generic_remove, .set_offline = tape_3590_offline, .set_online = tape_3590_online,};/* * Setup discipline structure. */static inttape_3590_init(void){ int rc; TAPE_DBF_AREA = debug_register("tape_3590", 2, 2, 4 * sizeof(long)); debug_register_view(TAPE_DBF_AREA, &debug_sprintf_view);#ifdef DBF_LIKE_HELL debug_set_level(TAPE_DBF_AREA, 6);#endif DBF_EVENT(3, "3590 init\n"); /* Register driver for 3590 tapes. */ rc = ccw_driver_register(&tape_3590_driver); if (rc) DBF_EVENT(3, "3590 init failed\n"); else DBF_EVENT(3, "3590 registered\n"); return rc;}static voidtape_3590_exit(void){ ccw_driver_unregister(&tape_3590_driver); debug_unregister(TAPE_DBF_AREA);}MODULE_DEVICE_TABLE(ccw, tape_3590_ids);MODULE_AUTHOR("(C) 2001,2006 IBM Corporation");MODULE_DESCRIPTION("Linux on zSeries channel attached 3590 tape device driver");MODULE_LICENSE("GPL");module_init(tape_3590_init);module_exit(tape_3590_exit);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?