RS: invoke a shell explicitly for scripts
[minix.git] / drivers / orinoco / hermes.c
blobe0feff77eb629155932e673999430a0d5a4de03a
1 /*
2 * hermes.c
4 * This file contains the lower level access functions for Prism based
5 * wireless cards. The file is based on hermes.c of the Linux kernel
7 * Adjusted to Minix by Stevens Le Blond <slblond@few.vu.nl>
8 * and Michael Valkering <mjvalker@cs.vu.nl>
9 */
11 /* Original copyright notices from Linux hermes.c
13 * Copyright (C) 2000, David Gibson, Linuxcare Australia
14 * <hermes@gibson.dropbear.id.au>
15 * Copyright (C) 2001, David Gibson, IBM <hermes@gibson.dropbear.id.au>
17 * The contents of this file are subject to the Mozilla Public License
18 * Version 1.1 (the "License"); you may not use this file except in
19 * compliance with the License. You may obtain a copy of the License
20 * at http://www.mozilla.org/MPL/
22 * Software distributed under the License is distributed on an "AS IS"
23 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
24 * the License for the specific language governing rights and
25 * limitations under the License.
27 * Alternatively, the contents of this file may be used under the
28 * terms of the GNU General Public License version 2 (the "GPL"), in
29 * which case the provisions of the GPL are applicable instead of the
30 * above. If you wish to allow the use of your version of this file
31 * only under the terms of the GPL and not to allow others to use your
32 * version of this file under the MPL, indicate your decision by
33 * deleting the provisions above and replace them with the notice and
34 * other provisions required by the GPL. If you do not delete the
35 * provisions above, a recipient may use your version of this file
36 * under either the MPL or the GPL.
39 #include "hermes.h"
41 /*****************************************************************************
42 * milli_delay *
43 * *
44 * Wait msecs milli seconds *
45 *****************************************************************************/
46 static void milli_delay(unsigned int msecs)
48 micro_delay((long)msecs * 1000);
52 /*****************************************************************************
53 * hermes_issue_cmd *
54 * *
55 * Issue a command to the chip. Waiting for it to complete is the caller's *
56 * problem. The only thing we have to do first is to see whether we can *
57 * actually write something in the CMD register: is it unbusy? *
58 * Returns -EBUSY if the command register is busy, 0 on success. *
59 *****************************************************************************/
60 static int hermes_issue_cmd (hermes_t * hw, u16_t cmd, u16_t param0) {
61 int k = HERMES_CMD_BUSY_TIMEOUT;
62 u16_t reg;
64 /* First wait for the command register to unbusy */
65 reg = hermes_read_reg (hw, HERMES_CMD);
66 while ((reg & HERMES_CMD_BUSY) && k) {
67 k--;
68 micro_delay (1);
69 reg = hermes_read_reg (hw, HERMES_CMD);
71 /* it takes too long. Bailing out */
72 if (reg & HERMES_CMD_BUSY) {
73 printf("Hermes: HERMES_CMD_BUSY timeout\n");
74 return -EBUSY;
77 /* write the values to the right registers */
78 hermes_write_reg (hw, HERMES_PARAM2, 0);
79 hermes_write_reg (hw, HERMES_PARAM1, 0);
80 hermes_write_reg (hw, HERMES_PARAM0, param0);
81 hermes_write_reg (hw, HERMES_CMD, cmd);
82 return 0;
85 /*****************************************************************************
86 * hermes_struct_init *
87 * *
88 * Initialize the hermes structure fields *
89 *****************************************************************************/
90 void hermes_struct_init (hermes_t * hw, u32_t address,
91 int io_space, int reg_spacing) {
92 hw->iobase = address;
93 hw->io_space = io_space;
94 hw->reg_spacing = reg_spacing;
95 hw->inten = 0x0;
99 /*****************************************************************************
100 * hermes_cor_reset *
102 * This is the first step in initializing the card's firmware and hardware: *
103 * write HERMES_PCI_COR_MASK to the Configuration Option Register *
104 *****************************************************************************/
105 int hermes_cor_reset (hermes_t *hw) {
106 int k;
107 u16_t reg;
109 /* Assert the reset until the card notice */
110 hermes_write_reg (hw, HERMES_PCI_COR, HERMES_PCI_COR_MASK);
112 milli_delay (HERMES_PCI_COR_ONT);
114 /* Give time for the card to recover from this hard effort */
115 hermes_write_reg (hw, HERMES_PCI_COR, 0x0000);
117 milli_delay (HERMES_PCI_COR_OFFT);
119 /* The card is ready when it's no longer busy */
120 k = HERMES_PCI_COR_BUSYT;
121 reg = hermes_read_reg (hw, HERMES_CMD);
122 while (k && (reg & HERMES_CMD_BUSY)) {
123 k--;
124 milli_delay (1);
125 reg = hermes_read_reg (hw, HERMES_CMD);
128 /* Did we timeout ? */
129 if (reg & HERMES_CMD_BUSY) {
130 printf ("Busy timeout after resetting the COR\n");
131 return -1;
134 return (0);
138 /*****************************************************************************
139 * hermes_present *
141 * Check whether we have access to the card. Does the SWSUPPORT0 contain the *
142 * value we put in it earlier? *
143 *****************************************************************************/
144 static int hermes_present (hermes_t * hw) {
145 int i = hermes_read_reg (hw, HERMES_SWSUPPORT0) == HERMES_MAGIC;
146 if (!i)
147 printf("Hermes: Error, card not present?\n");
148 return i;
152 /*****************************************************************************
153 * hermes_init *
155 * Initialize the card *
156 *****************************************************************************/
157 int hermes_init (hermes_t * hw)
159 u32_t status, reg, resp0;
160 int err = 0;
161 int k;
163 /* We don't want to be interrupted while resetting the chipset. By
164 * setting the control mask for hardware interrupt generation to 0,
165 * we won't be disturbed*/
166 hw->inten = 0x0;
167 hermes_write_reg (hw, HERMES_INTEN, 0);
169 /* Acknowledge any pending events waiting for acknowledgement. We
170 * assume there won't be any important to take care off */
171 hermes_write_reg (hw, HERMES_EVACK, 0xffff);
173 /* Normally it's a "can't happen" for the command register to
174 * be busy when we go to issue a command because we are
175 * serializing all commands. However we want to have some
176 * chance of resetting the card even if it gets into a stupid
177 * state, so we actually wait to see if the command register
178 * will unbusy itself here. */
179 k = HERMES_CMD_BUSY_TIMEOUT;
180 reg = hermes_read_reg (hw, HERMES_CMD);
181 while (k && (reg & HERMES_CMD_BUSY)) {
182 if (reg == 0xffff) {
183 /* Special case - the card has probably
184 * been removed, so don't wait for the
185 * timeout */
186 printf("Hermes: Card removed?\n");
187 return -ENODEV;
190 k--;
191 micro_delay (1);
192 reg = hermes_read_reg (hw, HERMES_CMD);
195 /* No need to explicitly handle the timeout - if we've timed
196 * out hermes_issue_cmd() will probably return -EBUSY below.
197 * But i check to be sure :-) */
198 if (reg & HERMES_CMD_BUSY) {
199 printf("Hermes: Timeout waiting for the CMD_BUSY to unset\n");
200 return -EBUSY;
203 /* According to the documentation, EVSTAT may contain
204 * obsolete event occurrence information. We have to acknowledge
205 * it by writing EVACK. */
206 reg = hermes_read_reg (hw, HERMES_EVSTAT);
207 hermes_write_reg (hw, HERMES_EVACK, reg);
209 err = hermes_issue_cmd (hw, HERMES_CMD_INIT, 0);
210 if (err){
211 printf("Hermes: errornr: 0x%x issueing HERMES_CMD_INIT\n",
212 err);
213 return err;
216 /* here we start waiting for the above command,CMD_INIT, to complete.
217 * Completion is noticeable when the HERMES_EV_CMD bit in the
218 * HERMES_EVSTAT register is set to 1 */
219 reg = hermes_read_reg (hw, HERMES_EVSTAT);
220 k = HERMES_CMD_INIT_TIMEOUT;
221 while ((!(reg & HERMES_EV_CMD)) && k) {
222 k--;
223 micro_delay (10);
224 reg = hermes_read_reg (hw, HERMES_EVSTAT);
228 /* the software support register 0 (there are 3) is filled with a
229 * magic number. With this one can test the availability of the card */
230 hermes_write_reg (hw, HERMES_SWSUPPORT0, HERMES_MAGIC);
232 if (!hermes_present (hw)) {
233 printf("Hermes: Card not present?: got mag. nr.0x%x\n",
234 hermes_read_reg (hw, HERMES_SWSUPPORT0));
237 if (!(reg & HERMES_EV_CMD)) {
238 printf("hermes @ %x: Timeout waiting for card to reset\n",
239 hw->iobase);
240 return -ETIMEDOUT;
243 status = hermes_read_reg (hw, HERMES_STATUS);
244 resp0 = hermes_read_reg (hw, HERMES_RESP0);
246 /* after having issued the command above, the completion set a bit in
247 * the EVSTAT register. This has to be acknowledged, as follows */
248 hermes_write_reg (hw, HERMES_EVACK, HERMES_EV_CMD);
250 /* Was the status, the result of the issued command, ok? */
251 /* The expression below should be zero. Non-zero means an error */
252 if (status & HERMES_STATUS_RESULT) {
253 printf("Hermes:Result of INIT_CMD wrong.error value: 0x%x\n",
254 (status & HERMES_STATUS_RESULT) >> 8);
255 err = -EIO;
258 return err;
261 /*****************************************************************************
262 * hermes_docmd_wait *
264 * Issue a command to the chip, and (busy) wait for it to complete. *
265 *****************************************************************************/
266 int hermes_docmd_wait (hermes_t * hw, u16_t cmd, u16_t parm0,
267 hermes_response_t * resp) {
268 int err;
269 int k;
270 u16_t reg;
271 u16_t status;
273 err = hermes_issue_cmd (hw, cmd, parm0);
274 if (err) {
275 printf("hermes @ %x: Error %d issuing command.\n",
276 hw->iobase, err);
277 return err;
280 /* Reads the Event status register. When the command has completed,
281 * the fourth bit in the HERMES_EVSTAT register is a 1. We will be
282 * waiting for that to happen */
283 reg = hermes_read_reg (hw, HERMES_EVSTAT);
284 k = HERMES_CMD_COMPL_TIMEOUT;
285 while ((!(reg & HERMES_EV_CMD)) && k) {
286 k--;
287 micro_delay (10);
288 reg = hermes_read_reg (hw, HERMES_EVSTAT);
291 /* check for a timeout: has the command still not completed? */
292 if (!(reg & HERMES_EV_CMD)) {
293 printf("hermes @ %x: Timeout waiting for command \
294 completion.\n", hw->iobase);
295 err = -ETIMEDOUT;
296 return err;
299 status = hermes_read_reg (hw, HERMES_STATUS);
300 /* some commands result in results residing in response registers.
301 * They have to be read before the acknowledgement below.
303 if (resp) {
304 resp->status = status;
305 resp->resp0 = hermes_read_reg (hw, HERMES_RESP0);
306 resp->resp1 = hermes_read_reg (hw, HERMES_RESP1);
307 resp->resp2 = hermes_read_reg (hw, HERMES_RESP2);
310 /* After issueing a Command, the card expects an Acknowledgement */
311 hermes_write_reg (hw, HERMES_EVACK, HERMES_EV_CMD);
313 /* check whether there has been a valid value in the Status register.
314 * the high order bits should have at least some value */
315 if (status & HERMES_STATUS_RESULT) {
316 printf("Hermes: EIO\n");
317 err = -EIO;
320 return err;
324 /*****************************************************************************
325 * hermes_allocate *
327 * Allocate bufferspace in the card, which will be then available for *
328 * writing by the host, TX buffers. The card will try to find enough memory *
329 * (creating a list of 128 byte blocks) and will return a pointer to the *
330 * first block. This pointer is a pointer to the frame identifier (fid), *
331 * holding information and data of the buffer. The fid is like a file *
332 * descriptor, a value indicating some resource *
333 *****************************************************************************/
334 int hermes_allocate (hermes_t * hw, u16_t size, u16_t * fid) {
335 int err = 0;
336 int k;
337 u16_t reg;
339 if ((size < HERMES_ALLOC_LEN_MIN) || (size > HERMES_ALLOC_LEN_MAX)) {
340 printf("Hermes: Invalid size\n");
341 return -EINVAL;
344 /* Issue a allocation request to the card, waiting for the command
345 * to complete */
346 err = hermes_docmd_wait (hw, HERMES_CMD_ALLOC, size, NULL);
347 if (err) {
348 printf( "Hermes: docmd_wait timeout\n");
349 return err;
352 /* Read the status event register to know whether the allocation
353 * succeeded. The HERMES_EV_ALLOC bit should be set */
354 reg = hermes_read_reg (hw, HERMES_EVSTAT);
355 k = HERMES_ALLOC_COMPL_TIMEOUT;
356 while ((!(reg & HERMES_EV_ALLOC)) && k) {
357 k--;
358 micro_delay (10);
359 reg = hermes_read_reg (hw, HERMES_EVSTAT);
362 /* tired of waiting to complete. Abort. */
363 if (!(reg & HERMES_EV_ALLOC)) {
364 printf("hermes @ %x:Timeout waiting for frame allocation\n",
365 hw->iobase);
366 return -ETIMEDOUT;
369 /* When we come here, everything has gone well. The pointer to the
370 * fid is in the ALLOCFID register. This fid is later on used
371 * to access this buffer */
372 *fid = hermes_read_reg (hw, HERMES_ALLOCFID);
374 /* always acknowledge the receipt of an event */
375 hermes_write_reg (hw, HERMES_EVACK, HERMES_EV_ALLOC);
377 return 0;
382 /*****************************************************************************
383 * hermes_bap_seek *
385 * Set up a Buffer Access Path (BAP) to read a particular chunk of data *
386 * from card's internal buffer. Setting a bap register is like doing a fseek *
387 * system call: setting an internal pointer to the right place in a buffer *
388 *****************************************************************************/
389 static int hermes_bap_seek (hermes_t * hw, int bap, u16_t id, u16_t offset) {
391 /* There are 2 BAPs. This can be used to use the access buffers
392 * concurrently: 1 for writing in the TX buffer and 1 for reading
393 * a RX buffer in case of an RX interrupt.
394 * The BAP consists of 2 registers, together with which one can
395 * point to a single byte in the required buffer (additionally
396 * there is a third register, but that one is not used in this
397 * function, the data register). With the SELECT register one chooses
398 * the fid, with the OFFSET register one chooses the offset in the fid
399 * buffer */
400 int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0;
401 int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0;
402 int k;
403 u16_t reg;
405 /* Check whether the offset is not too large, and whether it is a
406 * number of words. Offset can't be odd */
407 if ((offset > HERMES_BAP_OFFSET_MAX) || (offset % 2)) {
408 printf("Hermes: Offset error\n");
409 return -EINVAL;
412 /* We can't write to the offset register when the busy flag is set. If
413 * it is set, wait to automatically reset*/
414 k = HERMES_BAP_BUSY_TIMEOUT;
415 reg = hermes_read_reg (hw, oreg);
416 while ((reg & HERMES_OFFSET_BUSY) && k) {
417 k--;
418 micro_delay (1);
419 reg = hermes_read_reg (hw, oreg);
422 /* For some reason, the busy flag didn't reset automatically. Return */
423 if (reg & HERMES_OFFSET_BUSY) {
424 printf("Hermes: HERMES_OFFSET_BUSY still set, oreg: 0x%x\n",
425 reg);
426 return -ETIMEDOUT;
429 /* Now we actually set up the transfer. Write the fid in the select
430 * register, and the offset in the offset register */
431 hermes_write_reg (hw, sreg, id);
432 hermes_write_reg (hw, oreg, offset);
434 /* Wait for the BAP to be ready. This means that at first the
435 * OFFSET_BUSY bit is set by the card once we have written the values
436 * above. We wait until the card has done its internal processing and
437 * unset the OFFSET_BUSY bit */
438 k = HERMES_BAP_BUSY_TIMEOUT;
439 reg = hermes_read_reg (hw, oreg);
440 while ((reg & (HERMES_OFFSET_BUSY | HERMES_OFFSET_ERR)) && k) {
441 k--;
442 micro_delay (1);
443 reg = hermes_read_reg (hw, oreg);
446 /* Busy bit didn't reset automatically */
447 if (reg & HERMES_OFFSET_BUSY) {
448 printf("Hermes: Error with fid 0x%x. Err: 0x%x\n", id, reg);
449 return -ETIMEDOUT;
452 /* There has gone something wrong: offset is outside the buffer
453 * boundary or the fid is not correct */
454 if (reg & HERMES_OFFSET_ERR) {
455 printf("Hermes: Error with fid 0x%x. Err: 0x%x\n", id, reg);
456 return -EIO;
459 /* If we arrive here, the buffer can be accessed through the data
460 * register associated with the BAP */
461 return 0;
465 /*****************************************************************************
466 * hermes_bap_pread *
468 * Read a block of data from the chip's buffer, via the BAP. len must be *
469 * even. *
470 *****************************************************************************/
471 int hermes_bap_pread (hermes_t * hw, int bap, void *buf, unsigned len,
472 u16_t id, u16_t offset) {
473 /* The data register is the access point for the buffer made
474 * available by setting the BAP right. Which BAP does the user
475 * want to use? there are 2 of them */
476 int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
477 int err = 0;
479 /* reading (and writing) data goes a word a time, so should be even */
480 if ((len % 2)) {
481 printf("Hermes: Error in length to be read\n");
482 return -EINVAL;
485 /* Set the cards internal pointer to the right fid and to the right
486 * offset */
487 err = hermes_bap_seek (hw, bap, id, offset);
488 if (err) {
489 printf("Hermes: error hermes_bap_seek in hermes_bap_pread\n");
490 return err;
492 /* Actually do the transfer. The length is divided by 2 because
493 * transfers go a word at a time as far as the card is concerned */
494 hermes_read_words (hw, dreg, buf, len / 2);
496 return err;
499 /*****************************************************************************
500 * hermes_write_words *
502 * Write a sequence of words of the buffer to the card *
503 *****************************************************************************/
504 void hermes_write_words (hermes_t * hw, int off, const void *buf,
505 unsigned count) {
506 int i = 0;
508 for (i = 0; i < count; i++) {
509 hermes_write_reg (hw, off, *((u16_t *) buf + i));
513 /*****************************************************************************
514 * hermes_bap_pwrite *
516 * Write a block of data to the chip's buffer, via the BAP. len must be even.*
517 *****************************************************************************/
518 int hermes_bap_pwrite (hermes_t * hw, int bap, const void *buf, unsigned len,
519 u16_t id, u16_t offset) {
521 /* This procedure is quite the same as the hermes_bap_read */
522 int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
523 int err = 0;
525 if ((len % 2)) {
526 printf("Hermes: Error in length to be written\n");
527 return -EINVAL;
530 /* Set the cards internal pointer to the right fid and to the right
531 * offset */
532 err = hermes_bap_seek (hw, bap, id, offset);
533 if (err) {
534 printf("Hermes: hermes_bap_seek error in hermes_bap_pwrite\n");
535 return err;
539 /* Actually do the transfer */
540 hermes_write_words (hw, dreg, buf, len / 2);
542 return err;
547 /*****************************************************************************
548 * hermes_set_irqmask *
550 * Which events should the card respond to with an interrupt? *
551 *****************************************************************************/
552 int hermes_set_irqmask (hermes_t * hw, u16_t events) {
553 hw->inten = events;
554 hermes_write_reg (hw, HERMES_INTEN, events);
556 /* Compare written value with read value to check whether things
557 * succeeded */
558 if (hermes_read_reg (hw, HERMES_INTEN) != events) {
559 printf("Hermes: error setting irqmask\n");
560 return 1;
563 return (0);
566 /*****************************************************************************
567 * hermes_set_irqmask *
569 * Which events does the card respond to with an interrupt? *
570 *****************************************************************************/
571 u16_t hermes_get_irqmask (hermes_t * hw) {
572 return hermes_read_reg (hw, HERMES_INTEN);
576 /*****************************************************************************
577 * hermes_read_ltv *
579 * Read a Length-Type-Value record from the card. These are configurable *
580 * parameters in the cards firmware, like wepkey, essid, mac address etc. *
581 * Another name for them are 'rids', Resource Identifiers. See hermes_rids.h *
582 * for all available rids *
583 * If length is NULL, we ignore the length read from the card, and *
584 * read the entire buffer regardless. This is useful because some of *
585 * the configuration records appear to have incorrect lengths in *
586 * practice. *
587 *****************************************************************************/
588 int hermes_read_ltv (hermes_t * hw, int bap, u16_t rid, unsigned bufsize,
589 u16_t * length, void *buf) {
590 int err = 0;
591 int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
592 u16_t rlength, rtype;
593 unsigned nwords;
595 if ((bufsize % 2)) {
596 printf("Hermes: error in bufsize\n");
597 return -EINVAL;
600 err = hermes_docmd_wait (hw, HERMES_CMD_ACCESS, rid, NULL);
601 if (err) {
602 printf("Hermes: error hermes_docmd_wait in hermes_read_ltv\n");
603 return err;
606 err = hermes_bap_seek (hw, bap, rid, 0);
607 if (err) {
608 printf("Hermes: error hermes_bap_seek in hermes_read_ltv\n");
609 return err;
612 rlength = hermes_read_reg (hw, dreg);
614 if (!rlength) {
615 printf( "Hermes: Error rlength\n");
616 return -ENOENT;
619 rtype = hermes_read_reg (hw, dreg);
621 if (length)
622 *length = rlength;
624 if (rtype != rid) {
625 printf("hermes @ %x: hermes_read_ltv(): rid (0x%04x)",
626 hw->iobase, rid);
627 printf("does not match type (0x%04x)\n", rtype);
630 if (HERMES_RECLEN_TO_BYTES (rlength) > bufsize) {
631 printf("hermes @ %x: Truncating LTV record from ",
632 hw->iobase);
633 printf("%d to %d bytes. (rid=0x%04x, len=0x%04x)\n",
634 HERMES_RECLEN_TO_BYTES (rlength), bufsize, rid,
635 rlength);
637 nwords = MIN ((unsigned) rlength - 1, bufsize / 2);
638 hermes_read_words (hw, dreg, buf, nwords);
640 return 0;
644 /*****************************************************************************
645 * hermes_write_ltv *
647 * Write a Length-Type-Value record to the card. These are configurable *
648 * parameters in the cards firmware, like wepkey, essid, mac address etc. *
649 * Another name for them are 'rids', Resource Identifiers. See hermes_rids.h *
650 * for all available rids *
651 *****************************************************************************/
652 int hermes_write_ltv (hermes_t * hw, int bap, u16_t rid,
653 u16_t length, const void *value) {
654 int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
655 int err = 0;
656 unsigned count;
658 if (length == 0) {
659 printf("Hermes: length==0 in hermes_write_ltv\n");
660 return -EINVAL;
663 err = hermes_bap_seek (hw, bap, rid, 0);
664 if (err) {
665 printf("Hermes: error hermes_bap_seek in hermes_write_ltv\n");
666 return err;
669 hermes_write_reg (hw, dreg, length);
670 hermes_write_reg (hw, dreg, rid);
672 count = length - 1;
674 hermes_write_words (hw, dreg, value, count);
676 err = hermes_docmd_wait (hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE,
677 rid, NULL);
678 if (err)
679 printf("Hermes: error hermes_docmd_wait in hermes_write_ltv\n");
681 return err;
685 /*****************************************************************************
686 * hermes_write_wordrec *
688 * A shorthand for hermes_write_ltv when the field is 2 bytes long *
689 *****************************************************************************/
690 int hermes_write_wordrec (hermes_t * hw, int bap, u16_t rid, u16_t word) {
692 u16_t rec;
693 int err;
694 rec = (word);
696 err = hermes_write_ltv (hw, bap, rid,
697 HERMES_BYTES_TO_RECLEN (sizeof (rec)), &rec);
699 if (err)
700 printf("Hermes: error in write_wordrec\n");
701 return err;
705 /*****************************************************************************
706 * hermes_read_wordrec *
708 * A shorthand for hermes_read_ltv when the field is 2 bytes long *
709 *****************************************************************************/
710 int hermes_read_wordrec (hermes_t * hw, int bap, u16_t rid, u16_t * word) {
711 u16_t rec;
712 int err;
714 err = hermes_read_ltv (hw, bap, rid, sizeof (rec), NULL, &rec);
715 *word = (rec);
716 if (err)
717 printf("Hermes: Error in read_wordrec\n");
718 return err;
722 /*****************************************************************************
723 * hermes_read_words *
725 * Read a sequence of words from the card to the buffer *
726 *****************************************************************************/
727 void hermes_read_words (hermes_t * hw, int off, void *buf, unsigned count) {
728 int i = 0;
729 u16_t reg;
731 for (i = 0; i < count; i++) {
732 reg = hermes_read_reg (hw, off);
733 *((u16_t *) buf + i) = (u16_t) reg;
738 /*****************************************************************************
739 * hermes_read_reg *
741 * Read a value from a certain register. Currently only memory mapped *
742 * registers are supported, but accessing I/O spaced registers should be *
743 * quite trivial *
744 *****************************************************************************/
745 u16_t hermes_read_reg (const hermes_t * hw, u16_t off) {
746 int v = 0;
747 v = *((int *)(hw->locmem + (off << hw->reg_spacing)));
748 return (u16_t) v;
751 /*****************************************************************************
752 * hermes_write_reg *
754 * Write a value to a certain register. Currently only memory mapped *
755 * registers are supported, but accessing I/O spaced registers should be *
756 * quite trivial *
757 *****************************************************************************/
758 void hermes_write_reg (const hermes_t * hw, u16_t off, u16_t val) {
759 int v = (int) val;
760 *(int *)(hw->locmem + (off << hw->reg_spacing)) = v;