0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/module.h>
0011 #include <linux/init.h>
0012
0013 #include <asm/ccwdev.h>
0014 #include <asm/cio.h>
0015
0016 #include "cio.h"
0017 #include "cio_debug.h"
0018 #include "css.h"
0019 #include "device.h"
0020 #include "ioasm.h"
0021 #include "io_sch.h"
0022
0023
0024
0025
0026
0027 static void
0028 ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb)
0029 {
0030 struct subchannel *sch = to_subchannel(cdev->dev.parent);
0031 char dbf_text[15];
0032
0033 if (!scsw_is_valid_cstat(&irb->scsw) ||
0034 !(scsw_cstat(&irb->scsw) & (SCHN_STAT_CHN_DATA_CHK |
0035 SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK)))
0036 return;
0037 CIO_MSG_EVENT(0, "Channel-Check or Interface-Control-Check "
0038 "received"
0039 " ... device %04x on subchannel 0.%x.%04x, dev_stat "
0040 ": %02X sch_stat : %02X\n",
0041 cdev->private->dev_id.devno, sch->schid.ssid,
0042 sch->schid.sch_no,
0043 scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw));
0044 sprintf(dbf_text, "chk%x", sch->schid.sch_no);
0045 CIO_TRACE_EVENT(0, dbf_text);
0046 CIO_HEX_EVENT(0, irb, sizeof(struct irb));
0047 }
0048
0049
0050
0051
0052 static void
0053 ccw_device_path_notoper(struct ccw_device *cdev)
0054 {
0055 struct subchannel *sch;
0056
0057 sch = to_subchannel(cdev->dev.parent);
0058 if (cio_update_schib(sch))
0059 goto doverify;
0060
0061 CIO_MSG_EVENT(0, "%s(0.%x.%04x) - path(s) %02x are "
0062 "not operational \n", __func__,
0063 sch->schid.ssid, sch->schid.sch_no,
0064 sch->schib.pmcw.pnom);
0065
0066 sch->lpm &= ~sch->schib.pmcw.pnom;
0067 doverify:
0068 cdev->private->flags.doverify = 1;
0069 }
0070
0071
0072
0073
0074 static void
0075 ccw_device_accumulate_ecw(struct ccw_device *cdev, struct irb *irb)
0076 {
0077
0078
0079
0080
0081
0082 cdev->private->dma_area->irb.scsw.cmd.ectl = 0;
0083 if ((irb->scsw.cmd.stctl & SCSW_STCTL_ALERT_STATUS) &&
0084 !(irb->scsw.cmd.stctl & SCSW_STCTL_INTER_STATUS))
0085 cdev->private->dma_area->irb.scsw.cmd.ectl = irb->scsw.cmd.ectl;
0086
0087 if (!cdev->private->dma_area->irb.scsw.cmd.ectl)
0088 return;
0089
0090 memcpy(&cdev->private->dma_area->irb.ecw, irb->ecw, sizeof(irb->ecw));
0091 }
0092
0093
0094
0095
0096 static int
0097 ccw_device_accumulate_esw_valid(struct irb *irb)
0098 {
0099 if (!irb->scsw.cmd.eswf &&
0100 (irb->scsw.cmd.stctl == SCSW_STCTL_STATUS_PEND))
0101 return 0;
0102 if (irb->scsw.cmd.stctl ==
0103 (SCSW_STCTL_INTER_STATUS|SCSW_STCTL_STATUS_PEND) &&
0104 !(irb->scsw.cmd.actl & SCSW_ACTL_SUSPENDED))
0105 return 0;
0106 return 1;
0107 }
0108
0109
0110
0111
0112 static void
0113 ccw_device_accumulate_esw(struct ccw_device *cdev, struct irb *irb)
0114 {
0115 struct irb *cdev_irb;
0116 struct sublog *cdev_sublog, *sublog;
0117
0118 if (!ccw_device_accumulate_esw_valid(irb))
0119 return;
0120
0121 cdev_irb = &cdev->private->dma_area->irb;
0122
0123
0124 cdev_irb->esw.esw1.lpum = irb->esw.esw1.lpum;
0125
0126
0127 if (irb->scsw.cmd.eswf) {
0128 cdev_sublog = &cdev_irb->esw.esw0.sublog;
0129 sublog = &irb->esw.esw0.sublog;
0130
0131 cdev_sublog->esf = sublog->esf;
0132
0133
0134
0135
0136 if (irb->scsw.cmd.cstat & (SCHN_STAT_CHN_DATA_CHK |
0137 SCHN_STAT_CHN_CTRL_CHK |
0138 SCHN_STAT_INTF_CTRL_CHK)) {
0139
0140 cdev_sublog->arep = sublog->arep;
0141
0142 cdev_sublog->fvf = sublog->fvf;
0143
0144 cdev_sublog->sacc = sublog->sacc;
0145
0146 cdev_sublog->termc = sublog->termc;
0147
0148 cdev_sublog->seqc = sublog->seqc;
0149 }
0150
0151 cdev_sublog->devsc = sublog->devsc;
0152
0153 cdev_sublog->serr = sublog->serr;
0154
0155 cdev_sublog->ioerr = sublog->ioerr;
0156
0157 if (irb->scsw.cmd.cstat & SCHN_STAT_INTF_CTRL_CHK)
0158 cdev_irb->esw.esw0.erw.cpt = irb->esw.esw0.erw.cpt;
0159
0160 cdev_irb->esw.esw0.erw.fsavf = irb->esw.esw0.erw.fsavf;
0161 if (cdev_irb->esw.esw0.erw.fsavf) {
0162
0163 memcpy(cdev_irb->esw.esw0.faddr, irb->esw.esw0.faddr,
0164 sizeof (irb->esw.esw0.faddr));
0165
0166 cdev_irb->esw.esw0.erw.fsaf = irb->esw.esw0.erw.fsaf;
0167 }
0168
0169 cdev_irb->esw.esw0.erw.scavf = irb->esw.esw0.erw.scavf;
0170 if (irb->esw.esw0.erw.scavf)
0171
0172 cdev_irb->esw.esw0.saddr = irb->esw.esw0.saddr;
0173
0174 }
0175
0176
0177
0178 cdev_irb->esw.esw0.erw.auth = irb->esw.esw0.erw.auth;
0179
0180 cdev_irb->esw.esw0.erw.pvrf = irb->esw.esw0.erw.pvrf;
0181 if (irb->esw.esw0.erw.pvrf)
0182 cdev->private->flags.doverify = 1;
0183
0184 cdev_irb->esw.esw0.erw.cons = irb->esw.esw0.erw.cons;
0185 if (irb->esw.esw0.erw.cons)
0186 cdev_irb->esw.esw0.erw.scnt = irb->esw.esw0.erw.scnt;
0187 }
0188
0189
0190
0191
0192 void
0193 ccw_device_accumulate_irb(struct ccw_device *cdev, struct irb *irb)
0194 {
0195 struct irb *cdev_irb;
0196
0197
0198
0199
0200
0201
0202 if (!(scsw_stctl(&irb->scsw) & SCSW_STCTL_STATUS_PEND))
0203 return;
0204
0205
0206 ccw_device_msg_control_check(cdev, irb);
0207
0208
0209 if (scsw_is_valid_pno(&irb->scsw) && scsw_pno(&irb->scsw))
0210 ccw_device_path_notoper(cdev);
0211
0212 if (scsw_is_tm(&irb->scsw)) {
0213 memcpy(&cdev->private->dma_area->irb, irb, sizeof(struct irb));
0214 return;
0215 }
0216
0217
0218
0219 if (!scsw_is_solicited(&irb->scsw))
0220 return;
0221
0222 cdev_irb = &cdev->private->dma_area->irb;
0223
0224
0225
0226
0227
0228
0229 if (irb->scsw.cmd.fctl & SCSW_FCTL_CLEAR_FUNC)
0230 memset(&cdev->private->dma_area->irb, 0, sizeof(struct irb));
0231
0232
0233 if (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC) {
0234
0235 cdev_irb->scsw.cmd.key = irb->scsw.cmd.key;
0236
0237 cdev_irb->scsw.cmd.sctl = irb->scsw.cmd.sctl;
0238
0239 cdev_irb->scsw.cmd.cc |= irb->scsw.cmd.cc;
0240
0241 cdev_irb->scsw.cmd.fmt = irb->scsw.cmd.fmt;
0242
0243 cdev_irb->scsw.cmd.pfch = irb->scsw.cmd.pfch;
0244
0245 cdev_irb->scsw.cmd.isic = irb->scsw.cmd.isic;
0246
0247 cdev_irb->scsw.cmd.alcc = irb->scsw.cmd.alcc;
0248
0249 cdev_irb->scsw.cmd.ssi = irb->scsw.cmd.ssi;
0250 }
0251
0252
0253 ccw_device_accumulate_ecw(cdev, irb);
0254
0255
0256 cdev_irb->scsw.cmd.fctl |= irb->scsw.cmd.fctl;
0257
0258 cdev_irb->scsw.cmd.actl = irb->scsw.cmd.actl;
0259
0260 cdev_irb->scsw.cmd.stctl |= irb->scsw.cmd.stctl;
0261
0262
0263
0264
0265 if ((irb->scsw.cmd.stctl & SCSW_STCTL_PRIM_STATUS) ||
0266 ((irb->scsw.cmd.stctl ==
0267 (SCSW_STCTL_INTER_STATUS|SCSW_STCTL_STATUS_PEND)) &&
0268 (irb->scsw.cmd.actl & SCSW_ACTL_DEVACT) &&
0269 (irb->scsw.cmd.actl & SCSW_ACTL_SCHACT)) ||
0270 (irb->scsw.cmd.actl & SCSW_ACTL_SUSPENDED))
0271 cdev_irb->scsw.cmd.cpa = irb->scsw.cmd.cpa;
0272
0273 cdev_irb->scsw.cmd.dstat &= ~DEV_STAT_BUSY;
0274
0275 if (irb->scsw.cmd.stctl &
0276 (SCSW_STCTL_PRIM_STATUS | SCSW_STCTL_SEC_STATUS
0277 | SCSW_STCTL_INTER_STATUS | SCSW_STCTL_ALERT_STATUS))
0278 cdev_irb->scsw.cmd.dstat |= irb->scsw.cmd.dstat;
0279
0280 cdev_irb->scsw.cmd.cstat |= irb->scsw.cmd.cstat;
0281
0282 if ((irb->scsw.cmd.stctl & SCSW_STCTL_PRIM_STATUS) &&
0283 (irb->scsw.cmd.cstat & ~(SCHN_STAT_PCI | SCHN_STAT_INCORR_LEN))
0284 == 0)
0285 cdev_irb->scsw.cmd.count = irb->scsw.cmd.count;
0286
0287
0288 ccw_device_accumulate_esw(cdev, irb);
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302 if ((cdev_irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) &&
0303 !(cdev_irb->esw.esw0.erw.cons))
0304 cdev->private->flags.dosense = 1;
0305 }
0306
0307
0308
0309
0310 int
0311 ccw_device_do_sense(struct ccw_device *cdev, struct irb *irb)
0312 {
0313 struct subchannel *sch;
0314 struct ccw1 *sense_ccw;
0315 int rc;
0316
0317 sch = to_subchannel(cdev->dev.parent);
0318
0319
0320 if (scsw_actl(&irb->scsw) & (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT))
0321
0322
0323
0324
0325
0326
0327 return -EBUSY;
0328
0329
0330
0331
0332 sense_ccw = &to_io_private(sch)->dma_area->sense_ccw;
0333 sense_ccw->cmd_code = CCW_CMD_BASIC_SENSE;
0334 sense_ccw->cda = (__u32) __pa(cdev->private->dma_area->irb.ecw);
0335 sense_ccw->count = SENSE_MAX_COUNT;
0336 sense_ccw->flags = CCW_FLAG_SLI;
0337
0338 rc = cio_start(sch, sense_ccw, 0xff);
0339 if (rc == -ENODEV || rc == -EACCES)
0340 dev_fsm_event(cdev, DEV_EVENT_VERIFY);
0341 return rc;
0342 }
0343
0344
0345
0346
0347 void
0348 ccw_device_accumulate_basic_sense(struct ccw_device *cdev, struct irb *irb)
0349 {
0350
0351
0352
0353
0354
0355 if (!(scsw_stctl(&irb->scsw) & SCSW_STCTL_STATUS_PEND))
0356 return;
0357
0358
0359 ccw_device_msg_control_check(cdev, irb);
0360
0361
0362 if (scsw_is_valid_pno(&irb->scsw) && scsw_pno(&irb->scsw))
0363 ccw_device_path_notoper(cdev);
0364
0365 if (!(irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) &&
0366 (irb->scsw.cmd.dstat & DEV_STAT_CHN_END)) {
0367 cdev->private->dma_area->irb.esw.esw0.erw.cons = 1;
0368 cdev->private->flags.dosense = 0;
0369 }
0370
0371 if (ccw_device_accumulate_esw_valid(irb) &&
0372 irb->esw.esw0.erw.pvrf)
0373 cdev->private->flags.doverify = 1;
0374 }
0375
0376
0377
0378
0379
0380 int
0381 ccw_device_accumulate_and_sense(struct ccw_device *cdev, struct irb *irb)
0382 {
0383 ccw_device_accumulate_irb(cdev, irb);
0384 if ((irb->scsw.cmd.actl & (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT)) != 0)
0385 return -EBUSY;
0386
0387 if (cdev->private->flags.dosense &&
0388 !(irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK)) {
0389 cdev->private->dma_area->irb.esw.esw0.erw.cons = 1;
0390 cdev->private->flags.dosense = 0;
0391 return 0;
0392 }
0393 if (cdev->private->flags.dosense) {
0394 ccw_device_do_sense(cdev, irb);
0395 return -EBUSY;
0396 }
0397 return 0;
0398 }
0399