dasd_eckd.c
来自「linux-2.4.29操作系统的源码」· C语言 代码 · 共 1,885 行 · 第 1/4 页
C
1,885 行
ct_data = (eckd_count_t *) last_data; last_ccw = fcp->cpaddr; switch (fdata->intensity & ~0x08) { case 0x03: if (define_extent (last_ccw, DE_data, fdata->start_unit, fdata->start_unit, DASD_ECKD_CCW_WRITE_HOME_ADDRESS, device, fcp)) { goto clear_fcp; } last_ccw->flags |= CCW_FLAG_CC; last_ccw++; if (locate_record (last_ccw, LO_data, fdata->start_unit, 0, wrccws, DASD_ECKD_CCW_WRITE_HOME_ADDRESS, device, device->sizes.bp_block, fcp)) { goto clear_fcp; } last_ccw->flags |= CCW_FLAG_CC; last_ccw++; break; case 0x01: if (define_extent (last_ccw, DE_data, fdata->start_unit, fdata->start_unit, DASD_ECKD_CCW_WRITE_RECORD_ZERO, device, fcp)) { goto clear_fcp; } last_ccw->flags |= CCW_FLAG_CC; last_ccw++; if (locate_record (last_ccw, LO_data, fdata->start_unit, 0, wrccws, DASD_ECKD_CCW_WRITE_RECORD_ZERO, device, device->sizes.bp_block, fcp)) { goto clear_fcp; } last_ccw->flags |= CCW_FLAG_CC; last_ccw++; memset (r0_data, 0, sizeof (eckd_count_t)); break; case 0x04: fdata->blksize = 8; case 0x00: if (define_extent (last_ccw, DE_data, fdata->start_unit, fdata->start_unit, DASD_ECKD_CCW_WRITE_CKD, device, fcp)) { dasd_free_request (fcp, device); return NULL; } last_ccw->flags |= CCW_FLAG_CC; last_ccw++; if (locate_record (last_ccw, LO_data, fdata->start_unit, 0, wrccws, DASD_ECKD_CCW_WRITE_CKD, device, fdata->blksize, fcp)) { goto clear_fcp; } last_ccw->flags |= CCW_FLAG_CC; last_ccw++; break; default: MESSAGE (KERN_WARNING, "Unknown format flags...%d", fdata->intensity); return NULL; } if (fdata->intensity & 0x02) { MESSAGE (KERN_WARNING, "Unsupported format flag...%d", fdata->intensity); return NULL; } if (fdata->intensity & 0x01) { /* write record zero */ r0_data->cyl = cyl; r0_data->head = head; r0_data->record = 0; r0_data->kl = 0; r0_data->dl = 8; last_ccw->cmd_code = DASD_ECKD_CCW_WRITE_RECORD_ZERO; last_ccw->count = 8; last_ccw->flags |= CCW_FLAG_CC | CCW_FLAG_SLI; if (dasd_set_normalized_cda (last_ccw, __pa (r0_data), fcp, device)) { goto clear_fcp; } last_ccw++; } if ((fdata->intensity & ~0x08) & 0x04) { /* erase track */ memset (ct_data, 0, sizeof (eckd_count_t)); ct_data->cyl = cyl; ct_data->head = head; ct_data->record = 1; ct_data->kl = 0; ct_data->dl = 0; last_ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD; last_ccw->count = 8; last_ccw->flags |= CCW_FLAG_CC | CCW_FLAG_SLI; if (dasd_set_normalized_cda (last_ccw, __pa (ct_data), fcp, device)) { goto clear_fcp; } last_ccw++; } else { /* write remaining records */ for (i = 0; i < rpt; i++) { memset (ct_data + i, 0, sizeof (eckd_count_t)); (ct_data + i)->cyl = cyl; (ct_data + i)->head = head; (ct_data + i)->record = i + 1; (ct_data + i)->kl = 0; if (fdata->intensity & 0x08) { // special handling when formatting CDL switch (fdata->start_unit) { case 0: if (i < 3) { (ct_data + i)->kl = 4; (ct_data + i)->dl = sizes_trk0[i] - 4; } else (ct_data + i)->dl = fdata->blksize; break; case 1: (ct_data + i)->kl = 44; (ct_data + i)->dl = LABEL_SIZE - 44; break; default: (ct_data + i)->dl = fdata->blksize; break; } } else (ct_data + i)->dl = fdata->blksize; last_ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD; last_ccw->flags |= CCW_FLAG_CC | CCW_FLAG_SLI; last_ccw->count = 8; if (dasd_set_normalized_cda (last_ccw, __pa (ct_data + i), fcp, device)) { goto clear_fcp; } last_ccw++; } } (last_ccw - 1)->flags &= ~(CCW_FLAG_CC | CCW_FLAG_DC); fcp->device = device; fcp->buildclk = get_clock (); fcp->status = CQR_STATUS_FILLED; } goto out; clear_fcp: dasd_free_request (fcp, device); fcp=NULL; out: return fcp;}static dasd_era_tdasd_eckd_examine_error (ccw_req_t * cqr, devstat_t * stat){ dasd_device_t *device = (dasd_device_t *) cqr->device; if (stat->cstat == 0x00 && stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END)) return dasd_era_none; switch (device->devinfo.sid_data.cu_type) { case 0x3990: case 0x2105: return dasd_3990_erp_examine (cqr, stat); case 0x9343: return dasd_9343_erp_examine (cqr, stat); default: MESSAGE (KERN_WARNING, "%s", "default (unknown CU type) - RECOVERABLE return"); return dasd_era_recover; }}static dasd_erp_action_fn_tdasd_eckd_erp_action (ccw_req_t * cqr){ dasd_device_t *device = (dasd_device_t *) cqr->device; switch (device->devinfo.sid_data.cu_type) { case 0x3990: case 0x2105: return dasd_3990_erp_action; case 0x9343: /* Return dasd_9343_erp_action; */ default: return dasd_default_erp_action; }}static dasd_erp_postaction_fn_tdasd_eckd_erp_postaction (ccw_req_t * cqr){ return dasd_default_erp_postaction;}inline unsigned chardasd_eckd_cdl_cmd (dasd_device_t * device, int recid, int cmd){ dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private; int byt_per_blk = device->sizes.bp_block; int blk_per_trk = recs_per_track (&(private->rdc_data), 0, byt_per_blk); switch (cmd) { case READ: if (recid < 3) return DASD_ECKD_CCW_READ_KD_MT; if (recid < blk_per_trk) return DASD_ECKD_CCW_READ_MT; if (recid < 2 * blk_per_trk) return DASD_ECKD_CCW_READ_KD_MT; return DASD_ECKD_CCW_READ_MT; break; case WRITE: if (recid < 3) return DASD_ECKD_CCW_WRITE_KD_MT; if (recid < blk_per_trk) return DASD_ECKD_CCW_WRITE_MT; if (recid < 2 * blk_per_trk) return DASD_ECKD_CCW_WRITE_KD_MT; return DASD_ECKD_CCW_WRITE_MT; break; default: BUG (); } return 0; // never executed}static ccw_req_t *dasd_eckd_build_cp_from_req (dasd_device_t * device, struct request *req){ ccw_req_t *rw_cp = NULL; int rw_cmd; int bhct; long size; ccw1_t *ccw; DE_eckd_data_t *DE_data; LO_eckd_data_t *LO_data; struct buffer_head *bh; dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private; int byt_per_blk = device->sizes.bp_block; int shift = device->sizes.s2b_shift; int blk_per_trk = recs_per_track (&(private->rdc_data), 0, byt_per_blk); unsigned long reloc_sector = req->sector + device->major_info->gendisk.part[MINOR(req->rq_dev)].start_sect; int btrk = (reloc_sector >> shift) / blk_per_trk; int etrk = ((reloc_sector + req->nr_sectors - 1) >> shift) / blk_per_trk; int recid = reloc_sector >> shift; int locate4k_set = 0; int nlocs = 0; int errcode; if (req->cmd == READ) { rw_cmd = DASD_ECKD_CCW_READ_MT; } else if (req->cmd == WRITE) { rw_cmd = DASD_ECKD_CCW_WRITE_MT; } else { MESSAGE (KERN_ERR, "Unknown command %d", req->cmd); return ERR_PTR(-EINVAL); } /* Build the request */ /* count bhs to prevent errors, when bh smaller than block */ bhct = 0; for (bh = req->bh; bh; bh = bh->b_reqnext) { if (bh->b_size < byt_per_blk) { MESSAGE(KERN_ERR, "ignoring bogus sized request: %d<%d", bh->b_size, byt_per_blk); return ERR_PTR(-EINVAL); } bhct+= bh->b_size >> (device->sizes.s2b_shift+9); } if (btrk < 2 && private->uses_cdl) { if (etrk < 2) nlocs = bhct; else nlocs = 2 * blk_per_trk - recid; } rw_cp = dasd_alloc_request (dasd_eckd_discipline.name, 2 + nlocs + bhct + 1, sizeof (DE_eckd_data_t) + (1 + nlocs) * sizeof (LO_eckd_data_t), device); if (!rw_cp) { return ERR_PTR(-ENOMEM); } DE_data = rw_cp->data; LO_data = rw_cp->data + sizeof (DE_eckd_data_t); ccw = rw_cp->cpaddr; if ((errcode = define_extent (ccw, DE_data, btrk, etrk, rw_cmd, device, rw_cp))) { goto clear_rw_cp; } ccw->flags |= CCW_FLAG_CC; for (bh = req->bh; bh != NULL;) { for (size = 0; size < bh->b_size; size += byt_per_blk) { if (!locate4k_set) { // we need to chain a locate record before our rw-ccw ccw++; if ((recid / blk_per_trk) < 2 && private->uses_cdl) { /* Do a locate record for our special blocks */ int cmd = dasd_eckd_cdl_cmd (device,recid, req->cmd); if ((errcode = locate_record (ccw, LO_data++, recid / blk_per_trk, recid % blk_per_trk + 1, 1, cmd, device, dasd_eckd_cdl_reclen(device, recid), rw_cp))) { goto clear_rw_cp; } } else { // Do a locate record for standard blocks */ if ((errcode = locate_record (ccw, LO_data++, recid /blk_per_trk, recid %blk_per_trk + 1, (((reloc_sector + req->nr_sectors) >> shift) - recid), rw_cmd, device, device->sizes.bp_block, rw_cp))) { goto clear_rw_cp; } locate4k_set = 1; } ccw->flags |= CCW_FLAG_CC; } ccw++; ccw->flags |= CCW_FLAG_CC; ccw->cmd_code = locate4k_set ? rw_cmd : dasd_eckd_cdl_cmd (device, recid, req->cmd); ccw->count = byt_per_blk; if (!locate4k_set) { ccw->count = dasd_eckd_cdl_reclen (device,recid); if (ccw->count < byt_per_blk) { memset (bh->b_data + size + ccw->count, 0xE5, byt_per_blk - ccw->count); } } if ((errcode = dasd_set_normalized_cda (ccw, __pa (bh->b_data+size), rw_cp, device))) { goto clear_rw_cp; } recid++; } bh = bh->b_reqnext; } ccw->flags &= ~(CCW_FLAG_DC | CCW_FLAG_CC); rw_cp->device = device; rw_cp->expires = 5 * TOD_MIN; /* 5 minutes */ rw_cp->req = req; rw_cp->lpm = LPM_ANYPATH; rw_cp->retries = 256; rw_cp->buildclk = get_clock (); check_then_set (&rw_cp->status, CQR_STATUS_EMPTY, CQR_STATUS_FILLED); goto out; clear_rw_cp: dasd_free_request (rw_cp, device); rw_cp=ERR_PTR(errcode); out: return rw_cp;}#if 0intdasd_eckd_cleanup_request (ccw_req_t * cqr){ int ret = 0; struct request *req = cqr->req; dasd_device_t *device = cqr->device; int byt_per_blk = device->sizes.bp_block; for (bh = req->bh; bh != NULL;) { if (bh->b_size > byt_per_blk) { for (size = 0; size < bh->b_size; size += byt_per_blk) { ccw++; ccw->flags |= CCW_FLAG_CC; ccw->cmd_code = rw_cmd; ccw->count = byt_per_blk; set_normalized_cda (ccw, __pa (bh->b_data + size)); } bh = bh->b_reqnext; } else { /* group N bhs to fit into byt_per_blk */ for (size = 0; bh != NULL && size < byt_per_blk;) { ccw++; ccw->flags |= CCW_FLAG_DC; ccw->cmd_code = rw_cmd; ccw->count = bh->b_size; set_normalized_cda (ccw, __pa (bh->b_data)); size += bh->b_size; bh = bh->b_reqnext; } } } return ret;}#endif/* * DASD_ECKD_RESERVE * * DESCRIPTION * Buils a channel programm to reserve a device. * Options are set to 'synchronous wait for interrupt' and * 'timeout the request'. This leads to an terminate IO if * the interrupt is outstanding for a certain time. */ccw_req_t *dasd_eckd_reserve (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_RESERVE; 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_RELEASE * * DESCRIPTION * Buils a channel programm to releases a prior reserved * (see dasd_eckd_reserve) device. */ccw_req_t *dasd_eckd_release (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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?