📄 ibmphp_hpc.c
字号:
*---------------------------------------------------------------------*/static void get_hpc_access (void){ down (&sem_hpcaccess);}/*----------------------------------------------------------------------* Name: free_hpc_access()*---------------------------------------------------------------------*/void free_hpc_access (void){ up (&sem_hpcaccess);}/*----------------------------------------------------------------------* Name: ibmphp_lock_operations()** Action: make sure only one process can change the data structure*---------------------------------------------------------------------*/void ibmphp_lock_operations (void){ down (&semOperations); to_debug = TRUE;}/*----------------------------------------------------------------------* Name: ibmphp_unlock_operations()*---------------------------------------------------------------------*/void ibmphp_unlock_operations (void){ debug ("%s - Entry\n", __FUNCTION__); up (&semOperations); to_debug = FALSE; debug ("%s - Exit\n", __FUNCTION__);}/*----------------------------------------------------------------------* Name: poll_hpc()*---------------------------------------------------------------------*/#define POLL_LATCH_REGISTER 0#define POLL_SLOTS 1#define POLL_SLEEP 2static void poll_hpc (void){ struct slot myslot; struct slot *pslot = NULL; struct list_head *pslotlist; int rc; int poll_state = POLL_LATCH_REGISTER; u8 oldlatchlow = 0x00; u8 curlatchlow = 0x00; int poll_count = 0; u8 ctrl_count = 0x00; debug ("%s - Entry\n", __FUNCTION__); while (!ibmphp_shutdown) { if (ibmphp_shutdown) break; /* try to get the lock to do some kind of harware access */ down (&semOperations); switch (poll_state) { case POLL_LATCH_REGISTER: oldlatchlow = curlatchlow; ctrl_count = 0x00; list_for_each (pslotlist, &ibmphp_slot_head) { if (ctrl_count >= ibmphp_get_total_controllers()) break; pslot = list_entry (pslotlist, struct slot, ibm_slot_list); if (pslot->ctrl->ctlr_relative_id == ctrl_count) { ctrl_count++; if (READ_SLOT_LATCH (pslot->ctrl)) { rc = ibmphp_hpc_readslot (pslot, READ_SLOTLATCHLOWREG, &curlatchlow); if (oldlatchlow != curlatchlow) process_changeinlatch (oldlatchlow, curlatchlow, pslot->ctrl); } } } ++poll_count; poll_state = POLL_SLEEP; break; case POLL_SLOTS: list_for_each (pslotlist, &ibmphp_slot_head) { pslot = list_entry (pslotlist, struct slot, ibm_slot_list); // make a copy of the old status memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot)); rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL); if ((myslot.status != pslot->status) || (myslot.ext_status != pslot->ext_status)) process_changeinstatus (pslot, &myslot); } ctrl_count = 0x00; list_for_each (pslotlist, &ibmphp_slot_head) { if (ctrl_count >= ibmphp_get_total_controllers()) break; pslot = list_entry (pslotlist, struct slot, ibm_slot_list); if (pslot->ctrl->ctlr_relative_id == ctrl_count) { ctrl_count++; if (READ_SLOT_LATCH (pslot->ctrl)) rc = ibmphp_hpc_readslot (pslot, READ_SLOTLATCHLOWREG, &curlatchlow); } } ++poll_count; poll_state = POLL_SLEEP; break; case POLL_SLEEP: /* don't sleep with a lock on the hardware */ up (&semOperations); long_delay (POLL_INTERVAL_SEC * HZ); if (ibmphp_shutdown) break; down (&semOperations); if (poll_count >= POLL_LATCH_CNT) { poll_count = 0; poll_state = POLL_SLOTS; } else poll_state = POLL_LATCH_REGISTER; break; } /* give up the harware semaphore */ up (&semOperations); /* sleep for a short time just for good measure */ set_current_state (TASK_INTERRUPTIBLE); schedule_timeout (HZ/10); } up (&sem_exit); debug ("%s - Exit\n", __FUNCTION__);}/*----------------------------------------------------------------------* Name: process_changeinstatus** Action: compare old and new slot status, process the change in status** Input: pointer to slot struct, old slot struct** Return 0 or error codes* Value:** Side* Effects: None.** Notes:*---------------------------------------------------------------------*/static int process_changeinstatus (struct slot *pslot, struct slot *poldslot){ u8 status; int rc = 0; u8 disable = FALSE; u8 update = FALSE; debug ("process_changeinstatus - Entry pslot[%p], poldslot[%p]\n", pslot, poldslot); // bit 0 - HPC_SLOT_POWER if ((pslot->status & 0x01) != (poldslot->status & 0x01)) update = TRUE; // bit 1 - HPC_SLOT_CONNECT // ignore // bit 2 - HPC_SLOT_ATTN if ((pslot->status & 0x04) != (poldslot->status & 0x04)) update = TRUE; // bit 3 - HPC_SLOT_PRSNT2 // bit 4 - HPC_SLOT_PRSNT1 if (((pslot->status & 0x08) != (poldslot->status & 0x08)) || ((pslot->status & 0x10) != (poldslot->status & 0x10))) update = TRUE; // bit 5 - HPC_SLOT_PWRGD if ((pslot->status & 0x20) != (poldslot->status & 0x20)) // OFF -> ON: ignore, ON -> OFF: disable slot if ((poldslot->status & 0x20) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) disable = TRUE; // bit 6 - HPC_SLOT_BUS_SPEED // ignore // bit 7 - HPC_SLOT_LATCH if ((pslot->status & 0x80) != (poldslot->status & 0x80)) { update = TRUE; // OPEN -> CLOSE if (pslot->status & 0x80) { if (SLOT_PWRGD (pslot->status)) { // power goes on and off after closing latch // check again to make sure power is still ON long_delay (1 * HZ); rc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &status); if (SLOT_PWRGD (status)) update = TRUE; else // overwrite power in pslot to OFF pslot->status &= ~HPC_SLOT_POWER; } } // CLOSE -> OPEN else if ((SLOT_PWRGD (poldslot->status) == HPC_SLOT_PWRGD_GOOD) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) { disable = TRUE; } // else - ignore } // bit 4 - HPC_SLOT_BLINK_ATTN if ((pslot->ext_status & 0x08) != (poldslot->ext_status & 0x08)) update = TRUE; if (disable) { debug ("process_changeinstatus - disable slot\n"); pslot->flag = FALSE; rc = ibmphp_do_disable_slot (pslot); } if (update || disable) { ibmphp_update_slot_info (pslot); } debug ("%s - Exit rc[%d] disable[%x] update[%x]\n", __FUNCTION__, rc, disable, update); return rc;}/*----------------------------------------------------------------------* Name: process_changeinlatch** Action: compare old and new latch reg status, process the change** Input: old and current latch register status** Return 0 or error codes* Value:*---------------------------------------------------------------------*/static int process_changeinlatch (u8 old, u8 new, struct controller *ctrl){ struct slot myslot, *pslot; u8 i; u8 mask; int rc = 0; debug ("%s - Entry old[%x], new[%x]\n", __FUNCTION__, old, new); // bit 0 reserved, 0 is LSB, check bit 1-6 for 6 slots for (i = ctrl->starting_slot_num; i <= ctrl->ending_slot_num; i++) { mask = 0x01 << i; if ((mask & old) != (mask & new)) { pslot = ibmphp_get_slot_from_physical_num (i); if (pslot) { memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot)); rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL); debug ("%s - call process_changeinstatus for slot[%d]\n", __FUNCTION__, i); process_changeinstatus (pslot, &myslot); } else { rc = -EINVAL; err ("%s - Error bad pointer for slot[%d]\n", __FUNCTION__, i); } } } debug ("%s - Exit rc[%d]\n", __FUNCTION__, rc); return rc;}/*----------------------------------------------------------------------* Name: hpc_poll_thread** Action: polling** Return 0* Value:*---------------------------------------------------------------------*/static int hpc_poll_thread (void *data){ debug ("%s - Entry\n", __FUNCTION__); daemonize("hpc_poll"); allow_signal(SIGKILL); poll_hpc (); tid_poll = 0; debug ("%s - Exit\n", __FUNCTION__); return 0;}/*----------------------------------------------------------------------* Name: ibmphp_hpc_start_poll_thread** Action: start polling thread*---------------------------------------------------------------------*/int __init ibmphp_hpc_start_poll_thread (void){ int rc = 0; debug ("%s - Entry\n", __FUNCTION__); tid_poll = kernel_thread (hpc_poll_thread, NULL, 0); if (tid_poll < 0) { err ("%s - Error, thread not started\n", __FUNCTION__); rc = -1; } debug ("%s - Exit tid_poll[%d] rc[%d]\n", __FUNCTION__, tid_poll, rc); return rc;}/*----------------------------------------------------------------------* Name: ibmphp_hpc_stop_poll_thread** Action: stop polling thread and cleanup*---------------------------------------------------------------------*/void __exit ibmphp_hpc_stop_poll_thread (void){ debug ("%s - Entry\n", __FUNCTION__); ibmphp_shutdown = TRUE; debug ("before locking operations \n"); ibmphp_lock_operations (); debug ("after locking operations \n"); // wait for poll thread to exit debug ("before sem_exit down \n"); down (&sem_exit); debug ("after sem_exit down \n"); // cleanup debug ("before free_hpc_access \n"); free_hpc_access (); debug ("after free_hpc_access \n"); ibmphp_unlock_operations (); debug ("after unlock operations \n"); up (&sem_exit); debug ("after sem exit up\n"); debug ("%s - Exit\n", __FUNCTION__);}/*----------------------------------------------------------------------* Name: hpc_wait_ctlr_notworking** Action: wait until the controller is in a not working state** Return 0, HPC_ERROR* Value:*---------------------------------------------------------------------*/static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, void *wpg_bbar, u8 * pstatus){ int rc = 0; u8 done = FALSE; debug_polling ("hpc_wait_ctlr_notworking - Entry timeout[%d]\n", timeout); while (!done) { *pstatus = ctrl_read (ctlr_ptr, wpg_bbar, WPG_CTLR_INDEX); if (*pstatus == HPC_ERROR) { rc = HPC_ERROR; done = TRUE; } if (CTLR_WORKING (*pstatus) == HPC_CTLR_WORKING_NO) done = TRUE; if (!done) { long_delay (1 * HZ); if (timeout < 1) { done = TRUE; err ("HPCreadslot - Error ctlr timeout\n"); rc = HPC_ERROR; } else timeout--; } } debug_polling ("hpc_wait_ctlr_notworking - Exit rc[%x] status[%x]\n", rc, *pstatus); return rc;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -