📄 hwc_rw.c
字号:
internal_print ( DELAYED_WRITE, "*** " HWC_RW_PRINT_HEADER "page at 0x%x released, %i pages still in use ***\n", page, hwc_data.hwcb_count);#endif } return 0;}static int add_mto ( unsigned char *message, unsigned short int count){ unsigned short int mto_size; write_hwcb_t *hwcb; mto_t *mto; void *dest; if (!BUF_HWCB) return -ENOMEM; if (BUF_HWCB == hwc_data.current_hwcb) return -ENOMEM; mto_size = sizeof (mto_t) + count; hwcb = (write_hwcb_t *) BUF_HWCB; if ((MAX_HWCB_ROOM - hwcb->length) < mto_size) return -ENOMEM; mto = (mto_t *) (((unsigned long) hwcb) + hwcb->length); memcpy (mto, &mto_template, sizeof (mto_t)); dest = (void *) (((unsigned long) mto) + sizeof (mto_t)); memcpy (dest, message, count); mto->length += count; hwcb->length += mto_size; hwcb->msgbuf.length += mto_size; hwcb->msgbuf.mdb.length += mto_size; BUF_HWCB_MTO++; ALL_HWCB_MTO++; BUF_HWCB_CHAR += count; ALL_HWCB_CHAR += count; return count;}static int write_event_data_1 (void);static void do_poll_hwc (unsigned long data){ unsigned long flags; spin_lock_irqsave (&hwc_data.lock, flags); write_event_data_1 (); spin_unlock_irqrestore (&hwc_data.lock, flags);}void start_poll_hwc (void){ init_timer (&hwc_data.poll_timer); hwc_data.poll_timer.function = do_poll_hwc; hwc_data.poll_timer.data = (unsigned long) NULL; hwc_data.poll_timer.expires = jiffies + 2 * HZ; add_timer (&hwc_data.poll_timer); hwc_data.flags |= HWC_PTIMER_RUNS;}static int write_event_data_1 (void){ unsigned short int condition_code; int retval; write_hwcb_t *hwcb = (write_hwcb_t *) OUT_HWCB; if ((!hwc_data.write_prio) && (!hwc_data.write_nonprio) && hwc_data.read_statechange) return -EOPNOTSUPP; if (hwc_data.current_servc) return -EBUSY; retval = sane_write_hwcb (); if (retval < 0) return -EIO; if (!OUT_HWCB_MTO) return -ENODATA; if (!hwc_data.write_nonprio && hwc_data.write_prio) hwcb->msgbuf.type = ET_PMsgCmd; else hwcb->msgbuf.type = ET_Msg; condition_code = service_call (HWC_CMDW_WRITEDATA, OUT_HWCB);#ifdef DUMP_HWC_WRITE_ERROR if (condition_code != HWC_COMMAND_INITIATED) __asm__ ("LHI 1,0xe20\n\t" "L 2,0(%0)\n\t" "LRA 3,0(%1)\n\t" "J .+0 \n\t" : : "a" (&condition_code), "a" (OUT_HWCB) : "1", "2", "3");#endif switch (condition_code) { case HWC_COMMAND_INITIATED: hwc_data.current_servc = HWC_CMDW_WRITEDATA; hwc_data.current_hwcb = OUT_HWCB; retval = condition_code; break; case HWC_BUSY: retval = -EBUSY; break; case HWC_NOT_OPERATIONAL: start_poll_hwc (); default: retval = -EIO; } return retval;}static void flush_hwcbs (void){ while (hwc_data.hwcb_count > 1) release_write_hwcb (); release_write_hwcb (); hwc_data.flags &= ~HWC_FLUSH;}static int write_event_data_2 (u32 ext_int_param){ write_hwcb_t *hwcb; int retval = 0;#ifdef DUMP_HWC_WRITE_ERROR if ((ext_int_param & HWC_EXT_INT_PARAM_ADDR) != (unsigned long) hwc_data.current_hwcb) { internal_print ( DELAYED_WRITE, HWC_RW_PRINT_HEADER "write_event_data_2 : " "HWCB address does not fit " "(expected: 0x%lx, got: 0x%lx).\n", (unsigned long) hwc_data.current_hwcb, ext_int_param); return -EINVAL; }#endif hwcb = (write_hwcb_t *) OUT_HWCB;#ifdef DUMP_HWC_WRITE_LIST_ERROR if (((unsigned char *) hwcb) != hwc_data.current_hwcb) { __asm__ ("LHI 1,0xe22\n\t" "LRA 2,0(%0)\n\t" "LRA 3,0(%1)\n\t" "LRA 4,0(%2)\n\t" "LRA 5,0(%3)\n\t" "J .+0 \n\t" : : "a" (OUT_HWCB), "a" (hwc_data.current_hwcb), "a" (BUF_HWCB), "a" (hwcb) : "1", "2", "3", "4", "5"); }#endif#ifdef DUMP_HWC_WRITE_ERROR if (hwcb->response_code != 0x0020) { __asm__ ("LHI 1,0xe21\n\t" "LRA 2,0(%0)\n\t" "LRA 3,0(%1)\n\t" "LRA 4,0(%2)\n\t" "LH 5,0(%3)\n\t" "SRL 5,8\n\t" "J .+0 \n\t" : : "a" (OUT_HWCB), "a" (hwc_data.current_hwcb), "a" (BUF_HWCB), "a" (&(hwc_data.hwcb_count)) : "1", "2", "3", "4", "5"); }#endif switch (hwcb->response_code) { case 0x0020: retval = OUT_HWCB_CHAR; release_write_hwcb (); break; case 0x0040: case 0x0340: case 0x40F0: if (!hwc_data.read_statechange) { hwcb->response_code = 0; start_poll_hwc (); } retval = -EIO; break; default: internal_print ( DELAYED_WRITE, HWC_RW_PRINT_HEADER "write_event_data_2 : " "failed operation " "(response code: 0x%x " "HWCB address: 0x%x).\n", hwcb->response_code, hwcb); retval = -EIO; } if (retval == -EIO) { hwcb->control_mask[0] = 0; hwcb->control_mask[1] = 0; hwcb->control_mask[2] = 0; hwcb->response_code = 0; } hwc_data.current_servc = 0; hwc_data.current_hwcb = NULL; if (hwc_data.flags & HWC_FLUSH) flush_hwcbs (); return retval;}static void do_put_line ( unsigned char *message, unsigned short count){ if (add_mto (message, count) != count) { if (allocate_write_hwcb () < 0) reuse_write_hwcb ();#ifdef DUMP_HWC_WRITE_LIST_ERROR if (add_mto (message, count) != count) __asm__ ("LHI 1,0xe32\n\t" "LRA 2,0(%0)\n\t" "L 3,0(%1)\n\t" "LRA 4,0(%2)\n\t" "LRA 5,0(%3)\n\t" "J .+0 \n\t" : : "a" (message), "a" (&hwc_data.kmem_pages), "a" (BUF_HWCB), "a" (OUT_HWCB) : "1", "2", "3", "4", "5");#else add_mto (message, count);#endif }}static void put_line ( unsigned char *message, unsigned short count){ if ((!hwc_data.obuf_start) && (hwc_data.flags & HWC_WTIMER_RUNS)) { del_timer (&hwc_data.write_timer); hwc_data.flags &= ~HWC_WTIMER_RUNS; } hwc_data.obuf_start += count; do_put_line (message, count); hwc_data.obuf_start -= count;}static void set_alarm (void){ write_hwcb_t *hwcb; if ((!BUF_HWCB) || (BUF_HWCB == hwc_data.current_hwcb)) allocate_write_hwcb (); hwcb = (write_hwcb_t *) BUF_HWCB; hwcb->msgbuf.mdb.mdb_body.go.general_msg_flags |= GMF_SndAlrm;}static void hwc_write_timeout (unsigned long data){ unsigned long flags; spin_lock_irqsave (&hwc_data.lock, flags); hwc_data.obuf_start = hwc_data.obuf_count; if (hwc_data.obuf_count) put_line (hwc_data.obuf, hwc_data.obuf_count); hwc_data.obuf_start = 0; hwc_data.obuf_cursor = 0; hwc_data.obuf_count = 0; write_event_data_1 (); spin_unlock_irqrestore (&hwc_data.lock, flags);}static int do_hwc_write ( int from_user, unsigned char *msg, unsigned int count, unsigned char write_time){ unsigned int i_msg = 0; unsigned short int spaces = 0; unsigned int processed_characters = 0; unsigned char ch; unsigned short int obuf_count; unsigned short int obuf_cursor; unsigned short int obuf_columns; if (hwc_data.obuf_start) { obuf_cursor = 0; obuf_count = 0; obuf_columns = MIN (hwc_data.ioctls.columns, MAX_MESSAGE_SIZE - hwc_data.obuf_start); } else { obuf_cursor = hwc_data.obuf_cursor; obuf_count = hwc_data.obuf_count; obuf_columns = hwc_data.ioctls.columns; } for (i_msg = 0; i_msg < count; i_msg++) { if (from_user) get_user (ch, msg + i_msg); else ch = msg[i_msg]; processed_characters++; if ((obuf_cursor == obuf_columns) && (ch != '\n') && (ch != '\t')) { put_line (&hwc_data.obuf[hwc_data.obuf_start], obuf_columns); obuf_cursor = 0; obuf_count = 0; } switch (ch) { case '\n': put_line (&hwc_data.obuf[hwc_data.obuf_start], obuf_count); obuf_cursor = 0; obuf_count = 0; break; case '\a': hwc_data.obuf_start += obuf_count; set_alarm (); hwc_data.obuf_start -= obuf_count; break; case '\t': do { if (obuf_cursor < obuf_columns) { hwc_data.obuf[hwc_data.obuf_start + obuf_cursor] = HWC_ASCEBC (' '); obuf_cursor++; } else break; } while (obuf_cursor % hwc_data.ioctls.width_htab); break; case '\f': case '\v': spaces = obuf_cursor; put_line (&hwc_data.obuf[hwc_data.obuf_start], obuf_count); obuf_count = obuf_cursor; while (spaces) { hwc_data.obuf[hwc_data.obuf_start + obuf_cursor - spaces] = HWC_ASCEBC (' '); spaces--; } break; case '\b': if (obuf_cursor) obuf_cursor--; break; case '\r': obuf_cursor = 0; break; case 0x00: put_line (&hwc_data.obuf[hwc_data.obuf_start], obuf_count); obuf_cursor = 0; obuf_count = 0; goto out; default: if (isprint (ch)) hwc_data.obuf[hwc_data.obuf_start + obuf_cursor++] = HWC_ASCEBC (ch); } if (obuf_cursor > obuf_count) obuf_count = obuf_cursor; } if (obuf_cursor) { if (hwc_data.obuf_start || (hwc_data.ioctls.final_nl == 0)) { put_line (&hwc_data.obuf[hwc_data.obuf_start], obuf_count); obuf_cursor = 0; obuf_count = 0; } else { if (hwc_data.ioctls.final_nl > 0) { if (hwc_data.flags & HWC_WTIMER_RUNS) { mod_timer (&hwc_data.write_timer, jiffies + hwc_data.ioctls.final_nl * HZ / 10); } else { init_timer (&hwc_data.write_timer); hwc_data.write_timer.function = hwc_write_timeout; hwc_data.write_timer.data = (unsigned long) NULL; hwc_data.write_timer.expires = jiffies + hwc_data.ioctls.final_nl * HZ / 10; add_timer (&hwc_data.write_timer); hwc_data.flags |= HWC_WTIMER_RUNS; } } else; } } else; out: if (!hwc_data.obuf_start) { hwc_data.obuf_cursor = obuf_cursor; hwc_data.obuf_count = obuf_count; } if (write_time == IMMEDIATE_WRITE) write_event_data_1 (); return processed_characters;}signed int hwc_write (int from_user, const unsigned char *msg, unsigned int count){ unsigned long flags; int retval; spin_lock_irqsave (&hwc_data.lock, flags); retval = do_hwc_write (from_user, (unsigned char *) msg, count, IMMEDIATE_WRITE); spin_unlock_irqrestore (&hwc_data.lock, flags); return retval;}unsigned int hwc_chars_in_buffer (unsigned char flag){ unsigned short int number = 0; unsigned long flags; spin_lock_irqsave (&hwc_data.lock, flags); if (flag & IN_HWCB) number += ALL_HWCB_CHAR; if (flag & IN_WRITE_BUF) number += hwc_data.obuf_cursor; spin_unlock_irqrestore (&hwc_data.lock, flags); return number;}static inline int nr_setbits (kmem_pages_t arg){ int i; int nr = 0; for (i = 0; i < (sizeof (arg) << 3); i++) { if (arg & 1) nr++; arg >>= 1; } return nr;}unsigned int hwc_write_room (unsigned char flag){ unsigned int number = 0; unsigned long flags; write_hwcb_t *hwcb; spin_lock_irqsave (&hwc_data.lock, flags); if (flag & IN_HWCB) { if (BUF_HWCB) { hwcb = (write_hwcb_t *) BUF_HWCB; number += MAX_HWCB_ROOM - hwcb->length; } number += (hwc_data.ioctls.kmem_hwcb - nr_setbits (hwc_data.kmem_pages)) * (MAX_HWCB_ROOM - (sizeof (write_hwcb_t) + sizeof (mto_t))); } if (flag & IN_WRITE_BUF) number += MAX_HWCB_ROOM - hwc_data.obuf_cursor; spin_unlock_irqrestore (&hwc_data.lock, flags); return number;}void hwc_flush_buffer (unsigned char flag){ unsigned long flags; spin_lock_irqsave (&hwc_data.lock, flags); if (flag & IN_HWCB) { if (hwc_data.current_servc != HWC_CMDW_WRITEDATA) flush_hwcbs (); else hwc_data.flags |= HWC_FLUSH; } if (flag & IN_WRITE_BUF) { hwc_data.obuf_cursor = 0; hwc_data.obuf_count = 0; } spin_unlock_irqrestore (&hwc_data.lock, flags);}unsigned short int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -