dasd_eckd.c
来自「linux-2.4.29操作系统的源码」· C语言 代码 · 共 1,885 行 · 第 1/4 页
C
1,885 行
} cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RELEASE; cqr->cpaddr->flags |= CCW_FLAG_SLI; cqr->cpaddr->count = 32; if (dasd_set_normalized_cda (cqr->cpaddr, __pa (cqr->data), cqr, device)) { dasd_free_request (cqr, device); return NULL; } cqr->device = device; cqr->retries = 0; cqr->expires = 10 * TOD_SEC; cqr->buildclk = get_clock (); cqr->status = CQR_STATUS_FILLED; return cqr;}/* * DASD_ECKD_STEAL_LOCK * * DESCRIPTION * Buils a channel programm to break a device's reservation. * (unconditional reserve) */ccw_req_t *dasd_eckd_steal_lock (struct dasd_device_t * device){ ccw_req_t *cqr; cqr = dasd_alloc_request (dasd_eckd_discipline.name, 1 + 1, 32, device); if (cqr == NULL) { MESSAGE (KERN_WARNING, "%s", "No memory to allocate initialization request"); return NULL; } cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SLCK; cqr->cpaddr->flags |= CCW_FLAG_SLI; cqr->cpaddr->count = 32; if (dasd_set_normalized_cda (cqr->cpaddr, __pa (cqr->data), cqr, device)) { dasd_free_request (cqr, device); return NULL; } cqr->device = device; cqr->retries = 0; cqr->expires = 10 * TOD_SEC; cqr->buildclk = get_clock (); cqr->status = CQR_STATUS_FILLED; return cqr;}static inline ccw1_t *dasd_eckd_find_cmd (ccw_req_t * cqr, int cmd){ ccw1_t *cp; cp = cqr->cpaddr; do { if (cp->cmd_code == cmd) return cp; if (cp->cmd_code == CCW_CMD_TIC) { cp = (ccw1_t *) (long) cp->cda; continue; } if (cp->flags & (CCW_FLAG_DC | CCW_FLAG_CC)) { cp++; continue; } break; } while (1); return NULL;}static ccw_req_t *dasd_eckd_merge_cp (dasd_device_t * device){ return NULL;}static intdasd_eckd_fill_info (dasd_device_t * device, dasd_information2_t * info){ int rc = 0; info->label_block = 2; if (((dasd_eckd_private_t *) device->private)->uses_cdl) { info->FBA_layout = 0; info->format = DASD_FORMAT_CDL; } else { info->FBA_layout = 1; info->format = DASD_FORMAT_LDL; } info->characteristics_size = sizeof (dasd_eckd_characteristics_t); memcpy (info->characteristics, &((dasd_eckd_private_t *) device->private)->rdc_data, sizeof (dasd_eckd_characteristics_t)); info->confdata_size = sizeof (dasd_eckd_confdata_t); memcpy (info->configuration_data, &((dasd_eckd_private_t *) device->private)->conf_data, sizeof (dasd_eckd_confdata_t)); return rc;}/* * DASD_ECKD_READ_STATS * * DESCRIPTION * build the channel program to read the performance statistics * of the attached subsystem */ccw_req_t *dasd_eckd_read_stats (struct dasd_device_t * device){ int rc; ccw1_t *ccw; ccw_req_t *cqr; dasd_psf_prssd_data_t *prssdp; dasd_rssd_perf_stats_t *statsp; cqr = dasd_alloc_request (dasd_eckd_discipline.name, 1 /* PSF */ + 1 /* RSSD */, (sizeof (dasd_psf_prssd_data_t) + sizeof (dasd_rssd_perf_stats_t) ), device); if (cqr == NULL) { MESSAGE (KERN_WARNING, "%s", "No memory to allocate initialization request"); return NULL; } cqr->device = device; cqr->retries = 0; cqr->expires = 10 * TOD_SEC; /* Prepare for Read Subsystem Data */ prssdp = (dasd_psf_prssd_data_t *) cqr->data; memset (prssdp, 0, sizeof (dasd_psf_prssd_data_t)); prssdp->order = PSF_ORDER_PRSSD; prssdp->suborder = 0x01; /* Perfomance Statistics */ prssdp->varies[1] = 0x01; /* Perf Statistics for the Subsystem */ ccw = cqr->cpaddr; ccw->cmd_code = DASD_ECKD_CCW_PSF; ccw->count = sizeof (dasd_psf_prssd_data_t); ccw->flags |= CCW_FLAG_CC; if ((rc = dasd_set_normalized_cda (ccw,__pa (prssdp), cqr, device))) { dasd_free_request (cqr, device); return NULL; } ccw++; /* Read Subsystem Data - Performance Statistics */ statsp = (dasd_rssd_perf_stats_t *) (prssdp + 1); memset (statsp, 0, sizeof (dasd_rssd_perf_stats_t)); ccw->cmd_code = DASD_ECKD_CCW_RSSD; ccw->count = sizeof (dasd_rssd_perf_stats_t); if ((rc = dasd_set_normalized_cda (ccw,__pa (statsp), cqr, device))) { dasd_free_request (cqr, device); return NULL; } cqr->buildclk = get_clock (); cqr->status = CQR_STATUS_FILLED; return cqr; } /* end dasd_eckd_rstat *//* * DASD_ECKD_RET_STATS * * DESCRIPTION * returns pointer to Performance Statistics Data. */dasd_rssd_perf_stats_t *dasd_eckd_ret_stats (ccw_req_t *cqr){ dasd_psf_prssd_data_t *prssdp; dasd_rssd_perf_stats_t *statsp; if (cqr == NULL) { return NULL; } /* Prepare for Read Subsystem Data */ prssdp = (dasd_psf_prssd_data_t *) cqr->data; statsp = (dasd_rssd_perf_stats_t *) (prssdp + 1); return statsp;} /* end dasd_eckd_rstat *//* * DASD_ECKD_GET_ATTRIB * * DESCRIPTION * returnes the cache attributes used in Define Extend (DE). */intdasd_eckd_get_attrib (dasd_device_t *device, attrib_data_t *attrib){ dasd_eckd_private_t *private; private = (dasd_eckd_private_t *) device->private; *attrib = private->attrib; return 0; } /* end dasd_eckd_get_attrib *//* * DASD_ECKD_SET_ATTRIB * * DESCRIPTION * stores the attributes for cache operation to be used in Define Extend (DE). */intdasd_eckd_set_attrib (dasd_device_t *device, attrib_data_t *attrib){ dasd_eckd_private_t *private; private = (dasd_eckd_private_t *) device->private; private->attrib = *attrib; DBF_DEV_EVENT (DBF_ERR, device, "cache operation mode set to " "%x (%i cylinder prestage)", private->attrib.operation, private->attrib.nr_cyl); return 0; } /* end dasd_eckd_set_attrib */static voiddasd_eckd_dump_sense (struct dasd_device_t *device, ccw_req_t *req){ char *page = (char *) get_free_page (GFP_ATOMIC); devstat_t *stat = &device->dev_status; char *sense = stat->ii.sense.data; int len, sl, sct; if (page == NULL) { MESSAGE (KERN_ERR, "%s", "No memory to dump sense data"); return; } len = sprintf (page, KERN_ERR PRINTK_HEADER "device %04X on irq %d: I/O status report:\n", device->devinfo.devno, device->devinfo.irq); len += sprintf (page + len, KERN_ERR PRINTK_HEADER "in req: %p CS: 0x%02X DS: 0x%02X\n", req, stat->cstat, stat->dstat); len += sprintf (page + len, KERN_ERR PRINTK_HEADER "Failing CCW: %p\n", (void *) (long) stat->cpa); { ccw1_t *act = req->cpaddr; int i = req->cplength; do { DBF_EVENT (DBF_INFO, "CCW %p: %08X %08X", act, ((int *) act)[0], ((int *) act)[1]); DBF_EVENT (DBF_INFO, "DAT: %08X %08X %08X %08X", ((int *) (addr_t) act->cda)[0], ((int *) (addr_t) act->cda)[1], ((int *) (addr_t) act->cda)[2], ((int *) (addr_t) act->cda)[3]); act++; } while (--i); } if (stat->flag & DEVSTAT_FLAG_SENSE_AVAIL) { for (sl = 0; sl < 4; sl++) { len += sprintf (page + len, KERN_ERR PRINTK_HEADER "Sense(hex) %2d-%2d:", (8 * sl), ((8 * sl) + 7)); for (sct = 0; sct < 8; sct++) { len += sprintf (page + len, " %02x", sense[8 * sl + sct]); } len += sprintf (page + len, "\n"); } if (sense[27] & DASD_SENSE_BIT_0) { /* 24 Byte Sense Data */ len += sprintf (page + len, KERN_ERR PRINTK_HEADER "24 Byte: %x MSG %x, %s MSGb to SYSOP\n", sense[7] >> 4, sense[7] & 0x0f, sense[1] & 0x10 ? "" : "no"); } else { /* 32 Byte Sense Data */ len += sprintf (page + len, KERN_ERR PRINTK_HEADER "32 Byte: Format: %x " "Exception class %x\n", sense[6] & 0x0f, sense[22] >> 4); } } MESSAGE_LOG (KERN_ERR, "Sense data:\n%s", page); free_page ((unsigned long) page);}dasd_discipline_t dasd_eckd_discipline = { owner: THIS_MODULE, name:"ECKD", ebcname:"ECKD", max_blocks:240, id_check:dasd_eckd_id_check, check_characteristics:dasd_eckd_check_characteristics, init_analysis:dasd_eckd_init_analysis, do_analysis:dasd_eckd_do_analysis, fill_geometry:dasd_eckd_fill_geometry, start_IO:dasd_start_IO, term_IO:dasd_term_IO, format_device:dasd_eckd_format_device, examine_error:dasd_eckd_examine_error, erp_action:dasd_eckd_erp_action, erp_postaction:dasd_eckd_erp_postaction, build_cp_from_req:dasd_eckd_build_cp_from_req, dump_sense:dasd_eckd_dump_sense, int_handler:dasd_int_handler, reserve:dasd_eckd_reserve, release:dasd_eckd_release, steal_lock:dasd_eckd_steal_lock, merge_cp:dasd_eckd_merge_cp, fill_info:dasd_eckd_fill_info, read_stats:dasd_eckd_read_stats, ret_stats:dasd_eckd_ret_stats, get_attrib:dasd_eckd_get_attrib, set_attrib:dasd_eckd_set_attrib, list:LIST_HEAD_INIT(dasd_eckd_discipline.list),};intdasd_eckd_init (void){ int rc = 0; MESSAGE (KERN_INFO, "%s discipline initializing", dasd_eckd_discipline.name); ASCEBC (dasd_eckd_discipline.ebcname, 4); dasd_discipline_add (&dasd_eckd_discipline);#ifdef CONFIG_DASD_DYNAMIC { int i; for (i = 0; i < sizeof (dasd_eckd_known_devices) / sizeof (devreg_t); i++) { MESSAGE (KERN_INFO, "We are interested in: CU %04X/%02x", dasd_eckd_known_devices[i].ci.hc.ctype, dasd_eckd_known_devices[i].ci.hc.cmode); s390_device_register (&dasd_eckd_known_devices[i]); } }#endif /* CONFIG_DASD_DYNAMIC */ return rc;}voiddasd_eckd_cleanup (void){ MESSAGE (KERN_INFO, "%s discipline cleaning up", dasd_eckd_discipline.name);#ifdef CONFIG_DASD_DYNAMIC { int i; for (i = 0; i < sizeof (dasd_eckd_known_devices) / sizeof (devreg_t); i++) { MESSAGE (KERN_INFO, "We were interested in: CU %04X/%02x", dasd_eckd_known_devices[i].ci.hc.ctype, dasd_eckd_known_devices[i].ci.hc.cmode); s390_device_unregister (&dasd_eckd_known_devices[i]); } }#endif /* CONFIG_DASD_DYNAMIC */ dasd_discipline_del (&dasd_eckd_discipline);}#ifdef MODULEintinit_module (void){ int rc = 0; rc = dasd_eckd_init (); return rc;}voidcleanup_module (void){ dasd_eckd_cleanup (); return;}#endif/* * 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 + =
减小字号Ctrl + -
显示快捷键?