Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/kshim/bsd_kernel.c
34677 views
1
/*-
2
* Copyright (c) 2013 Hans Petter Selasky. All rights reserved.
3
*
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
6
* are met:
7
* 1. Redistributions of source code must retain the above copyright
8
* notice, this list of conditions and the following disclaimer.
9
* 2. Redistributions in binary form must reproduce the above copyright
10
* notice, this list of conditions and the following disclaimer in the
11
* documentation and/or other materials provided with the distribution.
12
*
13
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23
* SUCH DAMAGE.
24
*/
25
26
#include <bsd_global.h>
27
28
struct usb_process usb_process[USB_PROC_MAX];
29
30
static device_t usb_pci_root;
31
32
int (*bus_alloc_resource_any_cb)(struct resource *res, device_t dev,
33
int type, int *rid, unsigned int flags);
34
int (*ofw_bus_status_ok_cb)(device_t dev);
35
int (*ofw_bus_is_compatible_cb)(device_t dev, char *name);
36
37
/*------------------------------------------------------------------------*
38
* Implementation of busdma API
39
*------------------------------------------------------------------------*/
40
int
41
bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
42
bus_size_t boundary, bus_addr_t lowaddr,
43
bus_addr_t highaddr, bus_dma_filter_t *filter,
44
void *filterarg, bus_size_t maxsize, int nsegments,
45
bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc,
46
void *lockfuncarg, bus_dma_tag_t *dmat)
47
{
48
struct bus_dma_tag *ret;
49
50
ret = malloc(sizeof(struct bus_dma_tag), XXX, XXX);
51
if (*dmat == NULL)
52
return (ENOMEM);
53
ret->alignment = alignment;
54
ret->maxsize = maxsize;
55
56
*dmat = ret;
57
58
return (0);
59
}
60
61
int
62
bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
63
bus_dmamap_t *mapp)
64
{
65
void *addr;
66
67
addr = malloc(dmat->maxsize + dmat->alignment, XXX, XXX);
68
if (addr == NULL)
69
return (ENOMEM);
70
71
*mapp = addr;
72
addr = (void*)(((uintptr_t)addr + dmat->alignment - 1) & ~(dmat->alignment - 1));
73
74
*vaddr = addr;
75
return (0);
76
}
77
78
int
79
bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
80
bus_size_t buflen, bus_dmamap_callback_t *callback,
81
void *callback_arg, int flags)
82
{
83
bus_dma_segment_t segs[1];
84
85
segs[0].ds_addr = (uintptr_t)buf;
86
segs[0].ds_len = buflen;
87
88
(*callback)(callback_arg, segs, 1, 0);
89
90
return (0);
91
}
92
93
void
94
bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, int flags)
95
{
96
/* Assuming coherent memory */
97
__asm__ __volatile__("": : :"memory");
98
}
99
100
void
101
bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)
102
{
103
104
free(map, XXX);
105
}
106
107
int
108
bus_dma_tag_destroy(bus_dma_tag_t dmat)
109
{
110
111
free(dmat, XXX);
112
return (0);
113
}
114
115
/*------------------------------------------------------------------------*
116
* Implementation of resource management API
117
*------------------------------------------------------------------------*/
118
119
struct resource *
120
bus_alloc_resource_any(device_t dev, int type, int *rid, unsigned int flags)
121
{
122
struct resource *res;
123
int ret = EINVAL;
124
125
res = malloc(sizeof(*res), XXX, XXX);
126
if (res == NULL)
127
return (NULL);
128
129
res->__r_i = malloc(sizeof(struct resource_i), XXX, XXX);
130
if (res->__r_i == NULL) {
131
free(res, XXX);
132
return (NULL);
133
}
134
135
if (bus_alloc_resource_any_cb != NULL)
136
ret = (*bus_alloc_resource_any_cb)(res, dev, type, rid, flags);
137
if (ret == 0)
138
return (res);
139
140
free(res->__r_i, XXX);
141
free(res, XXX);
142
return (NULL);
143
}
144
145
int
146
bus_alloc_resources(device_t dev, struct resource_spec *rs,
147
struct resource **res)
148
{
149
int i;
150
151
for (i = 0; rs[i].type != -1; i++)
152
res[i] = NULL;
153
for (i = 0; rs[i].type != -1; i++) {
154
res[i] = bus_alloc_resource_any(dev,
155
rs[i].type, &rs[i].rid, rs[i].flags);
156
if (res[i] == NULL && !(rs[i].flags & RF_OPTIONAL)) {
157
bus_release_resources(dev, rs, res);
158
return (ENXIO);
159
}
160
}
161
return (0);
162
}
163
164
void
165
bus_release_resources(device_t dev, const struct resource_spec *rs,
166
struct resource **res)
167
{
168
int i;
169
170
for (i = 0; rs[i].type != -1; i++)
171
if (res[i] != NULL) {
172
bus_release_resource(
173
dev, rs[i].type, rs[i].rid, res[i]);
174
res[i] = NULL;
175
}
176
}
177
178
int
179
bus_setup_intr(device_t dev, struct resource *r, int flags,
180
driver_filter_t filter, driver_intr_t handler, void *arg, void **cookiep)
181
{
182
183
dev->dev_irq_filter = filter;
184
dev->dev_irq_fn = handler;
185
dev->dev_irq_arg = arg;
186
187
return (0);
188
}
189
190
int
191
bus_teardown_intr(device_t dev, struct resource *r, void *cookie)
192
{
193
194
dev->dev_irq_filter = NULL;
195
dev->dev_irq_fn = NULL;
196
dev->dev_irq_arg = NULL;
197
198
return (0);
199
}
200
201
int
202
bus_release_resource(device_t dev, int type, int rid, struct resource *r)
203
{
204
/* Resource releasing is not supported */
205
return (EINVAL);
206
}
207
208
void
209
bus_attach_children(device_t dev)
210
{
211
device_t child;
212
213
TAILQ_FOREACH(child, &dev->dev_children, dev_link) {
214
device_probe_and_attach(child);
215
}
216
}
217
218
bus_space_tag_t
219
rman_get_bustag(struct resource *r)
220
{
221
222
return (r->r_bustag);
223
}
224
225
bus_space_handle_t
226
rman_get_bushandle(struct resource *r)
227
{
228
229
return (r->r_bushandle);
230
}
231
232
u_long
233
rman_get_size(struct resource *r)
234
{
235
236
return (r->__r_i->r_end - r->__r_i->r_start + 1);
237
}
238
239
int
240
ofw_bus_status_okay(device_t dev)
241
{
242
if (ofw_bus_status_ok_cb == NULL)
243
return (0);
244
245
return ((*ofw_bus_status_ok_cb)(dev));
246
}
247
248
int
249
ofw_bus_is_compatible(device_t dev, char *name)
250
{
251
if (ofw_bus_is_compatible_cb == NULL)
252
return (0);
253
254
return ((*ofw_bus_is_compatible_cb)(dev, name));
255
}
256
257
/*------------------------------------------------------------------------*
258
* Implementation of mutex API
259
*------------------------------------------------------------------------*/
260
261
struct mtx Giant;
262
263
static void
264
mtx_system_init(void *arg)
265
{
266
mtx_init(&Giant, "Giant", NULL, MTX_DEF | MTX_RECURSE);
267
}
268
SYSINIT(mtx_system_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, mtx_system_init, NULL);
269
270
void
271
mtx_init(struct mtx *mtx, const char *name, const char *type, int opt)
272
{
273
mtx->owned = 0;
274
mtx->parent = mtx;
275
}
276
277
void
278
mtx_lock(struct mtx *mtx)
279
{
280
mtx = mtx->parent;
281
mtx->owned++;
282
}
283
284
void
285
mtx_unlock(struct mtx *mtx)
286
{
287
mtx = mtx->parent;
288
mtx->owned--;
289
}
290
291
int
292
mtx_owned(struct mtx *mtx)
293
{
294
mtx = mtx->parent;
295
return (mtx->owned != 0);
296
}
297
298
void
299
mtx_destroy(struct mtx *mtx)
300
{
301
/* NOP */
302
}
303
304
/*------------------------------------------------------------------------*
305
* Implementation of shared/exclusive mutex API
306
*------------------------------------------------------------------------*/
307
308
void
309
sx_init_flags(struct sx *sx, const char *name, int flags)
310
{
311
sx->owned = 0;
312
}
313
314
void
315
sx_destroy(struct sx *sx)
316
{
317
/* NOP */
318
}
319
320
void
321
sx_xlock(struct sx *sx)
322
{
323
sx->owned++;
324
}
325
326
void
327
sx_xunlock(struct sx *sx)
328
{
329
sx->owned--;
330
}
331
332
int
333
sx_xlocked(struct sx *sx)
334
{
335
return (sx->owned != 0);
336
}
337
338
/*------------------------------------------------------------------------*
339
* Implementaiton of condition variable API
340
*------------------------------------------------------------------------*/
341
342
void
343
cv_init(struct cv *cv, const char *desc)
344
{
345
cv->sleeping = 0;
346
}
347
348
void
349
cv_destroy(struct cv *cv)
350
{
351
/* NOP */
352
}
353
354
void
355
cv_wait(struct cv *cv, struct mtx *mtx)
356
{
357
cv_timedwait(cv, mtx, -1);
358
}
359
360
int
361
cv_timedwait(struct cv *cv, struct mtx *mtx, int timo)
362
{
363
int start = ticks;
364
int delta;
365
int time = 0;
366
367
if (cv->sleeping)
368
return (EWOULDBLOCK); /* not allowed */
369
370
cv->sleeping = 1;
371
372
while (cv->sleeping) {
373
if (timo >= 0) {
374
delta = ticks - start;
375
if (delta >= timo || delta < 0)
376
break;
377
}
378
mtx_unlock(mtx);
379
380
usb_idle();
381
382
if (++time >= (1000000 / hz)) {
383
time = 0;
384
callout_process(1);
385
}
386
387
/* Sleep for 1 us */
388
delay(1);
389
390
mtx_lock(mtx);
391
}
392
393
if (cv->sleeping) {
394
cv->sleeping = 0;
395
return (EWOULDBLOCK); /* not allowed */
396
}
397
return (0);
398
}
399
400
void
401
cv_signal(struct cv *cv)
402
{
403
cv->sleeping = 0;
404
}
405
406
void
407
cv_broadcast(struct cv *cv)
408
{
409
cv->sleeping = 0;
410
}
411
412
/*------------------------------------------------------------------------*
413
* Implementation of callout API
414
*------------------------------------------------------------------------*/
415
416
static void callout_proc_msg(struct usb_proc_msg *);
417
418
volatile int ticks = 0;
419
420
static LIST_HEAD(, callout) head_callout = LIST_HEAD_INITIALIZER(&head_callout);
421
422
static struct mtx mtx_callout;
423
static struct usb_proc_msg callout_msg[2];
424
425
static void
426
callout_system_init(void *arg)
427
{
428
mtx_init(&mtx_callout, "callout-mtx", NULL, MTX_DEF | MTX_RECURSE);
429
430
callout_msg[0].pm_callback = &callout_proc_msg;
431
callout_msg[1].pm_callback = &callout_proc_msg;
432
}
433
SYSINIT(callout_system_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, callout_system_init, NULL);
434
435
static void
436
callout_callback(struct callout *c)
437
{
438
mtx_lock(c->mtx);
439
440
mtx_lock(&mtx_callout);
441
if (c->entry.le_prev != NULL) {
442
LIST_REMOVE(c, entry);
443
c->entry.le_prev = NULL;
444
}
445
mtx_unlock(&mtx_callout);
446
447
if (c->c_func != NULL)
448
(c->c_func) (c->c_arg);
449
450
if (!(c->flags & CALLOUT_RETURNUNLOCKED))
451
mtx_unlock(c->mtx);
452
}
453
454
void
455
callout_process(int timeout)
456
{
457
ticks += timeout;
458
usb_proc_msignal(usb_process + 2, &callout_msg[0], &callout_msg[1]);
459
}
460
461
static void
462
callout_proc_msg(struct usb_proc_msg *pmsg)
463
{
464
struct callout *c;
465
int delta;
466
467
repeat:
468
mtx_lock(&mtx_callout);
469
470
LIST_FOREACH(c, &head_callout, entry) {
471
472
delta = c->timeout - ticks;
473
if (delta < 0) {
474
mtx_unlock(&mtx_callout);
475
476
callout_callback(c);
477
478
goto repeat;
479
}
480
}
481
mtx_unlock(&mtx_callout);
482
}
483
484
void
485
callout_init_mtx(struct callout *c, struct mtx *mtx, int flags)
486
{
487
memset(c, 0, sizeof(*c));
488
489
if (mtx == NULL)
490
mtx = &Giant;
491
492
c->mtx = mtx;
493
c->flags = (flags & CALLOUT_RETURNUNLOCKED);
494
}
495
496
void
497
callout_reset(struct callout *c, int to_ticks,
498
void (*func) (void *), void *arg)
499
{
500
callout_stop(c);
501
502
c->c_func = func;
503
c->c_arg = arg;
504
c->timeout = ticks + to_ticks;
505
506
mtx_lock(&mtx_callout);
507
LIST_INSERT_HEAD(&head_callout, c, entry);
508
mtx_unlock(&mtx_callout);
509
}
510
511
void
512
callout_stop(struct callout *c)
513
{
514
mtx_lock(&mtx_callout);
515
516
if (c->entry.le_prev != NULL) {
517
LIST_REMOVE(c, entry);
518
c->entry.le_prev = NULL;
519
}
520
mtx_unlock(&mtx_callout);
521
522
c->c_func = NULL;
523
c->c_arg = NULL;
524
}
525
526
void
527
callout_drain(struct callout *c)
528
{
529
if (c->mtx == NULL)
530
return; /* not initialised */
531
532
mtx_lock(c->mtx);
533
callout_stop(c);
534
mtx_unlock(c->mtx);
535
}
536
537
int
538
callout_pending(struct callout *c)
539
{
540
int retval;
541
542
mtx_lock(&mtx_callout);
543
retval = (c->entry.le_prev != NULL);
544
mtx_unlock(&mtx_callout);
545
546
return (retval);
547
}
548
549
/*------------------------------------------------------------------------*
550
* Implementation of device API
551
*------------------------------------------------------------------------*/
552
553
static const char unknown_string[] = { "unknown" };
554
555
static TAILQ_HEAD(, module_data) module_head =
556
TAILQ_HEAD_INITIALIZER(module_head);
557
static TAILQ_HEAD(, devclass) devclasses =
558
TAILQ_HEAD_INITIALIZER(devclasses);
559
560
int
561
bus_generic_resume(device_t dev)
562
{
563
return (0);
564
}
565
566
int
567
bus_generic_shutdown(device_t dev)
568
{
569
return (0);
570
}
571
572
int
573
bus_generic_suspend(device_t dev)
574
{
575
return (0);
576
}
577
578
int
579
bus_generic_print_child(device_t dev, device_t child)
580
{
581
return (0);
582
}
583
584
void
585
bus_generic_driver_added(device_t dev, driver_t *driver)
586
{
587
return;
588
}
589
590
device_t
591
device_get_parent(device_t dev)
592
{
593
return (dev ? dev->dev_parent : NULL);
594
}
595
596
void
597
device_set_interrupt(device_t dev, driver_filter_t *filter,
598
driver_intr_t *fn, void *arg)
599
{
600
dev->dev_irq_filter = filter;
601
dev->dev_irq_fn = fn;
602
dev->dev_irq_arg = arg;
603
}
604
605
void
606
device_run_interrupts(device_t parent)
607
{
608
device_t child;
609
610
if (parent == NULL)
611
return;
612
613
TAILQ_FOREACH(child, &parent->dev_children, dev_link) {
614
int status;
615
if (child->dev_irq_filter != NULL)
616
status = child->dev_irq_filter(child->dev_irq_arg);
617
else
618
status = FILTER_SCHEDULE_THREAD;
619
620
if (status == FILTER_SCHEDULE_THREAD) {
621
if (child->dev_irq_fn != NULL)
622
(child->dev_irq_fn) (child->dev_irq_arg);
623
}
624
}
625
}
626
627
void
628
device_set_ivars(device_t dev, void *ivars)
629
{
630
dev->dev_aux = ivars;
631
}
632
633
void *
634
device_get_ivars(device_t dev)
635
{
636
return (dev ? dev->dev_aux : NULL);
637
}
638
639
int
640
device_get_unit(device_t dev)
641
{
642
return (dev ? dev->dev_unit : 0);
643
}
644
645
int
646
bus_detach_children(device_t dev)
647
{
648
device_t child;
649
int error;
650
651
if (!dev->dev_attached)
652
return (EBUSY);
653
654
TAILQ_FOREACH(child, &dev->dev_children, dev_link) {
655
if ((error = device_detach(child)) != 0)
656
return (error);
657
}
658
return (0);
659
}
660
661
int
662
bus_generic_detach(device_t dev)
663
{
664
int error;
665
666
error = bus_detach_children(dev);
667
if (error == 0)
668
error = device_delete_children(dev);
669
return (error);
670
}
671
672
const char *
673
device_get_nameunit(device_t dev)
674
{
675
if (dev && dev->dev_nameunit[0])
676
return (dev->dev_nameunit);
677
678
return (unknown_string);
679
}
680
681
static devclass_t
682
devclass_create(const char *classname)
683
{
684
devclass_t dc;
685
686
dc = malloc(sizeof(*dc), M_DEVBUF, M_WAITOK | M_ZERO);
687
if (dc == NULL) {
688
return (NULL);
689
}
690
dc->name = classname;
691
TAILQ_INSERT_TAIL(&devclasses, dc, link);
692
return (dc);
693
}
694
695
static devclass_t
696
devclass_find_create(const char *classname)
697
{
698
devclass_t dc;
699
700
dc = devclass_find(classname);
701
if (dc == NULL)
702
dc = devclass_create(classname);
703
return (dc);
704
}
705
706
static uint8_t
707
devclass_add_device(devclass_t dc, device_t dev)
708
{
709
device_t *pp_dev;
710
device_t *end;
711
uint8_t unit;
712
713
pp_dev = dc->dev_list;
714
end = pp_dev + DEVCLASS_MAXUNIT;
715
unit = 0;
716
717
while (pp_dev != end) {
718
if (*pp_dev == NULL) {
719
*pp_dev = dev;
720
dev->dev_class = dc;
721
dev->dev_unit = unit;
722
snprintf(dev->dev_nameunit,
723
sizeof(dev->dev_nameunit),
724
"%s%d", dc->name, unit);
725
return (0);
726
}
727
pp_dev++;
728
unit++;
729
}
730
DPRINTF("Could not add device to devclass.\n");
731
return (1);
732
}
733
734
static void
735
devclass_delete_device(devclass_t dc, device_t dev)
736
{
737
if (dc == NULL) {
738
return;
739
}
740
dc->dev_list[dev->dev_unit] = NULL;
741
dev->dev_class = NULL;
742
}
743
744
static device_t
745
make_device(device_t parent, const char *name)
746
{
747
device_t dev = NULL;
748
devclass_t dc = NULL;
749
750
if (name) {
751
752
dc = devclass_find_create(name);
753
754
if (!dc) {
755
756
DPRINTF("%s:%d:%s: can't find device "
757
"class %s\n", __FILE__, __LINE__,
758
__FUNCTION__, name);
759
760
goto done;
761
}
762
}
763
dev = malloc(sizeof(*dev),
764
M_DEVBUF, M_WAITOK | M_ZERO);
765
766
if (dev == NULL)
767
goto done;
768
769
dev->dev_parent = parent;
770
TAILQ_INIT(&dev->dev_children);
771
772
if (name) {
773
dev->dev_fixed_class = 1;
774
if (devclass_add_device(dc, dev)) {
775
goto error;
776
}
777
}
778
done:
779
return (dev);
780
781
error:
782
if (dev) {
783
free(dev, M_DEVBUF);
784
}
785
return (NULL);
786
}
787
788
device_t
789
device_add_child(device_t dev, const char *name, int unit)
790
{
791
device_t child;
792
793
if (unit != -1) {
794
device_printf(dev, "Unit is not -1\n");
795
}
796
child = make_device(dev, name);
797
if (child == NULL) {
798
device_printf(dev, "Could not add child '%s'\n", name);
799
goto done;
800
}
801
if (dev == NULL) {
802
/* no parent */
803
goto done;
804
}
805
TAILQ_INSERT_TAIL(&dev->dev_children, child, dev_link);
806
done:
807
return (child);
808
}
809
810
int
811
device_delete_child(device_t dev, device_t child)
812
{
813
int error = 0;
814
device_t grandchild;
815
816
/* detach parent before deleting children, if any */
817
error = device_detach(child);
818
if (error)
819
goto done;
820
821
/* remove children second */
822
while ((grandchild = TAILQ_FIRST(&child->dev_children))) {
823
error = device_delete_child(child, grandchild);
824
if (error) {
825
device_printf(dev, "Error deleting child!\n");
826
goto done;
827
}
828
}
829
830
if (child->dev_class != NULL)
831
devclass_delete_device(child->dev_class, child);
832
833
if (dev != NULL) {
834
/* remove child from parent */
835
TAILQ_REMOVE(&dev->dev_children, child, dev_link);
836
}
837
free(child, M_DEVBUF);
838
839
done:
840
return (error);
841
}
842
843
int
844
device_delete_children(device_t dev)
845
{
846
device_t child;
847
int error = 0;
848
849
while ((child = TAILQ_FIRST(&dev->dev_children))) {
850
error = device_delete_child(dev, child);
851
if (error) {
852
device_printf(dev, "Error deleting child!\n");
853
break;
854
}
855
}
856
return (error);
857
}
858
859
void
860
device_quiet(device_t dev)
861
{
862
dev->dev_quiet = 1;
863
}
864
865
const char *
866
device_get_desc(device_t dev)
867
{
868
if (dev)
869
return &(dev->dev_desc[0]);
870
return (unknown_string);
871
}
872
873
static int
874
default_method(void)
875
{
876
/* do nothing */
877
DPRINTF("Default method called\n");
878
return (0);
879
}
880
881
void *
882
device_get_method(device_t dev, const char *what)
883
{
884
const struct device_method *mtod;
885
886
mtod = dev->dev_module->driver->methods;
887
while (mtod->func != NULL) {
888
if (strcmp(mtod->desc, what) == 0) {
889
return (mtod->func);
890
}
891
mtod++;
892
}
893
return ((void *)&default_method);
894
}
895
896
const char *
897
device_get_name(device_t dev)
898
{
899
if (dev == NULL || dev->dev_module == NULL)
900
return (unknown_string);
901
902
return (dev->dev_module->driver->name);
903
}
904
905
static int
906
device_allocate_softc(device_t dev)
907
{
908
const struct module_data *mod;
909
910
mod = dev->dev_module;
911
912
if ((dev->dev_softc_alloc == 0) &&
913
(mod->driver->size != 0)) {
914
dev->dev_sc = malloc(mod->driver->size,
915
M_DEVBUF, M_WAITOK | M_ZERO);
916
917
if (dev->dev_sc == NULL)
918
return (ENOMEM);
919
920
dev->dev_softc_alloc = 1;
921
}
922
return (0);
923
}
924
925
int
926
device_probe_and_attach(device_t dev)
927
{
928
const struct module_data *mod;
929
const char *bus_name_parent;
930
devclass_t dc;
931
932
if (dev->dev_attached)
933
return (0); /* fail-safe */
934
935
/*
936
* Find a module for our device, if any
937
*/
938
bus_name_parent = device_get_name(device_get_parent(dev));
939
940
TAILQ_FOREACH(mod, &module_head, entry) {
941
if (strcmp(mod->bus_name, bus_name_parent) != 0)
942
continue;
943
944
dc = devclass_find(mod->mod_name);
945
946
/* Does this device need assigning to the new devclass? */
947
if (dev->dev_class != dc) {
948
if (dev->dev_fixed_class)
949
continue;
950
if (dev->dev_class != NULL)
951
devclass_delete_device(dev->dev_class, dev);
952
if (devclass_add_device(dc, dev)) {
953
continue;
954
}
955
}
956
957
dev->dev_module = mod;
958
if (DEVICE_PROBE(dev) <= 0) {
959
960
if (device_allocate_softc(dev) == 0) {
961
962
if (DEVICE_ATTACH(dev) == 0) {
963
/* success */
964
dev->dev_attached = 1;
965
return (0);
966
}
967
}
968
}
969
/* else try next driver */
970
971
device_detach(dev);
972
}
973
974
return (ENODEV);
975
}
976
977
int
978
device_detach(device_t dev)
979
{
980
const struct module_data *mod = dev->dev_module;
981
int error;
982
983
if (dev->dev_attached) {
984
985
error = DEVICE_DETACH(dev);
986
if (error) {
987
return error;
988
}
989
dev->dev_attached = 0;
990
}
991
device_set_softc(dev, NULL);
992
dev->dev_module = NULL;
993
994
if (dev->dev_fixed_class == 0)
995
devclass_delete_device(dev->dev_class, dev);
996
997
return (0);
998
}
999
1000
void
1001
device_set_softc(device_t dev, void *softc)
1002
{
1003
if (dev->dev_softc_alloc) {
1004
free(dev->dev_sc, M_DEVBUF);
1005
dev->dev_sc = NULL;
1006
}
1007
dev->dev_sc = softc;
1008
dev->dev_softc_alloc = 0;
1009
}
1010
1011
void *
1012
device_get_softc(device_t dev)
1013
{
1014
if (dev == NULL)
1015
return (NULL);
1016
1017
return (dev->dev_sc);
1018
}
1019
1020
int
1021
device_is_attached(device_t dev)
1022
{
1023
return (dev->dev_attached);
1024
}
1025
1026
void
1027
device_set_desc(device_t dev, const char *desc)
1028
{
1029
snprintf(dev->dev_desc, sizeof(dev->dev_desc), "%s", desc);
1030
}
1031
1032
void
1033
device_set_desc_copy(device_t dev, const char *desc)
1034
{
1035
device_set_desc(dev, desc);
1036
}
1037
1038
void *
1039
devclass_get_softc(devclass_t dc, int unit)
1040
{
1041
return (device_get_softc(devclass_get_device(dc, unit)));
1042
}
1043
1044
int
1045
devclass_get_maxunit(devclass_t dc)
1046
{
1047
int max_unit = 0;
1048
1049
if (dc) {
1050
max_unit = DEVCLASS_MAXUNIT;
1051
while (max_unit--) {
1052
if (dc->dev_list[max_unit]) {
1053
break;
1054
}
1055
}
1056
max_unit++;
1057
}
1058
return (max_unit);
1059
}
1060
1061
device_t
1062
devclass_get_device(devclass_t dc, int unit)
1063
{
1064
return (((unit < 0) || (unit >= DEVCLASS_MAXUNIT) || (dc == NULL)) ?
1065
NULL : dc->dev_list[unit]);
1066
}
1067
1068
devclass_t
1069
devclass_find(const char *classname)
1070
{
1071
devclass_t dc;
1072
1073
TAILQ_FOREACH(dc, &devclasses, link) {
1074
if (strcmp(dc->name, classname) == 0)
1075
return (dc);
1076
}
1077
return (NULL);
1078
}
1079
1080
void
1081
module_register(void *data)
1082
{
1083
struct module_data *mdata = data;
1084
1085
TAILQ_INSERT_TAIL(&module_head, mdata, entry);
1086
(void)devclass_find_create(mdata->mod_name);
1087
}
1088
1089
/*------------------------------------------------------------------------*
1090
* System startup
1091
*------------------------------------------------------------------------*/
1092
1093
static void
1094
sysinit_run(const void **ppdata)
1095
{
1096
const struct sysinit *psys;
1097
1098
while ((psys = *ppdata) != NULL) {
1099
(psys->func) (psys->data);
1100
ppdata++;
1101
}
1102
}
1103
1104
/*------------------------------------------------------------------------*
1105
* USB process API
1106
*------------------------------------------------------------------------*/
1107
1108
static int usb_do_process(struct usb_process *);
1109
static int usb_proc_level = -1;
1110
static struct mtx usb_proc_mtx;
1111
1112
void
1113
usb_idle(void)
1114
{
1115
int old_level = usb_proc_level;
1116
int old_giant = Giant.owned;
1117
int worked;
1118
1119
device_run_interrupts(usb_pci_root);
1120
1121
do {
1122
worked = 0;
1123
Giant.owned = 0;
1124
1125
while (++usb_proc_level < USB_PROC_MAX)
1126
worked |= usb_do_process(usb_process + usb_proc_level);
1127
1128
usb_proc_level = old_level;
1129
Giant.owned = old_giant;
1130
1131
} while (worked);
1132
}
1133
1134
void
1135
usb_init(void)
1136
{
1137
sysinit_run(sysinit_data);
1138
}
1139
1140
void
1141
usb_uninit(void)
1142
{
1143
sysinit_run(sysuninit_data);
1144
}
1145
1146
static void
1147
usb_process_init_sub(struct usb_process *up)
1148
{
1149
TAILQ_INIT(&up->up_qhead);
1150
1151
cv_init(&up->up_cv, "-");
1152
cv_init(&up->up_drain, "usbdrain");
1153
1154
up->up_mtx = &usb_proc_mtx;
1155
}
1156
1157
static void
1158
usb_process_init(void *arg)
1159
{
1160
uint8_t x;
1161
1162
mtx_init(&usb_proc_mtx, "usb-proc-mtx", NULL, MTX_DEF | MTX_RECURSE);
1163
1164
for (x = 0; x != USB_PROC_MAX; x++)
1165
usb_process_init_sub(&usb_process[x]);
1166
1167
}
1168
SYSINIT(usb_process_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, usb_process_init, NULL);
1169
1170
static int
1171
usb_do_process(struct usb_process *up)
1172
{
1173
struct usb_proc_msg *pm;
1174
int worked = 0;
1175
1176
mtx_lock(&usb_proc_mtx);
1177
1178
repeat:
1179
pm = TAILQ_FIRST(&up->up_qhead);
1180
1181
if (pm != NULL) {
1182
1183
worked = 1;
1184
1185
(pm->pm_callback) (pm);
1186
1187
if (pm == TAILQ_FIRST(&up->up_qhead)) {
1188
/* nothing changed */
1189
TAILQ_REMOVE(&up->up_qhead, pm, pm_qentry);
1190
pm->pm_qentry.tqe_prev = NULL;
1191
}
1192
goto repeat;
1193
}
1194
mtx_unlock(&usb_proc_mtx);
1195
1196
return (worked);
1197
}
1198
1199
void *
1200
usb_proc_msignal(struct usb_process *up, void *_pm0, void *_pm1)
1201
{
1202
struct usb_proc_msg *pm0 = _pm0;
1203
struct usb_proc_msg *pm1 = _pm1;
1204
struct usb_proc_msg *pm2;
1205
usb_size_t d;
1206
uint8_t t;
1207
1208
t = 0;
1209
1210
if (pm0->pm_qentry.tqe_prev) {
1211
t |= 1;
1212
}
1213
if (pm1->pm_qentry.tqe_prev) {
1214
t |= 2;
1215
}
1216
if (t == 0) {
1217
/*
1218
* No entries are queued. Queue "pm0" and use the existing
1219
* message number.
1220
*/
1221
pm2 = pm0;
1222
} else if (t == 1) {
1223
/* Check if we need to increment the message number. */
1224
if (pm0->pm_num == up->up_msg_num) {
1225
up->up_msg_num++;
1226
}
1227
pm2 = pm1;
1228
} else if (t == 2) {
1229
/* Check if we need to increment the message number. */
1230
if (pm1->pm_num == up->up_msg_num) {
1231
up->up_msg_num++;
1232
}
1233
pm2 = pm0;
1234
} else if (t == 3) {
1235
/*
1236
* Both entries are queued. Re-queue the entry closest to
1237
* the end.
1238
*/
1239
d = (pm1->pm_num - pm0->pm_num);
1240
1241
/* Check sign after subtraction */
1242
if (d & 0x80000000) {
1243
pm2 = pm0;
1244
} else {
1245
pm2 = pm1;
1246
}
1247
1248
TAILQ_REMOVE(&up->up_qhead, pm2, pm_qentry);
1249
} else {
1250
pm2 = NULL; /* panic - should not happen */
1251
}
1252
1253
/* Put message last on queue */
1254
1255
pm2->pm_num = up->up_msg_num;
1256
TAILQ_INSERT_TAIL(&up->up_qhead, pm2, pm_qentry);
1257
1258
return (pm2);
1259
}
1260
1261
/*------------------------------------------------------------------------*
1262
* usb_proc_is_gone
1263
*
1264
* Return values:
1265
* 0: USB process is running
1266
* Else: USB process is tearing down
1267
*------------------------------------------------------------------------*/
1268
uint8_t
1269
usb_proc_is_gone(struct usb_process *up)
1270
{
1271
return (0);
1272
}
1273
1274
/*------------------------------------------------------------------------*
1275
* usb_proc_mwait
1276
*
1277
* This function will return when the USB process message pointed to
1278
* by "pm" is no longer on a queue. This function must be called
1279
* having "usb_proc_mtx" locked.
1280
*------------------------------------------------------------------------*/
1281
void
1282
usb_proc_mwait(struct usb_process *up, void *_pm0, void *_pm1)
1283
{
1284
struct usb_proc_msg *pm0 = _pm0;
1285
struct usb_proc_msg *pm1 = _pm1;
1286
1287
/* Just remove the messages from the queue. */
1288
if (pm0->pm_qentry.tqe_prev) {
1289
TAILQ_REMOVE(&up->up_qhead, pm0, pm_qentry);
1290
pm0->pm_qentry.tqe_prev = NULL;
1291
}
1292
if (pm1->pm_qentry.tqe_prev) {
1293
TAILQ_REMOVE(&up->up_qhead, pm1, pm_qentry);
1294
pm1->pm_qentry.tqe_prev = NULL;
1295
}
1296
}
1297
1298
/*------------------------------------------------------------------------*
1299
* SYSTEM attach
1300
*------------------------------------------------------------------------*/
1301
1302
#ifdef USB_PCI_PROBE_LIST
1303
static device_method_t pci_methods[] = {
1304
DEVMETHOD_END
1305
};
1306
1307
static driver_t pci_driver = {
1308
.name = "pci",
1309
.methods = pci_methods,
1310
};
1311
1312
static devclass_t pci_devclass;
1313
1314
DRIVER_MODULE(pci, pci, pci_driver, pci_devclass, 0, 0);
1315
1316
static const char *usb_pci_devices[] = {
1317
USB_PCI_PROBE_LIST
1318
};
1319
1320
#define USB_PCI_USB_MAX (sizeof(usb_pci_devices) / sizeof(void *))
1321
1322
static device_t usb_pci_dev[USB_PCI_USB_MAX];
1323
1324
static void
1325
usb_pci_mod_load(void *arg)
1326
{
1327
uint32_t x;
1328
1329
usb_pci_root = device_add_child(NULL, "pci", DEVICE_UNIT_ANY);
1330
if (usb_pci_root == NULL)
1331
return;
1332
1333
for (x = 0; x != USB_PCI_USB_MAX; x++) {
1334
usb_pci_dev[x] = device_add_child(usb_pci_root,
1335
usb_pci_devices[x], DEVICE_UNIT_ANY);
1336
if (usb_pci_dev[x] == NULL)
1337
continue;
1338
if (device_probe_and_attach(usb_pci_dev[x])) {
1339
device_printf(usb_pci_dev[x],
1340
"WARNING: Probe and attach failed!\n");
1341
}
1342
}
1343
}
1344
SYSINIT(usb_pci_mod_load, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_load, 0);
1345
1346
static void
1347
usb_pci_mod_unload(void *arg)
1348
{
1349
uint32_t x;
1350
1351
for (x = 0; x != USB_PCI_USB_MAX; x++) {
1352
if (usb_pci_dev[x]) {
1353
device_detach(usb_pci_dev[x]);
1354
device_delete_child(usb_pci_root, usb_pci_dev[x]);
1355
}
1356
}
1357
if (usb_pci_root)
1358
device_delete_child(NULL, usb_pci_root);
1359
}
1360
SYSUNINIT(usb_pci_mod_unload, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_unload, 0);
1361
#endif
1362
1363
/*------------------------------------------------------------------------*
1364
* MALLOC API
1365
*------------------------------------------------------------------------*/
1366
1367
#ifndef HAVE_MALLOC
1368
#define USB_POOL_ALIGN 8
1369
1370
static uint8_t usb_pool[USB_POOL_SIZE] __aligned(USB_POOL_ALIGN);
1371
static uint32_t usb_pool_rem = USB_POOL_SIZE;
1372
static uint32_t usb_pool_entries;
1373
1374
struct malloc_hdr {
1375
TAILQ_ENTRY(malloc_hdr) entry;
1376
uint32_t size;
1377
} __aligned(USB_POOL_ALIGN);
1378
1379
static TAILQ_HEAD(, malloc_hdr) malloc_head =
1380
TAILQ_HEAD_INITIALIZER(malloc_head);
1381
1382
void *
1383
usb_malloc(unsigned long size)
1384
{
1385
struct malloc_hdr *hdr;
1386
1387
size = (size + USB_POOL_ALIGN - 1) & ~(USB_POOL_ALIGN - 1);
1388
size += sizeof(struct malloc_hdr);
1389
1390
TAILQ_FOREACH(hdr, &malloc_head, entry) {
1391
if (hdr->size == size)
1392
break;
1393
}
1394
1395
if (hdr) {
1396
DPRINTF("MALLOC: Entries = %d; Remainder = %d; Size = %d\n",
1397
(int)usb_pool_entries, (int)usb_pool_rem, (int)size);
1398
1399
TAILQ_REMOVE(&malloc_head, hdr, entry);
1400
memset(hdr + 1, 0, hdr->size - sizeof(*hdr));
1401
return (hdr + 1);
1402
}
1403
if (usb_pool_rem >= size) {
1404
hdr = (void *)(usb_pool + USB_POOL_SIZE - usb_pool_rem);
1405
hdr->size = size;
1406
1407
usb_pool_rem -= size;
1408
usb_pool_entries++;
1409
1410
DPRINTF("MALLOC: Entries = %d; Remainder = %d; Size = %d\n",
1411
(int)usb_pool_entries, (int)usb_pool_rem, (int)size);
1412
1413
memset(hdr + 1, 0, hdr->size - sizeof(*hdr));
1414
return (hdr + 1);
1415
}
1416
return (NULL);
1417
}
1418
1419
void
1420
usb_free(void *arg)
1421
{
1422
struct malloc_hdr *hdr;
1423
1424
if (arg == NULL)
1425
return;
1426
1427
hdr = arg;
1428
hdr--;
1429
1430
TAILQ_INSERT_TAIL(&malloc_head, hdr, entry);
1431
}
1432
#endif
1433
1434
char *
1435
usb_strdup(const char *str)
1436
{
1437
char *tmp;
1438
int len;
1439
1440
len = 1 + strlen(str);
1441
1442
tmp = malloc(len,XXX,XXX);
1443
if (tmp == NULL)
1444
return (NULL);
1445
1446
memcpy(tmp, str, len);
1447
return (tmp);
1448
}
1449
1450