Changeset 1f0db02e in mainline
- Timestamp:
- 2009-07-07T21:48:51Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 30f869d
- Parents:
- 925be4e
- Location:
- kernel/genarch
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/genarch/include/drivers/via-cuda/cuda.h
r925be4e r1f0db02e 95 95 }; 96 96 97 enum cuda_xfer_state { 98 cx_listen, 99 cx_receive, 100 cx_rcv_end 101 }; 102 97 103 typedef struct { 98 104 irq_t irq; … … 100 106 indev_t *kbrdin; 101 107 uint8_t rcv_buf[CUDA_RCV_BUF_SIZE]; 108 size_t bidx; 109 enum cuda_xfer_state xstate; 102 110 SPINLOCK_DECLARE(dev_lock); 103 111 } cuda_instance_t; -
kernel/genarch/src/drivers/via-cuda/cuda.c
r925be4e r1f0db02e 42 42 #include <synch/spinlock.h> 43 43 44 static void cuda_packet_handle(cuda_instance_t *instance, size_t len); 44 static void cuda_packet_handle(cuda_instance_t *instance, uint8_t *buf, size_t len); 45 static void cuda_irq_listen(irq_t *irq); 46 static void cuda_irq_receive(irq_t *irq); 47 static void cuda_irq_rcv_end(irq_t *irq, void *buf, size_t *len); 45 48 46 49 /** B register fields */ … … 53 56 /** IER register fields */ 54 57 enum { 58 IER_CLR = 0x00, 55 59 IER_SET = 0x80, 56 SR_INT = 0x04 60 61 SR_INT = 0x04, 62 ALL_INT = 0x7f 57 63 }; 58 64 65 /** ACR register fields */ 66 enum { 67 SR_OUT = 0x10 68 }; 69 70 #include <print.h> 59 71 static irq_ownership_t cuda_claim(irq_t *irq) 60 72 { … … 65 77 ifr = pio_read_8(&dev->ifr); 66 78 67 if ((ifr & SR_INT) != 0) 68 return IRQ_ACCEPT; 69 else 79 if ((ifr & SR_INT) == 0) 70 80 return IRQ_DECLINE; 81 82 return IRQ_ACCEPT; 71 83 } 72 84 … … 74 86 { 75 87 cuda_instance_t *instance = irq->instance; 88 uint8_t rbuf[CUDA_RCV_BUF_SIZE]; 89 size_t len; 90 bool handle; 91 92 handle = false; 93 len = 0; 94 95 spinlock_lock(&instance->dev_lock); 96 97 /* Lower IFR.SR_INT so that CUDA can generate next int by raising it. */ 98 pio_write_8(&instance->cuda->ifr, SR_INT); 99 100 switch (instance->xstate) { 101 case cx_listen: cuda_irq_listen(irq); break; 102 case cx_receive: cuda_irq_receive(irq); break; 103 case cx_rcv_end: cuda_irq_rcv_end(irq, rbuf, &len); 104 handle = true; break; 105 } 106 107 spinlock_unlock(&instance->dev_lock); 108 109 /* Handle an incoming packet. */ 110 if (handle) 111 cuda_packet_handle(instance, rbuf, len); 112 } 113 114 /** Interrupt in listen state. 115 * 116 * Start packet reception. 117 */ 118 static void cuda_irq_listen(irq_t *irq) 119 { 120 cuda_instance_t *instance = irq->instance; 121 cuda_t *dev = instance->cuda; 122 uint8_t b; 123 124 b = pio_read_8(&dev->b); 125 126 if ((b & TREQ) != 0) { 127 printf("cuda_irq_listen: no TREQ?!\n"); 128 return; 129 } 130 131 pio_read_8(&dev->sr); 132 pio_write_8(&dev->b, pio_read_8(&dev->b) & ~TIP); 133 instance->xstate = cx_receive; 134 } 135 136 /** Interrupt in receive state. 137 * 138 * Receive next byte of packet. 139 */ 140 static void cuda_irq_receive(irq_t *irq) 141 { 142 cuda_instance_t *instance = irq->instance; 76 143 cuda_t *dev = instance->cuda; 77 144 uint8_t b, data; 78 size_t pos; 79 80 spinlock_lock(&instance->dev_lock); 81 82 /* We have received one or more CUDA packets. Process them all. */ 83 while (true) { 84 b = pio_read_8(&dev->b); 85 86 if ((b & TREQ) != 0) 87 break; /* No data */ 88 145 146 data = pio_read_8(&dev->sr); 147 if (instance->bidx < CUDA_RCV_BUF_SIZE) 148 instance->rcv_buf[instance->bidx++] = data; 149 150 b = pio_read_8(&dev->b); 151 152 if ((b & TREQ) == 0) { 153 pio_write_8(&dev->b, b ^ TACK); 154 } else { 155 pio_write_8(&dev->b, b | TACK | TIP); 156 instance->xstate = cx_rcv_end; 157 } 158 } 159 160 /** Interrupt in rcv_end state. 161 * 162 * Terminate packet reception. Either go back to listen state or start 163 * receiving another packet if CUDA has one for us. 164 */ 165 static void cuda_irq_rcv_end(irq_t *irq, void *buf, size_t *len) 166 { 167 cuda_instance_t *instance = irq->instance; 168 cuda_t *dev = instance->cuda; 169 uint8_t data, b; 170 171 b = pio_read_8(&dev->b); 172 data = pio_read_8(&dev->sr); 173 174 instance->xstate = cx_listen; 175 176 if ((b & TREQ) == 0) { 177 instance->xstate = cx_receive; 89 178 pio_write_8(&dev->b, b & ~TIP); 90 91 /* Read one packet. */ 92 93 pos = 0; 94 do { 95 data = pio_read_8(&dev->sr); 96 b = pio_read_8(&dev->b); 97 pio_write_8(&dev->b, b ^ TACK); 98 99 if (pos < CUDA_RCV_BUF_SIZE) 100 instance->rcv_buf[pos++] = data; 101 } while ((b & TREQ) == 0); 102 103 pio_write_8(&dev->b, b | TACK | TIP); 104 105 cuda_packet_handle(instance, pos); 106 } 107 108 spinlock_unlock(&instance->dev_lock); 109 } 110 111 static void cuda_packet_handle(cuda_instance_t *instance, size_t len) 112 { 113 uint8_t *data = instance->rcv_buf; 114 115 if (data[0] != 0x00 || data[1] != 0x40 || data[2] != 0x2c) 179 } else { 180 instance->xstate = cx_listen; 181 } 182 183 memcpy(buf, instance->rcv_buf, instance->bidx); 184 *len = instance->bidx; 185 instance->bidx = 0; 186 } 187 188 static void cuda_packet_handle(cuda_instance_t *instance, uint8_t *data, size_t len) 189 { 190 if (data[0] != 0x00 || data[1] != 0x40 || (data[2] != 0x2c 191 && data[2] != 0x8c)) 116 192 return; 117 193 … … 130 206 instance->cuda = dev; 131 207 instance->kbrdin = NULL; 208 instance->xstate = cx_listen; 209 instance->bidx = 0; 132 210 133 211 spinlock_initialize(&instance->dev_lock, "cuda_dev"); 212 213 /* Disable all interrupts from CUDA. */ 214 pio_write_8(&dev->ier, IER_CLR | ALL_INT); 134 215 135 216 irq_initialize(&instance->irq); … … 141 222 instance->irq.cir = cir; 142 223 instance->irq.cir_arg = cir_arg; 224 instance->irq.preack = true; 143 225 } 144 226 … … 148 230 void cuda_wire(cuda_instance_t *instance, indev_t *kbrdin) 149 231 { 232 cuda_t *dev = instance->cuda; 233 150 234 ASSERT(instance); 151 235 ASSERT(kbrdin); … … 155 239 156 240 /* Enable SR interrupt. */ 157 pio_write_8(&instance->cuda->ier, IER_SET | SR_INT); 241 pio_write_8(&dev->ier, TIP | TREQ); 242 pio_write_8(&dev->ier, IER_SET | SR_INT); 158 243 } 159 244
Note:
See TracChangeset
for help on using the changeset viewer.