nckernel  0.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
fdc_single.c
Go to the documentation of this file.
1 #include <sys/types.h>
2 #include <stddef.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <time.h>
6 #include <semaphore.h>
7 #include <errno.h>
8 #include <assert.h>
9 
10 #include <isr.h>
11 #include <interrupt.h>
12 #include <list.h>
13 #include <fdc.h>
14 #include <fdc_ctrl.h>
15 
16 #include <ston.h>
17 #include <fdc_single.h>
18 
19 #include <debug.h>
20 
21 struct fdc_key {
24 };
25 
26 struct fdc_single {
28  int initiated;
29  struct fdc_key key;
30 };
31 
32 static struct ston *s_ston;
33 
35 static int fdc_isr(int sub_irq, void *info, void *data)
36 {
37  struct fdc_single *single = data;
38  sem_t sem;
39 
40  sem = fdc_single_sem(single);
41  assert(sem && "Invalid sem");
42  sem_post(&sem);
43 
44  return 0;
45 }
46 
47 static void *create(const void *_key)
48 {
49  const struct fdc_key *key;
50  struct fdc_single *single;
51  unsigned long flags;
52  int ret;
53 
54  key = _key;
55 
56  single = malloc(sizeof(*single));
57  if (!single) {
58  return NULL;
59  }
60 
61  single->key.ctrl = key->ctrl;
62  single->key.drv = key->drv;
63  single->initiated = 0;
64 
65  if (sem_init(&single->sem, 0, 0) < 0) {
66  free(single);
67  return NULL;
68  }
69 
70  irq_local_save(&flags);
71  ret = register_irq(IRQ_NR_FDC, NORMAL_PRIORITY, fdc_isr, single);
72  irq_local_restore(flags);
73  if (ret < 0) {
74  sem_destroy(&single->sem);
75  free(single);
76  return NULL;
77  }
78 
79  return single;
80 }
81 
82 static int destroy(void *obj)
83 {
84  struct fdc_single *single = obj;
85  unsigned long flags;
86 
87  irq_local_save(&flags);
88  (void)unregister_irq(IRQ_NR_FDC, fdc_isr, single);
89  irq_local_restore(flags);
90 
91  sem_destroy(&single->sem);
92  free(single);
93  return 0;
94 }
95 
96 static int compare(const void *_key_a, const void *_key_b)
97 {
98  const struct fdc_key *key_a;
99  const struct fdc_key *key_b;
100 
101  key_a = _key_a;
102  key_b = _key_b;
103 
104  return (key_a->ctrl != key_b->ctrl) || (key_a->drv != key_b->drv);
105 }
106 
108 {
109  struct ston_ops ops = {
110  .create = create,
111  .destroy = destroy,
112  .compare = compare,
113  };
114 
115  s_ston = ston_init(&ops);
116  if (!s_ston) {
117  return -EFAULT;
118  }
119 
120  return 0;
121 }
122 
124 {
125  ston_fini(s_ston);
126  s_ston = NULL;
127  return 0;
128 }
129 
130 struct fdc_single *fdc_single_get(enum base_address ctrl, enum drive_letter drive)
131 {
132  struct fdc_key key;
133 
134  key.ctrl = ctrl;
135  key.drv = drive;
136 
137  return ston_create(s_ston, &key);
138 }
139 
140 int fdc_single_put(struct fdc_single *single)
141 {
142  return ston_destroy(s_ston, single);
143 }
144 
146 {
147  return single->sem;
148 }
149 
151 {
152  return single->key.drv;
153 }
154 
156 {
157  return single->key.ctrl;
158 }
159 
161 {
162  return single->initiated;
163 }
164 
165 void fdc_single_initiate(struct fdc_single *single)
166 {
167  single->initiated = 1;
168 }
169 
170 /* End of a file */