#include "css.h"
#include "device.h"
#include "ioasm.h"
+#include "io_sch.h"
/*
* Check for any kind of channel or interface control check but don't
* issue the message for the console device
*/
-static inline void
+static void
ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb)
{
if (!(irb->scsw.cstat & (SCHN_STAT_CHN_DATA_CHK |
stsch (sch->schid, &sch->schib);
CIO_MSG_EVENT(0, "%s(0.%x.%04x) - path(s) %02x are "
- "not operational \n", __FUNCTION__,
+ "not operational \n", __func__,
sch->schid.ssid, sch->schid.sch_no,
sch->schib.pmcw.pnom);
/*
* Copy valid bits from the extended control word to device irb.
*/
-static inline void
+static void
ccw_device_accumulate_ecw(struct ccw_device *cdev, struct irb *irb)
{
/*
/*
* Check if extended status word is valid.
*/
-static inline int
+static int
ccw_device_accumulate_esw_valid(struct irb *irb)
{
if (!irb->scsw.eswf && irb->scsw.stctl == SCSW_STCTL_STATUS_PEND)
/*
* Copy valid bits from the extended status word to device irb.
*/
-static inline void
+static void
ccw_device_accumulate_esw(struct ccw_device *cdev, struct irb *irb)
{
struct irb *cdev_irb;
cdev_irb = &cdev->private->irb;
+ /*
+ * If the clear function had been performed, all formerly pending
+ * status at the subchannel has been cleared and we must not pass
+ * intermediate accumulated status to the device driver.
+ */
+ if (irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC)
+ memset(&cdev->private->irb, 0, sizeof(struct irb));
+
/* Copy bits which are valid only for the start function. */
if (irb->scsw.fctl & SCSW_FCTL_START_FUNC) {
/* Copy key. */
cdev_irb->scsw.cpa = irb->scsw.cpa;
/* Accumulate device status, but not the device busy flag. */
cdev_irb->scsw.dstat &= ~DEV_STAT_BUSY;
- cdev_irb->scsw.dstat |= irb->scsw.dstat;
+ /* dstat is not always valid. */
+ if (irb->scsw.stctl &
+ (SCSW_STCTL_PRIM_STATUS | SCSW_STCTL_SEC_STATUS
+ | SCSW_STCTL_INTER_STATUS | SCSW_STCTL_ALERT_STATUS))
+ cdev_irb->scsw.dstat |= irb->scsw.dstat;
/* Accumulate subchannel status. */
cdev_irb->scsw.cstat |= irb->scsw.cstat;
/* Copy residual count if it is valid. */
ccw_device_do_sense(struct ccw_device *cdev, struct irb *irb)
{
struct subchannel *sch;
+ struct ccw1 *sense_ccw;
+ int rc;
sch = to_subchannel(cdev->dev.parent);
/*
* We have ending status but no sense information. Do a basic sense.
*/
- sch->sense_ccw.cmd_code = CCW_CMD_BASIC_SENSE;
- sch->sense_ccw.cda = (__u32) __pa(cdev->private->irb.ecw);
- sch->sense_ccw.count = SENSE_MAX_COUNT;
- sch->sense_ccw.flags = CCW_FLAG_SLI;
+ sense_ccw = &to_io_private(sch)->sense_ccw;
+ sense_ccw->cmd_code = CCW_CMD_BASIC_SENSE;
+ sense_ccw->cda = (__u32) __pa(cdev->private->irb.ecw);
+ sense_ccw->count = SENSE_MAX_COUNT;
+ sense_ccw->flags = CCW_FLAG_SLI;
/* Reset internal retry indication. */
cdev->private->flags.intretry = 0;
- return cio_start (sch, &sch->sense_ccw, 0xff);
+ rc = cio_start(sch, sense_ccw, 0xff);
+ if (rc == -ENODEV || rc == -EACCES)
+ dev_fsm_event(cdev, DEV_EVENT_VERIFY);
+ return rc;
}
/*