📄 dasd_eckd.c
字号:
data->length = reclen; data->operation.operation = 0x06; break; case DASD_ECKD_CCW_READ_CKD: case DASD_ECKD_CCW_READ_CKD_MT: data->auxiliary.last_bytes_used = 0x1; data->length = reclen; data->operation.operation = 0x16; break; case DASD_ECKD_CCW_READ_COUNT: data->operation.operation = 0x06; break; default: INTERNAL_ERROR ("unknown opcode 0x%x\n", cmd); } memcpy (&(data->seek_addr), &seek, sizeof (ch_t)); memcpy (&(data->search_arg), &seek, sizeof (ch_t)); data->search_arg.record = rec_on_trk; data->count += no_rec;}voiddasd_eckd_print_error (devstat_t * stat){ int sct, sl; char *sense = stat->ii.sense.data; PRINT_WARN ("IRQ on devno %x: with intparm:%x DS:0x%02x CS:0x%02x\n", stat->devno, stat->intparm, stat->dstat, stat->cstat); PRINT_WARN ("Failing CCW: %p\n", (ccw1_t *) stat->cpa); for (sl = 0; sl < 4; sl++) { PRINT_DEBUG ("Sense:"); for (sct = 0; sct < 8; sct++) { printk (" %2d:0x%02x", 8 * sl + sct, sense[8 * sl + sct]); } printk ("\n"); } if (sense[27] & 0x80) { /* 32 Byte Sense Data */ PRINT_INFO ("Sense Data is 32 Byte information\n"); PRINT_INFO ("Format: %x Exception class %x\n", sense[6] & 0x0f, sense[22] >> 4); } else { /* 24 Byte Sense Data */ PRINT_INFO ("Sense Data is 24 Byte information\n"); PRINT_INFO ("FMT: %x MSG %x, %s MSGb to SYSOP\n", sense[7] >> 4, sense[7] & 0x0f, sense[1] & 0x10 ? "" : "no"); }}intdasd_eckd_format_track (int di, int trk, int bs){ int rc = 0; int i; int flags = 0x00; /* FORMAT_R0 = 0x01, FORMAT_HA = 0x03 */ dasd_information_t * info=dasd_info[di]; cqr_t *fcp; DE_eckd_data_t *DE_data; LO_eckd_data_t *LO_data; eckd_count_t *ct_data; eckd_count_t *r0_data; ccw1_t *last_ccw; int retries = 5; int rpt = recs_per_track (&(info->rdc_data->eckd), 0, bs); int cyl = trk / info->rdc_data->eckd.trk_per_cyl; int head = trk % info->rdc_data->eckd.trk_per_cyl; fcp = request_cqr (2 + 1 + rpt, sizeof (DE_eckd_data_t) + sizeof (LO_eckd_data_t) + (rpt + 1) * sizeof (eckd_count_t)); fcp -> devindex=di; DE_data = (DE_eckd_data_t *) fcp->data; LO_data = (LO_eckd_data_t *) (((long) DE_data) + sizeof (DE_eckd_data_t)); r0_data = (eckd_count_t *) (((long) LO_data) + sizeof (LO_eckd_data_t)); ct_data = (eckd_count_t *) (((long) r0_data) + sizeof (eckd_count_t)); last_ccw = fcp->cpaddr; switch (flags) { case 0x03: define_extent (last_ccw, DE_data, trk, trk, DASD_ECKD_CCW_WRITE_HOME_ADDRESS, info); last_ccw->flags = CCW_FLAG_CC; last_ccw++; locate_record (last_ccw, LO_data, trk, 0, rpt, DASD_ECKD_CCW_WRITE_HOME_ADDRESS, info); last_ccw->flags = CCW_FLAG_CC; last_ccw++; break; case 0x01: define_extent (last_ccw, DE_data, trk, trk, DASD_ECKD_CCW_WRITE_RECORD_ZERO, info); last_ccw->flags = CCW_FLAG_CC; last_ccw++; locate_record (last_ccw, LO_data, trk, 0, rpt, DASD_ECKD_CCW_WRITE_RECORD_ZERO, info); last_ccw->flags = CCW_FLAG_CC; last_ccw++; break; case 0x00: define_extent (last_ccw, DE_data, trk, trk, DASD_ECKD_CCW_WRITE_CKD, info); last_ccw->flags = CCW_FLAG_CC; last_ccw++; locate_record (last_ccw, LO_data, trk, 0, rpt, DASD_ECKD_CCW_WRITE_CKD, info); LO_data->length = bs; last_ccw->flags = CCW_FLAG_CC; last_ccw++; break; default: PRINT_WARN ("Unknown format flags...%d\n", flags); return -EINVAL; } if (flags & 0x02) { PRINT_WARN ("Unsupported format flag...%d\n", flags); return -EINVAL; } if (flags & 0x01) { /* write record zero */ memset (r0_data, 0, sizeof (eckd_count_t)); r0_data->cyl = cyl; r0_data->head = head; r0_data->record = 0; r0_data->kl = 0; r0_data->dl = 8; last_ccw->cmd_code = 0x03; last_ccw->count = 8; last_ccw->flags = CCW_FLAG_CC | CCW_FLAG_SLI; last_ccw->cda = (void *) virt_to_phys (r0_data); last_ccw++; } /* write remaining records */ for (i = 0; i < rpt; i++, last_ccw++) { 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; (ct_data + i)->dl = bs; last_ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD; last_ccw->flags = CCW_FLAG_CC | CCW_FLAG_SLI; last_ccw->count = 8; last_ccw->cda = (void *) virt_to_phys (ct_data + i); } (last_ccw - 1)->flags &= ~(CCW_FLAG_CC | CCW_FLAG_DC); fcp -> devindex = di; fcp -> flags = DASD_DO_IO_SLEEP; do { DECLARE_WAITQUEUE(wait, current); unsigned long flags; int irq; int cs; irq = dasd_info[fcp->devindex]->info.irq; s390irq_spin_lock_irqsave (irq, flags); atomic_set(&fcp->status,CQR_STATUS_QUEUED); rc = dasd_start_IO ( fcp ); add_wait_queue (&dasd_waitq, &wait); do { current->state = TASK_UNINTERRUPTIBLE; s390irq_spin_unlock_irqrestore (irq, flags); schedule (); s390irq_spin_lock_irqsave (irq, flags); } while (((cs = atomic_read (&fcp->status)) != CQR_STATUS_DONE) && (cs != CQR_STATUS_ERROR)); remove_wait_queue (&dasd_waitq, &wait); s390irq_spin_unlock_irqrestore (irq, flags); retries --; } while ( (rc || (atomic_read(&fcp->status) != CQR_STATUS_DONE)) && retries); if ((rc || (atomic_read(&fcp->status) != CQR_STATUS_DONE))) rc = -EIO; release_cqr (fcp); return rc;}intdasd_eckd_ck_devinfo (dev_info_t * info){ return 0;}cqr_t *dasd_eckd_build_req (int devindex, struct request * req){ cqr_t *rw_cp = NULL; ccw1_t *ccw; DE_eckd_data_t *DE_data; LO_eckd_data_t *LO_data; struct buffer_head *bh; int rw_cmd; dasd_information_t *info = dasd_info[devindex]; int blk_per_trk = recs_per_track (&(info->rdc_data->eckd), 0, info->sizes.bp_block); int byt_per_blk = info->sizes.bp_block; int noblk = req-> nr_sectors >> info->sizes.s2b_shift; int btrk = (req->sector >> info->sizes.s2b_shift) / blk_per_trk; int etrk = ((req->sector + req->nr_sectors - 1) >> info->sizes.s2b_shift) / blk_per_trk; if ( ! noblk ) { PRINT_ERR("No blocks to write...returning\n"); return NULL; } if (req->cmd == READ) { rw_cmd = DASD_ECKD_CCW_READ_MT; } else#if DASD_PARANOIA > 2 if (req->cmd == WRITE)#endif /* DASD_PARANOIA */ { rw_cmd = DASD_ECKD_CCW_WRITE_MT; }#if DASD_PARANOIA > 2 else { PRINT_ERR ("Unknown command %d\n", req->cmd); return NULL; }#endif /* DASD_PARANOIA */ /* Build the request */ rw_cp = request_cqr (2 + noblk, sizeof (DE_eckd_data_t) + sizeof (LO_eckd_data_t)); if ( ! rw_cp ) { return NULL; } DE_data = rw_cp->data; LO_data = rw_cp->data + sizeof (DE_eckd_data_t); ccw = rw_cp->cpaddr; define_extent (ccw, DE_data, btrk, etrk, rw_cmd, info); ccw->flags = CCW_FLAG_CC; ccw++; locate_record (ccw, LO_data, btrk, (req->sector >> info->sizes.s2b_shift) % blk_per_trk + 1, req->nr_sectors >> info->sizes.s2b_shift, rw_cmd, info); ccw->flags = CCW_FLAG_CC; for (bh = req->bh; bh; bh = bh->b_reqnext) { long size; 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; ccw->cda = (void *) virt_to_phys (bh->b_data + size); } } ccw->flags &= ~(CCW_FLAG_DC | CCW_FLAG_CC); return rw_cp;}cqr_t *dasd_eckd_rw_label (int devindex, int rw, char *buffer){ int cmd_code = 0x03; dasd_information_t *info = dasd_info[devindex]; cqr_t *cqr; ccw1_t *ccw; switch (rw) { case READ: cmd_code = DASD_ECKD_CCW_READ; break; case WRITE: cmd_code = DASD_ECKD_CCW_WRITE; break;#if DASD_PARANOIA > 2 default: INTERNAL_ERROR ("unknown cmd %d", rw); return NULL;#endif /* DASD_PARANOIA */ } cqr = request_cqr (3, sizeof (DE_eckd_data_t) + sizeof (LO_eckd_data_t)); ccw = cqr->cpaddr; define_extent (ccw, cqr->data, 0, 0, cmd_code, info); ccw->flags |= CCW_FLAG_CC; ccw++; locate_record (ccw, cqr->data + 1, 0, 2, 1, cmd_code, info); ccw->flags |= CCW_FLAG_CC; ccw++; ccw->cmd_code = cmd_code; ccw->flags |= CCW_FLAG_SLI; ccw->count = sizeof (dasd_volume_label_t); ccw->cda = (void *) virt_to_phys ((void *) buffer); return cqr;}voiddasd_eckd_print_char (dasd_characteristics_t * i){ dasd_eckd_characteristics_t * c = (dasd_eckd_characteristics_t *)i; PRINT_INFO ("%x/%x (%x/%x) Cyl: %d Head: %d Sec: %d \n", c->dev_type, c->dev_model, c->cu_type, c->cu_model.model, c->no_cyl, c->trk_per_cyl, c->sec_per_trk); PRINT_INFO ("Estimate: %d Byte/trk %d byte/kByte %d kByte/trk \n", bytes_per_track (c), bytes_per_record (c, 0, 1024), recs_per_track (c, 0, 1024));};intdasd_eckd_ck_char (dasd_characteristics_t * i){ int rc = 0; dasd_eckd_print_char (i); return rc;}intdasd_eckd_format (int devindex, format_data_t * fdata){ int rc = 0; int i; dasd_information_t *info = dasd_info[devindex]; format_data_t fd; if (!fdata) { fd.start_unit = 0; fd.stop_unit = info->rdc_data->eckd.no_cyl * info->rdc_data->eckd.trk_per_cyl - 1; fd.blksize = 4096; } else { memcpy (&fd, fdata, sizeof (format_data_t)); if ( fd.stop_unit == -1 ) { fd.stop_unit = info->rdc_data->eckd.no_cyl * info->rdc_data->eckd.trk_per_cyl - 1; } if ( fd.blksize == 0 ) { fd.blksize = 4096; } } PRINT_INFO("Formatting device %d from %d to %d with bs %d\n", devindex,fd.start_unit,fd.stop_unit,fd.blksize); if ( fd.start_unit > fd.stop_unit ) { PRINT_WARN ("start unit .gt. stop unit\n"); return -EINVAL; } if ( (fd.start_unit > info->rdc_data->eckd.no_cyl * info->rdc_data->eckd.trk_per_cyl - 1) ) { PRINT_WARN ("start unit beyond end of disk\n"); return -EINVAL; } if ( (fd.stop_unit > info->rdc_data->eckd.no_cyl * info->rdc_data->eckd.trk_per_cyl - 1) ) { PRINT_WARN ("stop unit beyond end of disk\n"); return -EINVAL; } switch (fd.blksize) { case 512: case 1024: case 2048: case 4096: break; default: PRINT_WARN ("invalid blocksize\n"); return -EINVAL; } for (i = fd.start_unit; i <= fd.stop_unit; i++) { /* print 20 messages per disk at all */ if ( ! ( i % (info->rdc_data->eckd.trk_per_cyl * (info->rdc_data->eckd.no_cyl / 20 ) ))) { PRINT_INFO ("Format %d Cylinder: %d\n",devindex, i/info->rdc_data->eckd.trk_per_cyl); } rc = dasd_eckd_format_track (devindex, i, fd.blksize); if (rc) { PRINT_WARN ("Formatting of Track %d failed...exiting\n", i); break; } } PRINT_INFO("Formated device %d from %d to %d with bs %d\n", devindex,fd.start_unit,fd.stop_unit,fd.blksize); return rc;}cqr_t *dasd_eckd_fill_sizes_first (int di){ cqr_t *rw_cp = NULL; ccw1_t *ccw; DE_eckd_data_t *DE_data; LO_eckd_data_t *LO_data; dasd_information_t *info = dasd_info[di]; eckd_count_t *count_data= &(info->private.eckd.count_data); rw_cp = request_cqr (3, sizeof (DE_eckd_data_t) + sizeof (LO_eckd_data_t)); DE_data = rw_cp->data; LO_data = rw_cp->data + sizeof (DE_eckd_data_t); ccw = rw_cp->cpaddr; define_extent (ccw, DE_data, 0, 0, DASD_ECKD_CCW_READ_COUNT, info); ccw->flags = CCW_FLAG_CC; ccw++; locate_record (ccw, LO_data, 0, 1, 1, DASD_ECKD_CCW_READ_COUNT, info); ccw->flags = CCW_FLAG_CC; ccw++; ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT; ccw->count = 8; ccw->cda = (void *) __pa (count_data); rw_cp->devindex = di; atomic_set(&rw_cp->status,CQR_STATUS_FILLED); return rw_cp;}int dasd_eckd_fill_sizes_last (int devindex) { int sb; dasd_information_t *in = dasd_info[devindex]; int bs = in->private.eckd.count_data.dl; if (bs <= 0) { PRINT_INFO("Cannot figure out blocksize. did you format the disk?\n"); memset (&(in -> sizes), 0, sizeof(dasd_sizes_t )); return -EMEDIUMTYPE; } else { in->sizes.bp_block = bs; } in->sizes.bp_sector = in->sizes.bp_block; in->sizes.b2k_shift = 0; /* bits to shift a block to get 1k */ for (sb = 1024; sb < bs; sb = sb << 1) in->sizes.b2k_shift++; in->sizes.s2b_shift = 0; /* bits to shift 512 to get a block */ for (sb = 512; sb < bs; sb = sb << 1) in->sizes.s2b_shift++; in->sizes.blocks = in->rdc_data->eckd.no_cyl * in->rdc_data->eckd.trk_per_cyl * recs_per_track (&(in->rdc_data->eckd), 0, bs); in->sizes.kbytes = in->sizes.blocks << in->sizes.b2k_shift; PRINT_INFO ("Verified: %d B/trk %d B/Blk(%d B) %d Blks/trk %d kB/trk \n", bytes_per_track (&(in->rdc_data->eckd)), bytes_per_record (&(in->rdc_data->eckd), 0, in->sizes.bp_block), in->sizes.bp_block, recs_per_track (&(in->rdc_data->eckd), 0, in->sizes.bp_block), (recs_per_track (&(in->rdc_data->eckd), 0, in->sizes.bp_block) << in->sizes.b2k_shift )); return 0;}dasd_operations_t dasd_eckd_operations ={ ck_devinfo: dasd_eckd_ck_devinfo, get_req_ccw: dasd_eckd_build_req, rw_label: dasd_eckd_rw_label, ck_characteristics: dasd_eckd_ck_char, fill_sizes_first: dasd_eckd_fill_sizes_first, fill_sizes_last: dasd_eckd_fill_sizes_last, dasd_format: dasd_eckd_format,};/* * 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 + -