ppbconf.c revision 42475
128219Smsmith/*- 242475Snsouch * Copyright (c) 1997, 1998, 1999 Nicolas Souchu 328219Smsmith * All rights reserved. 428219Smsmith * 528219Smsmith * Redistribution and use in source and binary forms, with or without 628219Smsmith * modification, are permitted provided that the following conditions 728219Smsmith * are met: 828219Smsmith * 1. Redistributions of source code must retain the above copyright 928219Smsmith * notice, this list of conditions and the following disclaimer. 1028219Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1128219Smsmith * notice, this list of conditions and the following disclaimer in the 1228219Smsmith * documentation and/or other materials provided with the distribution. 1328219Smsmith * 1428219Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1528219Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1628219Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1728219Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1828219Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1928219Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2028219Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2128219Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2228219Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2328219Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2428219Smsmith * SUCH DAMAGE. 2528219Smsmith * 2642475Snsouch * $Id: ppbconf.c,v 1.9 1998/12/07 21:58:16 archie Exp $ 2728219Smsmith * 2828219Smsmith */ 2928219Smsmith#include <sys/param.h> 3028219Smsmith#include <sys/systm.h> 3128219Smsmith#include <sys/kernel.h> 3228219Smsmith#include <sys/malloc.h> 3328219Smsmith 3428219Smsmith#include <vm/vm.h> 3528219Smsmith#include <vm/pmap.h> 3628219Smsmith 3728219Smsmith#include <dev/ppbus/ppbconf.h> 3828257Smsmith#include <dev/ppbus/ppb_1284.h> 3928219Smsmith 4042475Snsouch#include "opt_ppb_1284.h" 4142475Snsouch 4238061SmsmithLIST_HEAD(, ppb_data) ppbdata; /* list of existing ppbus */ 4328219Smsmith 4428219Smsmith/* 4528219Smsmith * Add a null driver so that the linker set always exists. 4628219Smsmith */ 4728219Smsmith 4828219Smsmithstatic struct ppb_driver nulldriver = { 4928219Smsmith NULL, NULL, "null" 5028219Smsmith}; 5128219SmsmithDATA_SET(ppbdriver_set, nulldriver); 5228219Smsmith 5328219Smsmith 5428219Smsmith/* 5528219Smsmith * ppb_alloc_bus() 5628219Smsmith * 5728219Smsmith * Allocate area to store the ppbus description. 5828219Smsmith */ 5928219Smsmithstruct ppb_data * 6028219Smsmithppb_alloc_bus(void) 6128219Smsmith{ 6228219Smsmith struct ppb_data *ppb; 6328219Smsmith static int ppbdata_initted = 0; /* done-init flag */ 6428219Smsmith 6528219Smsmith ppb = (struct ppb_data *) malloc(sizeof(struct ppb_data), 6628219Smsmith M_TEMP, M_NOWAIT); 6728219Smsmith 6828219Smsmith /* 6928219Smsmith * Add the new parallel port bus to the list of existing ppbus. 7028219Smsmith */ 7128219Smsmith if (ppb) { 7228219Smsmith bzero(ppb, sizeof(struct ppb_data)); 7328219Smsmith 7428219Smsmith if (!ppbdata_initted) { /* list not initialised */ 7528219Smsmith LIST_INIT(&ppbdata); 7628219Smsmith ppbdata_initted = 1; 7728219Smsmith } 7828219Smsmith LIST_INSERT_HEAD(&ppbdata, ppb, ppb_chain); 7928219Smsmith } else { 8028219Smsmith printf("ppb_alloc_bus: cannot malloc!\n"); 8128219Smsmith } 8228219Smsmith return(ppb); 8328219Smsmith} 8428219Smsmith 8542475Snsouch#define PPB_PNP_PRINTER 0 8642475Snsouch#define PPB_PNP_MODEM 1 8742475Snsouch#define PPB_PNP_NET 2 8842475Snsouch#define PPB_PNP_HDC 3 8942475Snsouch#define PPB_PNP_PCMCIA 4 9042475Snsouch#define PPB_PNP_MEDIA 5 9142475Snsouch#define PPB_PNP_FDC 6 9242475Snsouch#define PPB_PNP_PORTS 7 9342475Snsouch#define PPB_PNP_SCANNER 8 9442475Snsouch#define PPB_PNP_DIGICAM 9 9542475Snsouch 9642475Snsouch#ifndef DONTPROBE_1284 9742475Snsouch 9828257Smsmithstatic char *pnp_tokens[] = { 9928257Smsmith "PRINTER", "MODEM", "NET", "HDC", "PCMCIA", "MEDIA", 10028257Smsmith "FDC", "PORTS", "SCANNER", "DIGICAM", "", NULL }; 10128257Smsmith 10242475Snsouch#if 0 10328257Smsmithstatic char *pnp_classes[] = { 10428257Smsmith "printer", "modem", "network device", 10528257Smsmith "hard disk", "PCMCIA", "multimedia device", 10628257Smsmith "floppy disk", "ports", "scanner", 10728257Smsmith "digital camera", "unknown device", NULL }; 10842475Snsouch#endif 10928257Smsmith 11028219Smsmith/* 11128257Smsmith * search_token() 11228257Smsmith * 11328257Smsmith * Search the first occurence of a token within a string 11439134Snsouch * 11539134Snsouch * XXX should use strxxx() calls 11628257Smsmith */ 11728257Smsmithstatic char * 11828257Smsmithsearch_token(char *str, int slen, char *token) 11928257Smsmith{ 12028257Smsmith char *p; 12128257Smsmith int tlen, i, j; 12228257Smsmith 12328257Smsmith#define UNKNOWN_LENGTH -1 12428257Smsmith 12528257Smsmith if (slen == UNKNOWN_LENGTH) 12628257Smsmith /* get string's length */ 12728257Smsmith for (slen = 0, p = str; *p != '\0'; p++) 12828257Smsmith slen ++; 12928257Smsmith 13028257Smsmith /* get token's length */ 13128257Smsmith for (tlen = 0, p = token; *p != '\0'; p++) 13228257Smsmith tlen ++; 13328257Smsmith 13428257Smsmith if (tlen == 0) 13528257Smsmith return (str); 13628257Smsmith 13728257Smsmith for (i = 0; i <= slen-tlen; i++) { 13828257Smsmith for (j = 0; j < tlen; j++) 13928257Smsmith if (str[i+j] != token[j]) 14028257Smsmith break; 14128257Smsmith if (j == tlen) 14228257Smsmith return (&str[i]); 14328257Smsmith } 14428257Smsmith 14528257Smsmith return (NULL); 14628257Smsmith} 14728257Smsmith 14828257Smsmith/* 14928257Smsmith * ppb_pnp_detect() 15028257Smsmith * 15128257Smsmith * Returns the class id. of the peripherial, -1 otherwise 15228257Smsmith */ 15328257Smsmithstatic int 15442475Snsouchppb_pnp_detect(struct ppb_data *ppb, struct ppb_device *pnpdev) 15528257Smsmith{ 15642475Snsouch char *token, *class = 0; 15728257Smsmith int i, len, error; 15838061Smsmith int class_id = -1; 15928257Smsmith char str[PPB_PnP_STRING_SIZE+1]; 16028257Smsmith 16142475Snsouch printf("Probing for PnP devices on ppbus%d:\n", 16238061Smsmith ppb->ppb_link->adapter_unit); 16342475Snsouch 16442475Snsouch if ((error = ppb_1284_read_id(pnpdev, PPB_NIBBLE, str, 16542475Snsouch PPB_PnP_STRING_SIZE, &len))) 16638061Smsmith goto end_detect; 16739134Snsouch 16842475Snsouch#ifdef DEBUG_1284 16942475Snsouch printf("ppb: <PnP> %d characters: ", len); 17042475Snsouch for (i = 0; i < len; i++) 17142475Snsouch printf("%c(0x%x) ", str[i], str[i]); 17242475Snsouch printf("\n"); 17342475Snsouch#endif 17428257Smsmith 17528257Smsmith /* replace ';' characters by '\0' */ 17628257Smsmith for (i = 0; i < len; i++) 17728257Smsmith str[i] = (str[i] == ';') ? '\0' : str[i]; 17828257Smsmith 17942475Snsouch if ((token = search_token(str, len, "MFG")) != NULL || 18042475Snsouch (token = search_token(str, len, "MANUFACTURER")) != NULL) 18128257Smsmith printf("ppbus%d: <%s", ppb->ppb_link->adapter_unit, 18228257Smsmith search_token(token, UNKNOWN_LENGTH, ":") + 1); 18328257Smsmith else 18428257Smsmith printf("ppbus%d: <unknown", ppb->ppb_link->adapter_unit); 18528257Smsmith 18642475Snsouch if ((token = search_token(str, len, "MDL")) != NULL || 18742475Snsouch (token = search_token(str, len, "MODEL")) != NULL) 18828257Smsmith printf(" %s", 18928257Smsmith search_token(token, UNKNOWN_LENGTH, ":") + 1); 19028257Smsmith else 19128257Smsmith printf(" unknown"); 19228257Smsmith 19328257Smsmith if ((token = search_token(str, len, "VER")) != NULL) 19428257Smsmith printf("/%s", 19528257Smsmith search_token(token, UNKNOWN_LENGTH, ":") + 1); 19628257Smsmith 19728257Smsmith if ((token = search_token(str, len, "REV")) != NULL) 19828257Smsmith printf(".%s", 19928257Smsmith search_token(token, UNKNOWN_LENGTH, ":") + 1); 20028257Smsmith 20128257Smsmith printf(">"); 20228257Smsmith 20328257Smsmith if ((token = search_token(str, len, "CLS")) != NULL) { 20428257Smsmith class = search_token(token, UNKNOWN_LENGTH, ":") + 1; 20528257Smsmith printf(" %s", class); 20628257Smsmith } 20728257Smsmith 20842475Snsouch if ((token = search_token(str, len, "CMD")) != NULL || 20942475Snsouch (token = search_token(str, len, "COMMAND")) != NULL) 21028257Smsmith printf(" %s", 21128257Smsmith search_token(token, UNKNOWN_LENGTH, ":") + 1); 21228257Smsmith 21328257Smsmith printf("\n"); 21428257Smsmith 21528257Smsmith if (class) 21628257Smsmith /* identify class ident */ 21728257Smsmith for (i = 0; pnp_tokens[i] != NULL; i++) { 21828257Smsmith if (search_token(class, len, pnp_tokens[i]) != NULL) { 21938061Smsmith class_id = i; 22038061Smsmith goto end_detect; 22128257Smsmith } 22228257Smsmith } 22328257Smsmith 22438061Smsmith class_id = PPB_PnP_UNKNOWN; 22538061Smsmith 22638061Smsmithend_detect: 22742475Snsouch return (class_id); 22842475Snsouch} 22939134Snsouch 23042475Snsouch/* 23142475Snsouch * ppb_scan_bus() 23242475Snsouch * 23342475Snsouch * Scan the ppbus for IEEE1284 compliant devices 23442475Snsouch */ 23542475Snsouchstatic int 23642475Snsouchppb_scan_bus(struct ppb_data *ppb) 23742475Snsouch{ 23842475Snsouch struct ppb_device pnpdev; /* temporary device to perform I/O */ 23942475Snsouch int error = 0; 24042475Snsouch 24142475Snsouch /* initialize the pnpdev structure for future use */ 24242475Snsouch bzero(&pnpdev, sizeof(pnpdev)); 24342475Snsouch pnpdev.ppb = ppb; 24442475Snsouch 24542475Snsouch if ((error = ppb_request_bus(&pnpdev, PPB_DONTWAIT))) { 24642475Snsouch if (bootverbose) 24742475Snsouch printf("ppb: cannot allocate ppbus!\n"); 24842475Snsouch 24942475Snsouch return (error); 25042475Snsouch } 25142475Snsouch 25242475Snsouch /* try all IEEE1284 modes, for one device only 25342475Snsouch * 25442475Snsouch * XXX We should implement the IEEE1284.3 standard to detect 25542475Snsouch * daisy chained devices 25642475Snsouch */ 25742475Snsouch 25842475Snsouch error = ppb_1284_negociate(&pnpdev, PPB_NIBBLE, PPB_REQUEST_ID); 25942475Snsouch 26042475Snsouch if ((ppb->state == PPB_ERROR) && (ppb->error == PPB_NOT_IEEE1284)) 26142475Snsouch goto end_scan; 26242475Snsouch 26342475Snsouch ppb_1284_terminate(&pnpdev); 26442475Snsouch 26542475Snsouch printf("ppc%d: IEEE1284 device found ", ppb->ppb_link->adapter_unit); 26642475Snsouch 26742475Snsouch if (!(error = ppb_1284_negociate(&pnpdev, PPB_NIBBLE, 0))) { 26842475Snsouch printf("/NIBBLE"); 26942475Snsouch ppb_1284_terminate(&pnpdev); 27042475Snsouch } 27142475Snsouch 27242475Snsouch if (!(error = ppb_1284_negociate(&pnpdev, PPB_PS2, 0))) { 27342475Snsouch printf("/PS2"); 27442475Snsouch ppb_1284_terminate(&pnpdev); 27542475Snsouch } 27642475Snsouch 27742475Snsouch if (!(error = ppb_1284_negociate(&pnpdev, PPB_ECP, 0))) { 27842475Snsouch printf("/ECP"); 27942475Snsouch ppb_1284_terminate(&pnpdev); 28042475Snsouch } 28142475Snsouch 28242475Snsouch if (!(error = ppb_1284_negociate(&pnpdev, PPB_ECP, PPB_USE_RLE))) { 28342475Snsouch printf("/ECP_RLE"); 28442475Snsouch ppb_1284_terminate(&pnpdev); 28542475Snsouch } 28642475Snsouch 28742475Snsouch if (!(error = ppb_1284_negociate(&pnpdev, PPB_EPP, 0))) { 28842475Snsouch printf("/EPP"); 28942475Snsouch ppb_1284_terminate(&pnpdev); 29042475Snsouch } 29142475Snsouch 29242475Snsouch#if 0 29342475Snsouch if (!(error = ppb_1284_negociate(&pnpdev, PPB_NIBBLE, PPB_REQUEST_ID))) { 29442475Snsouch printf("/NIBBLE_ID"); 29542475Snsouch ppb_1284_terminate(&pnpdev); 29642475Snsouch } 29742475Snsouch 29842475Snsouch if (!(error = ppb_1284_negociate(&pnpdev, PPB_PS2, PPB_REQUEST_ID))) { 29942475Snsouch printf("/PS2_ID"); 30042475Snsouch ppb_1284_terminate(&pnpdev); 30142475Snsouch } 30242475Snsouch 30342475Snsouch if (!(error = ppb_1284_negociate(&pnpdev, PPB_ECP, PPB_REQUEST_ID))) { 30442475Snsouch printf("/ECP_ID"); 30542475Snsouch ppb_1284_terminate(&pnpdev); 30642475Snsouch } 30742475Snsouch 30842475Snsouch if (!(error = ppb_1284_negociate(&pnpdev, PPB_ECP, 30942475Snsouch PPB_REQUEST_ID | PPB_USE_RLE))) { 31042475Snsouch printf("/ECP_RLE_ID"); 31142475Snsouch ppb_1284_terminate(&pnpdev); 31242475Snsouch } 31342475Snsouch#endif 31442475Snsouch 31542475Snsouch if (!(error = ppb_1284_negociate(&pnpdev, PPB_COMPATIBLE, 31642475Snsouch PPB_EXTENSIBILITY_LINK))) { 31742475Snsouch printf("/Extensibility Link"); 31842475Snsouch ppb_1284_terminate(&pnpdev); 31942475Snsouch } 32042475Snsouch 32142475Snsouch printf(" in FORWARD_IDLE state\n"); 32242475Snsouch 32342475Snsouch /* detect PnP devices */ 32442475Snsouch ppb->class_id = ppb_pnp_detect(ppb, &pnpdev); 32542475Snsouch 32638061Smsmith ppb_release_bus(&pnpdev); 32742475Snsouch 32842475Snsouch return (0); 32942475Snsouch 33042475Snsouchend_scan: 33142475Snsouch ppb_release_bus(&pnpdev); 33242475Snsouch return (error); 33328257Smsmith} 33428257Smsmith 33542475Snsouch#endif /* !DONTPROBE_1284 */ 33642475Snsouch 33728257Smsmith/* 33828219Smsmith * ppb_attachdevs() 33928219Smsmith * 34028219Smsmith * Called by ppcattach(), this function probes the ppbus and 34128219Smsmith * attaches found devices. 34228219Smsmith */ 34328219Smsmithint 34428219Smsmithppb_attachdevs(struct ppb_data *ppb) 34528219Smsmith{ 34628219Smsmith struct ppb_device *dev; 34728219Smsmith struct ppb_driver **p_drvpp, *p_drvp; 34828257Smsmith 34928219Smsmith LIST_INIT(&ppb->ppb_devs); /* initialise device/driver list */ 35028219Smsmith p_drvpp = (struct ppb_driver **)ppbdriver_set.ls_items; 35128257Smsmith 35242475Snsouch#ifndef DONTPROBE_1284 35342475Snsouch /* detect IEEE1284 compliant devices */ 35442475Snsouch ppb_scan_bus(ppb); 35542475Snsouch#endif /* !DONTPROBE_1284 */ 35628219Smsmith 35728219Smsmith /* 35828219Smsmith * Blindly try all probes here. Later we should look at 35928219Smsmith * the parallel-port PnP standard, and intelligently seek 36028219Smsmith * drivers based on configuration first. 36128219Smsmith */ 36228219Smsmith while ((p_drvp = *p_drvpp++) != NULL) { 36328219Smsmith if (p_drvp->probe && (dev = (p_drvp->probe(ppb))) != NULL) { 36428219Smsmith /* 36528219Smsmith * Add the device to the list of probed devices. 36628219Smsmith */ 36728219Smsmith LIST_INSERT_HEAD(&ppb->ppb_devs, dev, chain); 36828219Smsmith 36928219Smsmith /* Call the device's attach routine */ 37028219Smsmith (void)p_drvp->attach(dev); 37128219Smsmith } 37228219Smsmith } 37328219Smsmith return (0); 37428219Smsmith} 37528219Smsmith 37628219Smsmith/* 37728257Smsmith * ppb_next_bus() 37828219Smsmith * 37928257Smsmith * Return the next bus in ppbus queue 38028219Smsmith */ 38128257Smsmithstruct ppb_data * 38228257Smsmithppb_next_bus(struct ppb_data *ppb) 38328219Smsmith{ 38428219Smsmith 38528257Smsmith if (ppb == NULL) 38628257Smsmith return (ppbdata.lh_first); 38728219Smsmith 38828257Smsmith return (ppb->ppb_chain.le_next); 38928257Smsmith} 39028219Smsmith 39128257Smsmith/* 39228257Smsmith * ppb_lookup_bus() 39328257Smsmith * 39428257Smsmith * Get ppb_data structure pointer according to the base address of the ppbus 39528257Smsmith */ 39628257Smsmithstruct ppb_data * 39728257Smsmithppb_lookup_bus(int base_port) 39828257Smsmith{ 39928257Smsmith struct ppb_data *ppb; 40028219Smsmith 40128257Smsmith for (ppb = ppbdata.lh_first; ppb; ppb = ppb->ppb_chain.le_next) 40228257Smsmith if (ppb->ppb_link->base == base_port) 40328257Smsmith break; 40428219Smsmith 40528257Smsmith return (ppb); 40628219Smsmith} 40728219Smsmith 40828219Smsmith/* 40938061Smsmith * ppb_lookup_link() 41038061Smsmith * 41138061Smsmith * Get ppb_data structure pointer according to the unit value 41238061Smsmith * of the corresponding link structure 41338061Smsmith */ 41438061Smsmithstruct ppb_data * 41538061Smsmithppb_lookup_link(int unit) 41638061Smsmith{ 41738061Smsmith struct ppb_data *ppb; 41838061Smsmith 41938061Smsmith for (ppb = ppbdata.lh_first; ppb; ppb = ppb->ppb_chain.le_next) 42038061Smsmith if (ppb->ppb_link->adapter_unit == unit) 42138061Smsmith break; 42238061Smsmith 42338061Smsmith return (ppb); 42438061Smsmith} 42538061Smsmith 42638061Smsmith/* 42728257Smsmith * ppb_attach_device() 42828219Smsmith * 42928257Smsmith * Called by loadable kernel modules to add a device 43028219Smsmith */ 43128219Smsmithint 43228257Smsmithppb_attach_device(struct ppb_device *dev) 43328219Smsmith{ 43428219Smsmith struct ppb_data *ppb = dev->ppb; 43528219Smsmith 43628257Smsmith /* add the device to the list of probed devices */ 43728257Smsmith LIST_INSERT_HEAD(&ppb->ppb_devs, dev, chain); 43828219Smsmith 43928219Smsmith return (0); 44028219Smsmith} 44128219Smsmith 44228219Smsmith/* 44328257Smsmith * ppb_remove_device() 44428219Smsmith * 44528257Smsmith * Called by loadable kernel modules to remove a device 44628219Smsmith */ 44728219Smsmithvoid 44828257Smsmithppb_remove_device(struct ppb_device *dev) 44928219Smsmith{ 45028219Smsmith 45128257Smsmith /* remove the device from the list of probed devices */ 45228257Smsmith LIST_REMOVE(dev, chain); 45328219Smsmith 45428219Smsmith return; 45528219Smsmith} 45628219Smsmith 45728219Smsmith/* 45828257Smsmith * ppb_request_bus() 45928219Smsmith * 46028257Smsmith * Allocate the device to perform transfers. 46128257Smsmith * 46228257Smsmith * how : PPB_WAIT or PPB_DONTWAIT 46328219Smsmith */ 46428219Smsmithint 46528257Smsmithppb_request_bus(struct ppb_device *dev, int how) 46628219Smsmith{ 46728257Smsmith int s, error = 0; 46828219Smsmith struct ppb_data *ppb = dev->ppb; 46928219Smsmith 47028257Smsmith while (!error) { 47128257Smsmith s = splhigh(); 47228257Smsmith if (ppb->ppb_owner) { 47328257Smsmith splx(s); 47428219Smsmith 47528257Smsmith switch (how) { 47628257Smsmith case (PPB_WAIT | PPB_INTR): 47728257Smsmith error = tsleep(ppb, PPBPRI|PCATCH, "ppbreq", 0); 47828257Smsmith break; 47928219Smsmith 48028257Smsmith case (PPB_WAIT | PPB_NOINTR): 48128257Smsmith error = tsleep(ppb, PPBPRI, "ppbreq", 0); 48228257Smsmith break; 48328219Smsmith 48428257Smsmith default: 48528257Smsmith return (EWOULDBLOCK); 48628257Smsmith break; 48728257Smsmith } 48828219Smsmith 48928257Smsmith } else { 49028257Smsmith ppb->ppb_owner = dev; 49128219Smsmith 49238061Smsmith /* restore the context of the device 49338061Smsmith * The first time, ctx.valid is certainly false 49438061Smsmith * then do not change anything. This is usefull for 49538061Smsmith * drivers that do not set there operating mode 49638061Smsmith * during attachement 49738061Smsmith */ 49838061Smsmith if (dev->ctx.valid) 49938061Smsmith ppb_set_mode(dev, dev->ctx.mode); 50038061Smsmith 50128257Smsmith splx(s); 50228257Smsmith return (0); 50328257Smsmith } 50428257Smsmith } 50528219Smsmith 50628257Smsmith return (error); 50728219Smsmith} 50828219Smsmith 50928219Smsmith/* 51028257Smsmith * ppb_release_bus() 51128219Smsmith * 51228257Smsmith * Release the device allocated with ppb_request_dev() 51328219Smsmith */ 51428219Smsmithint 51528257Smsmithppb_release_bus(struct ppb_device *dev) 51628219Smsmith{ 51728257Smsmith int s; 51828219Smsmith struct ppb_data *ppb = dev->ppb; 51928219Smsmith 52028257Smsmith s = splhigh(); 52128257Smsmith if (ppb->ppb_owner != dev) { 52228257Smsmith splx(s); 52328219Smsmith return (EACCES); 52428257Smsmith } 52528219Smsmith 52628257Smsmith ppb->ppb_owner = 0; 52728257Smsmith splx(s); 52828219Smsmith 52938061Smsmith /* save the context of the device */ 53038061Smsmith dev->ctx.mode = ppb_get_mode(dev); 53138061Smsmith 53238061Smsmith /* ok, now the context of the device is valid */ 53338061Smsmith dev->ctx.valid = 1; 53438061Smsmith 53528257Smsmith /* wakeup waiting processes */ 53628257Smsmith wakeup(ppb); 53728219Smsmith 53828219Smsmith return (0); 53928219Smsmith} 540