📄 sclp_cpi.c
字号:
/* * Author: Martin Peschke <mpeschke@de.ibm.com> * Copyright (C) 2001 IBM Entwicklung GmbH, IBM Corporation * * SCLP Control-Program Identification. */#include <linux/config.h>#include <linux/version.h>#include <linux/kmod.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <linux/timer.h>#include <linux/string.h>#include <linux/err.h>#include <linux/slab.h>#include <asm/ebcdic.h>#include <asm/semaphore.h>#include "sclp.h"#include "sclp_rw.h"#define CPI_LENGTH_SYSTEM_TYPE 8#define CPI_LENGTH_SYSTEM_NAME 8#define CPI_LENGTH_SYSPLEX_NAME 8struct cpi_evbuf { struct evbuf_header header; u8 id_format; u8 reserved0; u8 system_type[CPI_LENGTH_SYSTEM_TYPE]; u64 reserved1; u8 system_name[CPI_LENGTH_SYSTEM_NAME]; u64 reserved2; u64 system_level; u64 reserved3; u8 sysplex_name[CPI_LENGTH_SYSPLEX_NAME]; u8 reserved4[16];} __attribute__((packed));struct cpi_sccb { struct sccb_header header; struct cpi_evbuf cpi_evbuf;} __attribute__((packed));/* Event type structure for write message and write priority message */static struct sclp_register sclp_cpi_event ={ .send_mask = EvTyp_CtlProgIdent_Mask};MODULE_AUTHOR( "Martin Peschke, IBM Deutschland Entwicklung GmbH " "<mpeschke@de.ibm.com>");MODULE_DESCRIPTION( "identify this operating system instance to the S/390 " "or zSeries hardware");static char *system_name = NULL;module_param(system_name, charp, 0);MODULE_PARM_DESC(system_name, "e.g. hostname - max. 8 characters");static char *sysplex_name = NULL;#ifdef ALLOW_SYSPLEX_NAMEmodule_param(sysplex_name, charp, 0);MODULE_PARM_DESC(sysplex_name, "if applicable - max. 8 characters");#endif/* use default value for this field (as well as for system level) */static char *system_type = "LINUX";static intcpi_check_parms(void){ /* reject if no system type specified */ if (!system_type) { printk("cpi: bug: no system type specified\n"); return -EINVAL; } /* reject if system type larger than 8 characters */ if (strlen(system_type) > CPI_LENGTH_SYSTEM_NAME) { printk("cpi: bug: system type has length of %li characters - " "only %i characters supported\n", strlen(system_type), CPI_LENGTH_SYSTEM_TYPE); return -EINVAL; } /* reject if no system name specified */ if (!system_name) { printk("cpi: no system name specified\n"); return -EINVAL; } /* reject if system name larger than 8 characters */ if (strlen(system_name) > CPI_LENGTH_SYSTEM_NAME) { printk("cpi: system name has length of %li characters - " "only %i characters supported\n", strlen(system_name), CPI_LENGTH_SYSTEM_NAME); return -EINVAL; } /* reject if specified sysplex name larger than 8 characters */ if (sysplex_name && strlen(sysplex_name) > CPI_LENGTH_SYSPLEX_NAME) { printk("cpi: sysplex name has length of %li characters" " - only %i characters supported\n", strlen(sysplex_name), CPI_LENGTH_SYSPLEX_NAME); return -EINVAL; } return 0;}static voidcpi_callback(struct sclp_req *req, void *data){ struct semaphore *sem; sem = (struct semaphore *) data; up(sem);}static struct sclp_req *cpi_prepare_req(void){ struct sclp_req *req; struct cpi_sccb *sccb; struct cpi_evbuf *evb; req = (struct sclp_req *) kmalloc(sizeof(struct sclp_req), GFP_KERNEL); if (req == NULL) return ERR_PTR(-ENOMEM); sccb = (struct cpi_sccb *) __get_free_page(GFP_KERNEL | GFP_DMA); if (sccb == NULL) { kfree(req); return ERR_PTR(-ENOMEM); } memset(sccb, 0, sizeof(struct cpi_sccb)); /* setup SCCB for Control-Program Identification */ sccb->header.length = sizeof(struct cpi_sccb); sccb->cpi_evbuf.header.length = sizeof(struct cpi_evbuf); sccb->cpi_evbuf.header.type = 0x0B; evb = &sccb->cpi_evbuf; /* set system type */ memset(evb->system_type, ' ', CPI_LENGTH_SYSTEM_TYPE); memcpy(evb->system_type, system_type, strlen(system_type)); sclp_ascebc_str(evb->system_type, CPI_LENGTH_SYSTEM_TYPE); EBC_TOUPPER(evb->system_type, CPI_LENGTH_SYSTEM_TYPE); /* set system name */ memset(evb->system_name, ' ', CPI_LENGTH_SYSTEM_NAME); memcpy(evb->system_name, system_name, strlen(system_name)); sclp_ascebc_str(evb->system_name, CPI_LENGTH_SYSTEM_NAME); EBC_TOUPPER(evb->system_name, CPI_LENGTH_SYSTEM_NAME); /* set sytem level */ evb->system_level = LINUX_VERSION_CODE; /* set sysplex name */ if (sysplex_name) { memset(evb->sysplex_name, ' ', CPI_LENGTH_SYSPLEX_NAME); memcpy(evb->sysplex_name, sysplex_name, strlen(sysplex_name)); sclp_ascebc_str(evb->sysplex_name, CPI_LENGTH_SYSPLEX_NAME); EBC_TOUPPER(evb->sysplex_name, CPI_LENGTH_SYSPLEX_NAME); } /* prepare request data structure presented to SCLP driver */ req->command = SCLP_CMDW_WRITEDATA; req->sccb = sccb; req->status = SCLP_REQ_FILLED; req->callback = cpi_callback; return req;}static voidcpi_free_req(struct sclp_req *req){ free_page((unsigned long) req->sccb); kfree(req);}static int __initcpi_module_init(void){ struct semaphore sem; struct sclp_req *req; int rc; rc = cpi_check_parms(); if (rc) return rc; rc = sclp_register(&sclp_cpi_event); if (rc) { /* could not register sclp event. Die. */ printk(KERN_WARNING "cpi: could not register to hardware " "console.\n"); return -EINVAL; } if (!(sclp_cpi_event.sclp_send_mask & EvTyp_CtlProgIdent_Mask)) { printk(KERN_WARNING "cpi: no control program identification " "support\n"); sclp_unregister(&sclp_cpi_event); return -ENOTSUPP; } req = cpi_prepare_req(); if (IS_ERR(req)) { printk(KERN_WARNING "cpi: couldn't allocate request\n"); sclp_unregister(&sclp_cpi_event); return PTR_ERR(req); } /* Prepare semaphore */ sema_init(&sem, 0); req->callback_data = &sem; /* Add request to sclp queue */ rc = sclp_add_request(req); if (rc) { printk(KERN_WARNING "cpi: could not start request\n"); cpi_free_req(req); sclp_unregister(&sclp_cpi_event); return rc; } /* make "insmod" sleep until callback arrives */ down(&sem); rc = ((struct cpi_sccb *) req->sccb)->header.response_code; if (rc != 0x0020) { printk(KERN_WARNING "cpi: failed with response code 0x%x\n", rc); rc = -ECOMM; } else rc = 0; cpi_free_req(req); sclp_unregister(&sclp_cpi_event); return rc;}static void __exit cpi_module_exit(void){}/* declare driver module init/cleanup functions */module_init(cpi_module_init);module_exit(cpi_module_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -