DF-5356 / rig2_shims.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 | /* * rig2_shims.h -- KERNEL-ENVIRONMENT EMULATION for the verbatim pccard.c * lifecycle rig (DF-2318 / DF-5355 / DF-5356). * * *** NOT VERBATIM *** -- everything the machine-extracted production code * (pccard_core.inc from sys/bus/pccard/pccard.c, * pccard_cis_core.inc from sys/bus/pccard/pccard_cis.c, * subrbus_rl.inc from sys/kern/subr_bus.c) * needs from the kernel environment, emulated in userland: * * - device_t is a fake device object; the device method layer * (device_add_child / device_probe_and_attach / device_get_state ...) * mirrors the production subr_bus.c semantics that matter here: * device_doattach(): attach ok -> devadded(dev) -> bus_child_pnpinfo_str * (subr_bus.c:2107-2114, :633-645) * probe/attach fail -> devnomatch(dev) -> bus_child_pnpinfo_str * (subr_bus.c:1984/2039 -> :673) * - bus_alloc_resource() implements a bridge window model: * SYS_RES_IOPORT window [0x110,0x2FF]; fixed ranges granted iff they * fit; "anywhere" (start==0) granted at the cursor. * This is the policy a real pcic/cbb bridge enforces * (its PCI I/O window is finite; fixed host ranges * outside it cannot be decoded). * SYS_RES_MEMORY size 4096 -> the CIS attribute/common window * (swapped by CARD_SET_RES_FLAGS, as in DF-2319). * SYS_RES_MEMORY size 1024 RF_ACTIVE -> the CCR mapping window. * - kmalloc/kfree are canary-banded and ledgered (leak accounting). * - panic() prints "RIG KERNEL PANIC: <msg>" and exits 42 -- the userland * analogue of the kernel's panic (which halts the system). */ #ifndef RIG2_SHIMS_H #define RIG2_SHIMS_H #include <sys/types.h> #include <sys/queue.h> /* byte-identical to kernel sys/sys/queue.h (hash-checked) */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <stdarg.h> #include <setjmp.h> #include <signal.h> #include <unistd.h> #include <errno.h> /* ---------------- kernel types ---------------- */ typedef void driver_intr_t_(void); #define driver_intr_t driver_intr_t_ /* resource types (sys/sys/bus_resource.h:41-44, production values) */ #define SYS_RES_IRQ 1 #define SYS_RES_DRQ 2 #define SYS_RES_MEMORY 3 #define SYS_RES_IOPORT 4 #define RF_ACTIVE 0x01 #define RF_SHAREABLE 0x80 #define rman_make_alignment_flags(x) 0 /* device states (sys/sys/bus.h:76-81) */ enum rig_devstate { DS_NOTPRESENT, DS_ALIVE, DS_ATTACHING, DS_ATTACHED, DS_BUSY }; /* ---------------- debug knobs (owned here; verbatim code externs them) - */ int pccard_debug = 0; int pccard_cis_debug = 0; int bootverbose = 0; #define kprintf printf #define ksnprintf snprintf #define ksprintf sprintf #define device_printf(d, ...) printf("pccard0: " __VA_ARGS__) #ifndef howmany #define howmany(x, y) (((x)+((y)-1))/(y)) #endif #define bzero(p, n) memset((p), 0, (n)) static void rig_panic(const char *fmt, ...) { va_list ap; va_start(ap, fmt); printf("RIG KERNEL PANIC: "); vprintf(fmt, ap); printf("\n"); va_end(ap); fflush(stdout); _exit(42); /* the kernel would halt here */ } #define panic rig_panic /* ---------------- allocation ledger ---------------- */ #define RIG_MAX_BLOCKS 65536 #define RIG_CANARY 0xC3 #define M_DEVBUF 0 #define M_BUS 1 #define M_NOWAIT 1 #define M_WAITOK 2 #define M_INTWAIT 2 #define M_ZERO 4 struct rig_block { void *p; size_t size; int live; const char *site; }; static struct rig_block rig_blocks[RIG_MAX_BLOCKS]; static int rig_nblocks; static void * rig_kmalloc(size_t sz, int flags, const char *site) { unsigned char *p, *q; size_t i; if (rig_nblocks >= RIG_MAX_BLOCKS) return NULL; p = malloc(sz + 16); if (p == NULL) return NULL; for (i = 0; i < 8; i++) p[i] = RIG_CANARY; q = p + 8 + sz; for (i = 0; i < 8; i++) q[i] = RIG_CANARY; if (flags & M_ZERO) memset(p + 8, 0, sz); rig_blocks[rig_nblocks].p = p + 8; rig_blocks[rig_nblocks].size = sz; rig_blocks[rig_nblocks].live = 1; rig_blocks[rig_nblocks].site = site; rig_nblocks++; return p + 8; } #define kmalloc(sz, type, flags) rig_kmalloc((sz), (flags), __func__) static void rig_kfree(void *p, const char *site) { int i; unsigned char *raw; size_t k, sz; if (p == NULL) return; for (i = rig_nblocks - 1; i >= 0; i--) if (rig_blocks[i].p == p) break; if (i < 0) { printf("RIG kfree(%p) of UNREGISTERED block (%s)\n", p, site); abort(); } if (!rig_blocks[i].live) { printf("RIG DOUBLE FREE of %p (%s)\n", p, site); abort(); } sz = rig_blocks[i].size; raw = (unsigned char *)p - 8; for (k = 0; k < 8; k++) if (raw[k] != RIG_CANARY || raw[sz + 8 + k] != RIG_CANARY) { printf("RIG HEAP SMASH on block %p (%zu bytes, %s)\n", p, sz, rig_blocks[i].site); abort(); } rig_blocks[i].live = 0; free(raw); } #define kfree(p, type) rig_kfree((p), __func__) /* ---------------- fake device tree ---------------- */ struct rig_device { struct rig_device *parent; struct rig_device *next; /* global tracking list */ void *ivars; int state; int deleted; char nameunit[32]; char desc[96]; }; typedef struct rig_device *device_t; extern struct rig_device rig_bus_dev; /* the pccard bus device (pccard0) */ extern struct rig_device rig_bridge_dev; /* pcic/cbb bridge (parent) */ extern struct rig_device *rig_devices; /* every child ever added */ extern int rig_nchildren; /* probe/attach policy for device_probe_and_attach(): how the driver layer * answers for pccard function children */ enum rig_probe_mode { PROBE_ATTACH_OK, /* probe+attach succeed -> devadded path */ PROBE_FAIL, /* probe fails -> devnomatch path */ PROBE_SILENT_FAIL /* fails but suppress the notify (rig-only) */ }; extern int rig_probe_mode; static __inline device_t device_add_child(device_t parent, const char *name, int unit) { device_t d = rig_kmalloc(sizeof(struct rig_device), M_ZERO, "device_add_child"); device_t *tp = &rig_devices; (void)name; (void)unit; d->parent = parent; d->state = DS_NOTPRESENT; snprintf(d->nameunit, sizeof(d->nameunit), "pccardfunc%d", rig_nchildren++); while (*tp != NULL) tp = &(*tp)->next; *tp = d; return d; } static __inline void device_set_ivars(device_t d, void *iv) { d->ivars = iv; } static __inline void * device_get_ivars(device_t d) { return d->ivars; } static __inline device_t device_get_parent(device_t d) { return d->parent; } static __inline int device_get_state(device_t d) { return d->state; } static __inline const char *device_get_nameunit(device_t d) { return d->nameunit; } static __inline void device_set_desc_copy(device_t d, const char *s) { snprintf(d->desc, sizeof(d->desc), "%s", s); } static __inline int device_get_unit(device_t d) { (void)d; return 0; } /* device_get_softc: only the pccard bus device has a softc here; the storage * is defined in rig2_main.c (type known after the verbatim includes). */ extern void *rig_sc_ptr; static __inline void * device_get_softc(device_t d) { (void)d; return rig_sc_ptr; } int bus_child_pnpinfo_str(device_t child, char *buf, size_t buflen); /* Emulates production device_probe_and_attach() -> device_doattach() * (subr_bus.c:2107-2114): on attach success devadded(dev) calls * bus_child_pnpinfo_str(); on probe failure devnomatch(dev) does the same * (subr_bus.c:1984/2039 -> :673). */ static __inline int device_probe_and_attach(device_t d) { char buf[1024]; if (rig_probe_mode == PROBE_ATTACH_OK) { d->state = DS_ATTACHED; *buf = '\0'; bus_child_pnpinfo_str(d, buf, sizeof(buf)); /* devadded() */ printf(" [devadded] %s pnpinfo=\"%s\"\n", d->nameunit, buf); return (0); } if (rig_probe_mode == PROBE_FAIL) { *buf = '\0'; bus_child_pnpinfo_str(d, buf, sizeof(buf)); /* devnomatch() */ } return (ENXIO); } static __inline int device_detach(device_t d) { d->state = DS_NOTPRESENT; return (0); } static __inline int device_delete_child(device_t p, device_t d) { (void)p; d->deleted = 1; d->state = DS_NOTPRESENT; return (0); } /* forward decl: defined VERBATIM in pccard_core.inc (static) */ static int pccard_child_pnpinfo_str(device_t bus, device_t child, char *buf, size_t buflen); /* BUS_CHILD_PNPINFO_STR method dispatch: the pccard bus is the only bus with * children in this rig, so the method resolves to the verbatim pccard * implementation (production DEVMETHOD table, pccard.c:1340). */ #define BUS_CHILD_PNPINFO_STR(p, c, b, l) pccard_child_pnpinfo_str((p), (c), (b), (l)) /* BUS_READ_IVAR dispatch -> verbatim pccard_read_ivar (pccard.c:1339 table); * defined in rig2_main.c after the verbatim code is visible. */ int rig_bus_read_ivar(device_t bus, device_t dev, int which, u_char *result); #define BUS_READ_IVAR(p, d, w, r) rig_bus_read_ivar((p), (d), (w), (u_char *)(r)) #define BUS_TEARDOWN_INTR(d, c, r, ck) ((void)0) /* intr_handler stays NULL */ /* CARD interface methods (card_if.h) -> bridge shims */ extern long rig_power_enables, rig_power_disables; extern long rig_flag_switches; #define POWER_ENABLE_SOCKET(p, d) (rig_power_enables++) #define POWER_DISABLE_SOCKET(p, d) (rig_power_disables++) /* ---------------- rman / resource emulation ---------------- */ typedef struct resource *bus_space_tag_t; typedef unsigned char *bus_space_handle_t; typedef unsigned long bus_addr_t; typedef unsigned long bus_size_t; struct resource { unsigned char *handle; size_t size; unsigned long start, end; device_t owner; }; #define RIG_MAPSIZE 4096 /* PCCARD_CIS_SIZE */ #define RIG_TOTBUF 65536 /* guard: [4096,65536) canary zone */ #define RIG_CCRBUF 4096 extern unsigned char rig_attr_img[RIG_TOTBUF]; extern unsigned char rig_com_img[RIG_TOTBUF]; extern unsigned char rig_ccr_img[RIG_CCRBUF]; extern struct resource rig_cis_res; extern struct resource rig_ccr_res; extern struct resource rig_irq_res; extern int rig_space; /* 0=attribute 1=common */ /* IOPORT window model (what a finite bridge window grants) */ #define RIG_IO_WIN_START 0x110 #define RIG_IO_WIN_END 0x2FF extern unsigned long rig_io_cursor; extern long rig_io_grants, rig_io_releases; extern long rig_ccr_allocs, rig_ccr_releases; #define RIG_IO_POOL 64 extern struct resource rig_io_pool[RIG_IO_POOL]; struct resource *rig_bus_alloc_io(unsigned long start, unsigned long end, unsigned long count); static __inline struct resource * bus_alloc_resource(device_t dev, int type, int *rid, bus_addr_t start, bus_addr_t end, bus_size_t size, u_int flags) { struct resource *r; (void)dev; (void)rid; if (type == SYS_RES_MEMORY && size == RIG_MAPSIZE) { /* CIS window (pccard_cis.c:130-131) */ rig_cis_res.handle = rig_attr_img; rig_space = 0; return &rig_cis_res; } if (type == SYS_RES_MEMORY && size == (1 << 10) && (flags & RF_ACTIVE)) { /* CCR mapping (pccard.c:629-630) */ rig_ccr_allocs++; rig_ccr_res.owner = dev; return &rig_ccr_res; } if (type == SYS_RES_IOPORT) { r = rig_bus_alloc_io(start, end, size); if (r != NULL) r->owner = dev; return r; } return NULL; } static __inline struct resource * bus_alloc_resource_any(device_t dev, int type, int *rid, u_int flags) { (void)dev; (void)rid; (void)flags; if (type == SYS_RES_IRQ) return &rig_irq_res; return NULL; } static __inline int bus_release_resource(device_t dev, int type, int rid, struct resource *res) { int i; (void)dev; (void)type; (void)rid; if (res == &rig_ccr_res) { rig_ccr_releases++; return 0; } if (res == &rig_cis_res || res == &rig_irq_res) return 0; for (i = 0; i < RIG_IO_POOL; i++) if (res == &rig_io_pool[i] && res->size != 0) { res->size = 0; rig_io_releases++; return 0; } return 0; } #define BUS_RELEASE_RESOURCE(p, d, t, r, res) bus_release_resource((d), (t), (r), (res)) static __inline bus_space_tag_t rman_get_bustag(struct resource *r) { return (bus_space_tag_t)r; } static __inline bus_space_handle_t rman_get_bushandle(struct resource *r) { return r->handle; } static __inline unsigned long rman_get_start(struct resource *r) { return r->start; } static __inline unsigned long rman_get_end(struct resource *r) { return r->end; } static __inline unsigned long rman_get_size(struct resource *r) { return r->size; } static __inline device_t rman_get_device(struct resource *r) { return r->owner; } static __inline void rman_set_device(struct resource *r, device_t d) { r->owner = d; } static __inline int rman_get_cpuid(struct resource *r) { (void)r; return 0; } /* CARD_SET_RES_FLAGS: swap the active CIS image (attr/common). The CCR * window call (pccard.c:636-637) is a no-op for the rig's static window. */ static __inline int rig_CARD_SET_RES_FLAGS(device_t p, device_t d, int t, int r, int flags) { (void)p; (void)d; (void)t; (void)r; rig_flag_switches++; rig_space = (flags == 0); /* 0 == PCCARD_A_MEM_COM */ rig_cis_res.handle = rig_space ? rig_com_img : rig_attr_img; return 0; } #define CARD_SET_RES_FLAGS(p, d, t, r, f) \ rig_CARD_SET_RES_FLAGS((p), (d), (t), (r), (f)) static __inline int rig_CARD_SET_MEMORY_OFFSET(device_t p, device_t d, int r, uint32_t off, uint32_t *deltap) { (void)p; (void)d; (void)r; *deltap = off & (RIG_CCRBUF - 1); return 0; } #define CARD_SET_MEMORY_OFFSET(p, d, r, o, dp) \ rig_CARD_SET_MEMORY_OFFSET((p), (d), (r), (o), (dp)) /* ---------------- bus space ---------------- */ static __inline uint8_t bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t off) { (void)t; if (h == rig_ccr_img) { if (off >= RIG_CCRBUF) { printf("RIG CCR READ OOB off=%lu\n", (unsigned long)off); abort(); } return h[off]; } if (off >= RIG_TOTBUF) return 0xFF; /* wild: master-abort analogue */ return h[off]; } static __inline void bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t off, uint8_t v) { (void)t; if (h == rig_ccr_img) { if (off >= RIG_CCRBUF) { printf("RIG CCR WRITE OOB off=%lu\n", (unsigned long)off); abort(); } h[off] = v; return; } printf("RIG UNEXPECTED bus_space_write_1 off=%lu v=%#x (dropped)\n", (unsigned long)off, v); } #endif /* RIG2_SHIMS_H */ |