7 #define KMSG_COMPONENT "dasd-fba"
9 #include <linux/stddef.h>
10 #include <linux/kernel.h>
11 #include <asm/debug.h>
13 #include <linux/slab.h>
16 #include <linux/module.h>
30 #define PRINTK_HEADER "dasd(fba):"
32 #define DASD_FBA_CCW_WRITE 0x41
33 #define DASD_FBA_CCW_READ 0x42
34 #define DASD_FBA_CCW_LOCATE 0x43
35 #define DASD_FBA_CCW_DEFINE_EXTENT 0x63
72 .probe = dasd_fba_probe,
75 .set_online = dasd_fba_set_online,
86 int blksize,
int beg,
int nr)
94 (data->mask).
perm = 0x0;
96 (data->mask).
perm = 0x1;
98 data->mask.
perm = 0x2;
106 int block_nr,
int block_ct)
114 data->operation.
cmd = 0x5;
116 data->operation.
cmd = 0x6;
118 data->operation.
cmd = 0x8;
137 "Allocating memory for private DASD "
141 device->
private = (
void *)
private;
143 memset(
private, 0,
sizeof(*
private));
148 "dasd block structure");
151 return PTR_ERR(block);
154 block->
base = device;
158 &private->rdc_data, 32);
161 "characteristics returned error %d", rc);
177 "New FBA DASD %04X/%02X (CU %04X/%02X) with %d MB "
183 ((private->rdc_data.blk_bdsa *
184 (private->rdc_data.blk_size >> 9)) >> 11),
185 private->rdc_data.blk_size,
186 readonly ?
", read-only device" :
"");
190 static int dasd_fba_do_analysis(
struct dasd_block *block)
196 rc = dasd_check_blocksize(private->rdc_data.blk_size);
199 private->rdc_data.blk_size);
202 block->
blocks =
private->rdc_data.blk_bdsa;
203 block->
bp_block =
private->rdc_data.blk_size;
205 for (sb = 512; sb <
private->rdc_data.blk_size; sb = sb << 1)
210 static int dasd_fba_fill_geometry(
struct dasd_block *block,
213 if (dasd_check_blocksize(block->
bp_block) != 0)
238 static void dasd_fba_check_for_device_change(
struct dasd_device *device,
246 if ((irb->
scsw.
cmd.dstat & mask) == mask)
255 unsigned long *idaws;
259 struct req_iterator iter;
262 int count, cidaw, cplength, datasize;
263 sector_t recid, first_rec, last_rec;
264 unsigned int blksize, off;
268 if (rq_data_dir(req) ==
READ) {
270 }
else if (rq_data_dir(req) ==
WRITE) {
276 first_rec = blk_rq_pos(req) >> block->
s2b_shift;
278 (blk_rq_pos(req) + blk_rq_sectors(req) - 1) >> block->
s2b_shift;
282 rq_for_each_segment(bv, req, iter) {
283 if (bv->bv_len & (blksize - 1))
286 count += bv->bv_len >> (block->
s2b_shift + 9);
287 #if defined(CONFIG_64BIT)
288 if (idal_is_needed (
page_address(bv->bv_page), bv->bv_len))
289 cidaw += bv->bv_len / blksize;
293 if (count != last_rec - first_rec + 1)
296 cplength = 2 +
count;
299 cidaw *
sizeof(
unsigned long);
304 if (private->rdc_data.mode.bits.data_chain == 0) {
305 cplength += count - 1;
306 datasize += (count - 1)*
sizeof(
struct LO_fba_data);
315 block->
bp_block, blk_rq_pos(req), blk_rq_sectors(req));
320 if (private->rdc_data.mode.bits.data_chain != 0) {
325 rq_for_each_segment(bv, req, iter) {
330 if (copy && rq_data_dir(req) ==
WRITE)
331 memcpy(copy + bv->bv_offset, dst, bv->bv_len);
333 dst = copy + bv->bv_offset;
335 for (off = 0; off < bv->bv_len; off += blksize) {
337 if (private->rdc_data.mode.bits.data_chain == 0) {
341 recid - first_rec, 1);
345 if (recid > first_rec)
352 if (idal_is_needed(dst, blksize)) {
355 idaws = idal_create_words(idaws, dst, blksize);
365 if (blk_noretry_request(req) ||
383 struct req_iterator iter;
386 unsigned int blksize, off;
392 blksize = cqr->
block->bp_block;
396 if (private->rdc_data.mode.bits.data_chain != 0)
398 rq_for_each_segment(bv, req, iter) {
400 for (off = 0; off < bv->bv_len; off += blksize) {
402 if (private->rdc_data.mode.bits.data_chain == 0)
410 if (rq_data_dir(req) ==
READ)
411 memcpy(dst, cda, bv->bv_len);
426 static void dasd_fba_handle_terminated_request(
struct dasd_ccw_req *cqr)
447 dasd_fba_dump_sense_dbf(
struct dasd_device *device,
struct irb *irb,
455 "%s: %s %02x%02x%02x %016llx %016llx %016llx "
457 scsw_is_tm(&irb->
scsw) ?
"t" :
"c",
458 scsw_cc(&irb->
scsw), scsw_cstat(&irb->
scsw),
459 scsw_dstat(&irb->
scsw), sense[0], sense[1],
463 "SORRY - NO VALID SENSE AVAILABLE\n");
479 "No memory to dump sense data");
483 " I/O status report for device %s:\n",
484 dev_name(&device->
cdev->dev));
486 " in req: %p CS: 0x%02X DS: 0x%02X\n", req,
489 " device %s: Failing CCW: %p\n",
490 dev_name(&device->
cdev->dev),
493 for (sl = 0; sl < 4; sl++) {
495 " Sense(hex) %2d-%2d:",
496 (8 * sl), ((8 * sl) + 7));
498 for (sct = 0; sct < 8; sct++) {
499 len +=
sprintf(page + len,
" %02x",
500 irb->
ecw[8 * sl + sct]);
502 len +=
sprintf(page + len,
"\n");
506 " SORRY - NO VALID SENSE AVAILABLE\n");
514 end =
min(act + 8, last);
516 " Related CP in req: %p\n", req);
519 " CCW %p: %08X %08X DAT:",
520 act, ((
int *) act)[0], ((
int *) act)[1]);
521 for (count = 0; count < 32 && count < act->
count;
522 count +=
sizeof(
int))
523 len +=
sprintf(page + len,
" %08X",
526 len +=
sprintf(page + len,
"\n");
541 " CCW %p: %08X %08X DAT:",
542 act, ((
int *) act)[0], ((
int *) act)[1]);
543 for (count = 0; count < 32 && count < act->
count;
544 count +=
sizeof(
int))
545 len +=
sprintf(page + len,
" %08X",
548 len +=
sprintf(page + len,
"\n");
553 if (act < last - 2) {
557 while (act <= last) {
559 " CCW %p: %08X %08X DAT:",
560 act, ((
int *) act)[0], ((
int *) act)[1]);
561 for (count = 0; count < 32 && count < act->
count;
562 count +=
sizeof(
int))
563 len +=
sprintf(page + len,
" %08X",
566 len +=
sprintf(page + len,
"\n");
593 .check_device = dasd_fba_check_characteristics,
594 .do_analysis = dasd_fba_do_analysis,
596 .fill_geometry = dasd_fba_fill_geometry,
599 .handle_terminated_request = dasd_fba_handle_terminated_request,
600 .erp_action = dasd_fba_erp_action,
601 .erp_postaction = dasd_fba_erp_postaction,
602 .check_for_device_change = dasd_fba_check_for_device_change,
603 .build_cp = dasd_fba_build_cp,
604 .free_cp = dasd_fba_free_cp,
605 .dump_sense = dasd_fba_dump_sense,
606 .dump_sense_dbf = dasd_fba_dump_sense_dbf,
607 .fill_info = dasd_fba_fill_info,
624 dasd_fba_cleanup(
void)