* Register a new event timer hardware. */
| 53 | * Register a new event timer hardware. |
| 54 | */ |
| 55 | int |
| 56 | et_register(struct eventtimer *et) |
| 57 | { |
| 58 | struct eventtimer *tmp, *next; |
| 59 | |
| 60 | if (et->et_quality >= 0 || bootverbose) { |
| 61 | if (et->et_frequency == 0) { |
| 62 | printf("Event timer \"%s\" quality %d\n", |
| 63 | et->et_name, et->et_quality); |
| 64 | } else { |
| 65 | printf("Event timer \"%s\" " |
| 66 | "frequency %ju Hz quality %d\n", |
| 67 | et->et_name, (uintmax_t)et->et_frequency, |
| 68 | et->et_quality); |
| 69 | } |
| 70 | } |
| 71 | KASSERT(et->et_start, ("et_register: timer has no start function")); |
| 72 | et->et_sysctl = SYSCTL_ADD_NODE_WITH_LABEL(NULL, |
| 73 | SYSCTL_STATIC_CHILDREN(_kern_eventtimer_et), OID_AUTO, et->et_name, |
| 74 | CTLFLAG_RW | CTLFLAG_MPSAFE, 0, |
| 75 | "event timer description", "eventtimer"); |
| 76 | SYSCTL_ADD_INT(NULL, SYSCTL_CHILDREN(et->et_sysctl), OID_AUTO, |
| 77 | "flags", CTLFLAG_RD, &(et->et_flags), 0, |
| 78 | "Event timer capabilities"); |
| 79 | SYSCTL_ADD_UQUAD(NULL, SYSCTL_CHILDREN(et->et_sysctl), OID_AUTO, |
| 80 | "frequency", CTLFLAG_RD, &(et->et_frequency), |
| 81 | "Event timer base frequency"); |
| 82 | SYSCTL_ADD_INT(NULL, SYSCTL_CHILDREN(et->et_sysctl), OID_AUTO, |
| 83 | "quality", CTLFLAG_RD, &(et->et_quality), 0, |
| 84 | "Goodness of event timer"); |
| 85 | ET_LOCK(); |
| 86 | if (SLIST_EMPTY(&eventtimers) || |
| 87 | SLIST_FIRST(&eventtimers)->et_quality < et->et_quality) { |
| 88 | SLIST_INSERT_HEAD(&eventtimers, et, et_all); |
| 89 | } else { |
| 90 | SLIST_FOREACH(tmp, &eventtimers, et_all) { |
| 91 | next = SLIST_NEXT(tmp, et_all); |
| 92 | if (next == NULL || next->et_quality < et->et_quality) { |
| 93 | SLIST_INSERT_AFTER(tmp, et, et_all); |
| 94 | break; |
| 95 | } |
| 96 | } |
| 97 | } |
| 98 | ET_UNLOCK(); |
| 99 | return (0); |
| 100 | } |
| 101 | |
| 102 | /* |
| 103 | * Deregister event timer hardware. |
no test coverage detected