proto_core.c (265055) | proto_core.c (284079) |
---|---|
1/*- 2 * Copyright (c) 2014 Marcel Moolenaar 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * --- 11 unchanged lines hidden (view full) --- 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2014 Marcel Moolenaar 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * --- 11 unchanged lines hidden (view full) --- 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sys/dev/proto/proto_core.c 265055 2014-04-28 17:58:40Z marcel $"); | 28__FBSDID("$FreeBSD: head/sys/dev/proto/proto_core.c 284079 2015-06-06 16:09:25Z marcel $"); |
29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/bus.h> 33#include <sys/conf.h> 34#include <sys/cons.h> 35#include <sys/fcntl.h> 36#include <sys/interrupt.h> --- 9 unchanged lines hidden (view full) --- 46#include <sys/uio.h> 47#include <machine/resource.h> 48#include <machine/stdarg.h> 49 50#include <dev/pci/pcivar.h> 51 52#include <dev/proto/proto.h> 53#include <dev/proto/proto_dev.h> | 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/bus.h> 33#include <sys/conf.h> 34#include <sys/cons.h> 35#include <sys/fcntl.h> 36#include <sys/interrupt.h> --- 9 unchanged lines hidden (view full) --- 46#include <sys/uio.h> 47#include <machine/resource.h> 48#include <machine/stdarg.h> 49 50#include <dev/pci/pcivar.h> 51 52#include <dev/proto/proto.h> 53#include <dev/proto/proto_dev.h> |
54#include <dev/proto/proto_busdma.h> |
|
54 55CTASSERT(SYS_RES_IRQ != PROTO_RES_UNUSED && 56 SYS_RES_MEMORY != PROTO_RES_UNUSED && 57 SYS_RES_IOPORT != PROTO_RES_UNUSED); 58CTASSERT(SYS_RES_IRQ != PROTO_RES_PCICFG && 59 SYS_RES_MEMORY != PROTO_RES_PCICFG && 60 SYS_RES_IOPORT != PROTO_RES_PCICFG); | 55 56CTASSERT(SYS_RES_IRQ != PROTO_RES_UNUSED && 57 SYS_RES_MEMORY != PROTO_RES_UNUSED && 58 SYS_RES_IOPORT != PROTO_RES_UNUSED); 59CTASSERT(SYS_RES_IRQ != PROTO_RES_PCICFG && 60 SYS_RES_MEMORY != PROTO_RES_PCICFG && 61 SYS_RES_IOPORT != PROTO_RES_PCICFG); |
62CTASSERT(SYS_RES_IRQ != PROTO_RES_BUSDMA && 63 SYS_RES_MEMORY != PROTO_RES_BUSDMA && 64 SYS_RES_IOPORT != PROTO_RES_BUSDMA); |
|
61 62devclass_t proto_devclass; 63char proto_driver_name[] = "proto"; 64 65static d_open_t proto_open; 66static d_close_t proto_close; 67static d_read_t proto_read; 68static d_write_t proto_write; --- 23 unchanged lines hidden (view full) --- 92 if (type == PROTO_RES_UNUSED) 93 return (EINVAL); 94 if (sc->sc_rescnt == PROTO_RES_MAX) 95 return (ENOSPC); 96 97 r = sc->sc_res + sc->sc_rescnt++; 98 r->r_type = type; 99 r->r_rid = rid; | 65 66devclass_t proto_devclass; 67char proto_driver_name[] = "proto"; 68 69static d_open_t proto_open; 70static d_close_t proto_close; 71static d_read_t proto_read; 72static d_write_t proto_write; --- 23 unchanged lines hidden (view full) --- 96 if (type == PROTO_RES_UNUSED) 97 return (EINVAL); 98 if (sc->sc_rescnt == PROTO_RES_MAX) 99 return (ENOSPC); 100 101 r = sc->sc_res + sc->sc_rescnt++; 102 r->r_type = type; 103 r->r_rid = rid; |
100 r->r_res = res; | 104 r->r_d.res = res; |
101 return (0); 102} 103 104#ifdef notyet 105static int 106proto_intr(void *arg) 107{ 108 struct proto_softc *sc = arg; --- 16 unchanged lines hidden (view full) --- 125 for (res = 0; res < sc->sc_rescnt; res++) { 126 r = sc->sc_res + res; 127 switch (r->r_type) { 128 case SYS_RES_IRQ: 129 /* XXX TODO */ 130 break; 131 case SYS_RES_MEMORY: 132 case SYS_RES_IOPORT: | 105 return (0); 106} 107 108#ifdef notyet 109static int 110proto_intr(void *arg) 111{ 112 struct proto_softc *sc = arg; --- 16 unchanged lines hidden (view full) --- 129 for (res = 0; res < sc->sc_rescnt; res++) { 130 r = sc->sc_res + res; 131 switch (r->r_type) { 132 case SYS_RES_IRQ: 133 /* XXX TODO */ 134 break; 135 case SYS_RES_MEMORY: 136 case SYS_RES_IOPORT: |
133 r->r_size = rman_get_size(r->r_res); | 137 r->r_size = rman_get_size(r->r_d.res); |
134 r->r_u.cdev = make_dev(&proto_devsw, res, 0, 0, 0666, 135 "proto/%s/%02x.%s", device_get_desc(dev), r->r_rid, 136 (r->r_type == SYS_RES_IOPORT) ? "io" : "mem"); 137 r->r_u.cdev->si_drv1 = sc; 138 r->r_u.cdev->si_drv2 = r; 139 break; 140 case PROTO_RES_PCICFG: 141 r->r_size = 4096; 142 r->r_u.cdev = make_dev(&proto_devsw, res, 0, 0, 0666, 143 "proto/%s/pcicfg", device_get_desc(dev)); 144 r->r_u.cdev->si_drv1 = sc; 145 r->r_u.cdev->si_drv2 = r; 146 break; | 138 r->r_u.cdev = make_dev(&proto_devsw, res, 0, 0, 0666, 139 "proto/%s/%02x.%s", device_get_desc(dev), r->r_rid, 140 (r->r_type == SYS_RES_IOPORT) ? "io" : "mem"); 141 r->r_u.cdev->si_drv1 = sc; 142 r->r_u.cdev->si_drv2 = r; 143 break; 144 case PROTO_RES_PCICFG: 145 r->r_size = 4096; 146 r->r_u.cdev = make_dev(&proto_devsw, res, 0, 0, 0666, 147 "proto/%s/pcicfg", device_get_desc(dev)); 148 r->r_u.cdev->si_drv1 = sc; 149 r->r_u.cdev->si_drv2 = r; 150 break; |
151 case PROTO_RES_BUSDMA: 152 r->r_d.busdma = proto_busdma_attach(sc); 153 r->r_size = 0; /* no read(2) nor write(2) */ 154 r->r_u.cdev = make_dev(&proto_devsw, res, 0, 0, 0666, 155 "proto/%s/busdma", device_get_desc(dev)); 156 r->r_u.cdev->si_drv1 = sc; 157 r->r_u.cdev->si_drv2 = r; 158 break; |
|
147 } 148 } 149 return (0); 150} 151 152int 153proto_detach(device_t dev) 154{ 155 struct proto_softc *sc; 156 struct proto_res *r; 157 u_int res; 158 159 sc = device_get_softc(dev); 160 | 159 } 160 } 161 return (0); 162} 163 164int 165proto_detach(device_t dev) 166{ 167 struct proto_softc *sc; 168 struct proto_res *r; 169 u_int res; 170 171 sc = device_get_softc(dev); 172 |
161 /* Don't detach if we have open device filess. */ | 173 /* Don't detach if we have open device files. */ |
162 for (res = 0; res < sc->sc_rescnt; res++) { 163 r = sc->sc_res + res; 164 if (r->r_opened) 165 return (EBUSY); 166 } 167 168 for (res = 0; res < sc->sc_rescnt; res++) { 169 r = sc->sc_res + res; 170 switch (r->r_type) { 171 case SYS_RES_IRQ: 172 /* XXX TODO */ | 174 for (res = 0; res < sc->sc_rescnt; res++) { 175 r = sc->sc_res + res; 176 if (r->r_opened) 177 return (EBUSY); 178 } 179 180 for (res = 0; res < sc->sc_rescnt; res++) { 181 r = sc->sc_res + res; 182 switch (r->r_type) { 183 case SYS_RES_IRQ: 184 /* XXX TODO */ |
185 bus_release_resource(dev, r->r_type, r->r_rid, 186 r->r_d.res); |
|
173 break; 174 case SYS_RES_MEMORY: 175 case SYS_RES_IOPORT: | 187 break; 188 case SYS_RES_MEMORY: 189 case SYS_RES_IOPORT: |
190 bus_release_resource(dev, r->r_type, r->r_rid, 191 r->r_d.res); 192 destroy_dev(r->r_u.cdev); 193 break; |
|
176 case PROTO_RES_PCICFG: 177 destroy_dev(r->r_u.cdev); 178 break; | 194 case PROTO_RES_PCICFG: 195 destroy_dev(r->r_u.cdev); 196 break; |
197 case PROTO_RES_BUSDMA: 198 proto_busdma_detach(sc, r->r_d.busdma); 199 destroy_dev(r->r_u.cdev); 200 break; |
|
179 } | 201 } |
180 if (r->r_res != NULL) { 181 bus_release_resource(dev, r->r_type, r->r_rid, 182 r->r_res); 183 r->r_res = NULL; 184 } | |
185 r->r_type = PROTO_RES_UNUSED; 186 } 187 sc->sc_rescnt = 0; 188 return (0); 189} 190 191/* 192 * Device functions --- 9 unchanged lines hidden (view full) --- 202 return (EBUSY); 203 return (0); 204} 205 206static int 207proto_close(struct cdev *cdev, int fflag, int devtype, struct thread *td) 208{ 209 struct proto_res *r; | 202 r->r_type = PROTO_RES_UNUSED; 203 } 204 sc->sc_rescnt = 0; 205 return (0); 206} 207 208/* 209 * Device functions --- 9 unchanged lines hidden (view full) --- 219 return (EBUSY); 220 return (0); 221} 222 223static int 224proto_close(struct cdev *cdev, int fflag, int devtype, struct thread *td) 225{ 226 struct proto_res *r; |
227 struct proto_softc *sc; |
|
210 | 228 |
229 sc = cdev->si_drv1; |
|
211 r = cdev->si_drv2; 212 if (!atomic_cmpset_acq_ptr(&r->r_opened, (uintptr_t)td->td_proc, 0UL)) 213 return (ENXIO); | 230 r = cdev->si_drv2; 231 if (!atomic_cmpset_acq_ptr(&r->r_opened, (uintptr_t)td->td_proc, 0UL)) 232 return (ENXIO); |
233 if (r->r_type == PROTO_RES_BUSDMA) 234 proto_busdma_cleanup(sc, r->r_d.busdma); |
|
214 return (0); 215} 216 217static int 218proto_read(struct cdev *cdev, struct uio *uio, int ioflag) 219{ 220 union { 221 uint8_t x1[8]; --- 17 unchanged lines hidden (view full) --- 239 return (EIO); 240 ofs = uio->uio_offset; 241 if (ofs + width > r->r_size) 242 return (EIO); 243 244 switch (width) { 245 case 1: 246 buf.x1[0] = (r->r_type == PROTO_RES_PCICFG) ? | 235 return (0); 236} 237 238static int 239proto_read(struct cdev *cdev, struct uio *uio, int ioflag) 240{ 241 union { 242 uint8_t x1[8]; --- 17 unchanged lines hidden (view full) --- 260 return (EIO); 261 ofs = uio->uio_offset; 262 if (ofs + width > r->r_size) 263 return (EIO); 264 265 switch (width) { 266 case 1: 267 buf.x1[0] = (r->r_type == PROTO_RES_PCICFG) ? |
247 pci_read_config(dev, ofs, 1) : bus_read_1(r->r_res, ofs); | 268 pci_read_config(dev, ofs, 1) : bus_read_1(r->r_d.res, ofs); |
248 break; 249 case 2: 250 buf.x2[0] = (r->r_type == PROTO_RES_PCICFG) ? | 269 break; 270 case 2: 271 buf.x2[0] = (r->r_type == PROTO_RES_PCICFG) ? |
251 pci_read_config(dev, ofs, 2) : bus_read_2(r->r_res, ofs); | 272 pci_read_config(dev, ofs, 2) : bus_read_2(r->r_d.res, ofs); |
252 break; 253 case 4: 254 buf.x4[0] = (r->r_type == PROTO_RES_PCICFG) ? | 273 break; 274 case 4: 275 buf.x4[0] = (r->r_type == PROTO_RES_PCICFG) ? |
255 pci_read_config(dev, ofs, 4) : bus_read_4(r->r_res, ofs); | 276 pci_read_config(dev, ofs, 4) : bus_read_4(r->r_d.res, ofs); |
256 break; 257#ifndef __i386__ 258 case 8: 259 if (r->r_type == PROTO_RES_PCICFG) 260 return (EINVAL); | 277 break; 278#ifndef __i386__ 279 case 8: 280 if (r->r_type == PROTO_RES_PCICFG) 281 return (EINVAL); |
261 buf.x8[0] = bus_read_8(r->r_res, ofs); | 282 buf.x8[0] = bus_read_8(r->r_d.res, ofs); |
262 break; 263#endif 264 default: 265 return (EIO); 266 } 267 268 error = uiomove(&buf, width, uio); 269 return (error); --- 30 unchanged lines hidden (view full) --- 300 if (error) 301 return (error); 302 303 switch (width) { 304 case 1: 305 if (r->r_type == PROTO_RES_PCICFG) 306 pci_write_config(dev, ofs, buf.x1[0], 1); 307 else | 283 break; 284#endif 285 default: 286 return (EIO); 287 } 288 289 error = uiomove(&buf, width, uio); 290 return (error); --- 30 unchanged lines hidden (view full) --- 321 if (error) 322 return (error); 323 324 switch (width) { 325 case 1: 326 if (r->r_type == PROTO_RES_PCICFG) 327 pci_write_config(dev, ofs, buf.x1[0], 1); 328 else |
308 bus_write_1(r->r_res, ofs, buf.x1[0]); | 329 bus_write_1(r->r_d.res, ofs, buf.x1[0]); |
309 break; 310 case 2: 311 if (r->r_type == PROTO_RES_PCICFG) 312 pci_write_config(dev, ofs, buf.x2[0], 2); 313 else | 330 break; 331 case 2: 332 if (r->r_type == PROTO_RES_PCICFG) 333 pci_write_config(dev, ofs, buf.x2[0], 2); 334 else |
314 bus_write_2(r->r_res, ofs, buf.x2[0]); | 335 bus_write_2(r->r_d.res, ofs, buf.x2[0]); |
315 break; 316 case 4: 317 if (r->r_type == PROTO_RES_PCICFG) 318 pci_write_config(dev, ofs, buf.x4[0], 4); 319 else | 336 break; 337 case 4: 338 if (r->r_type == PROTO_RES_PCICFG) 339 pci_write_config(dev, ofs, buf.x4[0], 4); 340 else |
320 bus_write_4(r->r_res, ofs, buf.x4[0]); | 341 bus_write_4(r->r_d.res, ofs, buf.x4[0]); |
321 break; 322#ifndef __i386__ 323 case 8: 324 if (r->r_type == PROTO_RES_PCICFG) 325 return (EINVAL); | 342 break; 343#ifndef __i386__ 344 case 8: 345 if (r->r_type == PROTO_RES_PCICFG) 346 return (EINVAL); |
326 bus_write_8(r->r_res, ofs, buf.x8[0]); | 347 bus_write_8(r->r_d.res, ofs, buf.x8[0]); |
327 break; 328#endif 329 default: 330 return (EIO); 331 } 332 333 return (0); 334} 335 336static int 337proto_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, 338 struct thread *td) 339{ 340 struct proto_ioc_region *region; | 348 break; 349#endif 350 default: 351 return (EIO); 352 } 353 354 return (0); 355} 356 357static int 358proto_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, 359 struct thread *td) 360{ 361 struct proto_ioc_region *region; |
362 struct proto_ioc_busdma *busdma; |
|
341 struct proto_res *r; | 363 struct proto_res *r; |
364 struct proto_softc *sc; |
|
342 int error; 343 | 365 int error; 366 |
367 sc = cdev->si_drv1; |
|
344 r = cdev->si_drv2; 345 346 error = 0; 347 switch (cmd) { 348 case PROTO_IOC_REGION: 349 region = (struct proto_ioc_region *)data; 350 region->size = r->r_size; 351 if (r->r_type == PROTO_RES_PCICFG) 352 region->address = 0; 353 else | 368 r = cdev->si_drv2; 369 370 error = 0; 371 switch (cmd) { 372 case PROTO_IOC_REGION: 373 region = (struct proto_ioc_region *)data; 374 region->size = r->r_size; 375 if (r->r_type == PROTO_RES_PCICFG) 376 region->address = 0; 377 else |
354 region->address = rman_get_start(r->r_res); | 378 region->address = rman_get_start(r->r_d.res); |
355 break; | 379 break; |
380 case PROTO_IOC_BUSDMA: 381 busdma = (struct proto_ioc_busdma *)data; 382 error = proto_busdma_ioctl(sc, r->r_d.busdma, busdma); 383 break; |
|
356 default: 357 error = ENOIOCTL; 358 break; 359 } 360 return (error); 361} 362 363static int --- 7 unchanged lines hidden (view full) --- 371 if (r->r_type != SYS_RES_MEMORY) 372 return (ENXIO); 373 if (offset & PAGE_MASK) 374 return (EINVAL); 375 if (prot & PROT_EXEC) 376 return (EACCES); 377 if (offset >= r->r_size) 378 return (EINVAL); | 384 default: 385 error = ENOIOCTL; 386 break; 387 } 388 return (error); 389} 390 391static int --- 7 unchanged lines hidden (view full) --- 399 if (r->r_type != SYS_RES_MEMORY) 400 return (ENXIO); 401 if (offset & PAGE_MASK) 402 return (EINVAL); 403 if (prot & PROT_EXEC) 404 return (EACCES); 405 if (offset >= r->r_size) 406 return (EINVAL); |
379 *paddr = rman_get_start(r->r_res) + offset; | 407 *paddr = rman_get_start(r->r_d.res) + offset; |
380#ifndef __sparc64__ 381 *memattr = VM_MEMATTR_UNCACHEABLE; 382#endif 383 return (0); 384} | 408#ifndef __sparc64__ 409 *memattr = VM_MEMATTR_UNCACHEABLE; 410#endif 411 return (0); 412} |