diff options
Diffstat (limited to 'drivers/net/wireless/hermes.c')
-rw-r--r-- | drivers/net/wireless/hermes.c | 124 |
1 files changed, 71 insertions, 53 deletions
diff --git a/drivers/net/wireless/hermes.c b/drivers/net/wireless/hermes.c index 29d39105f5b..bfa375369df 100644 --- a/drivers/net/wireless/hermes.c +++ b/drivers/net/wireless/hermes.c | |||
@@ -87,7 +87,8 @@ MODULE_LICENSE("Dual MPL/GPL"); | |||
87 | 87 | ||
88 | Callable from any context. | 88 | Callable from any context. |
89 | */ | 89 | */ |
90 | static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0) | 90 | static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0, |
91 | u16 param1, u16 param2) | ||
91 | { | 92 | { |
92 | int k = CMD_BUSY_TIMEOUT; | 93 | int k = CMD_BUSY_TIMEOUT; |
93 | u16 reg; | 94 | u16 reg; |
@@ -103,8 +104,8 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0) | |||
103 | return -EBUSY; | 104 | return -EBUSY; |
104 | } | 105 | } |
105 | 106 | ||
106 | hermes_write_regn(hw, PARAM2, 0); | 107 | hermes_write_regn(hw, PARAM2, param2); |
107 | hermes_write_regn(hw, PARAM1, 0); | 108 | hermes_write_regn(hw, PARAM1, param1); |
108 | hermes_write_regn(hw, PARAM0, param0); | 109 | hermes_write_regn(hw, PARAM0, param0); |
109 | hermes_write_regn(hw, CMD, cmd); | 110 | hermes_write_regn(hw, CMD, cmd); |
110 | 111 | ||
@@ -115,16 +116,72 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0) | |||
115 | * Function definitions | 116 | * Function definitions |
116 | */ | 117 | */ |
117 | 118 | ||
119 | /* For doing cmds that wipe the magic constant in SWSUPPORT0 */ | ||
120 | int hermes_doicmd_wait(hermes_t *hw, u16 cmd, | ||
121 | u16 parm0, u16 parm1, u16 parm2, | ||
122 | struct hermes_response *resp) | ||
123 | { | ||
124 | int err = 0; | ||
125 | int k; | ||
126 | u16 status, reg; | ||
127 | |||
128 | err = hermes_issue_cmd(hw, cmd, parm0, parm1, parm2); | ||
129 | if (err) | ||
130 | return err; | ||
131 | |||
132 | reg = hermes_read_regn(hw, EVSTAT); | ||
133 | k = CMD_INIT_TIMEOUT; | ||
134 | while ((!(reg & HERMES_EV_CMD)) && k) { | ||
135 | k--; | ||
136 | udelay(10); | ||
137 | reg = hermes_read_regn(hw, EVSTAT); | ||
138 | } | ||
139 | |||
140 | hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC); | ||
141 | |||
142 | if (!hermes_present(hw)) { | ||
143 | DEBUG(0, "hermes @ 0x%x: Card removed during reset.\n", | ||
144 | hw->iobase); | ||
145 | err = -ENODEV; | ||
146 | goto out; | ||
147 | } | ||
148 | |||
149 | if (!(reg & HERMES_EV_CMD)) { | ||
150 | printk(KERN_ERR "hermes @ %p: " | ||
151 | "Timeout waiting for card to reset (reg=0x%04x)!\n", | ||
152 | hw->iobase, reg); | ||
153 | err = -ETIMEDOUT; | ||
154 | goto out; | ||
155 | } | ||
156 | |||
157 | status = hermes_read_regn(hw, STATUS); | ||
158 | if (resp) { | ||
159 | resp->status = status; | ||
160 | resp->resp0 = hermes_read_regn(hw, RESP0); | ||
161 | resp->resp1 = hermes_read_regn(hw, RESP1); | ||
162 | resp->resp2 = hermes_read_regn(hw, RESP2); | ||
163 | } | ||
164 | |||
165 | hermes_write_regn(hw, EVACK, HERMES_EV_CMD); | ||
166 | |||
167 | if (status & HERMES_STATUS_RESULT) | ||
168 | err = -EIO; | ||
169 | out: | ||
170 | return err; | ||
171 | } | ||
172 | EXPORT_SYMBOL(hermes_doicmd_wait); | ||
173 | |||
118 | void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing) | 174 | void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing) |
119 | { | 175 | { |
120 | hw->iobase = address; | 176 | hw->iobase = address; |
121 | hw->reg_spacing = reg_spacing; | 177 | hw->reg_spacing = reg_spacing; |
122 | hw->inten = 0x0; | 178 | hw->inten = 0x0; |
123 | } | 179 | } |
180 | EXPORT_SYMBOL(hermes_struct_init); | ||
124 | 181 | ||
125 | int hermes_init(hermes_t *hw) | 182 | int hermes_init(hermes_t *hw) |
126 | { | 183 | { |
127 | u16 status, reg; | 184 | u16 reg; |
128 | int err = 0; | 185 | int err = 0; |
129 | int k; | 186 | int k; |
130 | 187 | ||
@@ -162,45 +219,11 @@ int hermes_init(hermes_t *hw) | |||
162 | 219 | ||
163 | /* We don't use hermes_docmd_wait here, because the reset wipes | 220 | /* We don't use hermes_docmd_wait here, because the reset wipes |
164 | the magic constant in SWSUPPORT0 away, and it gets confused */ | 221 | the magic constant in SWSUPPORT0 away, and it gets confused */ |
165 | err = hermes_issue_cmd(hw, HERMES_CMD_INIT, 0); | 222 | err = hermes_doicmd_wait(hw, HERMES_CMD_INIT, 0, 0, 0, NULL); |
166 | if (err) | ||
167 | return err; | ||
168 | |||
169 | reg = hermes_read_regn(hw, EVSTAT); | ||
170 | k = CMD_INIT_TIMEOUT; | ||
171 | while ( (! (reg & HERMES_EV_CMD)) && k) { | ||
172 | k--; | ||
173 | udelay(10); | ||
174 | reg = hermes_read_regn(hw, EVSTAT); | ||
175 | } | ||
176 | |||
177 | hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC); | ||
178 | |||
179 | if (! hermes_present(hw)) { | ||
180 | DEBUG(0, "hermes @ 0x%x: Card removed during reset.\n", | ||
181 | hw->iobase); | ||
182 | err = -ENODEV; | ||
183 | goto out; | ||
184 | } | ||
185 | |||
186 | if (! (reg & HERMES_EV_CMD)) { | ||
187 | printk(KERN_ERR "hermes @ %p: " | ||
188 | "Timeout waiting for card to reset (reg=0x%04x)!\n", | ||
189 | hw->iobase, reg); | ||
190 | err = -ETIMEDOUT; | ||
191 | goto out; | ||
192 | } | ||
193 | 223 | ||
194 | status = hermes_read_regn(hw, STATUS); | ||
195 | |||
196 | hermes_write_regn(hw, EVACK, HERMES_EV_CMD); | ||
197 | |||
198 | if (status & HERMES_STATUS_RESULT) | ||
199 | err = -EIO; | ||
200 | |||
201 | out: | ||
202 | return err; | 224 | return err; |
203 | } | 225 | } |
226 | EXPORT_SYMBOL(hermes_init); | ||
204 | 227 | ||
205 | /* Issue a command to the chip, and (busy!) wait for it to | 228 | /* Issue a command to the chip, and (busy!) wait for it to |
206 | * complete. | 229 | * complete. |
@@ -216,7 +239,7 @@ int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, | |||
216 | u16 reg; | 239 | u16 reg; |
217 | u16 status; | 240 | u16 status; |
218 | 241 | ||
219 | err = hermes_issue_cmd(hw, cmd, parm0); | 242 | err = hermes_issue_cmd(hw, cmd, parm0, 0, 0); |
220 | if (err) { | 243 | if (err) { |
221 | if (! hermes_present(hw)) { | 244 | if (! hermes_present(hw)) { |
222 | if (net_ratelimit()) | 245 | if (net_ratelimit()) |
@@ -271,6 +294,7 @@ int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, | |||
271 | out: | 294 | out: |
272 | return err; | 295 | return err; |
273 | } | 296 | } |
297 | EXPORT_SYMBOL(hermes_docmd_wait); | ||
274 | 298 | ||
275 | int hermes_allocate(hermes_t *hw, u16 size, u16 *fid) | 299 | int hermes_allocate(hermes_t *hw, u16 size, u16 *fid) |
276 | { | 300 | { |
@@ -313,7 +337,7 @@ int hermes_allocate(hermes_t *hw, u16 size, u16 *fid) | |||
313 | 337 | ||
314 | return 0; | 338 | return 0; |
315 | } | 339 | } |
316 | 340 | EXPORT_SYMBOL(hermes_allocate); | |
317 | 341 | ||
318 | /* Set up a BAP to read a particular chunk of data from card's internal buffer. | 342 | /* Set up a BAP to read a particular chunk of data from card's internal buffer. |
319 | * | 343 | * |
@@ -397,6 +421,7 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, | |||
397 | out: | 421 | out: |
398 | return err; | 422 | return err; |
399 | } | 423 | } |
424 | EXPORT_SYMBOL(hermes_bap_pread); | ||
400 | 425 | ||
401 | /* Write a block of data to the chip's buffer, via the | 426 | /* Write a block of data to the chip's buffer, via the |
402 | * BAP. Synchronization/serialization is the caller's problem. | 427 | * BAP. Synchronization/serialization is the caller's problem. |
@@ -422,6 +447,7 @@ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, | |||
422 | out: | 447 | out: |
423 | return err; | 448 | return err; |
424 | } | 449 | } |
450 | EXPORT_SYMBOL(hermes_bap_pwrite); | ||
425 | 451 | ||
426 | /* Read a Length-Type-Value record from the card. | 452 | /* Read a Length-Type-Value record from the card. |
427 | * | 453 | * |
@@ -463,7 +489,7 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize, | |||
463 | if (rtype != rid) | 489 | if (rtype != rid) |
464 | printk(KERN_WARNING "hermes @ %p: %s(): " | 490 | printk(KERN_WARNING "hermes @ %p: %s(): " |
465 | "rid (0x%04x) does not match type (0x%04x)\n", | 491 | "rid (0x%04x) does not match type (0x%04x)\n", |
466 | hw->iobase, __FUNCTION__, rid, rtype); | 492 | hw->iobase, __func__, rid, rtype); |
467 | if (HERMES_RECLEN_TO_BYTES(rlength) > bufsize) | 493 | if (HERMES_RECLEN_TO_BYTES(rlength) > bufsize) |
468 | printk(KERN_WARNING "hermes @ %p: " | 494 | printk(KERN_WARNING "hermes @ %p: " |
469 | "Truncating LTV record from %d to %d bytes. " | 495 | "Truncating LTV record from %d to %d bytes. " |
@@ -475,6 +501,7 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize, | |||
475 | 501 | ||
476 | return 0; | 502 | return 0; |
477 | } | 503 | } |
504 | EXPORT_SYMBOL(hermes_read_ltv); | ||
478 | 505 | ||
479 | int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, | 506 | int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, |
480 | u16 length, const void *value) | 507 | u16 length, const void *value) |
@@ -497,20 +524,11 @@ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, | |||
497 | 524 | ||
498 | hermes_write_bytes(hw, dreg, value, count << 1); | 525 | hermes_write_bytes(hw, dreg, value, count << 1); |
499 | 526 | ||
500 | err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE, | 527 | err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE, |
501 | rid, NULL); | 528 | rid, NULL); |
502 | 529 | ||
503 | return err; | 530 | return err; |
504 | } | 531 | } |
505 | |||
506 | EXPORT_SYMBOL(hermes_struct_init); | ||
507 | EXPORT_SYMBOL(hermes_init); | ||
508 | EXPORT_SYMBOL(hermes_docmd_wait); | ||
509 | EXPORT_SYMBOL(hermes_allocate); | ||
510 | |||
511 | EXPORT_SYMBOL(hermes_bap_pread); | ||
512 | EXPORT_SYMBOL(hermes_bap_pwrite); | ||
513 | EXPORT_SYMBOL(hermes_read_ltv); | ||
514 | EXPORT_SYMBOL(hermes_write_ltv); | 532 | EXPORT_SYMBOL(hermes_write_ltv); |
515 | 533 | ||
516 | static int __init init_hermes(void) | 534 | static int __init init_hermes(void) |