altos: Start work on AES and raw radio interfaces.
[fw/altos] / src / ao_aes.c
1 /*
2  * Copyright © 2011 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 #include "ao.h"
19
20 __xdata uint8_t ao_aes_mutex;
21 __xdata uint8_t ao_aes_done;
22 __xdata uint8_t ao_aes_dma_in, ao_aes_dma_out;
23 __xdata uint8_t ao_aes_dma_in_done, ao_aes_dma_out_done;
24 __pdata enum ao_aes_mode ao_aes_current_mode;
25
26 void
27 ao_aes_isr(void) __interrupt 4
28 {
29         S0CON = 0;
30         if (ENCCCS & ENCCCS_RDY) {
31                 ao_aes_done = 1;
32                 ao_wakeup(&ao_aes_done);
33         }
34 }
35
36 void
37 ao_aes_set_mode(enum ao_aes_mode mode)
38 {
39         ao_aes_current_mode = mode;
40 }
41
42 void
43 ao_aes_set_key(__xdata uint8_t *in)
44 {
45         ao_dma_set_transfer(ao_aes_dma_in,
46                             in,
47                             &ENCDIXADDR,
48                             7,
49                             DMA_CFG0_WORDSIZE_8 |
50                             DMA_CFG0_TMODE_SINGLE |
51                             DMA_CFG0_TRIGGER_ENC_DW,
52                             DMA_CFG1_SRCINC_1 |
53                             DMA_CFG1_DESTINC_0 |
54                             DMA_CFG1_PRIORITY_LOW);
55         ao_aes_done = 0;
56         ENCCCS = ENCCCS_MODE_CBC_MAC |
57                 ENCCCS_CMD_LOAD_KEY |
58                 ENCCCS_START;
59         while (!ao_aes_done)
60                 ao_sleep(&ao_aes_done);
61 }
62
63 void
64 ao_aes_run(__xdata uint8_t *in,
65            __xdata uint8_t *out)
66 {
67         uint8_t b;
68         if (in) {
69                 ao_dma_set_transfer(ao_aes_dma_in,
70                                     in,
71                                     &ENCDIXADDR,
72                                     7,
73                                     DMA_CFG0_WORDSIZE_8 |
74                                     DMA_CFG0_TMODE_SINGLE |
75                                     DMA_CFG0_TRIGGER_ENC_DW,
76                                     DMA_CFG1_SRCINC_1 |
77                                     DMA_CFG1_DESTINC_0 |
78                                     DMA_CFG1_PRIORITY_LOW);
79         }
80         if (out) {
81                 ao_dma_set_transfer(ao_aes_dma_out,
82                                     &ENCDOXADDR,
83                                     out,
84                                     7,
85                                     DMA_CFG0_WORDSIZE_8 |
86                                     DMA_CFG0_TMODE_SINGLE |
87                                     DMA_CFG0_TRIGGER_ENC_UP,
88                                     DMA_CFG1_SRCINC_0 |
89                                     DMA_CFG1_DESTINC_1 |
90                                     DMA_CFG1_PRIORITY_LOW);
91         }
92         switch (ao_aes_current_mode) {
93         case ao_aes_mode_cbc_mac:
94                 if (out)
95                         b = (ENCCCS_MODE_CBC |
96                              ENCCCS_CMD_ENCRYPT |
97                              ENCCCS_START);
98                 else
99                         b = (ENCCCS_MODE_CBC_MAC |
100                              ENCCCS_CMD_ENCRYPT |
101                              ENCCCS_START);
102                 break;
103         default:
104                 return;
105         }
106         ao_aes_done = 0;
107         ENCCCS = b;
108         if (out)
109                 while (!ao_aes_dma_out_done)
110                         ao_sleep(&ao_aes_dma_out_done);
111         else
112                 while (!ao_aes_done)
113                         ao_sleep(&ao_aes_done);
114 }
115
116 void
117 ao_aes_init(void)
118 {
119         ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done);
120         ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done);
121         ENCIE = 1;
122 }