📄 dasd_eckd.c
字号:
/* * File...........: linux/drivers/s390/block/dasd_eckd.c * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 */#include <linux/stddef.h>#include <linux/kernel.h>#ifdef MODULE#include <linux/module.h>#endif /* MODULE */#include <linux/malloc.h>#include <linux/dasd.h>#include <asm/io.h>#include <asm/irq.h>#include "dasd_types.h"#include "dasd_ccwstuff.h"#ifdef PRINTK_HEADER#undef PRINTK_HEADER#endif /* PRINTK_HEADER */#define PRINTK_HEADER "dasd(eckd):"#define ECKD_C0(i) (i->home_bytes)#define ECKD_F(i) (i -> formula)#define ECKD_F1(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f1):(i->factors.f_0x02.f1))#define ECKD_F2(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f2):(i->factors.f_0x02.f2))#define ECKD_F3(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f3):(i->factors.f_0x02.f3))#define ECKD_F4(i) (ECKD_F(i)==0x02?(i->factors.f_0x02.f4):0)#define ECKD_F5(i) (ECKD_F(i)==0x02?(i->factors.f_0x02.f5):0)#define ECKD_F6(i) (i -> factor6)#define ECKD_F7(i) (i -> factor7)#define ECKD_F8(i) (i -> factor8)#define DASD_ECKD_CCW_LOCATE_RECORD 0x47#define DASD_ECKD_CCW_READ_HOME_ADDRESS 0x0a#define DASD_ECKD_CCW_WRITE_HOME_ADDRESS 0x09#define DASD_ECKD_CCW_READ_RECORD_ZERO 0x16#define DASD_ECKD_CCW_WRITE_RECORD_ZERO 0x15#define DASD_ECKD_CCW_READ_COUNT 0x12#define DASD_ECKD_CCW_READ 0x06#define DASD_ECKD_CCW_READ_MT 0x86#define DASD_ECKD_CCW_WRITE 0x05#define DASD_ECKD_CCW_WRITE_MT 0x85#define DASD_ECKD_CCW_READ_CKD 0x1e#define DASD_ECKD_CCW_READ_CKD_MT 0x9e#define DASD_ECKD_CCW_WRITE_CKD 0x1d#define DASD_ECKD_CCW_WRITE_CKD_MT 0x9dtypedefstruct { __u16 cyl; __u16 head;} __attribute__ ((packed))ch_t;typedefstruct { __u16 cyl; __u16 head; __u32 sector;} __attribute__ ((packed))chs_t;typedefstruct { __u16 cyl; __u16 head; __u8 record;} __attribute__ ((packed))chr_t;typedefstruct { __u16 cyl; __u16 head; __u32 sector;} geom_t;typedef struct { struct { struct { unsigned char identifier:2; unsigned char token_id:1; unsigned char sno_valid:1; unsigned char subst_sno:1; unsigned char recNED:1; unsigned char emuNED:1; unsigned char reserved:1; } __attribute__ ((packed)) flags; __u8 descriptor; __u8 dev_class; __u8 reserved; unsigned char dev_type[6]; unsigned char dev_model[3]; unsigned char HDA_manufacturer[3]; unsigned char HDA_location[2]; unsigned char HDA_seqno[12]; __u16 ID; } __attribute__ ((packed)) ned1; struct { struct { unsigned char identifier:2; unsigned char token_id:1; unsigned char sno_valid:1; unsigned char subst_sno:1; unsigned char recNED:1; unsigned char emuNED:1; unsigned char reserved:1; } __attribute__ ((packed)) flags; __u8 descriptor; __u8 reserved[2]; unsigned char dev_type[6]; unsigned char dev_model[3]; unsigned char DASD_manufacturer[3]; unsigned char DASD_location[2]; unsigned char DASD_seqno[12]; __u16 ID; } __attribute__ ((packed)) ned2; struct { struct { unsigned char identifier:2; unsigned char token_id:1; unsigned char sno_valid:1; unsigned char subst_sno:1; unsigned char recNED:1; unsigned char emuNED:1; unsigned char reserved:1; } __attribute__ ((packed)) flags; __u8 descriptor; __u8 reserved[2]; unsigned char cont_type[6]; unsigned char cont_model[3]; unsigned char cont_manufacturer[3]; unsigned char cont_location[2]; unsigned char cont_seqno[12]; __u16 ID; } __attribute__ ((packed)) ned3; struct { struct { unsigned char identifier:2; unsigned char token_id:1; unsigned char sno_valid:1; unsigned char subst_sno:1; unsigned char recNED:1; unsigned char emuNED:1; unsigned char reserved:1; } __attribute__ ((packed)) flags; __u8 descriptor; __u8 reserved[2]; unsigned char cont_type[6]; unsigned char empty[3]; unsigned char cont_manufacturer[3]; unsigned char cont_location[2]; unsigned char cont_seqno[12]; __u16 ID; } __attribute__ ((packed)) ned4; unsigned char ned5[32]; unsigned char ned6[32]; unsigned char ned7[32]; struct { struct { unsigned char identifier:2; unsigned char reserved:6; } __attribute__ ((packed)) flags; __u8 selector; __u16 interfaceID; __u32 reserved; __u16 subsystemID; struct { unsigned char sp0:1; unsigned char sp1:1; unsigned char reserved:5; unsigned char scluster:1; } __attribute__ ((packed)) spathID; __u8 unit_address; __u8 dev_ID; __u8 dev_address; __u8 adapterID; __u16 link_address; struct { unsigned char parallel:1; unsigned char escon:1; unsigned char reserved:1; unsigned char ficon:1; unsigned char reserved2:4; } __attribute__ ((packed)) protocol_type; struct { unsigned char PID_in_236:1; unsigned char reserved:7; } __attribute__ ((packed)) format_flags; __u8 log_dev_address; unsigned char reserved2[12]; } __attribute__ ((packed)) neq;} __attribute__ ((packed))eckd_confdata_t;typedefstruct { struct { unsigned char perm:2; /* Permissions on this extent */ unsigned char reserved:1; unsigned char seek:2; /* Seek control */ unsigned char auth:2; /* Access authorization */ unsigned char pci:1; /* PCI Fetch mode */ } __attribute__ ((packed)) mask; struct { unsigned char mode:2; /* Architecture mode */ unsigned char ckd:1; /* CKD Conversion */ unsigned char operation:3; /* Operation mode */ unsigned char cfw:1; /* Cache fast write */ unsigned char dfw:1; /* DASD fast write */ } __attribute__ ((packed)) attributes; __u16 short blk_size; /* Blocksize */ __u16 fast_write_id; __u8 unused; __u8 reserved; ch_t beg_ext; ch_t end_ext;} __attribute__ ((packed, aligned (32)))DE_eckd_data_t;typedefstruct { struct { unsigned char orientation:2; unsigned char operation:6; } __attribute__ ((packed)) operation; struct { unsigned char last_bytes_used:1; unsigned char reserved:6; unsigned char read_count_suffix:1; } __attribute__ ((packed)) auxiliary; __u8 unused; __u8 count; ch_t seek_addr; chr_t search_arg; __u8 sector; __u16 length;} __attribute__ ((packed, aligned (32)))LO_eckd_data_t;/* Stuff for handling home addresses */typedef struct { __u8 skip_control[14]; __u16 cell_number; __u8 physical_addr[3]; __u8 flag; ch_t track_addr; __u8 reserved; __u8 key_length; __u8 reserved2[2];} __attribute__ ((packed, aligned (32)))eckd_home_t;static unsigned intround_up_multiple (unsigned int no, unsigned int mult){ int rem = no % mult; return (rem ? no - rem + mult : no);/* return (no % mult ? no - (no % mult) + mult : no); */}static unsigned intceil_quot (unsigned int d1, unsigned int d2){ return (d1 + (d2 - 1)) / d2;}static intbytes_per_record (dasd_eckd_characteristics_t * rdc, int kl, /* key length */ int dl /* data length */ ){ int bpr = 0; switch (rdc->formula) { case 0x01:{ unsigned int fl1, fl2; fl1 = round_up_multiple (ECKD_F2 (rdc) + dl, ECKD_F1 (rdc)); fl2 = round_up_multiple (kl ? ECKD_F2 (rdc) + kl : 0, ECKD_F1 (rdc)); bpr = fl1 + fl2; break; } case 0x02:{ unsigned int fl1, fl2, int1, int2; int1 = ceil_quot (dl + ECKD_F6 (rdc), ECKD_F5 (rdc) << 1); int2 = ceil_quot (kl + ECKD_F6 (rdc), ECKD_F5 (rdc) << 1); fl1 = round_up_multiple (ECKD_F1 (rdc) * ECKD_F2 (rdc) + (dl + ECKD_F6 (rdc) + ECKD_F4 (rdc) * int1), ECKD_F1 (rdc)); fl2 = round_up_multiple (ECKD_F1 (rdc) * ECKD_F3 (rdc) + (kl + ECKD_F6 (rdc) + ECKD_F4 (rdc) * int2), ECKD_F1 (rdc)); bpr = fl1 + fl2; break; } default: INTERNAL_ERROR ("unknown formula%d\n", rdc->formula); } return bpr;}static inline unsigned intbytes_per_track (dasd_eckd_characteristics_t * rdc){ return *(unsigned int *) (rdc->byte_per_track) >> 8;}static unsigned intrecs_per_track (dasd_eckd_characteristics_t * rdc, unsigned int kl, unsigned int dl){ int rpt = 0; int dn; switch ( rdc -> dev_type ) { case 0x3380: if (kl) return 1499 / (15 + 7 + ceil_quot (kl + 12, 32) + ceil_quot (dl + 12, 32)); else return 1499 / (15 + ceil_quot (dl + 12, 32)); case 0x3390: dn = ceil_quot (dl + 6, 232) + 1; if (kl) { int kn = ceil_quot (kl + 6, 232) + 1; return 1729 / (10 + 9 + ceil_quot (kl + 6 * kn, 34) + 9 + ceil_quot (dl + 6 * dn, 34)); } else return 1729 / (10 + 9 + ceil_quot (dl + 6 * dn, 34)); case 0x9345: dn = ceil_quot (dl + 6, 232) + 1; if (kl) { int kn = ceil_quot (kl + 6, 232) + 1; return 1420 / (18 + 7 + ceil_quot (kl + 6 * kn, 34) + ceil_quot (dl + 6 * dn, 34)); } else return 1420 / (18 + 7 + ceil_quot (dl + 6 * dn, 34)); } return rpt;}staticvoiddefine_extent (ccw1_t * de_ccw, DE_eckd_data_t * data, int trk, int totrk, int cmd, dasd_information_t * info){ ch_t geo, beg, end; geo.cyl = info->rdc_data->eckd.no_cyl; geo.head = info->rdc_data->eckd.trk_per_cyl; beg.cyl = trk / geo.head; beg.head = trk % geo.head; end.cyl = totrk / geo.head; end.head = totrk % geo.head; memset (de_ccw, 0, sizeof (ccw1_t)); de_ccw->cmd_code = CCW_DEFINE_EXTENT; de_ccw->count = 16; de_ccw->cda = (void *) virt_to_phys (data); memset (data, 0, sizeof (DE_eckd_data_t)); switch (cmd) { case DASD_ECKD_CCW_READ_HOME_ADDRESS: case DASD_ECKD_CCW_READ_RECORD_ZERO: case DASD_ECKD_CCW_READ: case DASD_ECKD_CCW_READ_MT: case DASD_ECKD_CCW_READ_CKD: /* Fallthrough */ case DASD_ECKD_CCW_READ_CKD_MT: case DASD_ECKD_CCW_READ_COUNT: data->mask.perm = 0x1; data->attributes.operation = 0x3; /* enable seq. caching */ break; case DASD_ECKD_CCW_WRITE: case DASD_ECKD_CCW_WRITE_MT: data->attributes.operation = 0x3; /* enable seq. caching */ break; case DASD_ECKD_CCW_WRITE_CKD: case DASD_ECKD_CCW_WRITE_CKD_MT: data->attributes.operation = 0x1; /* format through cache */ break; case DASD_ECKD_CCW_WRITE_HOME_ADDRESS: case DASD_ECKD_CCW_WRITE_RECORD_ZERO: data->mask.perm = 0x3; data->mask.auth = 0x1; data->attributes.operation = 0x1; /* format through cache */ break; default: INTERNAL_ERROR ("unknown opcode 0x%x\n", cmd); break; } data->attributes.mode = 0x3; data->beg_ext.cyl = beg.cyl; data->beg_ext.head = beg.head; data->end_ext.cyl = end.cyl; data->end_ext.head = end.head;}static inline voidlocate_record (ccw1_t * lo_ccw, LO_eckd_data_t * data, int trk, int rec_on_trk, int no_rec, int cmd, dasd_information_t * info){ ch_t geo = {info->rdc_data->eckd.no_cyl, info->rdc_data->eckd.trk_per_cyl}; ch_t seek = {trk / (geo.head), trk % (geo.head)}; int reclen = info->sizes.bp_block; memset (lo_ccw, 0, sizeof (ccw1_t)); lo_ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD; lo_ccw->count = 16; lo_ccw->cda = (void *) virt_to_phys (data); memset (data, 0, sizeof (LO_eckd_data_t)); switch (cmd) { case DASD_ECKD_CCW_WRITE_HOME_ADDRESS: data->operation.orientation = 0x3; data->operation.operation = 0x03; break; case DASD_ECKD_CCW_READ_HOME_ADDRESS: data->operation.orientation = 0x3; data->operation.operation = 0x16; break; case DASD_ECKD_CCW_WRITE_RECORD_ZERO: data->operation.orientation = 0x3; data->operation.operation = 0x03; data->count++; break; case DASD_ECKD_CCW_READ_RECORD_ZERO: data->operation.orientation = 0x3; data->operation.operation = 0x16; data->count++; break; case DASD_ECKD_CCW_WRITE: case DASD_ECKD_CCW_WRITE_MT: data->auxiliary.last_bytes_used = 0x1; data->length = reclen; data->operation.operation = 0x01; break; case DASD_ECKD_CCW_WRITE_CKD: case DASD_ECKD_CCW_WRITE_CKD_MT: data->auxiliary.last_bytes_used = 0x1; data->length = reclen; data->operation.operation = 0x03; break; case DASD_ECKD_CCW_READ: case DASD_ECKD_CCW_READ_MT: data->auxiliary.last_bytes_used = 0x1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -