struct subchannel *cio_probe_console(void) { struct subchannel_id schid; struct subchannel *sch; int sch_no, ret; sch_no = cio_get_console_sch_no(); if (sch_no == -1) { pr_warning("No CCW console was found\n"); return ERR_PTR(-ENODEV); } init_subchannel_id(&schid); schid.sch_no = sch_no; sch = css_alloc_subchannel(schid); if (IS_ERR(sch)) return sch; lockdep_set_class(sch->lock, &console_sch_key); isc_register(CONSOLE_ISC); sch->config.isc = CONSOLE_ISC; sch->config.intparm = (u32)(addr_t)sch; ret = cio_commit_config(sch); if (ret) { isc_unregister(CONSOLE_ISC); put_device(&sch->dev); return ERR_PTR(ret); } console_sch = sch; return sch; }
static int cio_get_console_sch_no(void) { struct subchannel_id schid; init_subchannel_id(&schid); if (console_irq != -1) { /* VM provided us with the irq number of the console. */ schid.sch_no = console_irq; if (stsch_err(schid, &console_subchannel.schib) != 0 || (console_subchannel.schib.pmcw.st != SUBCHANNEL_TYPE_IO) || !console_subchannel.schib.pmcw.dnv) return -1; console_devno = console_subchannel.schib.pmcw.dev; } else if (console_devno != -1) { /* At least the console device number is known. */ for_each_subchannel(cio_test_for_console, NULL); if (console_irq == -1) return -1; } else { /* unlike in 2.4, we cannot autoprobe here, since * the channel subsystem is not fully initialized. * With some luck, the HWC console can take over */ return -1; } return console_irq; }
/* * Called from the machine check handler for subchannel report words. */ static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow) { struct subchannel_id mchk_schid; struct subchannel *sch; if (overflow) { css_schedule_eval_all(); return; } CIO_CRW_EVENT(2, "CRW0 reports slct=%d, oflw=%d, " "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", crw0->slct, crw0->oflw, crw0->chn, crw0->rsc, crw0->anc, crw0->erc, crw0->rsid); if (crw1) CIO_CRW_EVENT(2, "CRW1 reports slct=%d, oflw=%d, " "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", crw1->slct, crw1->oflw, crw1->chn, crw1->rsc, crw1->anc, crw1->erc, crw1->rsid); init_subchannel_id(&mchk_schid); mchk_schid.sch_no = crw0->rsid; if (crw1) mchk_schid.ssid = (crw1->rsid >> 4) & 3; if (crw0->erc == CRW_ERC_PMOD) { sch = get_subchannel_by_schid(mchk_schid); if (sch) { css_update_ssd_info(sch); put_device(&sch->dev); } } /*
int idset_sch_get_first(struct idset *set, struct subchannel_id *schid) { int ssid = 0; int id = 0; int rc; rc = idset_get_first(set, &ssid, &id); if (rc) { init_subchannel_id(schid); schid->ssid = ssid; schid->sch_no = id; } return rc; }
inline int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data) { struct subchannel_id schid; int ret; init_subchannel_id(&schid); ret = -ENODEV; do { do { ret = fn(schid, data); if (ret) break; } while (schid.sch_no++ < __MAX_SUBCHANNEL); schid.sch_no = 0; } while (schid.ssid++ < max_ssid); return ret; }
static int cio_get_console_sch_no(void) { struct subchannel_id schid; struct schib schib; init_subchannel_id(&schid); if (console_irq != -1) { /* VM provided us with the irq number of the console. */ schid.sch_no = console_irq; if (stsch(schid, &schib) != 0 || (schib.pmcw.st != SUBCHANNEL_TYPE_IO) || !schib.pmcw.dnv) return -1; console_devno = schib.pmcw.dev; } else if (console_devno != -1) { /* At least the console device number is known. */ for_each_subchannel(cio_test_for_console, NULL); } return console_irq; }
struct subchannel *cio_probe_console(void) { struct subchannel_id schid; struct subchannel *sch; int sch_no, ret; sch_no = cio_get_console_sch_no(); if (sch_no == -1) { pr_warning("No CCW console was found\n"); return ERR_PTR(-ENODEV); } init_subchannel_id(&schid); schid.sch_no = sch_no; sch = css_alloc_subchannel(schid); if (IS_ERR(sch)) return sch; lockdep_set_class(sch->lock, &console_sch_key); isc_reg
struct subchannel * cio_probe_console(void) { int sch_no, ret; struct subchannel_id schid; if (xchg(&console_subchannel_in_use, 1) != 0) return ERR_PTR(-EBUSY); sch_no = cio_get_console_sch_no(); if (sch_no == -1) { console_subchannel_in_use = 0; pr_warning("No CCW console was found\n"); return ERR_PTR(-ENODEV); } memset(&console_subchannel, 0, sizeof(struct subchannel)); init_subchannel_id(&schid); schid.sch_no = sch_no; ret = cio_validate_subchannel(&console_subchannel, schid); if (ret) { console_subchannel_in_use = 0; return ERR_PTR(-ENODEV); } /* * enable console I/O-interrupt subclass */ isc_register(CONSOLE_ISC); console_subchannel.config.isc = CONSOLE_ISC; console_subchannel.config.intparm = (u32)(addr_t)&console_subchannel; ret = cio_commit_config(&console_subchannel); if (ret) { isc_unregister(CONSOLE_ISC); console_subchannel_in_use = 0; return ERR_PTR(ret); } return &console_subchannel; }
struct subchannel * cio_probe_console(void) { int sch_no, ret; struct subchannel_id schid; if (xchg(&console_subchannel_in_use, 1) != 0) return ERR_PTR(-EBUSY); sch_no = cio_get_console_sch_no(); if (sch_no == -1) { console_subchannel_in_use = 0; return ERR_PTR(-ENODEV); } memset(&console_subchannel, 0, sizeof(struct subchannel)); init_subchannel_id(&schid); schid.sch_no = sch_no; ret = cio_validate_subchannel(&console_subchannel, schid); if (ret) { console_subchannel_in_use = 0; return ERR_PTR(-ENODEV); } /* * enable console I/O-interrupt subclass 7 */ ctl_set_bit(6, 24); console_subchannel.schib.pmcw.isc = 7; console_subchannel.schib.pmcw.intparm = (__u32)(unsigned long)&console_subchannel; ret = cio_modify(&console_subchannel); if (ret) { console_subchannel_in_use = 0; return ERR_PTR(ret); } return &console_subchannel; }