📄 hwc_rw.c
字号:
int retval = 0; subvec = start; while (((void *) subvec) < end) { subvec = find_gds_subvector ( subvec, end, GDS_KEY_SelfDefTextMsg); if (!subvec) break; subvec_data = (gds_subvector_t *) (((unsigned long) subvec) + sizeof (gds_subvector_t)); subvec_end = (void *) (((unsigned long) subvec) + subvec->length); retval += eval_selfdeftextmsg (subvec_data, subvec_end); subvec = (gds_subvector_t *) subvec_end; } return retval;}inline static int eval_cpmsu (gds_vector_t * start, void *end){ gds_vector_t *vec; gds_subvector_t *vec_data; void *vec_end; int retval = 0; vec = start; while (((void *) vec) < end) { vec = find_gds_vector (vec, end, GDS_ID_TextCmd); if (!vec) break; vec_data = (gds_subvector_t *) (((unsigned long) vec) + sizeof (gds_vector_t)); vec_end = (void *) (((unsigned long) vec) + vec->length); retval += eval_textcmd (vec_data, vec_end); vec = (gds_vector_t *) vec_end; } return retval;}inline static int eval_mdsmu (gds_vector_t * start, void *end){ gds_vector_t *vec; gds_vector_t *vec_data; void *vec_end; int retval = 0; vec = find_gds_vector (start, end, GDS_ID_CPMSU); if (vec) { vec_data = (gds_vector_t *) (((unsigned long) vec) + sizeof (gds_vector_t)); vec_end = (void *) (((unsigned long) vec) + vec->length); retval = eval_cpmsu (vec_data, vec_end); } return retval;}inline static int eval_evbuf (gds_vector_t * start, void *end){ gds_vector_t *vec; gds_vector_t *vec_data; void *vec_end; int retval = 0; vec = find_gds_vector (start, end, GDS_ID_MDSMU); if (vec) { vec_data = (gds_vector_t *) (((unsigned long) vec) + sizeof (gds_vector_t)); vec_end = (void *) (((unsigned long) vec) + vec->length); retval = eval_mdsmu (vec_data, vec_end); } return retval;}static int process_evbufs (void *start, void *end){ int retval = 0; evbuf_t *evbuf; void *evbuf_end; gds_vector_t *evbuf_data; evbuf = (evbuf_t *) start; while (((void *) evbuf) < end) { evbuf_data = (gds_vector_t *) (((unsigned long) evbuf) + sizeof (evbuf_t)); evbuf_end = (void *) (((unsigned long) evbuf) + evbuf->length); switch (evbuf->type) { case ET_OpCmd: case ET_CntlProgOpCmd: case ET_PMsgCmd:#ifdef DUMP_HWCB_INPUT internal_print ( DELAYED_WRITE, HWC_RW_PRINT_HEADER "event buffer " "at 0x%x up to 0x%x, length: %d\n", (unsigned long) evbuf, (unsigned long) (evbuf_end - 1), evbuf->length); dump_storage_area ((void *) evbuf, evbuf->length);#endif retval += eval_evbuf (evbuf_data, evbuf_end); break; case ET_StateChange: retval = -ENOSYS; break; default: printk ( KERN_WARNING HWC_RW_PRINT_HEADER "unconditional read: " "unknown event buffer found, " "type 0x%x", evbuf->type); retval = -ENOSYS; } evbuf = (evbuf_t *) evbuf_end; } return retval;}static int unconditional_read_1 (void){ unsigned short int condition_code; read_hwcb_t *hwcb = (read_hwcb_t *) hwc_data.page; int retval; if ((!hwc_data.read_prio) && (!hwc_data.read_nonprio)) return -EOPNOTSUPP; if (hwc_data.current_servc) return -EBUSY; memset (hwcb, 0x00, PAGE_SIZE); memcpy (hwcb, &read_hwcb_template, sizeof (read_hwcb_t)); condition_code = service_call (HWC_CMDW_READDATA, hwc_data.page);#ifdef DUMP_HWC_READ_ERROR if (condition_code == HWC_NOT_OPERATIONAL) __asm__ ("LHI 1,0xe40\n\t" "L 2,0(0,%0)\n\t" "LRA 3,0(0,%1)\n\t" "J .+0 \n\t" : : "a" (&condition_code), "a" (hwc_data.page) : "1", "2", "3");#endif switch (condition_code) { case HWC_COMMAND_INITIATED: hwc_data.current_servc = HWC_CMDW_READDATA; hwc_data.current_hwcb = hwc_data.page; retval = condition_code; break; case HWC_BUSY: retval = -EBUSY; break; default: retval = -EIO; } return retval;}static int unconditional_read_2 (void){ read_hwcb_t *hwcb = (read_hwcb_t *) hwc_data.page;#ifdef DUMP_HWC_READ_ERROR if ((hwcb->response_code != 0x0020) && (hwcb->response_code != 0x0220) && (hwcb->response_code != 0x60F0) && (hwcb->response_code != 0x62F0)) __asm__ ("LHI 1,0xe41\n\t" "LRA 2,0(0,%0)\n\t" "L 3,0(0,%1)\n\t" "J .+0\n\t" : : "a" (hwc_data.page), "a" (&(hwcb->response_code)) : "1", "2", "3");#endif hwc_data.current_servc = 0; hwc_data.current_hwcb = NULL; switch (hwcb->response_code) { case 0x0020: case 0x0220: return process_evbufs ( (void *) (((unsigned long) hwcb) + sizeof (read_hwcb_t)), (void *) (((unsigned long) hwcb) + hwcb->length)); case 0x60F0: case 0x62F0: return 0; case 0x0100: internal_print ( IMMEDIATE_WRITE, HWC_RW_PRINT_HEADER "unconditional read: HWCB boundary violation - this " "must not occur in a correct driver, please contact " "author\n"); return -EIO; case 0x0300: internal_print ( IMMEDIATE_WRITE, HWC_RW_PRINT_HEADER "unconditional read: " "insufficient HWCB length - this must not occur in a " "correct driver, please contact author\n"); return -EIO; case 0x01F0: internal_print ( IMMEDIATE_WRITE, HWC_RW_PRINT_HEADER "unconditional read: " "invalid command - this must not occur in a correct " "driver, please contact author\n"); return -EIO; case 0x40F0: internal_print ( IMMEDIATE_WRITE, HWC_RW_PRINT_HEADER "unconditional read: invalid function code - this " "must not occur in a correct driver, please contact " "author\n"); return -EIO; case 0x70F0: internal_print ( IMMEDIATE_WRITE, HWC_RW_PRINT_HEADER "unconditional read: invalid selection mask - this " "must not occur in a correct driver, please contact " "author\n"); return -EIO; case 0x0040: internal_print ( IMMEDIATE_WRITE, HWC_RW_PRINT_HEADER "unconditional read: HWC equipment check - don't " "know how to handle this case\n"); return -EIO; default: internal_print ( IMMEDIATE_WRITE, HWC_RW_PRINT_HEADER "unconditional read: invalid response code %x - this " "must not occur in a correct driver, please contact " "author\n", hwcb->response_code); return -EIO; }}static int write_event_mask_1 (void){ unsigned int condition_code; int retval; memcpy (hwc_data.page, &init_hwcb_template, sizeof (init_hwcb_t)); condition_code = service_call (HWC_CMDW_WRITEMASK, hwc_data.page);#ifdef DUMP_HWC_INIT_ERROR if (condition_code != HWC_COMMAND_INITIATED) __asm__ ("LHI 1,0xe10\n\t" "L 2,0(0,%0)\n\t" "LRA 3,0(0,%1)\n\t" "J .+0\n\t" : : "a" (&condition_code), "a" (hwc_data.page) : "1", "2", "3");#endif switch (condition_code) { case HWC_COMMAND_INITIATED: hwc_data.current_servc = HWC_CMDW_WRITEMASK; hwc_data.current_hwcb = hwc_data.page; retval = condition_code; break; case HWC_BUSY: retval = -EBUSY; break; default: retval = -EIO; } return retval;}static int write_event_mask_2 (void){ init_hwcb_t *hwcb = (init_hwcb_t *) hwc_data.page; int retval = 0; if (hwcb->hwc_receive_mask & ET_Msg_Mask) hwc_data.write_nonprio = 1; if (hwcb->hwc_receive_mask & ET_PMsgCmd_Mask) hwc_data.write_prio = 1; if (hwcb->hwc_send_mask & ET_OpCmd_Mask) hwc_data.read_nonprio = 1; if (hwcb->hwc_send_mask & ET_PMsgCmd_Mask) hwc_data.read_nonprio = 1; if ((hwcb->response_code != 0x0020) || (!hwc_data.write_nonprio) || ((!hwc_data.read_nonprio) && (!hwc_data.read_prio)))#ifdef DUMP_HWC_INIT_ERROR __asm__ ("LHI 1,0xe11\n\t" "LRA 2,0(0,%0)\n\t" "L 3,0(0,%1)\n\t" "J .+0\n\t" : : "a" (hwcb), "a" (&(hwcb->response_code)) : "1", "2", "3");#else retval = -EIO#endif hwc_data.current_servc = 0; hwc_data.current_hwcb = NULL; return retval;}static int set_hwc_ioctls (hwc_ioctls_t * ioctls, char correct){ int retval = 0; hwc_ioctls_t tmp; if (ioctls->width_htab > MAX_MESSAGE_SIZE) { if (correct) tmp.width_htab = MAX_MESSAGE_SIZE; else retval = -EINVAL; } else tmp.width_htab = ioctls->width_htab; tmp.echo = ioctls->echo; if (ioctls->columns > MAX_MESSAGE_SIZE) { if (correct) tmp.columns = MAX_MESSAGE_SIZE; else retval = -EINVAL; } else tmp.columns = ioctls->columns; switch (ioctls->code) { case CODE_EBCDIC: case CODE_ASCII: tmp.code = ioctls->code; break; default: if (correct) tmp.code = CODE_ASCII; else retval = -EINVAL; } tmp.final_nl = ioctls->final_nl; if (ioctls->max_hwcb < 2) { if (correct) tmp.max_hwcb = 2; else retval = -EINVAL; } else tmp.max_hwcb = ioctls->max_hwcb; tmp.tolower = ioctls->tolower; if (ioctls->kmem_hwcb > ioctls->max_hwcb) { if (correct) tmp.kmem_hwcb = ioctls->max_hwcb; else retval = -EINVAL; } else tmp.kmem_hwcb = ioctls->kmem_hwcb; if (ioctls->kmem_hwcb > MAX_KMEM_PAGES) { if (correct) ioctls->kmem_hwcb = MAX_KMEM_PAGES; else retval = -EINVAL; } if (ioctls->kmem_hwcb < 2) { if (correct) ioctls->kmem_hwcb = 2; else retval = -EINVAL; } tmp.delim = ioctls->delim; if (!(retval < 0)) hwc_data.ioctls = tmp; return retval;}int hwc_init (void){ int retval;#ifdef BUFFER_STRESS_TEST init_hwcb_t *hwcb; int i;#endif#ifdef CONFIG_3215 if (MACHINE_IS_VM) return 0;#endif spin_lock_init (&hwc_data.lock); retval = write_event_mask_1 (); if (retval < 0) return retval;#ifdef USE_VM_DETECTION if (MACHINE_IS_VM) { if (hwc_data.init_ioctls.columns > 76) hwc_data.init_ioctls.columns = 76; hwc_data.init_ioctls.tolower = 1; if (!hwc_data.init_ioctls.delim) hwc_data.init_ioctls.delim = DEFAULT_CASE_DELIMITER; } else { hwc_data.init_ioctls.tolower = 0; hwc_data.init_ioctls.delim = 0; }#endif retval = set_hwc_ioctls (&hwc_data.init_ioctls, 1); hwc_data.kmem_start = (unsigned long) alloc_bootmem_pages (hwc_data.ioctls.kmem_hwcb * PAGE_SIZE); hwc_data.kmem_end = hwc_data.kmem_start + hwc_data.ioctls.kmem_hwcb * PAGE_SIZE - 1; ctl_set_bit (0, 9);#ifdef BUFFER_STRESS_TEST internal_print ( DELAYED_WRITE, HWC_RW_PRINT_HEADER "use %i bytes for buffering.\n", hwc_data.ioctls.kmem_hwcb * PAGE_SIZE); for (i = 0; i < 500; i++) { hwcb = (init_hwcb_t *) BUF_HWCB; internal_print ( DELAYED_WRITE, HWC_RW_PRINT_HEADER "This is stress test message #%i, free: %i bytes\n", i, MAX_HWCB_ROOM - (hwcb->length + sizeof (mto_t))); }#endif return retval;}void do_hwc_interrupt (void){ spin_lock (&hwc_data.lock); if (!hwc_data.current_servc) { unconditional_read_1 (); } else { switch (hwc_data.current_servc) { case HWC_CMDW_WRITEMASK: write_event_mask_2 (); break; case HWC_CMDW_WRITEDATA: write_event_data_2 (); break; case HWC_CMDW_READDATA: unconditional_read_2 (); break; } write_event_data_1 (); } wake_up_hwc_tty (); spin_unlock (&hwc_data.lock);}int hwc_ioctl (unsigned int cmd, unsigned long arg){ hwc_ioctls_t tmp = hwc_data.ioctls; int retval = 0; unsigned long flags; unsigned int obuf; spin_lock_irqsave (&hwc_data.lock, flags); switch (cmd) { case TIOCHWCSHTAB: if (get_user (tmp.width_htab, (ioctl_htab_t *) arg)) goto fault; break; case TIOCHWCSECHO: if (get_user (tmp.echo, (ioctl_echo_t *) arg)) goto fault; break; case TIOCHWCSCOLS: if (get_user (tmp.columns, (ioctl_cols_t *) arg)) goto fault; break; case TIOCHWCSCODE: if (get_user (tmp.code, (ioctl_code_t *) arg)) goto fault; break; case TIOCHWCSNL: if (get_user (tmp.final_nl, (ioctl_nl_t *) arg)) goto fault; break; case TIOCHWCSOBUF: if (get_user (obuf, (unsigned int *) arg)) goto fault; if (obuf & 0xFFF) tmp.max_hwcb = (((obuf | 0xFFF) + 1) >> 12); else tmp.max_hwcb = (obuf >> 12); break; case TIOCHWCSCASE: if (get_user (tmp.tolower, (ioctl_case_t *) arg)) goto fault; break; case TIOCHWCSDELIM: if (get_user (tmp.delim, (ioctl_delim_t *) arg)) goto fault; break; case TIOCHWCSINIT: retval = set_hwc_ioctls (&hwc_data.init_ioctls, 1); break; case TIOCHWCGHTAB: if (put_user (tmp.width_htab, (ioctl_htab_t *) arg)) goto fault; break; case TIOCHWCGECHO: if (put_user (tmp.echo, (ioctl_echo_t *) arg)) goto fault; break; case TIOCHWCGCOLS: if (put_user (tmp.columns, (ioctl_cols_t *) arg)) goto fault; break; case TIOCHWCGCODE: if (put_user (tmp.code, (ioctl_code_t *) arg)) goto fault; break; case TIOCHWCGNL: if (put_user (tmp.final_nl, (ioctl_nl_t *) arg)) goto fault; break; case TIOCHWCGOBUF: if (put_user (tmp.max_hwcb, (ioctl_obuf_t *) arg)) goto fault; break; case TIOCHWCGKBUF: if (put_user (tmp.kmem_hwcb, (ioctl_obuf_t *) arg)) goto fault; break; case TIOCHWCGCASE: if (put_user (tmp.tolower, (ioctl_case_t *) arg)) goto fault; break; case TIOCHWCGDELIM: if (put_user (tmp.delim, (ioctl_delim_t *) arg)) goto fault; break;#if 0 case TIOCHWCGINIT: if (put_user (&hwc_data.init_ioctls, (hwc_ioctls_t *) arg)) goto fault; break; case TIOCHWCGCURR: if (put_user (&hwc_data.ioctls, (hwc_ioctls_t *) arg)) goto fault; break;#endif default: goto noioctlcmd; } if (_IOC_DIR (cmd) == _IOC_WRITE) retval = set_hwc_ioctls (&tmp, 0); goto out; fault: retval = -EFAULT; goto out; noioctlcmd: retval = -ENOIOCTLCMD; out: spin_unlock_irqrestore (&hwc_data.lock, flags); return retval;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -